一.简介
BMP(Bitmap-File)图形文件是Windows采用的图形文件格式,在Windows环境下运行的所有图象处理软件都支持BMP图象文件格式。Windows系统内部各图像绘制操作都是以BMP为基础的。Windows 3.0以前的BMP图文件格式与显示设备有关,因此把这种BMP图象文件格式称为设备相关位图DDB(device-dependent bitmap)文件格式。Windows 3.0以后的BMP图象文件与显示设备无关,因此把这种BMP图象文件格式称为设备无关位图DIB(device-independent bitmap)格式(注:Windows 3.0以后,在系统中仍然存在DDB位图,象BitBlt()这种函数就是基于DDB位图的,只不过如果你想将图像以BMP格式保存到磁盘文件中时,微软极力推荐你以DIB格式保存),目的是为了让Windows能够在任何类型的显示设备上显示所存储的图象。BMP位图文件默认的文件扩展名是BMP或者bmp(有时它也会以.DIB或.RLE作扩展名)。
二.BMP格式结构
BMP文件的数据按照从文件头开始的先后顺序分为四个部分:
◆ 位图文件头(bmp file header): 提供文件的格式、大小等信息
◆ 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息
◆ 调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表
◆ 位图数据(bitmap data):图像数据区
BMP图片文件数据表如下:
数据段名称 | 大小(byte) | 开始地址 | 结束地址 |
位图文件头(bitmap-file header) | 14 | 0000h | 000Dh |
位图信息头(bitmap-information header) | 40 | 000Eh | 0035h |
调色板(color table) | 由biBitCount决定 | 0036h | 未知 |
图片点阵数据(bitmap data) | 由图片大小和颜色定 | 未知 | 未知 |
三.BMP文件头
BMP文件头结构体定义如下:
typedef struct tagBITMAPFILEHEADER
{
UINT16 bfType; //2Bytes,必须为"BM",即0x424D 才是Windows位图文件
DWORD bfSize; //4Bytes,整个BMP文件的大小
UINT16 bfReserved1; //2Bytes,保留,为0
UINT16 bfReserved2; //2Bytes,保留,为0
DWORD bfOffBits; //4Bytes,文件起始位置到图像像素数据的字节偏移量
} BITMAPFILEHEADER;
BMP文件头数据表如下:
变量名 | 地址偏移 | 大小 | 作用说明 |
bfType | 0000h | 2Bytes | 文件标识符,必须为"BM",即0x424D 才是Windows位图文件 ‘BM’:Windows 3.1x, 95, NT,… ‘BA’:OS/2 Bitmap Array ‘CI’:OS/2 Color Icon ‘CP’:OS/2 Color Pointer ‘IC’:OS/2 Icon ‘PT’:OS/2 Pointer 因为OS/2系统并没有被普及开,所以在编程时,你只需判断第一个标识“BM”就行 |
bfSize | 0002h | 4Bytes | 整个BMP文件的大小(以位B为单位) |
bfReserved1 | 0006h | 2Bytes | 保留,必须设置为0 |
bfReserved2 | 0008h | 2Bytes | 保留,必须设置为0 |
bfOffBits | 000Ah | 4Bytes | 说明从文件头0000h开始到图像像素数据的字节偏移量(以字节Bytes为单位),以为位图的调色板长度根据位图格式不同而变化,可以用这个偏移量快速从文件中读取图像数据 |
四.BMP信息头
BMP信息头结构体定义如下:
typedef struct _tagBMP_INFOHEADER
{
DWORD biSize; //4Bytes,INFOHEADER结构体大小,存在其他版本I NFOHEADER,用作区分
LONG biWidth; //4Bytes,图像宽度(以像素为单位)
LONG biHeight; //4Bytes,图像高度,+:图像存储顺序为Bottom2Top,-:Top2Bottom
WORD biPlanes; //2Bytes,图像数据平面,BMP存储RGB数据,因此总为1
WORD biBitCount; //2Bytes,图像像素位数
DWORD biCompression; //4Bytes,0:不压缩,1:RLE8,2:RLE4
DWORD biSizeImage; //4Bytes,4字节对齐的图像数据大小
LONG biXPelsPerMeter; //4 Bytes,用象素/米表示的水平分辨率
LONG biYPelsPerMeter; //4 Bytes,用象素/米表示的垂直分辨率
DWORD biClrUsed; //4 Bytes,实际使用的调色板索引数,0:使用所有的调色板索引
DWORD biClrImportant; //4 Bytes,重要的调色板索引数,0:所有的调色板索引都重要
}BMP_INFOHEADER;
BMP信息头数据表如下:
变量名 | 地址偏移 | 大小 | 作用说明 |
biSize | 000Eh | 4Bytes | BNP信息头即BMP_INFOHEADER结构体所需要的字节数(以字节为单位) |
biWidth | 0012h | 4Bytes | 说明图像的宽度(以像素为单位) |
biHeight | 0016h | 4Bytes | 说明图像的高度(以像素为单位)。这个值还有一个用处,指明图像是正向的位图还是倒向的位图,该值是正数说明图像是倒向的即图像存储是由下到上;该值是负数说明图像是倒向的即图像存储是由上到下。大多数BMP位图是倒向的位图,所以此值是正值。 |
biPlanes | 001Ah | 2Bytes | 为目标设备说明位面数,其值总设置为1 |
biBitCount | 001Ch | 2Bytes | 说明一个像素点占几位(以比特位/像素位单位),其值可为1,4,8,16,24或32 |
biCompression | 001Eh | 4Bytes | 说明图像数据的压缩类型,取值范围为: 0 BI_RGB 不压缩(最常用) 1 BI_RLE8 8比特游程编码(BLE),只用于8位位图 2 BI_RLE4 4比特游程编码(BLE),只用于4位位图 3 BI_BITFIELDS比特域(BLE),只用于16/32位位图 4 |
biSizeImage | 0022h | 4Bytes | 说明图像的大小,以字节为单位。当用BI_RGB格式时,总设置为0 |
biXPelsPerMeter | 0026h | 4Bytes | 说明水平分辨率,用像素/米表示,有符号整数 |
biYPelsPerMeter | 002Ah | 4Bytes | 说明垂直分辨率,用像素/米表示,有符号整数 |
biClrUsed | 002Eh | 4Bytes | 说明位图实际使用的调色板索引数,0:使用所有的调色板索引 |
biClrImportant | 0032h | 4Bytes | 说明对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要。 |
五.BMP调色板
BMP调色板结构体定义如下:
typedef struct _tagRGBQUAD
{
BYTE rgbBlue; //指定蓝色强度
BYTE rgbGreen; //指定绿色强度
BYTE rgbRed; //指定红色强度
BYTE rgbReserved; //保留,设置为0
} RGBQUAD;
1,4,8位图像才会使用调色板数据,16,24,32位图像不需要调色板数据,即调色板最多只需要256项(索引0 - 255)。
颜色表的大小根据所使用的颜色模式而定:2色图像为8字节;16色图像位64字节;256色图像为1024字节。其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(32位位图的透明度值,一般不需要)。即首先4字节表示颜色号1的颜色,接下来表示颜色号2的颜色,依此类推。
颜色表中RGBQUAD结构数据的个数有biBitCount来确定,当biBitCount=1,4,8时,分别有2,16,256个表项。
当biBitCount=1时,为2色图像,BMP位图中有2个数据结构RGBQUAD,一个调色板占用4字节数据,所以2色图像的调色板长度为2*4为8字节。
当biBitCount=4时,为16色图像,BMP位图中有16个数据结构RGBQUAD,一个调色板占用4字节数据,所以16像的调色板长度为16*4为64字节。
当biBitCount=8时,为256色图像,BMP位图中有256个数据结构RGBQUAD,一个调色板占用4字节数据,所以256色图像的调色板长度为256*4为1024字节。
当biBitCount=16,24或32时,没有颜色表。
五.BMP图像数据区
位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:
当biBitCount=1时,8个像素占1个字节;
当biBitCount=4时,2个像素占1个字节;
当biBitCount=8时,1个像素占1个字节;
当biBitCount=24时,1个像素占3个字节;
Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充,
一个扫描行所占的字节数计算方法:
DataSizePerLine= (biWidth* biBitCount+31)/8;
// 一个扫描行所占的字节数
DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数
位图数据的大小(不压缩情况下):
DataSize= DataSizePerLine* biHeight;
颜色表接下来位为位图文件的图像数据区,在此部分记录着每点像素对应的颜色号,其记录方式也随颜色模式而定,既2色图像每点占1位(8位为1字节);16色图像每点占4位(半字节);256色图像每点占8位(1字节);真彩色图像每点占24位(3字节)。所以,整个数据区的大小也会随之变化。究其规律而言,可的出如下计算公式:图像数据信息大小=(图像宽度*图像高度*记录像素的位数)/8。
六.调色板
1.我们知道,自然界中的所有颜色都可以由红、绿、蓝(R,G,B)三基色组合而成。而计算机对于像素的处理,用一个字节,将每种基色分为了256种等级,那么红、绿、蓝的不同组合共有256*256*256=16777216种,如此之多的组合,对于人眼的辨别能力来说,已经相当足够了,这就是我们平时所说的"真彩色".
对每个像素进行了(R,G,B)量化的图像就是位图,其在计算机中对应文件的扩展名一般为.bmp.
然而,对于"真彩色"来说,它的颜色种类实际上已经超出了人眼的识别范围,在很多时候,我们并没有必要将颜色划分得如此之细.而"真彩色"图片存储空间过大,也是这种文件的一种弊端.我们可以来计算一下一个800*600的"真彩色"图片所需要的存储空间的大小:
800*600*3 = 1440000(字节)= 1.37M(字节)
这是不是和你们平时看到的WINDOWS壁纸一样大小(当然,这里除去了位图文件中文件头以及其他信息头的大小,这些将在后面讲到).如果每个图形文件都花费掉如此大的空间,是很不划算的,于是就出现了"调色板",它的功能在于缓解位图文件存储空间过大的问题.位图文件也就出现了单色,16色,256色,16位,24位真彩色几种格式.
对于一个16色位图文件,它每个象素,只需要4bit,因为调色板提供了这16种等级对应的(R,G,B)值,我们只需要4bit来存储象素在调色板中的索引值,这样,一个800*600的16色位图文件所需要的存储空间为:
800*600*4/8 = 240000(字节) = 0.22 M(字节)
而调色板所带来的额外开销仅仅为16*4=64字节.存储空间大为减少了!
对于单色,16色,256色3种位图文件,都是以调色板方式进行存储;而对16位及24位真彩色以调色板进行存储是不划算的,它们直接按照R,G,B分量进行存储。
2.位图中的调色板模块
调色板(色数*4字节)
16)28-...:调色板规范.对于调色板中的每个元素,用下述方法来描述RGB的值:
1字节用于蓝色分量
1字节用于绿色分量
1字节用于红色分量
1字节为保留字
调色板针对的是需要调色板的位图,即单色,16色和256色等.对于不以调色板方式存储的位图,则没有此信息.它实际上就是一个数组,用来储存上面所提到的RGB元素,其中元素的个数由14)里提到的颜色索引数来定,当该值为0的时候,则根据色数来定,其大小等于2的n次幂,n是9)中提到的每个像素的位数(实际上,数组大小通常也就是2,16,256...).