BMP位图格式详解.docx
- 文档编号:10382737
- 上传时间:2023-02-10
- 格式:DOCX
- 页数:15
- 大小:1.12MB
BMP位图格式详解.docx
《BMP位图格式详解.docx》由会员分享,可在线阅读,更多相关《BMP位图格式详解.docx(15页珍藏版)》请在冰豆网上搜索。
BMP位图格式详解
位图格式BMP是bitmap的缩写形式,bitmap顾名思义,就是位图也即Windows位图。
它一般由4部分组成:
文件头信息块、图像描述信息块、颜色表(在真彩色模式无颜色表)和图像数据区组成。
在系统中以BMP为扩展名保存。
打开Windows的画图程序,在保存图像时,可以看到三个选项:
2色位图(黑白)、16色位图、256色位图和24位位图。
现在讲解BMP的4个组成部分:
1.文件头信息块
0000-0001:
文件标识,为字母ASCII码“BM”。
0002-0005:
文件大小。
0006-0009:
保留,每字节以“00”填写。
000A-000D:
记录图像数据区的起始位置。
各字节的信息含义依次为:
文件头信息块大小,图像描述信息块的大小,图像颜色表的大小,保留(为01)。
2.图像描述信息块
000E-0011:
图像描述信息块的大小,常为28H。
0012-0015:
图像宽度。
0016-0019:
图像高度。
001A-001B:
图像的plane总数(恒为1)。
001C-001D:
记录像素的位数,很重要的数值,图像的颜色数由该值决定。
001E-0021:
数据压缩方式(数值位0:
不压缩;1:
8位压缩;2:
4位压缩)。
0022-0025:
图像区数据的大小。
0026-0029:
水平每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。
002A-002D:
垂直每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。
002E-0031:
此图像所用的颜色数,如值为0,表示所有颜色一样重要。
3.颜色表
颜色表的大小根据所使用的颜色模式而定:
2色图像为8字节;16色图像位64字节;256色图像为1024字节。
其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(32位位图的透明度值,一般不需要)。
即首先4字节表示颜色号0的颜色,接下来表示颜色号1的颜色,依此类推。
4.图像数据区
颜色表接下来位是位图文件的图像数据区,在此部分记录着每点像素对应的颜色号,其记录方式也随颜色模式而定,既2色图像每点占1位;16色图像每点占4位;256色图像每点占8位;真彩色图像每点占24位。
所以,整个数据区的大小也会随之变化。
究其规律而言,可的出如下计算公式:
图像数据信息大小=(图像宽度*图像高度*记录像素的位数)/8。
然而,未压缩的图像信息区的大小。
除了真彩色模式外,其余的均大于或等于数据信息的大小。
这是为什么呢?
原因有两个:
1. BMP文件记录一行图像是以字节为单位的。
因此,就不存在一个字节中的数据位信息表示的点在不同的两行中。
也就是说,设显示模式位16色,在每个字节分配两个点信息时,如果图像的宽度位奇数,那么最后一个像素点的信息将独占一个字节,这个字节的后4位将没有意义。
接下来的一个字节将开始记录下一行的信息。
2. 为了显示的方便,除了真彩色外,其他的每中颜色模式的行字节数要用数据“00”补齐为4的整数倍。
如果显示模式为16色,当图像宽为19时,存储时每行则要补充4-(19/2+1)%4=2个字节(加1是因为里面有一个像素点要独占了一字节)。
如果显示模式为256色,当图像宽为19时,每行也要补充4-19%4=1个字节。
bmp文件大体上分成四个部分。
位图文件头BITMAPFILEHEADER、位图信息头BITMAPINFOHEADER、调色板Palette、实际的位图数据ImageDate
第一部分为位图文件头BITMAPFILEHEADER,是一个结构,其定义如下:
typedefunsignedcharBYTE
typedefunsignedshortWORD
typedefunsignedlongDWORD
typedefstructtagBITMAPFILEHEADER{
WORDbfType;//类型名,必须是0x424D,即字符串“BM”,
DWORDbfSize;//文件大小
WORDbfReserved1;//保留字,不考虑
WORDbfReserved2;//保留字,同上
DWORDbfOffBits;//实际位图数据的偏移字节数,即前三个部分长度之和
}BITMAPFILEHEADER;
第二部分为位图信息头BITMAPINFOHEADER,也是一个结构,其定义如下:
typedefstructtagBITMAPINFOHEADER{
DWORDbiSize;//指定此结构体的长度,为40
LONGbiWidth;//位图宽
LONGbiHeight;//位图高
WORDbiPlanes;//平面数,为1
WORDbiBitCount//采用颜色位数,可以是1,2,4,8,16,24,新的可以是32
DWORDbiCompression;//压缩方式,可以是0,1,2,其中0表示不压缩
DWORDbiSizeImage;//实际位图数据占用的字节数
LONGbiXPelsPerMeter;//X方向分辨率
LONGbiYPelsPerMeter;//Y方向分辨率
DWORDbiClrUsed;//使用的颜色数,如果为0,则表示默认值(2^颜色位数)
DWORDbiClrImportant;//重要颜色数,如果为0,则表示所有颜色都是重要的
}BITMAPINFOHEADER;
第三部分为调色板Palette,当然,这里是对那些需要调色板的位图文件而言的。
24位和32位是不需要调色板的。
typedefstructtagRGBQUAD{
BYTErgbBlue;//该颜色的蓝色分量
BYTErgbGreen;//该颜色的绿色分量
BYTErgbRed;//该颜色的红色分量
BYTErgbReserved;//保留值
}RGBQUAD;
第四部分就是实际的图象数据了。
对于用到调色板的位图,图象数据就是该象素颜在调色板中的索引值。
对于真彩色图,图象数据就是实际的R、G、B值。
对于2色位图,用1位就可以表示该象素的颜色(一般0表示黑,1表示白),所以一个字节可以表示8个象素。
对于16色位图,用4位可以表示一个象素的颜色,所以一个字节可以表示2个象素。
对于256色位图,一个字节刚好可以表示1个象素。
对于真彩色图,三个字节才能表示1个象素。
要注意两点:
(1)每一行的字节数必须是4的整倍数,如果不是,则需要补齐。
(2)一般来说,.bMP文件的数据从下到上,从左到右的。
也就是说,从文件中最先读到的是图象最下面一行的左边第一个象素,然后是左边第二个象素……接下来是倒数第二行左边第一个象素,左边第二个象素……依次类推,最后得到的是最上面一行的最右一个象素。
16色系统调色板:
0=RGB(0,0,0)=0x00000000;
1=RGB(128,0,0)=0x00000080;
2=RGB(0,128,0)=0x00008000;
3=RGB(128,128,0)=0x00008080;
4=RGB(0,0,128)=0x00800000;
5=RGB(128,0,128)=0x00800080;
6=RGB(0,128,128)=0x00808000;
7=RGB(128,128,128)=0x00808080;
8=RGB(192,192,192)=0x00c0c0c0;
9=RGB(255,0,0)=0x000000ff;
10=RGB(0,255,0)=0x0000ff00;
11=RGB(255,255,0)=0x0000ffff;
12=RGB(0,0,255)=0x00ff0000;
13=RGB(255,0,255)=0x00ff00ff;
14=RGB(0,255,255)=0x00ffff00;
15=RGB(255,255,255)=0x00ffffff;
图像数据起始:
000A-000D
图像数据大小:
0022-0025
图像信息大小:
000E-0011
图像宽度:
0012-0015
图像高度:
0016-0019
BMP文件格式,又称为Bitmap(位图)或是DIB(Device-IndependentDevice,设备无关位图),是Windows系统中广泛使用的图像文件格式。
由于它可以不作任何变换地保存图像像素域的数据,因此成为我们取得RAW数据的重要来源。
Windows的图形用户界面(graphicaluserinterfaces)也在它的内建图像子系统GDI中对BMP格式提供了支持。
下面以Notepad++为分析工具,结合Windows的位图数据结构对BMP文件格式进行一个深度的剖析。
BMP文件的数据按照从文件头开始的先后顺序分为四个部分:
bmp文件头(bmpfileheader):
提供文件的格式、大小等信息
位图信息头(bitmapinformation):
提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息
调色板(colorpalette):
可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表
位图数据(bitmapdata):
就是图像数据啦^_^
下面结合Windows结构体的定义,通过一个表来分析这四个部分。
我们一般见到的图像以24位图像为主,即R、G、B三种颜色各用8个bit来表示,这样的图像我们称为真彩色,这种情况下是不需要调色板的,也就是所位图信息头后面紧跟的就是位图数据了。
因此,我们常常见到有这样一种说法:
位图文件从文件头开始偏移54个字节就是位图数据了,这其实说的是24或32位图的情况。
这也就解释了我们按照这种程序写出来的程序为什么对某些位图文件没用了。
下面针对一幅特定的图像进行分析,来看看在位图文件中这四个数据段的排布以及组成。
我们使用的图像显示如下:
这是一幅16位的位图文件,因此它是含有调色板的。
在拉出图像数据进行分析之前,我们首先进行几个约定:
1.在BMP文件中,如果一个数据需要用几个字节来表示的话,那么该数据的存放字节顺序为“低地址村存放低位数据,高地址存放高位数据”。
如数据0x1756在内存中的存储顺序为:
这种存储方式称为小端方式(littleendian),与之相反的是大端方式(bigendian)。
对两者的使用情况有兴趣的可以深究一下,其中还是有学问的。
2. 以下所有分析均以字节为序号单位进行。
下面我们对从文件中拉出来的数据进行剖析:
一、bmp文件头
Windows为bmp文件头定义了如下结构体:
typedef struct tagBITMAPFILEHEADER
{
UINT16 bfType;
DWORD bfSize;
UINT16 bfReserved1;
UINT16 bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
其中:
对照文件数据我们看到:
1-2 :
424dh='BM',表示这是Windows支持的位图格式。
有很多声称开头两个字节必须为'BM'才是位图文件,从上表来看应为开头两个字节必须为'BM'才是Windows位图文件。
3-5 :
00010436h=66614B=65.05kB,通过查询文件属性发现一致。
6-9 :
这是两个保留段,为0。
A-D:
00000436h=1078。
即从文件头到位图数据需偏移1078字节。
我们稍后将验证这个数据。
共有14个字节。
二、位图信息头
同样地,Windows为位图信息头定义了如下结构体:
代码
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
对照数据文件:
0E-11:
00000028h=40,这就是说我这个位图信息头的大小为40个字节。
前面我们已经说过位图信息头一般有40个字节,既然是这样,为什么这里还要给一个字段来说明呢?
这里涉及到一些历史,其实位图信息头原本有很多大小的版本的。
我们看一下下表:
出于兼容性的考虑,大多数应用使用了旧版的位图信息头来保存文件。
而OS/2已经过时了,因此现在最常用的格式就仅有V3header了。
因此,我们在前面说位图信息头的大小为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,水平分辨率,缺省。
2A-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,f2,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(BitsPerPixel)为每像素的比特数。
在程序中,我们可以表示为:
intiLineByteCnt=(((m_iImageWidth*m_iBitsPerPixel)+31)>>5)<<2;
这样,位图数据区的大小为:
m_iImageDataSize=iLineByteCnt*m_iImageHeight;
我们在扫描完一行数据后,也可能接下来的数据并不是下一行的数据,可能需要跳过一段填充数据:
skip=4-((m_iImageWidth*m_iBitsPerPixel)>>3)&3;
五、拾遗
至此,我们通过分析一个具体的位图文件例子详细地剖析了位图文件的组成。
需要注意的是:
我们讲的主要是PC机上的位图文件的构成,对于嵌入式平台,可能在调色板数据段与PC机的不同。
如在嵌入式平台上常见的16位r5g6b5位图实际上采用的掩模的方式而不是索引的方式来表示图像。
此时,在调色板数据段共有四个部分,每个部分为四个字节,实际表示的是彩色版规范。
即:
第一个部分是红色分量的掩模
第二个部分是绿色分量的掩模
第三个部分是蓝色分量的掩模
第四个部分是Alpha分量的掩模(缺省为0)
典型的调色板规范在文件中的顺序为为:
00F80000E00700001F00000000000000
其中
00F8 0000为FB00h=1111100000000000(二进制),是蓝红分量的掩码。
E007 0000为 07E0h=0000011111100000(二进制),是绿色分量的掩码。
1F00 0000为001Fh=0000000000011111(二进制),是蓝色分量的掩码。
0000 0000设置为0。
将掩码跟像素值进行“与”运算再进行移位操作就可以得到各色分量值。
看看掩码,就可以明白事实上在每个像素值的两个字节16位中,按从高到低取5、6、5位分别就是r、g、b分量值。
取出分量值后把r、g、b值分别乘以8、4、8就可以补齐每个分量为一个字节,再把这三个字节按BGR组合,放入存储器,就可以转换为24位标准BMP格式了。
这样我们假设在位图数据区有一个像素的数据在文件中表示为02F1。
这个数据实际上应为F102:
r=(F102ANDF800)>>8=F0h=240
g=(F102 AND 07E0)>>3=20h=32
b=(F102 AND 001F)<<3= 10h=16
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- BMP 位图 格式 详解