BMP 文件格式

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 格式的文件。

文件结构

位图图像文件由固定大小的结构(文件头)以及以预定顺序出现的可变大小的结构体组成。由于该文件格式几经演进,这些结构体的版本也很多。

位图图像的文件结构.jpg

参考上图,位图文件由以下结构依次构成:

结构体名称 可选 大小 用途 备注
位图文件头
(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时表示颜色数为默认的 2^{色深}
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的情况下存在。
见本文的最后部分

四、调色板

这部分定义了图像中所用的颜色。如上所述,位图图像一个像素接着一个像素储存,每个像素使用一个或者多个字节的值表示,所以调色板的目的就是要告诉应用程序这些值所对应的实际颜色。

调色板的条目数为 2^n(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=\left\lceil \frac{BitsPerPixel \cdot ImageWidth}{32} \right\rceil \cdot 4 = \left\lfloor \frac{BitsPerPixel \cdot ImageWidth + 31}{32} \right\rfloor \cdot 4
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,它们是位掩码,用于定义像素中特定位组到特定通道的成员资格。下图定义了此机制:

32位像素的BITFIELDS机制

BITFIELDS位掩码定义的样本字段必须是连续且不重叠的,但是样本字段的顺序是任意的。最普遍的场序是:Alpha,Blue,Green,Red(MSB到LSB)。仅当DIB标头的Compression成员设置为BI_BITFIELDS时,红色,绿色和蓝色位掩码才有效。只要在DIB标头中存在或将DIB标头的Compression成员设置为BI_ALPHABITFIELDS [5](仅Windows CE),alpha位掩码就有效。

16位像素的BITFIELDS机制
DIB中所有可能的像素格式

BMP 文件例子解析

使用画图软件绘制图像为 bmp 格式,下面是一些例子:

单色图像

这后面有一个很小的BMP单色图 \rightarrow [图片上传失败...(image-fd91f4-1572484665335)]

放大后显示为:

BMP单色例子截图

其文件内容为(全部以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 字节,保留字节,此处为 0

    • 0x08 ~ 0x09
      2 字节,保留自己,此处为 0

    • 0x0a ~ 0x0d
      4 字节,位图数据的地址,此处为 0x3e, 表示实际的像素在 0x3e 处开始存储。

  • 0x0e ~ 0x11
    4 字节,DIB表头的大小(字节数),此处值为 0x28 = 40, 可以由此得知,此文件使用的 DIB 头版本为 BITMAPINFOHEADER, 由此我们可确定 从 0x0e ~ 0x35 的内容为 DIB 头

  • 0x0e ~ 0x35
    40 字节,DIB 头

    • 0x0e ~ 0x11
      4 字节,DIB表头的大小(字节数),此处值为 0x28 = 40

    • 0x12 ~ 0x15
      4 字节,位图宽度,单位为像素(有符号整数),此处为 5

    • 0x16 ~ 0x19
      4 字节,位图高度,单位为像素(有符号整数),此处为 6

    • 0x1A ~ 0x1B
      2 字节,色彩平面数,必须为 1,此处为 1

    • 0x1C ~ 0x1D
      2 字节,每个像素所占位数,此处为 1

    • 0x1E ~ 0x21
      4 字节,所使用的压缩方法,此处为 0 ,表示无压缩

    • 0x22 ~ 0x25
      4 个字节,图像大小。指原始位图数据的大小。此处为 0x18 = 24,此值为实际存储像素时占用的字节数。本图像为 6 行,每行占用 4 个字节,像素共占用 24 个字节

    • 0x26 ~ 0x29
      4 个字节,图像的横向分辨率,此处为 0

    • 0x2A ~ 0x2D
      4 个字节,图像的纵向分辨率,此处为 0

    • 0x2E ~ 0x31
      4 个字节,调色板的颜色数,为0时表示颜色数为默认的 2^n 个。此处为 0 ,表示调色板有 2^1 = 2

    • 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的颜色,即白色
  • 0x3e ~ 0x55
    24 个字节,此处储存实际的图像像素点

    • 0x3e ~ 0x41
      4 个字节,存储图像的第一行,图像为 1 bbp 的图像,每个 bit 位保存一个像素,0x3e 的值 0xf8 = 11111000b 即第一行的第 1 个像素颜色为调色板中的第二个颜色为白色,第 2 个像素也为白色……第 5 个像素为白色,此图像一行只有 5 个像素,后面填充 0 ,因为图像的一行在保存时字节数必须为 4 的倍数,后面再填充 3 个字节。

    • 0x42 ~ 0x45
      4 个字节,存储图像的第 2 行

      \vdots

    • 0x52 ~ 0x55
      4 个字节,存储图像的第 6 行

16色图像

这后面有一个很小的 BMP 16色图 \rightarrow [图片上传失败...(image-887bb6-1572484665335)]

放大后显示为:

BMP16色例子截图

其文件内容为(全部以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 字节,保留字节,此处为 0

    • 0x08 ~ 0x09
      2 字节,保留自己,此处为 0

    • 0x0a ~ 0x0d
      4 字节,位图数据的地址,此处为 0x76, 表示实际的像素在 0x76 处开始存储。

  • 0x0e ~ 0x11
    4 字节,DIB表头的大小(字节数),此处值为 0x28 = 40, 可以由此得知,此文件使用的 DIB 头版本为 BITMAPINFOHEADER, 由此我们可确定 从 0x0e ~ 0x35 的内容为 DIB 头

  • 0x0e ~ 0x35
    40 字节,DIB 头

    • 0x0e ~ 0x11
      4 字节,DIB表头的大小(字节数),此处值为 0x28 = 40

    • 0x12 ~ 0x15
      4 字节,位图宽度,单位为像素(有符号整数),此处为 5

    • 0x16 ~ 0x19
      4 字节,位图高度,单位为像素(有符号整数),此处为 6

    • 0x1A ~ 0x1B
      2 字节,色彩平面数,必须为 1,此处为 1

    • 0x1C ~ 0x1D
      2 字节,每个像素所占位数,此处为 4, 表示每个像素由 4 个bit位存储

    • 0x1E ~ 0x21
      4 字节,所使用的压缩方法,此处为 0 ,表示无压缩

    • 0x22 ~ 0x25
      4 个字节,图像大小。指原始位图数据的大小。此处为 0x18 = 24,此值为实际存储像素时占用的字节数。本图像为 6 行,每行占用 4 个字节,像素共占用 24 个字节

    • 0x26 ~ 0x29
      4 个字节,图像的横向分辨率,此处为 0

    • 0x2A ~ 0x2D
      4 个字节,图像的纵向分辨率,此处为 0

    • 0x2E ~ 0x31
      4 个字节,调色板的颜色数,为0时表示颜色数为默认的 2^n 个。此处为 0 ,表示调色板有 2^4 = 16

    • 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 的颜色

      \vdots
      \vdots

    • 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 行

      \vdots

    • 0x8a ~ 0x8d
      4 个字节,存储图像的第 6 行

256色图像

这后面有一个很小的 BMP 256色图 \rightarrow [图片上传失败...(image-78d072-1572484665335)]

放大后显示为:

BMP256色例子截图

其文件内容为(全部以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 字节,保留字节,此处为 0

    • 0x08 ~ 0x09
      2 字节,保留自己,此处为 0

    • 0x0a ~ 0x0d
      4 字节,位图数据的地址,此处为 0x0436, 表示实际的像素在 0x0436 处开始存储。

  • 0x0e ~ 0x11
    4 字节,DIB表头的大小(字节数),此处值为 0x28 = 40, 可以由此得知,此文件使用的 DIB 头版本为 BITMAPINFOHEADER, 由此我们可确定 从 0x0e ~ 0x35 的内容为 DIB 头

  • 0x0e ~ 0x35
    40 字节,DIB 头

    • 0x0e ~ 0x11
      4 字节,DIB表头的大小(字节数),此处值为 0x28 = 40

    • 0x12 ~ 0x15
      4 字节,位图宽度,单位为像素(有符号整数),此处为 5

    • 0x16 ~ 0x19
      4 字节,位图高度,单位为像素(有符号整数),此处为 6

    • 0x1A ~ 0x1B
      2 字节,色彩平面数,必须为 1,此处为 1

    • 0x1C ~ 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 个字节,图像的横向分辨率,此处为 0

    • 0x2A ~ 0x2D
      4 个字节,图像的纵向分辨率,此处为 0

    • 0x2E ~ 0x31
      4 个字节,调色板的颜色数,为0时表示颜色数为默认的 2^n 个。此处为 0 ,表示调色板有 2^8 = 256

    • 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 的颜色

      \vdots
      \vdots

    • 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 行

      \vdots

    • 0x45e ~ 0x465
      8 个字节,存储图像的第 6 行

24位图像

这后面有一个很小的 BMP 24位图 \rightarrow [站外图片上传中...(image-7c27fb-1572484665335)]

放大后显示为:

BMP24位BMP例子截图

其文件内容为(全部以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 字节,保留字节,此处为 0

    • 0x08 ~ 0x09
      2 字节,保留自己,此处为 0

    • 0x0a ~ 0x0d
      4 字节,位图数据的地址,此处为 0x36, 表示实际的像素在 0x36 处开始存储。

  • 0x0e ~ 0x11
    4 字节,DIB表头的大小(字节数),此处值为 0x28 = 40, 可以由此得知,此文件使用的 DIB 头版本为 BITMAPINFOHEADER, 由此我们可确定 从 0x0e ~ 0x35 的内容为 DIB 头

  • 0x0e ~ 0x35
    40 字节,DIB 头

    • 0x0e ~ 0x11
      4 字节,DIB表头的大小(字节数),此处值为 0x28 = 40

    • 0x12 ~ 0x15
      4 字节,位图宽度,单位为像素(有符号整数),此处为 5

    • 0x16 ~ 0x19
      4 字节,位图高度,单位为像素(有符号整数),此处为 6

    • 0x1A ~ 0x1B
      2 字节,色彩平面数,必须为 1,此处为 1

    • 0x1C ~ 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 个字节,图像的横向分辨率,此处为 0

    • 0x2A ~ 0x2D
      4 个字节,图像的纵向分辨率,此处为 0

    • 0x2E ~ 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 行

      \vdots

    • 0x86 ~ 0x95
      8 个字节,存储图像的第 6 行


例子中的图片可能无法显示,可以在这里 百度云 存储图片 中找到


雷震西山 2019年10月31日

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容