BMP文件分析有助于用MCU解码BMP文件.24位样图:
我们使用HEX方式打开.发现如下:
首先,0x42,0x4D,就是BM,证明这是一个BMP文件.
大小如图:
读法按照LE方式,就是0x000000f6,就是246字节,看看Windows识别图.
实际数据偏移是0x00000036.
高亮字符为数据开始处:
下图高亮处表示图像头占用长度0x00000028
下图高亮而且红框内是图像的宽度,不是红框且高亮的是图像高度.
使用彩色平面数0x0001,所有BMP都是这个数值,貌似.
色深就是0x0018,换过来就是24位深了:
图像掩码,这张图是全部颜色表示,所以是全零.
接下来看到实际像素占用0x000000C0,就是192,和我们之前的246,不一样.这个是从数据开始算的.
接着是水平像素,就是每米像素多少,估计是为了100%比例来还原图像的,红框外的是垂直像素.
位图中实际使用的颜色表中的颜色数:
位图中重要颜色数量:
然后按左下到右上顺序刷,如下序列:
3个字节一个,例如这个绿色:
其中4C就是蓝色76,B1就是绿色177,22就是红色34.颜色差别太小,人是看不出来的.我们用C语言来表示,就是由两部分组成.其实计算实际偏移量的时候,已经是第一部分结束,所以是这样的:
//BMP头文件
typedef __packed struct
{
uint16_t bfType ; //文件标志.只对'BM',用来识别BMP位图类型
uint32_t bfSize ; //文件大小,占四个字节
uint16_t bfReserved1 ;//保留
uint16_t bfReserved2 ;//保留
uint32_t bfOffBits ; //从文件开始到位图数据(bitmap data)开始之间的的偏移量
} BITMAPFILEHEADER ;
紧接着是信息头:
typedef __packed struct
{
uint32_t biSize ; //说明BITMAPINFOHEADER结构所需要的字数。
long biWidth ; //说明图象的宽度,以象素为单位
long biHeight ; //说明图象的高度,以象素为单位
uint16_t biPlanes ; //为目标设备说明位面数,其值将总是被设为1
uint16_t biBitCount ; //说明比特数/象素,其值为1、4、8、16、24、或32
uint32_t biCompression ; //说明图象数据压缩的类型。其值可以是下述值之一:
//BI_RGB:没有压缩;
//BI_RLE8:每个象素8比特的RLE压缩编码,压缩格式由2字节组成(重复象素计数和颜色索引);
//BI_RLE4:每个象素4比特的RLE压缩编码,压缩格式由2字节组成
//BI_BITFIELDS:每个象素的比特由指定的掩码决定。
uint32_t biSizeImage ; //说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0
long biXPelsPerMeter ; //说明水平分辨率,用象素/米表示
long biYPelsPerMeter ; //说明垂直分辨率,用象素/米表示
uint32_t biClrUsed ; //说明位图实际使用的彩色表中的颜色索引数
uint32_t biClrImportant ; //说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
} BITMAPINFOHEADER ;
然后排序刚才也发现了,是BGR,所以结构体如下:
typedef __packed struct
{
uint8_t rgbBlue ; //指定蓝色强度
uint8_t rgbGreen ; //指定绿色强度
uint8_t rgbRed ; //指定红色强度
uint8_t rgbReserved ;//保留,设置为0
} RGBQUAD ;
位图信息头如果不是888,还需要掩码,我们MCU一般用565也够了,省事.
typedef __packed struct
{
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bmiHeader;
uint32_t RGB_MASK[3]; //调色板用于存放RGB掩码.
//RGBQUAD bmiColors[256];
} BITMAPINFO;