您的位置:首页 > 其它

2,BMP文件格式解析

2016-08-31 15:38 260 查看
BMP图像

42 4D 5A 00 00 00 00 00 00 00 36 00 00 00 28 00

00 00 03 00 00 00 03 00 00 00 01 00 18 00 00 00

00 00 24 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 FF FF FF 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 FF FF FF 00 00 00

图像是3×3的,左下和右上两个象素为白色,其余均为黑色

42 4D 是BITMAPFILEHEADER结构体的bfType,这两个字节是固定的”BM”,表示该文件是bmp文件。

5A 00 00 00 表示bmp文件的大小,是BITMAPFILEHEADER结构体的bfSize,由于内存高低位颠倒,所以文件大小为&H0000005A=90字节。

00 00 是BITMAPFILEHEADER结构体的bfReserved1,无意义。

00 00 是BITMAPFILEHEADER结构体的bfReserved2,无意义。

36 00 00 00 表示DIB数据在文件中的偏移量,是BITMAPFILEHEADER结构体的bfOffBits,由于内存高低位颠倒,所以DIB偏移量为&H00000036=54字节。

BITMAPFILEHEADER结构体结束,总共14字节,下面是BITMAPINFOHEADER结构体。

28 00 00 00 是BITMAPINFOHEADER结构体的biSize,由于内存高低位颠倒,所以BITMAPINFOHEADER结构体大小为&H00000028=40字节。

03 00 00 00 是BITMAPINFOHEADER结构体的biWidth,表示bmp文件的宽度,由于内存高低位颠倒,所以bmp文件宽度为&H00000003=3像素。

03 00 00 00 是BITMAPINFOHEADER结构体的biHeight,表示bmp文件的高度,由于内存高低位颠倒,所以bmp文件高度为&H00000003=3像素。

01 00 是BITMAPINFOHEADER结构体的biPlanes,表示bmp表示的平面数,显然只有一个平面,该值恒为1,由于内存高低位颠倒,所以平面数为&H0001=1。

18 00 是BITMAPINFOHEADER结构体的biBitCount,表示bmp图片的颜色位数,由于内存高低位颠倒,所以颜色位数为&H0018=24位色。

00 00 00 00 是BITMAPINFOHEADER结构体的biCompression,全为0表示图片未压缩。

24 00 00 00 是BITMAPINFOHEADER结构体的biSizeImage,表示DIB数据区的容量大小,由于内存高低位颠倒,所以DIB大小为&H00000024=36字节。

00 00 00 00 是BITMAPINFOHEADER结构体的biXPelsPerMeter,表示图片X轴每米多少像素,可省略不写。

00 00 00 00 是BITMAPINFOHEADER结构体的biYPelsPerMeter,表示图片X轴每米多少像素,可省略不写。

00 00 00 00 是BITMAPINFOHEADER结构体的biClrUsed,表示使用了多少个颜色索引表,这里等于0,没有颜色索引表。

00 00 00 00 是BITMAPINFOHEADER结构体的biClrImportant,表示有多少个重要的颜色,等于0时表示所有颜色都很重要。

BITMAPINFOHEADER结构体结束,总共40字节。

BITMAPFILEHEADER结构体加BITMAPINFOHEADER结构体等于14+40=54,正好满足DIB的偏移量,所以后面就是DIB数据区。

由于从BITMAPINFOHEADER结构体得知bmp图片是24位色,所以一个像素只使用3个字节。

FF FF FF 表示第1个像素颜色,蓝:&HFF,绿:&HFF,红:&HFF。

00 00 00 表示第2个像素颜色,蓝:&H00,绿:&H00,红:&H00。

00 00 00 表示第3个像素颜色,蓝:&H00,绿:&H00,红:&H00。

这是一个3*3像素的图片,前面这3个像素就是图片的最底部的一行,从左到右,因为DIB扫描行是上下颠倒的,但是左右不颠倒。

另外,DIB数据规定,每个扫描行的字节数必须是4字节的整数倍,不足的需补零凑够4字节的整数倍,这里每行的3个像素只有9字节,需补3字节凑够一个扫描行12字节才满足4字节的整数倍,所以接下来的3字节为:

00 00 00 表示第1扫描行填充字节,无意义。

00 00 00 表示第4个像素颜色,蓝:&H00,绿:&H00,红:&H00。

00 00 00 表示第5个像素颜色,蓝:&H00,绿:&H00,红:&H00。

00 00 00 表示第6个像素颜色,蓝:&H00,绿:&H00,红:&H00。

00 00 00 表示第2扫描行填充字节,无意义。

00 00 00 表示第7个像素颜色,蓝:&H00,绿:&H00,红:&H00。

00 00 00 表示第8个像素颜色,蓝:&H00,绿:&H00,红:&H00。

FF FF FF 表示第9个像素颜色,蓝:&HFF,绿:&HFF,红:&HFF。

00 00 00 表示第3扫描行填充字节,无意义。

以C:\WINDOWS\Blue Lace 16.bmp为例,简要说明一下bmp图片的结构。这张图片是一张典型的4位、16色的bmp图片,每台电脑上都应该有这张图片。在说明之前请安装好UltraEdit软件以便察看bmp图片的16进制值。

一个bmp图片由3大部分组成:BITMAPFILEHEADER结构体,BITMAPINFO结构体,DIB数据区。其中DIB意思就是Device-Independent Bitmap(设备无关位图)。两个结构体的定义如下:(注意Integer类型占2个字节,Long类型占4个字节)

Private Type BITMAPFILEHEADER

bfType As Integer

bfSize As Long

bfReserved1 As Integer

bfReserved2 As Integer

bfOffBits As Long

End Type

Private Type BITMAPINFO

bmiHeader As BITMAPINFOHEADER

bmiColors As RGBQUAD

End Type

其中BITMAPINFO结构体中还有两个子结构体,分别定义如下:

Private Type BITMAPINFOHEADER ‘40 bytes

biSize As Long

biWidth As Long

biHeight As Long

biPlanes As Integer

biBitCount As Integer

biCompression As Long

biSizeImage As Long

biXPelsPerMeter As Long

biYPelsPerMeter As Long

biClrUsed As Long

biClrImportant As Long

End Type

Private Type RGBQUAD

rgbBlue As Byte

rgbGreen As Byte

rgbRed As Byte

rgbReserved As Byte

End Type

下面用UltraEdit打开C:\WINDOWS\Blue Lace 16.bmp察看其16进制数据。

一个bmp文件以BITMAPFILEHEADER结构体开始,BITMAPFILEHEADER的第1个属性是bfType(2字节),这里恒定等于&H4D42。由于内存中的数据排列高位在左,低位在右,所以内存中从左往右看就显示成(42 4D),所以在UltraEdit中头两个字节显示为(42 4D)就是这样形成的,以后的数据都是这个特点,不再作重复说明。

BITMAPFILEHEADER的第2个属性是bfSize(4字节),表示整个bmp文件的大小,这里等于&H000004F8=1272字节。

BITMAPFILEHEADER的第3个、第4个属性分别是bfReserved1、bfReserved2(各2字节),这里是2个保留属性,都为0,这里等于&H0000、&H0000。

BITMAPFILEHEADER的第5个属性是bfOffBits(4字节),表示DIB数据区在bmp文件中的位置偏移量,这里等于&H00000076=118,表示数据区从文件开始往后数的118字节开始。

BITMAPFILEHEADER结构体这里就讲完了,大家会发现BITMAPFILEHEADER只占了bmp文件开始的14字节长度,但需要特别说明的是在vb中定义一个BITMAPFILEHEADER结构体变量,其长度占了16个字节,原因就是第1个属性本来应该只分配2个字节,但实际被分配了4个字节,多出来2个字节,所以如果想保存一张bmp图片,写入BITMAPFILEHEADER结构体时一定要注意这一点。

接下来是BITMAPINFO结构体部分。BITMAPINFO段由两部分组成:BITMAPINFOHEADER结构体和RGBQUAD结构体。其中RGBQUAD结构体表示图片的颜色信息,有些时候可以省略,一般的24位图片和32位图片都不带RGBQUAD结构体,因为DIB数据区直接表示的RGB值,一般4位图片和8位图片才带有RGBQUAD结构体。(多少位的图片就是用多少位来表示一个颜色信息,例如4位图片表示用4个bit来表示一个颜色信息。)一个bmp文件中有没有RGBQUAD结构体,可以根据前面BITMAPFILEHEADER结构体的第5个属性bfOffBits来判断,因为BITMAPINFOHEADER结构体长度为40bit,如果BITMAPINFOHEADER结构体结束后还未到DIB数据区的偏移量,就说明接下来的数据是RGBQUAD结构体部分。这里讲的C:\WINDOWS\Blue Lace 16.bmp是一个4bit图片,所以它带有RGBQUAD结构体。

下面进入正题BITMAPINFOHEADER部分。

BITMAPINFOHEADER的第1个属性是biSize(4字节),表示BITMAPINFOHEADER结构体的长度,最常见的长度是40字节,UltraEdit中可以看到紧接着的4个字节等于&H00000028=40字节。

BITMAPINFOHEADER的第2个属性是biWidth(4字节),表示bmp图片的宽度,这里等于&H00000030=48像素。

BITMAPINFOHEADER的第3个属性是biHeight(4字节),表示bmp图片的高度,这里等于&H00000030=48像素。

BITMAPINFOHEADER的第4个属性是biPlanes(2字节),表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1,这里等于&H0001。

BITMAPINFOHEADER的第5个属性是biBitCount(2字节),表示bmp图片的颜色位数,即24位图、32位图等等。这里等于&H0004,表示该图片为4位图。

BITMAPINFOHEADER的第6个属性是biCompression(4字节),表示图片的压缩属性,bmp图片是不压缩的,等于0,所以这里为&H00000000。

BITMAPINFOHEADER的第7个属性是biSizeImage(4字节),表示bmp图片数据区的大小,当上一个熟悉biCompression等于0时,这里的值可以省略不填,所以这里等于&H00000000。

BITMAPINFOHEADER的第8个属性是biXPelsPerMeter(4字节),表示图片X轴每米多少像素,可省略,这里等于&H00000EC3=3779像素/米。

BITMAPINFOHEADER的第9个属性是biYPelsPerMeter(4字节),表示图片Y轴每米多少像素,可省略,这里等于&H00000EC3=3779像素/米。

BITMAPINFOHEADER的第10个属性是biClrUsed(4字节),表示使用了多少个颜色索引表,一般biBitCount属性小于16才会用到,等于0时表示有2^biBitCount个颜色索引表,所以这里仍等于&H00000000。

BITMAPINFOHEADER的第11个属性是biClrImportant(4字节),表示有多少个重要的颜色,等于0时表示所有颜色都很重要,所以这里等于&H00000000。

至此BITMAPINFOHEADER结构体结束。

由于这个图片到这里还未到达DIB数据区的偏移量,所以接下来的部分是RGBQUAD结构体。RGBQUAD结构体由4个字节型数据组成,所以一个RGBQUAD结构体只占用4字节空间,从左到右每个字节依次表示(蓝色,绿色,红色,未使用)。举例的这个图片我数了数总共有16个RGBQUAD结构体,由于该图片是4位图,2^4正好等于16,所以它把16种颜色全部都枚举出来了,这些颜色就是一个颜色索引表。颜色索引表编号从0开始,总共16个颜色,所以编号为0-15。从UltraEdit中可以看到按照顺序,这16个RGBQUAD结构体依次为:

编号:(蓝,绿,红,空)

0号:(00,00,00,00)

1号:(00,00,80,00)

2号:(00,80,00,00)

3号:(00,80,80,00)

4号:(80,00,00,00)

5号:(80,00,80,00)

6号:(80,80,00,00)

7号:(80,80,80,00)

8号:(C0,C0,C0,00)

9号:(00,00,FF,00)

10号:(00,FF,00,00)

11号:(00,FF,FF,00)

12号:(FF,00,00,00)

13号:(FF,00,FF,00)

14号:(FF,FF,00,00)

15号:(FF,FF,FF,00)

为了更直观的表示这些颜色,可以见后面的图片。

到这里,正好满足DIB数据区的偏移量,所以后面的字节就是图片内容了。这里需要提醒的是所有的DIB数据扫描行是上下颠倒的,也就是说一幅图片先绘制底部的像素,再绘制顶部的像素,所以这些DIB数据所表示的像素点就是从图片的左下角开始,一直表示到图片的右上角。

由于这里的图片是4位图片,也就是说4bit就表示一个像素,一个字节有8个bit,所以一个字节能表示2个像素。

从UltraEdit中可以看到,DIB数据区第一个字节是&H44,16进制正好是将2进制数每4个一组书写的,跟4bit图片正好吻合,所以&H44表示两个像素,高位的4表示第一个像素,低位的4表示第二个像素。这里的4不是表示RGB颜色,而是表示颜色索引号为4,由于索引号从0开始编号的,所以4表示索引表中第5个颜色,从附图中可以看到索引号为4的是蓝色。这是第一字节,表示的是图片左下角开始2个像素,如果有PhotoShop打开这个图片可以看到,左下角2个像素取出来的颜色RGB值正好等于索引表中第5个颜色的RGB值。后面的DIB数据以此类推。

至此一个bmp图片就全部解析完了,根据这些信息就可以完整的绘制一张bmp图片来
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: