參考網址: http://blog.csdn.net/z1179675084/article/details/14645359
http://hi.baidu.com/guoggn/item/636e08145b5d39fc746a8461
http://blog.chinaunix.net/uid-26669729-id-3077015.html
http://blog.csdn.net/luxiaoxun/article/details/7622988
關鍵:
1)字節對齊問題__attribute__((packed)) 最大字節對齊
2) _attribute__((packed))的作用是告訴編譯器取消結構在編譯過程中的優化對齊
3) 字節數的統計
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mman.h> /*map頭文件*/
#include <linux/fb.h>
#include <fcntl.h>
#include <string.h>
#include <arpa/inet.h>
//14byte文件頭
typedef struct
{
unsigned char cfType[2];//文件類型,"BM"(0x4D42)
unsigned int cfSize;//文件大小(字節)
unsigned int cfReserved;//保留,值爲0
unsigned int cfoffBits;//數據區相對於文件頭的偏移量(字節)
}__attribute__((packed)) BITMAPFILEHEADER;
/*_attribute__((packed))的作用是告訴編譯器取消結構在
編譯過程中的優化對齊 */
//40byte信息頭
typedef struct
{
unsigned int ciSize;//BITMAPFILEHEADER所佔的字節數
unsigned int ciWidth;//寬度
unsigned int ciHeight;//高度
unsigned short int ciPlanes;//目標設備的位平面數,值爲1
unsigned short int ciBitCount;//每個像素的位數
char ciCompress[4];//壓縮說明
unsigned int ciSizeImage;//用字節表示的圖像大小,該數據必須是4的倍數
unsigned int ciXPelsPerMeter;//目標設備的水平像素數/米
unsigned int ciYPelsPerMeter;//目標設備的垂直像素數/米
unsigned int ciClrUsed; //位圖使用調色板的顏色數
unsigned intciClrImportant; //指定重要的顏色數,當該域的值等於顏色數時(或者等於0時),表示所有顏色都一樣重要
}__attribute__((packed)) BITMAPINFOHEADER;
typedef struct
{
unsigned char blue;
unsigned char green;
unsigned char red;
}__attribute__((packed)) PIXEL;//顏色模式RGB
BITMAPFILEHEADER FileHead;
BITMAPINFOHEADER InfoHead;
static int xres = 0;
static int yres = 0;
static int bits_per_pixel = 0;
static char *fb_addr = NULL;
int show_bmp(char *picname)
{
FILE *fp;
int rc;
int line_x, line_y;
long int location = 0;
char tmp[1024*10];
static unsigned short b,g,r;
static unsigned short rgb; /*2個字節*/
PIXEL pix;
fp = fopen( picname, "rb" );
if (fp == NULL)
{
printf("open errror\n");
return( -1 );
}
printf("Open OK \n");
/* BITMAPFILEHEADER*/
rc = fread( &FileHead, sizeof(BITMAPFILEHEADER),1, fp );
if ( rc != 1)
{
printf("read header error!\n");
fclose( fp );
return( -2 );
}
printf("Read BITMAPFILEHEADER OK\n");
//檢測是否是bmp圖像
if (memcmp(FileHead.cfType, "BM", 2) != 0)
{
printf("it's not a BMP file\n");
fclose( fp );
return( -3 );
}
/*BITMAPINFOHEADER*/
rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp );
if ( rc != 1)
{
printf("read infoheader error!\n");
fclose( fp );
return( -4 );
}
printf("Read BITMAPINFOHEADER OK\n");
//跳轉的數據區
fseek(fp, FileHead.cfoffBits, SEEK_SET);
//向framebuffer中寫BMP圖片 rgb高位有效
for (line_y = 0; line_y<yres; line_y++)
for (line_x = 0; line_x<xres; line_x++)
{
rc = fread(&pix , sizeof(PIXEL),1, fp);
location = line_x*2+(yres-line_y)*xres*2;
r=((pix.red>>3)<<11)&0xfb80;
g=((pix.green>>2)<<5)&0x07e0;
b=(pix.blue>>3)&0x001f;
rgb=r|g|b;
*((unsigned short *)(fb_addr+location)) = rgb;
}
fclose( fp );
return 0 ;
}
int main(int argc, char *argv[ ])
{
int fbfd,fb_size ;
struct fb_var_screeninfo vinfo; /*記錄用戶可修改的顯示控制參數*/
struct fb_fix_screeninfo finfo; /*取得緩衝區的物理地址*/
// 打開/dev/fb*設備文件
fbfd = open("/dev/fb0", O_RDWR|O_CREAT, S_IRWXU);
if (fbfd <0 )
{
printf("open error\n");
exit(1);
}
//需要的 屏幕內存空間的字節數 ,取得顯示屏幕參數
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
{
printf("Error reading variable information.\n");
exit(1);
}
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
{
printf("Error reading variable information.\n");
exit(1);
}
printf("R:%d,G:%d,B:%d \n", vinfo.red, vinfo.green, vinfo.blue );
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; /* 每像素位數*/
fb_size=xres*yres*bits_per_pixel/8; /*計算屏幕的總大小(字節)*/
// fd的內存地址空間映射到我們的程序地址空間
// void *mmap(void *start, size_t length, int prot, int flags,int fd, off_t offset);
if ( (fb_addr = (char *)mmap( 0, fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0) )<0)
{
printf( "mmap error\n" );
exit(1);
}
printf("show_bmp\n");
show_bmp( argv[1] );
//刪除對象映射
munmap(fb_addr, fb_size);
close(fbfd);
return 0;
}
執行開發板程序:
圖片顯示: