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图像的主要内容,如果未能解决你的问题,请参考以下文章