2024年3月26日发(作者:)

    本文由任胜强安工大贡献

    doc文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机

查看。

    BMP 文件格式,又称为 Bitmap(位图)或是 DIB(Device-Independent Device

,设备无关位图), 是 Windows 系统中广泛使用的图像文件格式。由于它可以不作任

何变换地保存图像像素域的数 据, 因此成为我们取得 RAW 数据的重要来源。 Wind

ows 的图形用户界面 (graphical user interfaces) 也在它的内建图像子系统 GD

I 中对 BMP 格式提供了支持。 下面以 Notepad++为分析工具,结合 Windows 的位图

数据结构对 BMP 文件格式进行一个深度 的剖析。 BMP 文件的数据按照从文件头开始

的先后顺序分为四个部分: bmp 文件头 文件头(bmp file header):提供文件的格式

、大小等信息 : 位图信息头(bitmap information):提供图像数据的尺寸、位平面

数、压缩方式、颜色索 位图信息头 : 引等信息 调色板(color palette):可选,如

使用索引来表示图像,调色板就是索引与其对应的颜色 调色板 : 的映射表 位图数

据(bitmap data):就是图像数据啦^_^ 位图数据 : 下面结合 Windows 结构体的定

义,通过一个表来分析这四个部分。

    我们一般见到的图像以 24 位图像为主,即 R、G、B 三种颜色各用 8 个 bit 

来表示,这样的图 像我们称为真彩色, 这种情况下是不需要调色板的, 也就是所位

图信息头后面紧跟的就是位图 数据了。因此,我们常常见到有这样一种说法:位图文

件从文件头开始偏移 54 个字节就是位 位图文件从文件头开始偏移 图数据了, 位图

的情况 图数据了,这其实说的是 24 或 32 位图的情况。这也就解释了我们按照这种

程序写出来的程 序为什么对某些位图文件没用了。 序为什么对某些位图文件没用了

。 下面针对一幅特定的图像进行分析,来看看在位图文件中这四个数据段的排布以及

组成。 我们使用的图像显示如下:

    这是一幅 16 位的位图文件,因此它是含有调色板的。 在拉出图像数据进行分

析之前,我们首先进行几个约定: 1. 在 BMP 文件中,如果一个数据需要用几个字节

来表示的话,那么该数据的存放字节顺 序为“低地址村存放低位数据,高地址存放高

位数据”。如数据 0x1756 在内存中的存储顺序为:

    这种存储方式称为小端方式(little endian) , 与之相反的是大端方式(big e

ndian)。对两者的使 用情况有兴趣的可以深究一下,其中还是有学问的。 2. 以下

所有分析均以字节为序号单位进行。 下面我们对从文件中拉出来的数据进行剖析:

    一、bmp 文件头 Windows 为 bmp 文件头定义了如下结构体:

    typedef struct tagBITMAPFILEHEADER { UINT16 bfType; DWORD bfSize; UIN

T16 bfReserved1; UINT16 bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER;

    其中:

    对照文件数据我们看到:

    1-2

    : 424dh = 'BM',表示这是 Windows 支持的位图格式。 有很多声称开头两个字

节必须为'BM' 才是位图文件,从上表来看应为开头两个字节必须为'BM'才是 Window

s 位图文件。

    3-5 6-9

    :00010436h = 66614 B = 65.05 kB,通过查询文件属性发现一致。 :这是两

个保留段,为 0。

    A-D: 00000436h = 1078。 即从文件头到位图数据需偏移 1078 字节。 我们稍

后将验证这个数据。 共有 14 个字节。 二、位图信息头 位图信息头 同样地,Wind

ows 为位图信息头定义了如下结构体:

    代码

    对照数据文件: 对照数据

    0E-11:00000028h = 40,这就是说我这个位图信息头的大小为 40 个字节。前面

我们已经说过位图 信息头一般有 40 个字节, 既然是这样, 为什么这里还要给一个

字段来说明呢?这里涉及 到一些历史,其实位图信息头原本有很多大小的版本的。我

们看一下下表:

    出于兼容性的考虑,大多数应用使用了旧版的位图信息头来保存文件。而 OS/2

page 1

 已经过时了, 因此现在最常用的格式就仅有 V3 header 了。因此,我们在前面说位

图信息头的大小为 40 字节。 12-15:00000100h = 256,图像宽为 255 像素,与文

件属性一致。 16-19:00000100h = 256,图像高为 255 像素,与文件属性一致。这

是一个正数,说明图像数 据是从图像左下角到右上角排列的。 1A-1B:0001h, 该值

总为 1。 1C-1D:0008h = 8, 表示每个像素占 8 个比特,即该图像共有 256 种颜色

。 1E-21:00000000h,BI_RGB, 说明本图像不压缩。 22-25:00000000h,图像的大

小,因为使用 BI_RGB,所以设置为 0。 26-29:00000000h,水平分辨率,缺省。 2

A-2D:00000000h,垂直分辨率,缺省。 2E-31: 00000100h = 256,说明本位图实际

使用的颜色索引数为 256, 1C-ID 得到的结论一致。 与 32-35:00000100h = 256,

说明本位图重要的颜色索引数为 256,与前面得到的结论一致。

    三、调色板 调色板 下面的数据就是调色板了。前面也已经提过,调色板其实是

一张映射表,标识颜色索引 号与其代表的颜色的对应关系。 它在文件中的布局就像

一个二维数组 palette[N][4],其中 N 表示总的颜色索引数,每行的四个元素分别表

示该索引对应的 B、G、R 和 Alpha 的值, 每个分量占一个字节。如不设透明通道时

,Alpha 为 0。因为前面知道,本图有 256 个颜

    色索引,因此 N = 256。索引号就是所在行的行号,对应的颜色就是所在行的四

个元素。 这里截取一些数据来说明:

    索引: 蓝 索引:(蓝,绿,红,Alpha) 0 号:(fe,fa,fd,00) 1 号:(fd,

f3,fc,00) 2 号:(f4,f3,fc,00) 3 号:(fc,f2,f4,00) 4 号:(f6,f2,f

2,00) 5 号:(fb,f9,f6,00) 等 等。 一共有 256 种颜色,每个颜色占用 4 个

字节,就是一共 1024 个字节,再加上前面的文件信息 头和位图信息头的 54 个字节

加起来一共是 1078 个字节。也就是说在位图数据出现之前一共有 1078 个字节, 与

我们在文件信息头得到的信息: 文件头到文图数据区的偏移为 1078 个字节一致! 

四、位图数据 位图数据 下面就是位图数据了, 每个像素占一个字节, 取得这个字

节后, 以该字节为索引查询相应的颜色, 并显示到相应的显示设备上就可以了。 注

意: 由于位图信息头中的图像高度是正数, 所以位图数据在文件中的排列顺序是从

左下角到右 上角,以行为主序排列的。

    也即我们见到的第一个像素 60 是图像最左下角的数据, 第二个人像素 60 为

图像最后一行第二列 的数据,…一直到最后一行的最后一列数据,后面紧接的是倒数

第二行的第一列的数据,依此类 推。 如果图像是 24 位或是 32 位数据的位图的话

,位图数据区就不是索引而是实际的像素值了。下 面说明一下,此时位图数据区的每

个像素的 RGB 颜色阵列排布: 24 位 RGB 按照 BGR 的顺序来存储每个像素的各颜色

通道的值,一个像素的所有颜色分量值都 存完后才存下一个下一个像素,不进行交织

存储。 32 位数据按照 BGRA 的顺序存储,其余与 24 位位图的方式一样。 像素的排

布规则与前述一致。 对齐规则 讲完了像素的排列规则以及各像素的颜色分量的排列

规则, 最后我们谈谈数据的对齐规则。 我们 知道 Windows 默认的扫描的最小单位

是 4 字节,如果数据对齐满足这个值的话对于数据的获取 速度等都是有很大的增益

的。因此,BMP 图像顺应了这个要求,要求每行的数据的长度必须是 4 的倍数,如果

不够需要进行比特填充(以 0 填充),这样可以达到按行的快速存取。这时,位 图

数据区的大小就未必是 图片宽×每像素字节数×图片高 能表示的了, 因为每行可能

还需要进 行比特填充。 填充后的每行的字节数为:

    ,其中 BPP(Bits Per Pixel)为每像素的比特数。

    在程序中,我们可以表示为: int iLineByteCnt = (((m_iImageWidth * m_iB

itsPerPixel) + 31) >> 5) << 2; 这样,位图数据区的大小为:

    m_iImageDataSize = iLineByteCnt * m_iImageHeight;

    我们在扫描完一行数据后, 也可能接下来的数据并不是下一行的数据, 可能需

要跳过一段填充数 据:

    skip = 4 - ((m_iImageWidth * m_iBitsPerPixel)>>3) & 3;

    五、拾遗 至此,我们通过分析一个具体的位图文件例子详细地剖析了位图文件

的组成。需要注意的是:我 们讲的主要是 PC 机上的位图文件的构成,对于嵌入式平

台,可能在调色板数据段与 PC 机的不 同。 如在嵌入式平台上常见的 16 位 r5g6b

5 位图实际上采用的掩模的方式而不是索引的方式来表 示图像。 此时, 在调色板数

page 2