zoukankan      html  css  js  c++  java
  • linux显示bmp图像

    fb_show_bmp.c

      1 #include <unistd.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <fcntl.h>
      5 #include <string.h>
      6 #include <linux/fb.h>
      7 #include <sys/mman.h>
      8 #include <sys/ioctl.h>
      9 #include <arpa/inet.h>
     10 #include <errno.h>
     11 
     12 //14byte文件头
     13 typedef struct
     14 {
     15     char cfType[2];  //文件类型,"BM"(0x4D42)
     16     int  cfSize;     //文件大小(字节)
     17     int  cfReserved; //保留,值为0
     18     int  cfoffBits;  //数据区相对于文件头的偏移量(字节)
     19 }__attribute__((packed)) BITMAPFILEHEADER;
     20 //__attribute__((packed))的作用是告诉编译器取消结构在编译过程中的优化对齐
     21 
     22 //40byte信息头
     23 typedef struct
     24 {
     25     char ciSize[4];          //BITMAPFILEHEADER所占的字节数
     26     int  ciWidth;            //宽度
     27     int  ciHeight;           //高度
     28     char ciPlanes[2];        //目标设备的位平面数,值为1
     29     int  ciBitCount;         //每个像素的位数
     30     char ciCompress[4];      //压缩说明
     31     char ciSizeImage[4];     //用字节表示的图像大小,该数据必须是4的倍数
     32     char ciXPelsPerMeter[4]; //目标设备的水平像素数/米
     33     char ciYPelsPerMeter[4]; //目标设备的垂直像素数/米
     34     char ciClrUsed[4];       //位图使用调色板的颜色数
     35     char ciClrImportant[4];  //指定重要的颜色数,当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要
     36 }__attribute__((packed)) BITMAPINFOHEADER;
     37 
     38 typedef struct
     39 {
     40     unsigned char blue;
     41     unsigned char green;
     42     unsigned char red;
     43     unsigned char reserved;
     44 }__attribute__((packed)) PIXEL; //颜色模式RGB
     45 
     46 
     47 
     48 typedef struct
     49 {
     50     int          fbfd;
     51     char         *fbp;
     52     unsigned int xres;
     53     unsigned int yres;
     54     unsigned int xres_virtual;
     55     unsigned int yres_virtual;
     56     unsigned int xoffset;
     57     unsigned int yoffset;
     58     unsigned int bpp;
     59     unsigned long line_length;
     60     unsigned long size;
     61 
     62     struct fb_bitfield red;
     63     struct fb_bitfield green;
     64     struct fb_bitfield blue;
     65 } FB_INFO;
     66 
     67 typedef struct
     68 {
     69     unsigned int width;
     70     unsigned int height;
     71     unsigned int bpp;
     72     unsigned long size;
     73     unsigned int data_offset;
     74 } IMG_INFO;
     75 
     76 
     77 
     78 FB_INFO fb_info;
     79 IMG_INFO img_info;
     80 
     81 int show_bmp(char *img_name);
     82 
     83 static int cursor_bitmap_format_convert(char *dst,char *src, unsigned long img_len_one_line)
     84 {
     85     int img_len ,fb_len ;
     86     char *p;
     87     __u32 val;
     88     PIXEL pix;
     89 
     90     p = (char *)&val;
     91 
     92     img_len = img_info.width; /*一行图片的长度*/
     93     fb_len = fb_info.xres; /*一行显示屏的长度*/
     94 
     95     /*进行x轴的偏移*/
     96     dst += fb_info.xoffset * (fb_info.bpp / 8);
     97     fb_len -= fb_info.xoffset;
     98 
     99     /*bmp 数据是上下左右颠倒的,这里只进行左右的处理*/
    100     /*先定位到图片的最后一个像素的地址,然后往第一个像素的方向处理,进行左右颠倒的处理*/
    101     src += img_len_one_line - 1;
    102 
    103     /*处理一行要显示的数据*/
    104     while(1) {
    105         if (img_info.bpp == 32)
    106             pix.reserved = *(src--);
    107         pix.red   = *(src--);
    108         pix.green = *(src--);
    109         pix.blue  = *(src--);
    110 
    111         val = 0x00;
    112         val |= (pix.red >> (8 - fb_info.red.length)) << fb_info.red.offset;
    113         val |= (pix.green >> (8 - fb_info.green.length)) << fb_info.green.offset;
    114         val |= (pix.blue >> (8 - fb_info.blue.length)) << fb_info.blue.offset;
    115 
    116 
    117         if (fb_info.bpp == 16) {
    118             *(dst++) = *(p + 0);
    119             *(dst++) = *(p + 1);
    120         }
    121         else if (fb_info.bpp == 24) {
    122             *(dst++) = *(p + 0);
    123             *(dst++) = *(p + 1);
    124             *(dst++) = *(p + 2);
    125         }
    126         else if (fb_info.bpp == 32) {
    127             *(dst++) = *(p + 0);
    128             *(dst++) = *(p + 1);
    129             *(dst++) = *(p + 2);
    130             *(dst++) = *(p + 3);
    131         }
    132 
    133         /*超过图片长度或显示屏长度认为一行处理完了*/
    134         img_len--;
    135         fb_len--;
    136         if (img_len <= 0 || fb_len <= 0)
    137             break;
    138     }
    139 #if 0
    140     printf("r = %d
    ", pix.red);
    141     printf("g = %d
    ", pix.green);
    142     printf("b = %d
    ", pix.blue);
    143 #endif
    144     return 0;
    145 }
    146 
    147 int show_bmp(char *img_name)
    148 {
    149 
    150     FILE *fp;
    151     int ret = 0;
    152     BITMAPFILEHEADER FileHead;
    153     BITMAPINFOHEADER InfoHead;
    154 
    155     if(img_name == NULL) {
    156         printf("img_name is null
    ");
    157         return -1;
    158     }
    159 
    160     fp = fopen( img_name, "rb" );
    161     if(fp == NULL) {
    162         printf("img[%s] open failed
    ", img_name);
    163         ret = -1;
    164         goto err_showbmp;
    165     }
    166 
    167     /* 移位到文件头部 */
    168     fseek(fp, 0, SEEK_SET);
    169 
    170     ret = fread(&FileHead, sizeof(BITMAPFILEHEADER), 1, fp);
    171     if ( ret != 1) {
    172         printf("img read failed
    ");
    173         ret = -1;
    174         goto err_showbmp;
    175     }
    176 
    177     //检测是否是bmp图像
    178     if (memcmp(FileHead.cfType, "BM", 2) != 0) {
    179         printf("it's not a BMP file[%c%c]
    ", FileHead.cfType[0], FileHead.cfType[1]);
    180         ret = -1;
    181         goto err_showbmp;
    182     }
    183 
    184     ret = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp );
    185     if ( ret != 1) {
    186         printf("read infoheader error!
    ");
    187         ret = -1;
    188         goto err_showbmp;
    189     }
    190 
    191     img_info.width       = InfoHead.ciWidth;
    192     img_info.height      = InfoHead.ciHeight;
    193     img_info.bpp         = InfoHead.ciBitCount;
    194     img_info.size        = FileHead.cfSize;
    195     img_info.data_offset = FileHead.cfoffBits;
    196 
    197     printf("img info w[%d] h[%d] bpp[%d] size[%ld] offset[%d]
    ", img_info.width, img_info.height, img_info.bpp, img_info.size, img_info.data_offset);
    198 
    199     if (img_info.bpp != 24 && img_info.bpp != 32) {
    200         printf("img bpp is not 24 or 32
    ");
    201         ret = -1;
    202         goto err_showbmp;
    203     }
    204 
    205 
    206     /*
    207      *一行行处理
    208      */
    209     char *buf_img_one_line;
    210     char *buf_fb_one_line;
    211     char *p;
    212     int fb_height;
    213 
    214     long img_len_one_line = img_info.width * (img_info.bpp / 8);
    215     long fb_len_one_line = fb_info.line_length;
    216 
    217     printf("img_len_one_line = %ld
    ", img_len_one_line);
    218     printf("fb_len_one_line = %ld
    ", fb_info.line_length);
    219 
    220     buf_img_one_line = (char *)calloc(1, img_len_one_line + 256);
    221     if(buf_img_one_line == NULL) {
    222         printf("alloc failed
    ");
    223         ret = -1;
    224         goto err_showbmp;
    225     }
    226 
    227     buf_fb_one_line = (char *)calloc(1, fb_len_one_line + 256);
    228     if(buf_fb_one_line == NULL) {
    229         printf("alloc failed
    ");
    230         ret = -1;
    231         goto err_showbmp;
    232     }
    233 
    234 
    235     fseek(fp, img_info.data_offset, SEEK_SET);
    236 
    237     p = fb_info.fbp + fb_info.yoffset * fb_info.line_length; /*进行y轴的偏移*/
    238     fb_height = fb_info.yres;
    239     while (1) {
    240         memset(buf_img_one_line, 0, img_len_one_line);
    241         memset(buf_fb_one_line, 0, fb_len_one_line);
    242         ret = fread(buf_img_one_line, 1, img_len_one_line, fp);
    243         if (ret < img_len_one_line) {
    244             /*图片读取完成,则图片显示完成*/
    245             printf("read to end of img file
    ");
    246             cursor_bitmap_format_convert(buf_fb_one_line, buf_img_one_line, img_len_one_line); /*数据转换*/
    247             memcpy(fb_info.fbp, buf_fb_one_line, fb_len_one_line);
    248             break;
    249         }
    250 
    251         cursor_bitmap_format_convert(buf_fb_one_line, buf_img_one_line, img_len_one_line); /*数据转换*/
    252         memcpy(p, buf_fb_one_line, fb_len_one_line); /*显示一行*/
    253         p += fb_len_one_line;
    254 
    255         /*超过显示屏宽度认为图片显示完成*/
    256         fb_height--;
    257         if (fb_height <= 0)
    258             break;
    259     }
    260 
    261     free(buf_img_one_line);
    262     free(buf_fb_one_line);
    263 
    264     fclose(fp);
    265     return ret;
    266 err_showbmp:
    267     if (fp)
    268         fclose(fp);
    269     return ret;
    270 }
    271 
    272 int show_picture(char *img_name)
    273 {
    274     struct fb_var_screeninfo vinfo;
    275     struct fb_fix_screeninfo finfo;
    276 
    277     if (fb_info.fbfd <= -1) {
    278         printf("fb open fialed
    ");
    279         return -1;
    280     }
    281 
    282     if (ioctl(fb_info.fbfd, FBIOGET_FSCREENINFO, &finfo)) {
    283         printf("fb ioctl fialed
    ");
    284         return -1;
    285     }
    286 
    287     if (ioctl(fb_info.fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
    288         printf("fb ioctl fialed
    ");
    289         return -1;
    290     }
    291 
    292     fb_info.xres = vinfo.xres;
    293     fb_info.yres = vinfo.yres;
    294     fb_info.xres_virtual = vinfo.xres_virtual;
    295     fb_info.yres_virtual = vinfo.yres_virtual;
    296     fb_info.xoffset = vinfo.xoffset;
    297     fb_info.yoffset = vinfo.yoffset;
    298     fb_info.bpp  = vinfo.bits_per_pixel;
    299     fb_info.line_length = finfo.line_length;
    300     fb_info.size = finfo.smem_len;
    301 
    302     memcpy(&fb_info.red, &vinfo.red, sizeof(struct fb_bitfield));
    303     memcpy(&fb_info.green, &vinfo.green, sizeof(struct fb_bitfield));
    304     memcpy(&fb_info.blue, &vinfo.blue, sizeof(struct fb_bitfield));
    305 
    306     printf("fb info x[%d] y[%d] x_v[%d] y_v[%d] xoffset[%d] yoffset[%d] bpp[%d] line_length[%ld] size[%ld]
    ", fb_info.xres, fb_info.yres, fb_info.xres_virtual, fb_info.yres_virtual, fb_info.xoffset, fb_info.yoffset, fb_info.bpp, fb_info.line_length, fb_info.size);
    307 
    308     printf("fb info red off[%d] len[%d] msb[%d]
    ", fb_info.red.offset, fb_info.red.length, fb_info.red.msb_right);
    309     printf("fb info green off[%d] len[%d] msb[%d]
    ", fb_info.green.offset, fb_info.green.length, fb_info.green.msb_right);
    310     printf("fb info blue off[%d] len[%d] msb[%d]
    ", fb_info.blue.offset, fb_info.blue.length, fb_info.blue.msb_right);
    311 
    312     if (fb_info.bpp != 16 && fb_info.bpp != 24 && fb_info.bpp != 32) {
    313         printf("fb bpp is not 16,24 or 32
    ");
    314         return -1;
    315     }
    316 
    317     if (fb_info.red.length > 8 || fb_info.green.length > 8 || fb_info.blue.length > 8) {
    318         printf("fb red|green|blue length is invalid
    ");
    319         return -1;
    320     }
    321 
    322     // 内存映射
    323     fb_info.fbp = (char *)mmap(0, fb_info.size, PROT_READ | PROT_WRITE, MAP_SHARED, fb_info.fbfd, 0);
    324     if (fb_info.fbp == (char *)-1) {
    325         printf("mmap fialed
    ");
    326         return -1;
    327     }
    328 
    329     show_bmp(img_name);
    330 
    331     //删除映射
    332     munmap(fb_info.fbp, fb_info.size);
    333 
    334     return 0;
    335 }
    336 
    337 
    338 int main(int argc, char **argv)
    339 {
    340     char img_name[64];
    341 
    342     if (argc != 2) {
    343         printf("arg error
    ");
    344         return 0;
    345     }
    346 
    347     snprintf(img_name, sizeof(img_name), "%s", argv[1]);
    348     printf("img_name = %s
    ", img_name);
    349 
    350     fb_info.fbfd = open("/dev/fb0", O_RDWR);
    351     if (!fb_info.fbfd) {
    352         printf("Error: cannot open framebuffer device(/dev/fb0).
    ");
    353         return -1;
    354     }
    355     show_picture(img_name);
    356 
    357     close(fb_info.fbfd);
    358         return 0;
    359 }
  • 相关阅读:
    页面出现Incorrect string以及数据库内容乱码
    页面中的导航监测
    基于.NET平台常用的框架整理
    强化学习-简介
    强化学习五大方面-奖励与策略结构
    强化学习五大方面-环境
    MSP430G2ET时钟系统
    java每日一练 2020.7.27
    Java多线程
    java每日一练 2020.7.26
  • 原文地址:https://www.cnblogs.com/live-program/p/11940974.html
Copyright © 2011-2022 走看看