BMP文件中图像数据是按啥顺序存放的?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BMP文件中图像数据是按啥顺序存放的?相关的知识,希望对你有一定的参考价值。

如题,是在C语言中,什么顺序?

BMP文件的数据按照从文件头开始的先后顺序分为四个部分:
◆ 位图文件头(bmp file header): 提供文件的格式、大小等信息
◆ 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息
◆ 调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表
◆ 位图数据(bitmap data):图像数据区
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信息头结构体定义如下:
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调色板结构体定义如下:
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。
参考技术A bmp是最原始的图像格式。其排列很简单。就是每个像素一个数据如果是2色2×2即4像素的图像如下0 00 0就表示白色的图像。它的数据排列是最原始的一个点(像素)一个颜色数据。如果整体是16位(即65536色的图像)色。每个像素就就是16位2进制代码表示的。比如上面2色图转换成16位色图就是0000000000000000 00000000000000000000000000000000 0000000000000000根据这个原理我们也可以计算图像的大小。比如30万像素的24位色bmp就是(24×300000)/8 B这么大。 参考技术B 从左下角开始,一行一行存储 参考技术C 是按你设置的顺序来排列的。点鼠标右键有排列图标,按选项设吧。 参考技术D 图片到图片文件,数据的顺序,为从下往上,从左往右;文件头什么的到处都有;

北亚工程师详细解说BMP文件格式

    BMP是一种与硬件设备无关的图像文件格式,使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BblP文件所占用的空间很大。BMP文件的图像深度可选lbit、4bit、8bit及24bit。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。

    由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。

    典型的BMP图像文件由三部分组成:位图文件头数据结构,它包含BMP图像文件的类型、显示内容等信息;位图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息。

    具体数据举例:

    如某BMP文件开头:

424D 4690 0000 0000 0000 4600 0000 2800 0000 8000 0000 9000 0000 0100*1000 0300 0000 0090 0000 A00F 0000 A00F 0000 0000 0000 0000 0000*00F8 0000 E007 0000 1F00 0000 0000 0000*02F1 84F1 04F1 84F1 84F1 06F2 84F1 06F2 04F2 86F2 06F2 86F2 86F2 …. ….

    BMP文件可分为四个部分:位图文件头、位图信息头、彩色板、图像数据阵列,在上图中已用*分隔。

一、图像文件头 

1)1:图像文件头。424Dh=”BM”,表示是Windows支持的BMP格式。

2)2-3:整个文件大小。4690 0000,为00009046h=36934。

3)4-5:保留,必须设置为0。

4)6-7:从文件开始到位图数据之间的偏移量。4600 0000,为00000046h=70,上面的文件头就是35字=70字节。

5)8-9:位图图信息头长度。

6)10-11:位图宽度,以像素为单位。8000 0000,为00000080h=128。

7)12-13:位图高度,以像素为单位。9000 0000,为00000090h=144。

8)14:位图的位面数,该值总是1。0100,为0001h=1。

二、位图信息头 

9)15:每个像素的位数。有1(单色),4(16色),8(256色),16(64K色,高彩色),24(16M色,真彩色),32(4096M色,增强型真彩色)。1000为0010h=16。

10)16-17:压缩说明:有0(不压缩),1(RLE 8,8位RLE压缩),2(RLE 4,4位RLE压缩,3(Bitfields,位域存放)。RLE简单地说是采用像素数+像素值的方式进行压缩。T408采用的是位域存放方式,用两个字节表示一个像素,位域分配为r5b6g5。图中0300 0000为00000003h=3。

11)18-19:用字节数表示的位图数据的大小,该数必须是4的倍数,数值上等于位图宽度×位图高度×每个像素位数。0090 0000为00009000h=80×90×2h=36864。

12)20-21:用象素/米表示的水平分辨率。A00F 0000为0000 0FA0h=4000。

13)22-23:用象素/米表示的垂直分辨率。A00F 0000为0000 0FA0h=4000。

14)24-25:位图使用的颜色索引数。设为0的话,则说明使用所有调色板项。

15)26-27:对图象显示有重要影响的颜色索引的数目。如果是0,表示都重要。

三、彩色板 (非必有)

16)28-35:彩色板规范。对于调色板中的每个表项,用下述方法来描述RGB的值:

1字节用于蓝色分量

1字节用于绿色分量

1字节用于红色分量

1字节用于填充符(设置为0)

    对于24-位真彩色图像就不使用彩色板,因为位图中的RGB值就代表了每个象素的颜色。

   如,彩色板为00F8 0000 E007 0000 1F00 0000 0000 0000,其中:

00FB 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就可以补齐第个分量为一个字节,再把这三个字节按rgb组合,放入存储器(同样要反序),就可以转换为24位标准BMP格式了。

四、图像数据阵列 

17)17-...:每两个字节表示一个像素。阵列中的第一个字节表示位图左下角的象素,而最后一个字节表示位图右上角的象素。

   下面用winhex打开一个bmp文件,察看其16进制数据。

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

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

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

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

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

    接下来是BITMAPINFO结构体部分。BITMAPINFO(frombyte.com)段由两部分组成: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个字节等于0×00000028=40字节。

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

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

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

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

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

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

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

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

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

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

    至此BITMAPINFOHEADER结构体结束。

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

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

    至此一个bmp图片就全部解析完了,根据这些信息就可以完整的绘制一张bmp图片来。当然也可以简单手工修复一个破坏不算严重的BMP文件!


本文出自 “SUN” 博客,请务必保留此出处http://sun510.blog.51cto.com/9640486/1915907

以上是关于BMP文件中图像数据是按啥顺序存放的?的主要内容,如果未能解决你的问题,请参考以下文章

数据恢复培训资料:BMP文件详解

交叉引用、前向声明等:按啥顺序?

Nginx:限速和缓存按啥顺序执行?

SVG 点按啥顺序绘制?

您应该按啥顺序将一组已知键插入 B-Tree 以获得最小高度?

pytest 固定装置按啥顺序执行?