基于S3c244016位24位的BMP图片显示程序
[复制链接]
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <linux/fb.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <arpa/inet.h>
/*************************************************** * BMP文件信息头结构 ***************************************************/ //14byte typedef struct { char cfType[2]; /* 文件类型, 必须为 "BM" (0x4D42)*/ char cfSize[4]; /* 文件的大小(字节) */ char cfReserved[4]; /* 保留, 必须为 0 */ char cfoffBits[4]; /* 位图阵列相对于文件头的偏移量(字节)*/ }__attribute__((packed)) BITMAPFILEHEADER; /* 文件头结构 */
//40byte typedef struct { char ciSize[4]; /* size of BITMAPINFOHEADER */ char ciWidth[4]; /* 位图宽度(像素) */ char ciHeight[4]; /* 位图高度(像素) */ char ciPlanes[2]; /* 目标设备的位平面数, 必须置为1 */ char ciBitCount[2]; /* 每个像素的位数, 1,4,8或24 */ char ciCompress[4]; /* 位图阵列的压缩方法,0=不压缩 */ char ciSizeImage[4]; /* 图像大小(字节) */ char ciXPelsPerMeter[4];/* 目标设备水平每米像素个数 */ char ciYPelsPerMeter[4];/* 目标设备垂直每米像素个数 */ char ciClrUsed[4]; /* 位图实际使用的颜色表的颜色数 */ char ciClrImportant[4]; /* 重要颜色索引的个数 */ } BITMAPINFOHEADER; /* 位图信息头结构 */
typedef struct { unsigned char blue; unsigned char green; unsigned char red; } PIXEL; /****************************************************/ BITMAPFILEHEADER FileHead; BITMAPINFOHEADER InfoHead;
char *fbp = 0; int xres = 0; int yres = 0; int bits_per_pixel = 0; int put_to_framebuf ( char *bmpfile ); long chartolong ( char * string, int length ); /****************************************************************************** * ******************************************************************************/ int main ( int argc, char *argv[] ) { int fbfd = 0; struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; long int screensize = 0; /***********************************************************帧缓存相关的*/ // Open the file for reading and writing fbfd = open("/dev/fb0", O_RDWR); if (!fbfd) { printf("Error cannot open framebuffer device.\n"); exit(1); }
// Get fixed screen information if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)){ printf("Error reading fixed information.\n"); exit(2); } // Get variable screen information if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) { printf("Error reading variable information.\n"); exit(3); }
printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel ); xres = vinfo.xres; yres = vinfo.yres; bits_per_pixel = vinfo.bits_per_pixel;
// Figure out the size of the screen in bytes screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
// Map the device to memory fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); if ((int)fbp == -1) { printf("Error failed to map framebuffer device to memory.\n"); exit(4); } printf("sizeof header=%d\n", sizeof(BITMAPFILEHEADER)); printf("into show_bmp fun\n"); /*******************************************************************************/ int i; for(i = 1; i < sizeof(argv);i++){ put_to_framebuf( argv ); //显示图像 if(argc != 2) //判断如果只有一张图片则不进行延时 sleep(1); } munmap(fbp, screensize); close(fbfd); return 0; }
/****************************************************************************** *name : put_to_framebuffers *参数介绍 : line_x,line_y是坐标偏移量; start_x,start_y是数据写入计数器; addr_x,addr_y,是写入数据的地址; 功能 : 将一个24位的图片显示在显示屏上 返回值 : 无 time : 2010.7.21 ******************************************************************************/ int put_to_framebuf( char *bmpfile ) { FILE *fp; int rc; int ciBitCount, ciWidth, ciHeight,cfoffBits; int line_x, line_y,start_x,start_y,addr_x,addr_y; long int location = 0 ; /* 打开位图文件 */ fp = fopen( bmpfile, "rb" ); if (fp == NULL){ return( -1 ); } /* 读取位图文件头 */ rc = fread( &FileHead, sizeof(BITMAPFILEHEADER),1, fp ); if ( rc != 1){ printf("read header error!\n"); fclose( fp ); return( -2 ); } /* 判断位图的类型 */ if (memcmp(FileHead.cfType, "BM", 2) != 0){ printf("it's not a BMP file\n"); fclose( fp ); return( -3 ); }
/* 读取位图信息头 */ rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp ); if ( rc != 1){ printf("read infoheader error!\n"); fclose( fp ); return( -4 ); } /*将数组中的数连接成32位的数*移位实现*/ ciWidth = InfoHead.ciWidth[3]<<24 |InfoHead.ciWidth[2]<<16 | \ InfoHead.ciWidth[1]<<8 |InfoHead.ciWidth[0]; ciHeight = InfoHead.ciHeight[3]<<24|InfoHead.ciHeight[2]<<16| \ InfoHead.ciHeight[1]<<8|InfoHead.ciHeight[0]; ciBitCount = InfoHead.ciBitCount[3]<<24|InfoHead.ciBitCount[2]<<16| \ InfoHead.ciBitCount[1]<<8|InfoHead.ciBitCount[0]; cfoffBits = FileHead.cfoffBits[3]<<24|FileHead.cfoffBits[2]<<16| \ FileHead.cfoffBits[1]<<8|FileHead.cfoffBits[0]; /*也可使用内存复制实现数据的转换***************//* ciWidth = (int) chartolong( InfoHead.ciWidth, 4 ); ciHeight = (int) chartolong( InfoHead.ciHeight, 4 ); ciBitCount = (int) chartolong( InfoHead.ciBitCount, 4 );*/ fseek(fp, cfoffBits, SEEK_SET); /*设置偏移量*/ printf("width=%d, height=%d, bitCount=%d, offset=%d\n", ciWidth, ciHeight, ciBitCount, (int)chartolong(FileHead.cfoffBits, 4)); if(ciWidth>240&&ciHeight>320){printf("图片过大!无法预览!\n"); return 0;} if(ciWidth<240||ciHeight<320){ //如果是小图片,则按其尺寸大小在屏幕的中间显示 line_y = (ciHeight - 320)/2; if(ciWidth<=ciHeight) line_x = (240 - ciWidth)/2; else line_x = 0; } else{ line_x =0; line_y =0; } start_x= start_y = 0; while(!feof(fp)) { PIXEL pix; unsigned short int color; char rgb[2];
addr_x = line_x + start_x; addr_y = line_y + start_y; location = addr_x * bits_per_pixel / 8 + (ciHeight - addr_y - 1) * xres * bits_per_pixel / 8; if(chartolong(InfoHead.ciBitCount,2) == 24){ rc = fread( (char *)&pix, 1, 3, fp ); if (rc != 3 ) { break; } color=(pix.red >>3)<<11 | (pix.green>>2)<<5 | pix.blue>>3; //将24位的数据转换成十六位565格式 } else if(chartolong(InfoHead.ciBitCount,2) == 16){ rc = fread( (char *)&rgb,1,2, fp ); if (rc != 2 ) { break; } color = rgb[0] | rgb[1]<<8; } *((unsigned short int*)(fbp + location)) = color ; start_x++; if (start_x == ciWidth ){ start_x = 0; start_y++; if(start_y== ciHeight) { break; } } }
fclose( fp ); return( 0 ); }
/****************************************************************************** *数据转化 ******************************************************************************/ long chartolong( char * string, int length ) { long number; if (length <= 4) { memset( &number, 0x00, sizeof(long) ); memcpy( &number, string, length ); } return( number ); }
|