BMP文件格式,又称为Bitmap(位图),或是DIB(Device-Independent Device,设备无关图),是windows系统中广泛使用的图片文件格式,由于它可以不作任何变换地址保存图像像素域的数据,因为称为我们取得RAW数据的重要来源。Windows的图像用户界面也在他的内建图像子系统GDI中对BMP格式提供了支持。
一般图像以24位图像为主,即R、G、B三种颜色各8bit来表示,这样的图像称之为真彩色,此时是不需要调色板的,也就是说位图信息头后紧跟着就是位图数据了。所以位图文件从文件头开始偏移54个字节就是位图数据了,这就是24位或者32位图的情况。这也就解释了我们按照这种程序写出来的程序为什么对于某些图文件没有用了。
byte – 8字节
word – 16字节
int/unit/dword – 32字节
文件头:
BMP的文件头共14个字节
字节顺序 |
数据结构 |
描述 |
1,2 |
word |
高8位位字母‘B,低8位为字母’M‘ |
3,4,5,6 |
unit |
文件尺寸 |
7,8 |
word |
保留字1 |
9,10 |
word |
保留字1 |
11,12,13,14 |
unit |
位图数据部分相对于文件的起始偏移量 |
数据部分偏移量的存在,说明图像数据部分并不一定要紧随图像参数或调色板之后放置,BMP图片的制作者其实可以在调色板之后、数据部分之前填充任何内容,只要正确地设置偏移量即可。
图像参数信息:
字节顺序 |
数据结构 |
描述 |
15,16,17,18 |
unit |
当前结构体的大小,通常是40或56 |
19,20,21,22 |
int |
图像宽度(像素) |
23,24,25,26 |
int |
图像高度(像素) |
27,28 |
word |
恒为1 |
29,30 |
word |
每个像素占用的位数即bpp |
31,32,33,34 |
unit |
压缩方式 |
35,36,37,38 |
unit |
图像的尺寸 |
39,40,41,42 |
int |
水平分辨率 |
43,44,45,46 |
int |
垂直分辨率 |
47,48,49,50 |
uint |
引用色彩数 |
51,52,53,54 |
uint |
关键色彩数 |
31-34字节表示图像数据的压缩方式,参数取值范围是0,1,2,3等
0 – RGB方式
1 – 8bpp的run-length-encoding方式
2 – 4bpp的run-length-encoding方式
3 – bit-fields方式
只有压缩方式选项被设置为bit-fileds时,当前结构体大小为56字节,否则,为40字节。
调色板
当bpp <= 8时,BMP使用调试版记录色彩信息,调色板每条数据(即每条色彩值)都是一个uint型数据。当调色板存在时,图像数据块中存储的只是各个像素的色彩在调色板中的索引值,必须通过在调色板中查表,才能获取各个像素的只是颜色。若引入调色板,则调色板数据块紧随在图像参数数据块之后。
bpp == 1 时,调色板合法索引值只有0和1.因此调色板块只有两个色彩值,分别表示索引值为0和1的色彩信息。
bpp == 4或 bpp == 8 时,合法索引值范围扩大为[0,15]和 [0,255]。但图像不一定使用到了全部16种或256种颜色。第47-50字节存储的uint型数据指出图像种实际应用的色彩书,也即调色板种的色彩值数目。当然他不应该超出调色板的合法索引值范围。
当bpp == 4 或bpp == 8时,可以采用Run-Length-Encoding方式压缩 图像的存储空间,即压缩方式选项的值为1或2,(当选项值为0时不压缩)。这种编码格式所要考虑的情况是,如4bpp或8bpp位图尺寸较大时,由于色彩总数是非常有限的,所以图像中必然会出现和诺颜色重复的像素,因此BMP图像格式的设计者决定采用一种简单的措施来挽回一些被浪费掉的存储空间,这个简单的措施就是RLE压缩方法。
RLE—Run-Length-Encoding
先用一个字节来存储重复色彩的数量,再用一个字节来存储这个色彩的值,即用来个字节代表一段重复的像素并且,他们给这段重复色彩的数量起了一个名字,叫做Run-Length。由于runleng为0时是没有意义,因此设计者把runleng=0作为每行的终止符。
如果一张位图中没有重复的像素,这种情况最好不要使用压缩算法。(红蓝像素点阵),如果既有重复像素,又有点阵的情况的时候,就需要修改runlength=0时候的意义了。
设计者规定,如果遇到runlength=0时继续读取下一个字节,如果该字节值为n,意味着后面n个像素将采用逐字翻译的方式来解析。也就是说n个像素前面没有runlength这个字节。
上诉方法导致了runlength==0的作为行终止符的含义修改了。但是runlength==0之后的nage 字节值为0,1,2时仍然没有意义,所以规定,当这个值为0时,表示行结束符;当这个值为1时,表示文件结束符;当这个值大于等于3时才逐字翻译。
RGB和Bit-Fields
当图像中引用的色彩数超过256时,我们就需要16bpp或更高的位图,调色板不适合bpp较大的位图,因此16bpp以上的位图不适合使用调色板。不使用调色板的位图图像有两种编码格式:RGB和Bit-Fileds
RGB编码是一种均分思想,使Red、Green、Blue三个颜色分包含的信息容量尽可能的一样大。
16bpp-RGB:在每个像素所占的16bits种,低5位表示Blue分量;中5位表示Green分量;高5位表示Red分量;最高意味无意义。所以从低到高的顺序实际上使B-G-R。
24bpp-RGB:24bpp的位图又称为真彩位图,它通常只有一种的编码格式,在24bits中,低8位表示Blue分量;中8位表示Green分量;高8位表示Red分量;
32bpp-RGB:在32bits中,低24位的编码方式与24bpp位图相同,最高八位用来表示Alpha分量。32bpp的位图尺寸太大,一般只有在图像处理的中间过程使用,对于需要半透过效果的图像,更好的选择使PNG格式。
BF编码格式与RGB不同,他利用位域操作,认为的确定RGB三分量所包含的信息容量。在图像参数信息模块的介绍中提及,当压缩方式选项设置位BF时,图像参数结构将比平时多16字节。这16字节实际上时4个dword的位域掩码。按照先后顺序,他们分别是R、G、B、A四个分量的位域掩码,如果没有Alpha分量,则Alpha掩码没有实际意义。
位域掩码的作用是:指出像素色彩中的RGB分量,就像子网掩码指出子网网段一样。
16-bpp-BF-565:这是BF编码格式最著名和最普遍的应用。他的Red、Green、Blue分量的位掩码分别是0xF800、0x07E0、0x001F。
图像数据块
图像数据块从头文件中起始偏移量字段所指出的位置开始,其中存放着位图图像的数据,数据格式由图像参数信息块中的压缩方式选项取值决定。操作图像数据块时,有一些注意事项:
当压缩方式为RGB时,图像数据块以“行”为单位双字对齐。
bpp<8时,每个字节将存放多个像素的色彩所以,则先出现的像素存放在高位。