1、位图文件头
//14byte
typedef struct
{
char cfType[2];//"BM"(0x4D42)
int32_t cfSize;
int16_t cfReserved1;
int16_t cfReserved2;
int32_t cfoffBits;
}__attribute__((packed)) BITMAPFILEHEADER;
2、信息数据头
//40byte
typedef struct
{
char ciSize[4];//BITMAPFILEHEADER所占的字节数
int32_t ciWidth;
int32_t ciHeight;
int16_t ciPlanes;
int16_t ciBitCount;
int32_t ciCompress;
int32_t ciSizeImage;
int32_t ciXPelsPerMeter;
int32_t ciYPelsPerMeter;
int32_t ciClrUsed;
int32_t ciClrImportant;
}__attribute__((packed)) BITMAPINFOHEADER;
3、rgb格式
typedef struct
{
uint16_t color;
//unsigned char color0;
//unsigned char color1;
}__attribute__((packed)) RGB565;
typedef struct
{
unsigned char blue;
unsigned char green;
unsigned char red;
}__attribute__((packed)) RGB888;
typedef struct
{
unsigned char blue;
unsigned char green;
unsigned char red;
unsigned char alpha;
}__attribute__((packed)) ARGB8888;
4、调色板[可以通过读取这个结构体可以判断16位图像是rgb555或rgb565]
typedef struct
{
uint32_t r;
uint32_t g;
uint32_t b;
}__attribute__((packed)) COLORPALETTE;
#565
if ((bmp_rgb_16.r==0xf800) && (bmp_rgb_16.r=0x7e0) && (bmp_rgb_16.r=0x1f))
#555
if ((bmp_rgb_16.r==0x7c00) && (bmp_rgb_16.r=0x3e0) && (bmp_rgb_16.r=0x1f))
4、像素数组
BMP文件保存像素数据结构:以行像素为单位,从左到右,从下到上。
fp = fopen( bmp_file, "rb" );
rc = fread( &FileHead, sizeof(BITMAPFILEHEADER),1, fp );
if (memcmp(FileHead.cfType, "BM", 2) != 0)
rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp );
fseek(fp, FileHead.cfoffBits, SEEK_SET);
line_x = line_y = 0;
if (InfoHead.ciBitCount==32){
ARGB8888 pix;
while(!feof(fp)) {
rc = fread( (unsigned char *)&pix, 1, sizeof(ARGB8888), fp);
if (rc != sizeof(ARGB8888))
break;
location = line_x * bits_per_pixel / 8 + (InfoHead.ciHeight - line_y - 1) * xres * bits_per_pixel / 8;
*(fbp + location + 0)=pix.blue;
*(fbp + location + 1)=pix.green;
*(fbp + location + 2)=pix.red;
*(fbp + location + 3)=pix.alpha;
line_x++;
if (line_x == InfoHead.ciWidth ){
line_x = 0;
line_y++;
if(line_y == InfoHead.ciHeight)
break;
}
}
}
5、行补0
BMP图像每行数据使用Dword,所以是4字节,
32位,24位数据刚好是4的倍数不用补0
16位是双字节,行末尾有可能不是4的倍数,图像工具生成BMP图像时会自动补0,自定义程序读取像素时加上判断跳过0即可,不然读取的图像会错位,因为多了0像素。