linux显示bmp图像

Posted Alvin2012

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }

 

以上是关于linux显示bmp图像的主要内容,如果未能解决你的问题,请参考以下文章

Linux应用开发-LCD显示BMP图片

Linux应用开发第二章图像处理应用开发

linux应用编程--显示bmp图片

使用内联 ASM c++ 显示 640x480 BMP 图像

使用 mfc 对话框显示 .bmp 图像时出错

WINDOWS程序设计对话框加载显示bmp图像及刷新