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


发布评论