linux字符終端圖片展示

所用操作系統概述:linux3.2.0內核,64位的Ubuntu12.04虛擬機
  關於linux下操作fb0的介紹網上已經有很多資料了,大家可以隨便搜索一下就能找到大量的比較詳細的原理性的東西的介紹,我也是根據網上的資料自己寫了一個小的測試程序,拿出來跟大家分享。必要說明的一點是直接操作fb0只能在除了tty7圖形界面的其它終端纔有效,具體原因我也不是很清楚,感覺像是圖形界面下看不到真正的tty終端,所以沒辦法顯示吧,具體原因有大神也可以給解答一下。
  我測試的時候是用的tty1字符終端(在圖形界面下,同時按Ctrl+Alt+F1就可以進入tty1字符終端界面),實際效果如圖,源碼見附件。但是在安卓下測試這個程序也不能正常工作,除非是在機器啓動時,系統在進入linux系統但還沒運行安卓應用之前測試的時候是可以直接寫的,但是感覺跟Ubuntu下現象還是不一致,顯示的不是很正常。誰瞭解怎麼在安卓下直接操作/dev/graphics/fb0也可以留言。
  測試的效果圖如下,代碼包連接如下https://download.csdn.net/download/jxhln/10925387,在這裏插入圖片描述
2019-01-18 13:52 修正
  下面的代碼我又用另外版本的虛擬機測試了一下,發現不正常工作,雖然也能顯示自己寫進去的東西,但是與實際圖片相差甚遠,後來發現同一個Windows主機上安裝的虛擬機得到fb中line_length還不一樣,由於這個原因導致在填充顯示器的實際行時一個每一行需填充8192字節的像素,而另一個每一行只需填充3200字節的像素,故導致其中一個虛擬機顯示正常,另外一個虛擬即顯示不正常,故需根據這個line_length改變自己程序中實際填充的字節數才能得到想要的圖片(對照下面的程序,虛擬機line_length爲8192的fb_width爲8193/4=2048,line_length爲3200的fb_width=3200/4=8,除以4是因爲下面的bits_per_pixel爲32位,故每4字節代表一個實際像素點)。
  調用ioctl(fbFd, FBIOGET_FSCREENINFO, &finfo)和ioctl(fbFd, FBIOGET_VSCREENINFO, &vinfo) 可以得到fb下列fixed和variable配置信息,其中fbFd爲fb0的設備描述符,finfo和vinfo爲保存fb配置信息的結構,定義如下

#include <linux/fb.h>  //struct fb_fix_screeninfo和struct fb_var_screeninfo的頭文件
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;`

在這裏插入圖片描述

測試的C代碼如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#define  PIC_DAT  1
#define  PIC_DAT2 2
#define  DM16A_1  3
#define  DM16A_3  4

#define  PIC_SELECT 1

#if (PIC_SELECT == PIC_DAT)
#include "pic_data.h"
#elif (PIC_SELECT == DM16A_3)                                                                                    
#include "dm16a_3.h"
#elif (PIC_SELECT == DM16A_1)
#include "dm16a_1_dealed.h"
#elif (PIC_SELECT == PIC_DAT2)
#include "pic_data2.h"
#endif


#define   FB_DEV  "/dev/fb0"
//#define   FB_DEV  "/dev/graphics/fb0"
/***************** function declaration ******************/
void usage(char *msg);
int  fb_open(char *fb_device);
int  fb_close(int fd);
int  fb_stat(int fd, int *width, int *height, int *depth);
void *fb_mmap(int fd, unsigned int screensize);
int  fb_munmap(void *start, size_t length);
void deal_pic_data2show_buffer(unsigned char * des,const unsigned char * src,unsigned int len);

/************ function implementation ********************/
int main(int argc, char *argv[])
{
    /*
    * declaration for framebuffer device
    */
    int             fbdev;
    char           *fb_device;
    unsigned char  *fbmem;
    unsigned int    screensize;
    unsigned int    fb_width;
    unsigned int    fb_height;
    unsigned int    fb_depth;
     unsigned int    x;
    unsigned int    y;
    unsigned int    show_width;
    unsigned int    show_height;
    unsigned char   * show_buffer;
    unsigned int    data_len;
    unsigned int    len;
    unsigned char   bytes_per_pix;
    /*
    * open framebuffer device
    */
    if(PIC_SELECT != PIC_DAT || PIC_SELECT != PIC_DAT2
            || PIC_SELECT != DM16A_1 || PIC_SELECT != DM16A_3)
    if ((fb_device = getenv("FRAMEbuffer")) == NULL)
        fb_device = FB_DEV;
    fbdev = fb_open(fb_device);
    /*
    * get status of framebuffer device
    */
    fb_stat(fbdev, &fb_width, &fb_height, &fb_depth);
    /*
    * map framebuffer device to shared memory
    */
    bytes_per_pix = fb_depth / 8;
    screensize = fb_width * fb_height * bytes_per_pix;
    fbmem = fb_mmap(fbdev, screensize);
#if 0   
    show_width  = fb_width;
    show_height = fb_height; 
#endif
    show_width  = pic_width;
    show_height = pic_height; 
    data_len = show_width * show_height * 4;
    show_buffer = malloc(data_len);
    if(show_buffer == NULL)
        return -1;
#if (PIC_SELECT == PIC_DAT)
        memset(show_buffer,0xff,data_len);
        memcpy(show_buffer,pic_buf,sizeof(pic_buf));
#else                                                                                                            
        len = sizeof(pic_buf);
        deal_pic_data2show_buffer(show_buffer,pic_buf,len);
#endif
while(1){
        for(x = 0;x < show_height;x ++)
            for(y = 0;y < show_width * bytes_per_pix;y ++)
                fbmem[x * fb_width * bytes_per_pix + y] = 
                    show_buffer[x * show_width * bytes_per_pix + y];
        //memset(fbmem,0xff,fb_height * fb_width * 4);
    }
    fb_munmap(fbmem, screensize);
    /*
    * close framebuffer device
    */
    fb_close(fbdev);
    return (0);
}
/*
* open framebuffer device.
* return positive file descriptor if success,
* else return -1.
*/
int fb_open(char *fb_device)
{
    int  fd;
    if ((fd = open(fb_device, O_RDWR)) < 0) {
        perror(__func__);
        return (-1);
    }
    return (fd);
}
/*
* get framebuffer's width,height,and depth.
* return 0 if success, else return -1.
*/
int fb_stat(int fd, int *width, int *height, int *depth)
{
    struct fb_fix_screeninfo fb_finfo;
    struct fb_var_screeninfo fb_vinfo;
    if (ioctl(fd, FBIOGET_FSCREENINFO, &fb_finfo)) {
        perror(__func__);
        return (-1);                                                                                             
    }
    if (ioctl(fd, FBIOGET_VSCREENINFO, &fb_vinfo)) {
        perror(__func__);
        return (-1);
    }
*width = fb_vinfo.xres;
    *height = fb_vinfo.yres;
    *depth = fb_vinfo.bits_per_pixel;
    return (0);
}
/*
* map shared memory to framebuffer device.
* return maped memory if success,
* else return -1, as mmap dose.
*/
void  * fb_mmap(int fd, unsigned int screensize)
{
    caddr_t         fbmem;
    if ((fbmem = mmap(0, screensize, PROT_READ | PROT_WRITE,
    MAP_SHARED, fd, 0)) == MAP_FAILED) {
        perror(__func__);
        return (void *) (-1);
    }
    return (fbmem);
} 
/*
* unmap map memory for framebuffer device.
*/
int fb_munmap(void *start, size_t length)
{
    return (munmap(start, length));
}
/*
* close framebuffer device
*/
int fb_close(int fd)
{
    return (close(fd));
}
void deal_pic_data2show_buffer(unsigned char * des,const unsigned char * src,unsigned int len){

    int i = 0;
    unsigned char show_data;
    unsigned short tmp_data;
    for(i = 0;i < (len / 2);i ++){
        tmp_data = (src[i * 2] << 8 | src[i * 2 + 1]);
        show_data = (tmp_data >> 6);
        des[i * 4]     = show_data;                                                                              
        des[i * 4 + 1] = show_data;
        des[i * 4 + 2] = show_data;
        des[i * 4 + 3] = 0xff;
    }

}

```                                            -----  大白
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章