使用画图工具(ms+R调出运行框,输入mspaint即可)分别存储2个文件
1.bmp(400*300px),2.bmp(200*150px)白画布。

使用Beyond Compare比较下2个文件数据,注意使用Hex16进制方式。

前2个字节42 4D对应字符BM,是文件类型,这里表示ms的bmp文件类型
紧着的4个字节是文件字节数,F6 D8 01 00==》1.bmp
应为存储方式是高位字在高地址的方式存储,所以
实际是0001D8F6==>转成10进制数值是121078字节=》除以1024就是118K,自己核对下文件属性看看文件大小是不是118k;
而2.bmp文件的是66 79 00 00
对应00007966=>31078字节=》30.3k

随后的4个字节全为00,系统保留。

再后面的4个字节代表的是实际的图像数据开始的位置(偏移量)
这里都是36 04 00 00
也就是00000436H,在Beyond Compare里Ctrl+G,选择Hex,16进制方式,输入
0436转到该位置发现文件数据全是FF也就是白色:

BMP位图文件格式分析_第1张图片



然后在看下windows定义的bmp文件头结构体定义就更清晰了:
typedef struct tagBITMAPFILEHEADER 
{  
UINT16 bfType;  /*bmp文件类型-占2字节*/  
DWORD bfSize; /*bmp文件大小-占4字节*/
UINT16 bfReserved1; /*保留-占2字节*/
UINT16 bfReserved2; /*保留-占2字节*/
DWORD bfOffBits;  /*位图数据偏移-占4字节*/
} BITMAPFILEHEADER; 

共14个字节。

文件头后面是文件信息头部,主要是位图文件的详细信息,windows定义的文件信息头的结构体如下:
typedef struct    tagBITMAPINFOHEADER
{
DWORD biSize; /*文件信息头占的字节大小-该字段占4字节*/
LONG biWidth; /*宽度4字节*/
LONG biHeight; /*高度4字节*/
WORD biPlanes; /*颜色平面数2字节, 总是1(文章1.bmp,2.bmp里可以看到01 00这2个字节)*/
WORD biBitCount; /*每个图像像素所占比特数,占2字节,我们这里是8bit,256种颜色,呵呵*/
DWORD biCompression; /*图像数据压缩类型4字节*/
DWORD biSizeImage; /*图像大小4字节*/
LONG biXPelsPerMeter; /*水平分辨率4字节*/
LONG biYPelsPerMeter; /*垂直分辨率4字节*/
DWORD biClrUsed; /*所使用颜色表索引数4字节*/
DWORD biClrImportant; /*对图像重要影响的索引数4字节占据*/
} BITMAPINFOHEADER;

统计下:4+4+4+2+2+4+4+4+4+4+4=40共40个字节,验证。

我们的位图里是00 00 00 28==>十进制就是40个字节,文件信息头占40字节;
紧接着后面
(注明:那个空白应该是Beyond Compare比对文件产生的,跳过,只看有字符数据的部分)
1.bmp图像尺寸:
biWidth字段:
90 01 00 00=>逆转下顺序 0x00000190=>400px
biHeight字段:
2C 01 00 00=>0x0000012C=>300px

同理2.bmp图像尺寸:
biWidth字段:
C8 00 00 00=>逆转下顺序 0x000000C8=>200px
biHeight字段:
96 00 00 00=>0x00000096=>150px

接着看:
01 00==>位图平面数,总是为1
08 00==》位图位数8位图像(00 08),一个像素占1个字节。
00 00 00 00==》压缩类型,0 不压缩
图像大小:
1.bmp=>C0 D4 01 00 ==>0x0001D4C0 ==>120000
验证400*300=120000  正确。


2.bmp=>30 75 00 00 ==>0x7530 ==>30000
验证200*150=30000  正确。

其他几个字节就不看了。

从第54个字节开始是一张颜色索引表
每4个字节代表一种颜色,形式如下
(蓝,绿,红,Alpha)就是(B,G,R,A)
可以看到:
00 00 00 00=(00,00,00,00)==黑色
00 00 80 00=(00,00,80,00)===红色
00,80,00,00=(00,80,00,00)==绿色
.....
256个颜色就是
256*4=1024个字节,也就是说位图文件除去真正的像素数据,光文件头之类的信息就是14+40+1024=1078个字节大小

根据前面的文件头提到的偏移
00000436H==1078
正好吻合。
ctrl+G,转到1078开始的部分就是图像的数据信息。

数据存储是从图像左下角到右上角,按行存储,即先存储最后一行的第一个像素,其次第二个,依次类推。