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;