BMP文件格式
BMP 取自 Bitmap 的缩写。BMP 文件格式,也被称为位图图像文件或设备无关位图(DIB, device independent bitmap)的文件格式或简称为位图(bitmap),是一个用于存储位图数字图像的文件格式,独立于的显示装置,尤其是在 Microsoft Windows 和 OS/2 操作系统上。文件扩展名为.bmp, Windows GDI API 内部使用的 DIB 数据结构(.dib)与 BMP 文件格式几乎相同。
BMP 文件格式能够存储各种颜色深度的单色和彩色二维数字图像,并且可以选择存储数据压缩,alpha 通道和颜色配置文件。在 Windows Metafile(WMF) 规范中涵盖了 BMP 格式的文件。
文件结构
位图图像文件由固定大小的结构(文件头)以及以预定顺序出现的可变大小的结构体组成。由于该文件格式几经演进,这些结构体的版本也很多。
参考上图,位图文件由以下结构依次构成:
结构体名称 | 可选 | 大小 | 用途 | 备注 |
---|---|---|---|---|
位图文件头 (Bitmap file header) |
否 | 14 字节 | 存储位图文件一般信息 | 仅在读取文件时有用 |
DIB 头 (DIB header) |
否 | 固定(存在 7 种版本) | 存储位图详细信息及像素格式 | 紧跟在位图文件头后 |
附加位掩码 (Extra bit masks) |
是 | 3或4 DWORD(12或16字节) | 定义像素格式 | 仅在DIB头是BITMAPINFOHEADER且Compression Method成员设置为BI_BITFIELDS或BI_ALPHABITFIELDS的情况下存在 |
调色板 (Color table) |
半可选,见备注 | 可变 | 定义图像数据(像素数组)所用颜色 | 色深(color depths) ≤ 8时不能省略 |
填充区A (Gap1) |
是 | 可变 | 结构对齐 | 位图文件头中为偏移到像素数组的填充 |
像素数组 (Pixel array) |
否 | 可变 | 实际的像素数值 | 像素数据在DIB头和附加位掩码中定义。像素数组中每行均以4字节对齐 |
填充去B (Gap2) |
是 | 可变 | 结构体对齐 | DIB头中为偏移到ICC色彩特性数据位置的填充 |
ICC色彩特性数据 (ICC color profile) |
是 | 可变 | 定义色彩特性 | 可以包含外部文件路径,由该文件来定义色彩特性 |
一、位图文件头 Bitmap file header
这部分数据块位于文件开头,共 14 字节,用于进行文件的识别。典型的应用程序会首先普通读取这部分数据以确保的确是位图文件并且没有损坏。所有的整数值都以小端序(little-endian)存放(即最低有效位前置)。
偏移量 | 大小 (字节数) |
用途 |
---|---|---|
0x00 | 2 | 用于标识BMP和DIB文件,一般为0x42 0x4D, 即 ASCII 的 BM 。以下为可能的取值: <li> BM – Windows 3.1x, 95, NT, ... etc.<li> BA – OS/2 struct Bitmap Array<li> CI – OS/2 struct Color Icon <li> CP – OS/2 const Color Pointer<li> IC – OS/2 struct Icon<li> PT – OS/2 Pointer |
0x02 | 4 | BMP文件的大小(单位为字节) |
0x06 | 2 | 保留;实际值因创建程序而异 |
0x08 | 2 | 保留;实际值因创建程序而异 |
0x0a | 4 | 位图数据(像素数组)的地址偏移,也就是图像数据的起始地址。 |
二、DIB头 DIB header (bitmap information header)
这部分告诉应用程序图像的详细信息,在屏幕上显示图像将会使用这些信息,它从文件的第15个字节开始。
这部分数据块对应了Windows和OS/2中的内部使用的头结构以及其它一些版本的变体。但所有版本均以一个DWORD位(32位)开始,用以说明该数据块的大小,使得应用程序能够根据这个大小来区分该图像实际使用了哪种版本的DIB头结构。
存在多种版本的头结构的原因是微软对DIB格式进行过多次扩展。下表即为所有不同版本的DIB头:
大小 | 结构名称 | 操作系统支持 | 特性 | 作者 |
---|---|---|---|---|
12 | BITMAPCOREHEADER OS21XBITMAPHEADER |
OS/2和3.0版本以来的Windows | ||
64 | BITMAPCOREHEADER2 OS22XBITMAPHEADER |
OS/2 | 添加半调网屏;添加RLE及霍夫曼1D压缩。 | |
40 | BITMAPINFOHEADER | Windows 3.0及更高版本 | 删除RLE-24及霍夫曼1D压缩;添加16/32位像素格式;添加可选的RGB位掩码。 | |
52 | BITMAPV2INFOHEADER | Undocumented | 删除可选的RGB位掩码;添加必选的RGB位掩码。 | Adobe Photoshop |
56 | BITMAPV3INFOHEADER | Not officially documented | 添加必选的Alpha通道位掩码。 | Adobe Photoshop |
108 | BITMAPV4HEADER | Windows 95/NT4及更高版本 | 添加色彩空间类型和伽玛校正。 | |
124 | BITMAPV5HEADER | Windows 98/2000及更高版本 | 添加ICC色彩特性。 |
BITMAPCOREHEADER之后的版本都只是在前一版本结构末尾追加字段。
下面我们对比较常见的两个版本进行说明
BITMAPCOREHEADER
DIB 头从地址 0x0E 开始,下面列出 BITMAPCOREHEADER 版本的 DIB 头。除非有特殊说明,其中所有值均为无符号整数。
Offset | Size(bytes) | Purpose |
---|---|---|
0x0E | 4 | DIB 头结构的大小(字节数),对于此版本,值为 12 |
0x12 | 2 | 位图宽度,单位为像素 |
0x14 | 2 | 位图高度,单位为像素 |
0x16 | 2 | 色彩平面数,必须为 1 |
0x18 | 2 | 每个像素所占位数,典型值为 1、4、8 和 24 |
注意:
- OS/2 BITMAPCOREHEADER的位图都是未压缩的,而且不能是16或32位/像素。
- Windows 2.x BITMAPCOREHEADER 与 OS/2 1.x BITMAPCOREHEADER(如上表所示)的不同之处在于,图像宽度和高度字段是有符号整数,而不是无符号整数。
BITMAPINFOHEADER
出于兼容性的考量,大多数应用程序使用较旧版本的DIB头保存文件。由于 Windows 2000 之后不再支持 OS/2, 因此目前常见的Windows格式是 BITMAPINFOHEADER 标头。下表对其进行说明,除非有特殊说明,其中所有值均为无符号整数。
Offset | Size(bytes) | Windows BITMAPINFOHEADER |
---|---|---|
0x0E | 4 | 该 DIB 表头的大小(字节数),对于此版本,值为 40 |
0x12 | 4 | 位图宽度,单位为像素(有符号整数) |
0x16 | 4 | 位图高度,单位为像素(有符号整数) |
0x1A | 2 | 色彩平面数,必须为 1 |
0x1C | 2 | 每个像素所占位数,即图像的色深(color depth)。典型值为1、4、8、16、24和32 |
0x1E | 4 | 所使用的压缩方法,可取值见下表 |
0x22 | 4 | 图像大小。指原始位图数据的大小(详见后文),与文件大小不是同一个概念。可以为 BI_RGB 位图指定一个虚拟 0 |
0x26 | 4 | 图像的横向分辨率,单位为像素每米(有符号整数) |
0x2A | 4 | 图像的纵向分辨率,单位为像素每米(有符号整数) |
0x2E | 4 | 调色板的颜色数,为0时表示颜色数为默认的 个 |
0x32 | 4 | 重要颜色数,为0时表示所有颜色都是重要的;通常不使用本项 |
压缩方法(字节 0x1E ~ 0x21)的有效值如下表所示:
Value | Identified by (标识) | Compression method | Comments |
---|---|---|---|
0 | BI_RGB | 无 | 无压缩,最常见 |
1 | BI_RLE8 | RLE 8位/像素 | 只能用于格式为8位/像素的位图 |
2 | BI_RLE4 | RLE 4位/像素 | 只能用于格式为4位/像素的位图 |
3 | BI_BITFIELDS | 位字段或者霍夫曼1D压缩(BITMAPCOREHEADER2) | 像素格式由位掩码指定,或位图经过霍夫曼1D压缩(BITMAPCOREHEADER2) |
4 | BI_JPEG | JPEG或RLE-24压缩(BITMAPCOREHEADER2) | 位图包含JPEG图像或经过RLE-24压缩(BITMAPCOREHEADER2) |
5 | BI_PNG | PNG | 位图包含PNG图像 |
6 | BI_ALPHABITFIELDS | RGBA位域掩码 | 针对Windows CE .NET 4.0及之后版本 |
11 | BI_CMYK | 无 | only Windows Metafile CMYK |
12 | BI_CMYKRLE8 | RLE-8 | only Windows Metafile CMYK |
13 | BI_CMYKRLE4 | RLE-4 | only Windows Metafile CMYK |
注意:BI_JPEG和BI_PNG仅对打印机驱动有效,不支持屏幕渲染。
三、附加位掩码 Extra bit masks
此项仅在DIB头是BITMAPINFOHEADER且Compression Method成员设置为BI_BITFIELDS或BI_ALPHABITFIELDS的情况下存在。
见本文的最后部分
四、调色板
这部分定义了图像中所用的颜色。如上所述,位图图像一个像素接着一个像素储存,每个像素使用一个或者多个字节的值表示,所以调色板的目的就是要告诉应用程序这些值所对应的实际颜色。
调色板的条目数为 (n为 DIB 头中指定的的每个像素所占位数) 或 DIB 头中指定的调色板的颜色数。
典型的位图文件使用RGB彩色模型。大多数情况下,调色板的每个条目占 4 个字节,按顺序表示 蓝色、绿色、红色、0x00。每个条目的格式如下:
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
其中,第四个字节一般没有使用(大多数应用程序将它设为0),也有些应用程序将第四个字节作为 alfa 通道使用。
调色板是一个字节块(一个表),列出了图像使用的颜色。对于索引型的位图(每个像素所占位数为1、4 或 8),调色板的作用是告诉应用程序,像素的实际颜色,此时,像素点存储的值为此调色板中此像素颜色的索引,根据索引得到像素点真实的颜色。对于非索引型的位图,调色板的作用是列出位图中使用的颜色,以优化具有有限颜色显示功能的设备,并便于将来转换为不同的像素格式和着色。
如上所述,当像素采用每像素16位或更高时,通常不使用调色板。
五、像素存储
位图中的像素是以行为单位进行存储的,每一行再存储时都以 4 字节对齐,即每一行的大小都向上取整为 4 字节(32 位 DWORD)的倍数。如果图像的高度大于 1, 多个经过填充实现对齐的行就形成了像素数组。
所以存储一行像素所需的字节数,可以通过以下公式计算:
RowSize单位为字节,ImageWidth单位为像素;注意公式中的特殊括号,表示向上、向下取整
像素阵列 Pixel array (bitmap data)
像素阵列是一个32位DWORD块,它逐像素描述图像,每个像素使用 1 个或多个自己表示。
通常,像素是从下到上、从左到右保存的。但如果使用的不是 BITMAPCOREHEADER, 那么未压缩的 Windows 位图还可以从上到下存储,此时图像高度为负值。
每一行的末尾通过填充若干个字节的数据(并不一定为0)使该行的长度为4字节的倍数。像素数组读入内存后,每一行的起始地址必须为4的倍数。这个限制仅针对内存中的像素数组,针对存储时,仅要求每一行的大小为4字节的倍数,对文件的偏移地址没有限制。
例如:对于24位色的位图,如果它的宽度为1像素,那么除了每一行的数据(蓝、绿、红)需要占3字节外,还会填充1字节;而如果宽为2像素,则需要2字节的填充;宽为3像素时,需要3字节填充;宽为4像素时则不需要填充。
压缩
- 索引色图像可以使用4位或8位RLE或霍夫曼1D算法压缩
- OS/2 BITMAPCOREHEADER2 24位色图像则可以使用24位RLE算法压缩
- 16位色与32位色图像始终为未压缩数据
- 如果需要,任何色深的图像都可以以未压缩形式存储
像素格式
此处的单位 bbp 为 (bit/pixel), 位每像素
- 1 bbp, 每像素 1 位,支持 2 种不同的颜色。像素值存储在每一个bit位中,每个字节存储 8 个像素,最左侧像素对应第一个字节的最高位。像素的颜色由调色板给出,像素为 0 表示调色板中的一个条目的颜色;像素为 1 表示调色板中的第二个(最后一个)条目的颜色
- 2 bbp, 每像素 2 位,支持 4 种不同的颜色。每个字节对应 4 个像素,最左侧像素为第一个字节的最高两位。使用 2 位的索引可以对调色板中最多 4 种颜色进行索引
- 4 bbp, 每像素 4 位,支持 16 种不同的颜色。每个字节存储 2 个像素,最左侧的像素为第一个字节的高 4 位。 像素值对最多 16 个条目的调色板进行索引
- 8 bbp, 每像素 8 位,支持 256 种颜色。每个字节存储 1 个像素。像素值对最多 256 个颜色条目的调色板进行索引
- 16 bbp, 每个像素 16 位,支持 65536 种颜色。每 2 个字节存储 1 个像素。该像素的 不透明度(alfa)、红、绿、蓝 值即存储于此两个字节中
- 24 bbp, 每个像素 24 位,支持 16,777,216 种颜色。每3字节存储1个像素。每个像素值存储实际的 红色、绿色、蓝色 值,顺序为:蓝、绿、红(每个通道占 8 位)
- 32 bbp, 每个像素 32 位,支持 4,294,967,296 种颜色,每 4 个字节存储一个像素。此 DWORD 存储像素的 不透明度(alfa)、红、绿、蓝值
位掩码
为了解决哪些位定义了哪些样本的歧义,DIB标头提供了某些默认值以及特定的BITFIELDS,它们是位掩码,用于定义像素中特定位组到特定通道的成员资格。下图定义了此机制:
BITFIELDS位掩码定义的样本字段必须是连续且不重叠的,但是样本字段的顺序是任意的。最普遍的场序是:Alpha,Blue,Green,Red(MSB到LSB)。仅当DIB标头的Compression成员设置为BI_BITFIELDS时,红色,绿色和蓝色位掩码才有效。只要在DIB标头中存在或将DIB标头的Compression成员设置为BI_ALPHABITFIELDS [5](仅Windows CE),alpha位掩码就有效。
BMP 文件例子解析
使用画图软件绘制图像为 bmp 格式,下面是一些例子:
单色图像
这后面有一个很小的BMP单色图 [图片上传失败...(image-fd91f4-1572484665335)]
放大后显示为:
其文件内容为(全部以16进制表示):
Offset | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x00 | 42 | 4d | 56 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 3e | 00 | 00 | 00 | 28 | 00 |
0x10 | 00 | 00 | 05 | 00 | 00 | 00 | 06 | 00 | 00 | 00 | 01 | 00 | 01 | 00 | 00 | 00 |
0x20 | 00 | 00 | 18 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
0x30 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | ff | ff | ff | 00 | f8 | 00 |
0x40 | 00 | 00 | f0 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 98 | 00 | 00 | 00 | f0 | 00 |
0x50 | 00 | 00 | 00 | 00 | 00 | 00 |
对其进行解析:
-
0x00 ~ 0x0d
14 字节,位图文件头0x00 ~ 0x01
2 字节,文件头最开头两字节为字符 "BM"0x02 ~ 0x05
4 字节,为 BMP 文件的大小,此处值为 0x56 = 86, 由实际查看可知其文件 确实为 86 字节大小0x06 ~ 0x07
2 字节,保留字节,此处为 00x08 ~ 0x09
2 字节,保留自己,此处为 00x0a ~ 0x0d
4 字节,位图数据的地址,此处为 0x3e, 表示实际的像素在 0x3e 处开始存储。
0x0e ~ 0x11
4 字节,DIB表头的大小(字节数),此处值为 0x28 = 40, 可以由此得知,此文件使用的 DIB 头版本为 BITMAPINFOHEADER, 由此我们可确定 从 0x0e ~ 0x35 的内容为 DIB 头-
0x0e ~ 0x35
40 字节,DIB 头0x0e ~ 0x11
4 字节,DIB表头的大小(字节数),此处值为 0x28 = 400x12 ~ 0x15
4 字节,位图宽度,单位为像素(有符号整数),此处为 50x16 ~ 0x19
4 字节,位图高度,单位为像素(有符号整数),此处为 60x1A ~ 0x1B
2 字节,色彩平面数,必须为 1,此处为 10x1C ~ 0x1D
2 字节,每个像素所占位数,此处为 10x1E ~ 0x21
4 字节,所使用的压缩方法,此处为 0 ,表示无压缩0x22 ~ 0x25
4 个字节,图像大小。指原始位图数据的大小。此处为 0x18 = 24,此值为实际存储像素时占用的字节数。本图像为 6 行,每行占用 4 个字节,像素共占用 24 个字节0x26 ~ 0x29
4 个字节,图像的横向分辨率,此处为 00x2A ~ 0x2D
4 个字节,图像的纵向分辨率,此处为 00x2E ~ 0x31
4 个字节,调色板的颜色数,为0时表示颜色数为默认的 个。此处为 0 ,表示调色板有 个0x32 ~ 0x35
4 个字节,重要颜色数。此处为 0
-
0x36 ~ 0x3d
8 个字节,调色板。由上面可知,调色板条目数量为 2 ,每个条目占 4 个字节,所以调色板一共占 8 个字节- 0x36 ~ 0x39
4 个字节,调色板第一个颜色,此处值全为 0, 由调色板的定义可知,此处表示RGB全为0的颜色,即黑色 - 0x3a ~ 0x3d
4个字节,调色板的第二个颜色,此处值为 0xff, 0xff, 0xff, 0x00, 由调色板的定义可知,表示RGB全为255的颜色,即白色
- 0x36 ~ 0x39
-
0x3e ~ 0x55
24 个字节,此处储存实际的图像像素点0x3e ~ 0x41
4 个字节,存储图像的第一行,图像为 1 bbp 的图像,每个 bit 位保存一个像素,0x3e 的值 0xf8 = 11111000b 即第一行的第 1 个像素颜色为调色板中的第二个颜色为白色,第 2 个像素也为白色……第 5 个像素为白色,此图像一行只有 5 个像素,后面填充 0 ,因为图像的一行在保存时字节数必须为 4 的倍数,后面再填充 3 个字节。-
0x42 ~ 0x45
4 个字节,存储图像的第 2 行 0x52 ~ 0x55
4 个字节,存储图像的第 6 行
16色图像
这后面有一个很小的 BMP 16色图 [图片上传失败...(image-887bb6-1572484665335)]
放大后显示为:
其文件内容为(全部以16进制表示):
Offset | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x00 | 42 | 4d | 8e | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 76 | 00 | 00 | 00 | 28 | 00 |
0x10 | 00 | 00 | 05 | 00 | 00 | 00 | 06 | 00 | 00 | 00 | 01 | 00 | 04 | 00 | 00 | 00 |
0x20 | 00 | 00 | 18 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
0x30 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 80 | 00 | 00 | 80 |
0x40 | 00 | 00 | 00 | 80 | 80 | 00 | 80 | 00 | 00 | 00 | 80 | 00 | 80 | 00 | 80 | 80 |
0x50 | 00 | 00 | 80 | 80 | 80 | 00 | c0 | c0 | c0 | 00 | 00 | 00 | ff | 00 | 00 | ff |
0x60 | 00 | 00 | 00 | ff | ff | 00 | ff | 00 | 00 | 00 | ff | 00 | ff | 00 | ff | ff |
0x70 | 00 | 00 | ff | ff | ff | 00 | 88 | 8b | 80 | 00 | ff | 8b | a0 | 00 | cc | aa |
0x80 | a0 | 00 | 7c | cc | 70 | 00 | bb | b7 | 60 | 00 | 00 | 99 | 90 | 00 |
对其进行解析:
-
0x00 ~ 0x0d
14 字节,位图文件头0x00 ~ 0x01
2 字节,文件头最开头两字节为字符 "BM"0x02 ~ 0x05
4 字节,为 BMP 文件的大小,此处值为 0x8e = 142, 由实际查看可知其文件 确实为 142 字节大小0x06 ~ 0x07
2 字节,保留字节,此处为 00x08 ~ 0x09
2 字节,保留自己,此处为 00x0a ~ 0x0d
4 字节,位图数据的地址,此处为 0x76, 表示实际的像素在 0x76 处开始存储。
0x0e ~ 0x11
4 字节,DIB表头的大小(字节数),此处值为 0x28 = 40, 可以由此得知,此文件使用的 DIB 头版本为 BITMAPINFOHEADER, 由此我们可确定 从 0x0e ~ 0x35 的内容为 DIB 头-
0x0e ~ 0x35
40 字节,DIB 头0x0e ~ 0x11
4 字节,DIB表头的大小(字节数),此处值为 0x28 = 400x12 ~ 0x15
4 字节,位图宽度,单位为像素(有符号整数),此处为 50x16 ~ 0x19
4 字节,位图高度,单位为像素(有符号整数),此处为 60x1A ~ 0x1B
2 字节,色彩平面数,必须为 1,此处为 10x1C ~ 0x1D
2 字节,每个像素所占位数,此处为 4, 表示每个像素由 4 个bit位存储0x1E ~ 0x21
4 字节,所使用的压缩方法,此处为 0 ,表示无压缩0x22 ~ 0x25
4 个字节,图像大小。指原始位图数据的大小。此处为 0x18 = 24,此值为实际存储像素时占用的字节数。本图像为 6 行,每行占用 4 个字节,像素共占用 24 个字节0x26 ~ 0x29
4 个字节,图像的横向分辨率,此处为 00x2A ~ 0x2D
4 个字节,图像的纵向分辨率,此处为 00x2E ~ 0x31
4 个字节,调色板的颜色数,为0时表示颜色数为默认的 个。此处为 0 ,表示调色板有 个0x32 ~ 0x35
4 个字节,重要颜色数。此处为 0
-
0x36 ~ 0x3d
64 个字节,调色板。由上面可知,调色板条目数量为 16 ,每个条目占 4 个字节,所以调色板一共占 64 个字节0x36 ~ 0x39
4 个字节,调色板第 1 个颜色,此处值全为 0, 由调色板的定义可知,此处表示RGB全为0的颜色,即黑色0x3a ~ 0x3d
4个字节,调色板的第 2 个颜色,此处值为 0x00, 0x00, 0x80, 0x00, 由调色板的定义可知,表示BGR分别为 0、0、128 的颜色-
0x3e ~ 0x41
4个字节,调色板的第 3 个颜色,此处值为 0x00, 0x80, 0x00, 0x00, 由调色板的定义可知,表示BGR分别为 0、128、0 的颜色
0x72 ~ 0x75
4个字节,调色板的第 16 个颜色,此处值为 0xff, 0xff, 0xff, 0x00, 由调色板的定义可知,表示BGR分别为 255、255、255 的颜色,即白色
-
0x76 ~ 0x8d
24 个字节,此处储存实际的图像像素点0x76 ~ 0x79
4 个字节,存储图像的第一行,图像为 4 bbp 的图像,每 4 个 bit 位保存一个像素,0x76 的值 0x88 保存两个像素,第一行的第 1 个像素颜色为调色板中的第 9 个颜色为 BRG 分别为 192、192、192 的颜色,第 2 个像素也为此颜色。第 2 个字节存储第 3 第 4 个像素,第 3 个字节的高位存储第 5 个像素,后面填充 0 ,因为图像的一行在保存时字节数必须为 4 的倍数,后面再填充 1 个字节。-
0x7a ~ 0x7d
4 个字节,存储图像的第 2 行 0x8a ~ 0x8d
4 个字节,存储图像的第 6 行
256色图像
这后面有一个很小的 BMP 256色图 [图片上传失败...(image-78d072-1572484665335)]
放大后显示为:
其文件内容为(全部以16进制表示):
Offset | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 42 | 4d | 66 | 04 | 00 | 00 | 00 | 00 | 00 | 00 | 36 | 04 | 00 | 00 | 28 | 00 |
0x0010 | 00 | 00 | 05 | 00 | 00 | 00 | 06 | 00 | 00 | 00 | 01 | 00 | 08 | 00 | 00 | 00 |
0x0020 | 00 | 00 | 30 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
0x0030 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 80 | 00 | 00 | 80 |
0x0040 | 00 | 00 | 00 | 80 | 80 | 00 | 80 | 00 | 00 | 00 | 80 | 00 | 80 | 00 | 80 | 80 |
0x0050 | 00 | 00 | c0 | c0 | c0 | 00 | c0 | dc | c0 | 00 | f0 | ca | a6 | 00 | 00 | 20 |
0x0060 | 40 | 00 | 00 | 20 | 60 | 00 | 00 | 20 | 80 | 00 | 00 | 20 | a0 | 00 | 00 | 20 |
0x0070 | c0 | 00 | 00 | 20 | e0 | 00 | 00 | 40 | 00 | 00 | 00 | 40 | 20 | 00 | 00 | 40 |
0x0080 | 40 | 00 | 00 | 40 | 60 | 00 | 00 | 40 | 80 | 00 | 00 | 40 | a0 | 00 | 00 | 40 |
0x0090 | c0 | 00 | 00 | 40 | e0 | 00 | 00 | 60 | 00 | 00 | 00 | 60 | 20 | 00 | 00 | 60 |
0x00a0 | 40 | 00 | 00 | 60 | 60 | 00 | 00 | 60 | 80 | 00 | 00 | 60 | a0 | 00 | 00 | 60 |
0x00b0 | c0 | 00 | 00 | 60 | e0 | 00 | 00 | 80 | 00 | 00 | 00 | 80 | 20 | 00 | 00 | 80 |
0x00c0 | 40 | 00 | 00 | 80 | 60 | 00 | 00 | 80 | 80 | 00 | 00 | 80 | a0 | 00 | 00 | 80 |
0x00d0 | c0 | 00 | 00 | 80 | e0 | 00 | 00 | a0 | 00 | 00 | 00 | a0 | 20 | 00 | 00 | a0 |
0x00e0 | 40 | 00 | 00 | a0 | 60 | 00 | 00 | a0 | 80 | 00 | 00 | a0 | a0 | 00 | 00 | a0 |
0x00f0 | c0 | 00 | 00 | a0 | e0 | 00 | 00 | c0 | 00 | 00 | 00 | c0 | 20 | 00 | 00 | c0 |
0x0100 | 40 | 00 | 00 | c0 | 60 | 00 | 00 | c0 | 80 | 00 | 00 | c0 | a0 | 00 | 00 | c0 |
0x0110 | c0 | 00 | 00 | c0 | e0 | 00 | 00 | e0 | 00 | 00 | 00 | e0 | 20 | 00 | 00 | e0 |
0x0120 | 40 | 00 | 00 | e0 | 60 | 00 | 00 | e0 | 80 | 00 | 00 | e0 | a0 | 00 | 00 | e0 |
0x0130 | c0 | 00 | 00 | e0 | e0 | 00 | 40 | 00 | 00 | 00 | 40 | 00 | 20 | 00 | 40 | 00 |
0x0140 | 40 | 00 | 40 | 00 | 60 | 00 | 40 | 00 | 80 | 00 | 40 | 00 | a0 | 00 | 40 | 00 |
0x0150 | c0 | 00 | 40 | 00 | e0 | 00 | 40 | 20 | 00 | 00 | 40 | 20 | 20 | 00 | 40 | 20 |
0x0160 | 40 | 00 | 40 | 20 | 60 | 00 | 40 | 20 | 80 | 00 | 40 | 20 | a0 | 00 | 40 | 20 |
0x0170 | c0 | 00 | 40 | 20 | e0 | 00 | 40 | 40 | 00 | 00 | 40 | 40 | 20 | 00 | 40 | 40 |
0x0180 | 40 | 00 | 40 | 40 | 60 | 00 | 40 | 40 | 80 | 00 | 40 | 40 | a0 | 00 | 40 | 40 |
0x0190 | c0 | 00 | 40 | 40 | e0 | 00 | 40 | 60 | 00 | 00 | 40 | 60 | 20 | 00 | 40 | 60 |
0x01a0 | 40 | 00 | 40 | 60 | 60 | 00 | 40 | 60 | 80 | 00 | 40 | 60 | a0 | 00 | 40 | 60 |
0x01b0 | c0 | 00 | 40 | 60 | e0 | 00 | 40 | 80 | 00 | 00 | 40 | 80 | 20 | 00 | 40 | 80 |
0x01c0 | 40 | 00 | 40 | 80 | 60 | 00 | 40 | 80 | 80 | 00 | 40 | 80 | a0 | 00 | 40 | 80 |
0x01d0 | c0 | 00 | 40 | 80 | e0 | 00 | 40 | a0 | 00 | 00 | 40 | a0 | 20 | 00 | 40 | a0 |
0x01e0 | 40 | 00 | 40 | a0 | 60 | 00 | 40 | a0 | 80 | 00 | 40 | a0 | a0 | 00 | 40 | a0 |
0x01f0 | c0 | 00 | 40 | a0 | e0 | 00 | 40 | c0 | 00 | 00 | 40 | c0 | 20 | 00 | 40 | c0 |
0x0200 | 40 | 00 | 40 | c0 | 60 | 00 | 40 | c0 | 80 | 00 | 40 | c0 | a0 | 00 | 40 | c0 |
0x0210 | c0 | 00 | 40 | c0 | e0 | 00 | 40 | e0 | 00 | 00 | 40 | e0 | 20 | 00 | 40 | e0 |
0x0220 | 40 | 00 | 40 | e0 | 60 | 00 | 40 | e0 | 80 | 00 | 40 | e0 | a0 | 00 | 40 | e0 |
0x0230 | c0 | 00 | 40 | e0 | e0 | 00 | 80 | 00 | 00 | 00 | 80 | 00 | 20 | 00 | 80 | 00 |
0x0240 | 40 | 00 | 80 | 00 | 60 | 00 | 80 | 00 | 80 | 00 | 80 | 00 | a0 | 00 | 80 | 00 |
0x0250 | c0 | 00 | 80 | 00 | e0 | 00 | 80 | 20 | 00 | 00 | 80 | 20 | 20 | 00 | 80 | 20 |
0x0260 | 40 | 00 | 80 | 20 | 60 | 00 | 80 | 20 | 80 | 00 | 80 | 20 | a0 | 00 | 80 | 20 |
0x0270 | c0 | 00 | 80 | 20 | e0 | 00 | 80 | 40 | 00 | 00 | 80 | 40 | 20 | 00 | 80 | 40 |
0x0280 | 40 | 00 | 80 | 40 | 60 | 00 | 80 | 40 | 80 | 00 | 80 | 40 | a0 | 00 | 80 | 40 |
0x0290 | c0 | 00 | 80 | 40 | e0 | 00 | 80 | 60 | 00 | 00 | 80 | 60 | 20 | 00 | 80 | 60 |
0x02a0 | 40 | 00 | 80 | 60 | 60 | 00 | 80 | 60 | 80 | 00 | 80 | 60 | a0 | 00 | 80 | 60 |
0x02b0 | c0 | 00 | 80 | 60 | e0 | 00 | 80 | 80 | 00 | 00 | 80 | 80 | 20 | 00 | 80 | 80 |
0x02c0 | 40 | 00 | 80 | 80 | 60 | 00 | 80 | 80 | 80 | 00 | 80 | 80 | a0 | 00 | 80 | 80 |
0x02d0 | c0 | 00 | 80 | 80 | e0 | 00 | 80 | a0 | 00 | 00 | 80 | a0 | 20 | 00 | 80 | a0 |
0x02e0 | 40 | 00 | 80 | a0 | 60 | 00 | 80 | a0 | 80 | 00 | 80 | a0 | a0 | 00 | 80 | a0 |
0x02f0 | c0 | 00 | 80 | a0 | e0 | 00 | 80 | c0 | 00 | 00 | 80 | c0 | 20 | 00 | 80 | c0 |
0x0300 | 40 | 00 | 80 | c0 | 60 | 00 | 80 | c0 | 80 | 00 | 80 | c0 | a0 | 00 | 80 | c0 |
0x0310 | c0 | 00 | 80 | c0 | e0 | 00 | 80 | e0 | 00 | 00 | 80 | e0 | 20 | 00 | 80 | e0 |
0x0320 | 40 | 00 | 80 | e0 | 60 | 00 | 80 | e0 | 80 | 00 | 80 | e0 | a0 | 00 | 80 | e0 |
0x0330 | c0 | 00 | 80 | e0 | e0 | 00 | c0 | 00 | 00 | 00 | c0 | 00 | 20 | 00 | c0 | 00 |
0x0340 | 40 | 00 | c0 | 00 | 60 | 00 | c0 | 00 | 80 | 00 | c0 | 00 | a0 | 00 | c0 | 00 |
0x0350 | c0 | 00 | c0 | 00 | e0 | 00 | c0 | 20 | 00 | 00 | c0 | 20 | 20 | 00 | c0 | 20 |
0x0360 | 40 | 00 | c0 | 20 | 60 | 00 | c0 | 20 | 80 | 00 | c0 | 20 | a0 | 00 | c0 | 20 |
0x0370 | c0 | 00 | c0 | 20 | e0 | 00 | c0 | 40 | 00 | 00 | c0 | 40 | 20 | 00 | c0 | 40 |
0x0380 | 40 | 00 | c0 | 40 | 60 | 00 | c0 | 40 | 80 | 00 | c0 | 40 | a0 | 00 | c0 | 40 |
0x0390 | c0 | 00 | c0 | 40 | e0 | 00 | c0 | 60 | 00 | 00 | c0 | 60 | 20 | 00 | c0 | 60 |
0x03a0 | 40 | 00 | c0 | 60 | 60 | 00 | c0 | 60 | 80 | 00 | c0 | 60 | a0 | 00 | c0 | 60 |
0x03b0 | c0 | 00 | c0 | 60 | e0 | 00 | c0 | 80 | 00 | 00 | c0 | 80 | 20 | 00 | c0 | 80 |
0x03c0 | 40 | 00 | c0 | 80 | 60 | 00 | c0 | 80 | 80 | 00 | c0 | 80 | a0 | 00 | c0 | 80 |
0x03d0 | c0 | 00 | c0 | 80 | e0 | 00 | c0 | a0 | 00 | 00 | c0 | a0 | 20 | 00 | c0 | a0 |
0x03e0 | 40 | 00 | c0 | a0 | 60 | 00 | c0 | a0 | 80 | 00 | c0 | a0 | a0 | 00 | c0 | a0 |
0x03f0 | c0 | 00 | c0 | a0 | e0 | 00 | c0 | c0 | 00 | 00 | c0 | c0 | 20 | 00 | c0 | c0 |
0x0400 | 40 | 00 | c0 | c0 | 60 | 00 | c0 | c0 | 80 | 00 | c0 | c0 | a0 | 00 | f0 | fb |
0x0410 | ff | 00 | a4 | a0 | a0 | 00 | 80 | 80 | 80 | 00 | 00 | 00 | ff | 00 | 00 | ff |
0x0420 | 00 | 00 | 00 | ff | ff | 00 | ff | 00 | 00 | 00 | ff | 00 | ff | 00 | ff | ff |
0x0430 | 00 | 00 | ff | ff | ff | 00 | ef | ef | ef | 67 | ef | 00 | 00 | 00 | ff | ff |
0x0440 | 6f | 6f | 79 | 00 | 00 | 00 | fc | fc | 7a | fa | fa | 00 | 00 | 00 | db | d2 |
0x0450 | fc | d2 | b4 | 00 | 00 | 00 | 7f | fb | 7f | b3 | 71 | 00 | 00 | 00 | 52 | 52 |
0x0460 | 5f | 4f | 4f | 00 | 00 | 00 |
对其进行解析:
-
0x00 ~ 0x0d
14 字节,位图文件头0x00 ~ 0x01
2 字节,文件头最开头两字节为字符 "BM"0x02 ~ 0x05
4 字节,为 BMP 文件的大小,此处值为 0x0466 = 1126, 由实际查看可知其文件 确实为 1126 字节大小0x06 ~ 0x07
2 字节,保留字节,此处为 00x08 ~ 0x09
2 字节,保留自己,此处为 00x0a ~ 0x0d
4 字节,位图数据的地址,此处为 0x0436, 表示实际的像素在 0x0436 处开始存储。
0x0e ~ 0x11
4 字节,DIB表头的大小(字节数),此处值为 0x28 = 40, 可以由此得知,此文件使用的 DIB 头版本为 BITMAPINFOHEADER, 由此我们可确定 从 0x0e ~ 0x35 的内容为 DIB 头-
0x0e ~ 0x35
40 字节,DIB 头0x0e ~ 0x11
4 字节,DIB表头的大小(字节数),此处值为 0x28 = 400x12 ~ 0x15
4 字节,位图宽度,单位为像素(有符号整数),此处为 50x16 ~ 0x19
4 字节,位图高度,单位为像素(有符号整数),此处为 60x1A ~ 0x1B
2 字节,色彩平面数,必须为 1,此处为 10x1C ~ 0x1D
2 字节,每个像素所占位数,此处为 8, 表示每个像素由 8 个bit位存储0x1E ~ 0x21
4 字节,所使用的压缩方法,此处为 0 ,表示无压缩0x22 ~ 0x25
4 个字节,图像大小。指原始位图数据的大小。此处为 0x30 = 48,此值为实际存储像素时占用的字节数。本图像为 6 行,每行 5 个像素,每个像素使用 1 个字节,因为每行存储字节必须为 4 的倍数,所以每行使用 8 个字节,像素共占用 6*8=48 个字节0x26 ~ 0x29
4 个字节,图像的横向分辨率,此处为 00x2A ~ 0x2D
4 个字节,图像的纵向分辨率,此处为 00x2E ~ 0x31
4 个字节,调色板的颜色数,为0时表示颜色数为默认的 个。此处为 0 ,表示调色板有 个0x32 ~ 0x35
4 个字节,重要颜色数。此处为 0
-
0x36 ~ 0x0435
1024 个字节,调色板。由上面可知,调色板条目数量为 256 ,每个条目占 4 个字节,所以调色板一共占 1024 个字节0x36 ~ 0x39
4 个字节,调色板第 1 个颜色,此处值全为 0, 由调色板的定义可知,此处表示RGB全为0的颜色,即黑色0x3a ~ 0x3d
4个字节,调色板的第 2 个颜色,此处值为 0x00, 0x00, 0x80, 0x00, 由调色板的定义可知,表示BGR分别为 0、0、128 的颜色-
0x3e ~ 0x41
4个字节,调色板的第 3 个颜色,此处值为 0x00, 0x80, 0x00, 0x00, 由调色板的定义可知,表示BGR分别为 0、128、0 的颜色
0x0432 ~ 0x0435
4个字节,调色板的第 256 个颜色,此处值为 0xff, 0xff, 0xff, 0x00, 由调色板的定义可知,表示BGR分别为 255、255、255 的颜色,即白色
-
0x0436 ~ 0x465
48 个字节,此处储存实际的图像像素点0x436 ~ 0x43d
8 个字节,存储图像的第一行,图像为 8 bbp 的图像,每 8 个 bit 位保存一个像素,即每个字节保存一个像素,0x436 的值 0xef,表示第一行的第 1 个像素颜色为调色板中的第 240 个颜色,BRG 分别为 192、160、224 的颜色,第 2 个像素其颜色索引为 0x437 的值,也是 0xef。后面的字节依次存储第 3 、4、5个像素的颜色索引。因为图像的一行在保存时字节数必须为 4 的倍数,后面再填充 3 个字节。-
0x43e ~ 0x445
8 个字节,存储图像的第 2 行 0x45e ~ 0x465
8 个字节,存储图像的第 6 行
24位图像
这后面有一个很小的 BMP 24位图 [站外图片上传中...(image-7c27fb-1572484665335)]
放大后显示为:
其文件内容为(全部以16进制表示):
Offset | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x00 | 42 | 4d | 96 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 36 | 00 | 00 | 00 | 28 | 00 |
0x10 | 00 | 00 | 05 | 00 | 00 | 00 | 06 | 00 | 00 | 00 | 01 | 00 | 18 | 00 | 00 | 00 |
0x20 | 00 | 00 | 60 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
0x30 | 00 | 00 | 00 | 00 | 00 | 00 | d7 | c3 | ff | c9 | ae | ff | c9 | ae | ff | 3b |
0x40 | 85 | ff | d7 | c3 | ff | 00 | ff | ff | ff | ff | ff | ff | 5d | 9f | ff | 50 |
0x50 | 97 | ff | 20 | ff | 20 | 00 | ff | 10 | 10 | ff | 10 | 10 | 40 | ff | 40 | 00 |
0x60 | ff | 00 | 10 | f1 | 09 | 00 | ff | 60 | 60 | ff | 30 | 30 | ff | 00 | 00 | ff |
0x70 | 40 | 40 | 90 | cf | 75 | 00 | 40 | f6 | ff | 00 | f2 | ff | 40 | f6 | ff | 79 |
0x80 | c5 | 5a | 4c | b1 | 22 | 00 | 40 | 40 | 40 | 40 | 40 | 40 | 5b | 55 | f2 | 24 |
0x90 | 1c | ed | 24 | 1c | ed | 00 |
对其进行解析:
-
0x00 ~ 0x0d
14 字节,位图文件头0x00 ~ 0x01
2 字节,文件头最开头两字节为字符 "BM"0x02 ~ 0x05
4 字节,为 BMP 文件的大小,此处值为 0x96 = 150, 由实际查看可知其文件 确实为 150 字节大小0x06 ~ 0x07
2 字节,保留字节,此处为 00x08 ~ 0x09
2 字节,保留自己,此处为 00x0a ~ 0x0d
4 字节,位图数据的地址,此处为 0x36, 表示实际的像素在 0x36 处开始存储。
0x0e ~ 0x11
4 字节,DIB表头的大小(字节数),此处值为 0x28 = 40, 可以由此得知,此文件使用的 DIB 头版本为 BITMAPINFOHEADER, 由此我们可确定 从 0x0e ~ 0x35 的内容为 DIB 头-
0x0e ~ 0x35
40 字节,DIB 头0x0e ~ 0x11
4 字节,DIB表头的大小(字节数),此处值为 0x28 = 400x12 ~ 0x15
4 字节,位图宽度,单位为像素(有符号整数),此处为 50x16 ~ 0x19
4 字节,位图高度,单位为像素(有符号整数),此处为 60x1A ~ 0x1B
2 字节,色彩平面数,必须为 1,此处为 10x1C ~ 0x1D
2 字节,每个像素所占位数,此处为 0x18=24, 表示每个像素由 24 个bit位存储0x1E ~ 0x21
4 字节,所使用的压缩方法,此处为 0 ,表示无压缩0x22 ~ 0x25
4 个字节,图像大小。指原始位图数据的大小。此处为 0x60 = 96,此值为实际存储像素时占用的字节数。本图像为 6 行,每行 5 个像素,每个像素使用 3 个字节,因为每行存储字节必须为 4 的倍数,所以每行使用 16 个字节,像素共占用 6*16=96 个字节0x26 ~ 0x29
4 个字节,图像的横向分辨率,此处为 00x2A ~ 0x2D
4 个字节,图像的纵向分辨率,此处为 00x2E ~ 0x31
4 个字节,调色板的颜色数,此处为 0, 24位图像不使用调色板0x32 ~ 0x35
4 个字节,重要颜色数。此处为 0
-
0x36 ~ 0x95
96 个字节,此处储存实际的图像像素点0x36 ~ 0x45
16 个字节,存储图像的第一行,图像为 24 bbp 的图像,每 24 个 bit 位保存一个像素,即每 3 个字节保存一个像素,0x36 ~ 0x38 的值 0xd7 0xc3 0x ff,表示第一行的第 1 个像素颜色 BRG 分别为 215、195、255 的颜色。后面的字节依次存储第 2、3 、4、5个像素的颜色索引。因为图像的一行在保存时字节数必须为 4 的倍数,后面再填充 1 个字节。-
0x46 ~ 0x55
16 个字节,存储图像的第 2 行 0x86 ~ 0x95
8 个字节,存储图像的第 6 行
例子中的图片可能无法显示,可以在这里 百度云 存储图片 中找到
雷震西山 2019年10月31日