BMP 文件格式

如题所述

第1个回答  2022-07-23

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

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

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

这部分数据块位于文件开头,共 14 字节,用于进行文件的识别。典型的应用程序会首先普通读取这部分数据以确保的确是位图文件并且没有损坏。所有的整数值都以小端序(little-endian)存放(即最低有效位前置)。

这部分告诉应用程序图像的详细信息,在屏幕上显示图像将会使用这些信息,它从文件的第15个字节开始。

这部分数据块对应了Windows和OS/2中的内部使用的头结构以及其它一些版本的变体。但所有版本均以一个DWORD位(32位)开始,用以说明该数据块的大小,使得应用程序能够根据这个大小来区分该图像实际使用了哪种版本的DIB头结构。

存在多种版本的头结构的原因是微软对DIB格式进行过多次扩展。下表即为所有不同版本的DIB头:

BITMAPCOREHEADER之后的版本都只是在前一版本结构末尾追加字段。

下面我们对比较常见的两个版本进行说明

DIB 头从地址 0x0E 开始,下面列出 BITMAPCOREHEADER 版本的 DIB 头。除非有特殊说明,其中所有值均为无符号整数。

注意:

出于兼容性的考量,大多数应用程序使用较旧版本的DIB头保存文件。由于 Windows 2000 之后不再支持 OS/2, 因此目前常见的Windows格式是 BITMAPINFOHEADER 标头。下表对其进行说明,除非有特殊说明,其中所有值均为无符号整数。

压缩方法(字节 0x1E ~ 0x21)的有效值如下表所示:

注意:BI_JPEG和BI_PNG仅对打印机驱动有效,不支持屏幕渲染。

此项仅在DIB头是BITMAPINFOHEADER且Compression Method成员设置为BI_BITFIELDS或BI_ALPHABITFIELDS的情况下存在。
见本文的最后部分

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

调色板的条目数为 (n为 DIB 头中指定的的每个像素所占位数) 或 DIB 头中指定的调色板的颜色数。

典型的位图文件使用RGB彩色模型。大多数情况下,调色板的每个条目占 4 个字节,按顺序表示 蓝色、绿色、红色、0x00。每个条目的格式如下:

其中,第四个字节一般没有使用(大多数应用程序将它设为0),也有些应用程序将第四个字节作为 alfa 通道使用。

调色板是一个字节块(一个表),列出了图像使用的颜色。对于索引型的位图(每个像素所占位数为1、4 或 8),调色板的作用是告诉应用程序,像素的实际颜色,此时,像素点存储的值为此调色板中此像素颜色的索引,根据索引得到像素点真实的颜色。对于非索引型的位图,调色板的作用是列出位图中使用的颜色,以优化具有有限颜色显示功能的设备,并便于将来转换为不同的像素格式和着色。

如上所述,当像素采用每像素16位或更高时,通常不使用调色板。

位图中的像素是以行为单位进行存储的,每一行再存储时都以 4 字节对齐,即每一行的大小都向上取整为 4 字节(32 位 DWORD)的倍数。如果图像的高度大于 1, 多个经过填充实现对齐的行就形成了像素数组。

所以存储一行像素所需的字节数,可以通过以下公式计算:

RowSize单位为字节,ImageWidth单位为像素;注意公式中的特殊括号,表示向上、向下取整

像素阵列是一个32位DWORD块,它逐像素描述图像,每个像素使用 1 个或多个自己表示。

通常,像素是从下到上、从左到右保存的。但如果使用的不是 BITMAPCOREHEADER, 那么未压缩的 Windows 位图还可以从上到下存储,此时图像高度为负值。

每一行的末尾通过填充若干个字节的数据(并不一定为0)使该行的长度为4字节的倍数。像素数组读入内存后,每一行的起始地址必须为4的倍数。这个限制仅针对内存中的像素数组,针对存储时,仅要求每一行的大小为4字节的倍数,对文件的偏移地址没有限制。

例如:对于24位色的位图,如果它的宽度为1像素,那么除了每一行的数据(蓝、绿、红)需要占3字节外,还会填充1字节;而如果宽为2像素,则需要2字节的填充;宽为3像素时,需要3字节填充;宽为4像素时则不需要填充。

此处的单位 bbp 为 (bit/pixel), 位每像素

为了解决哪些位定义了哪些样本的歧义,DIB标头提供了某些默认值以及特定的BITFIELDS,它们是位掩码,用于定义像素中特定位组到特定通道的成员资格。下图定义了此机制:

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

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

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

放大后显示为:

其文件内容为(全部以16进制表示):

对其进行解析:

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

放大后显示为:

其文件内容为(全部以16进制表示):

对其进行解析:

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

放大后显示为:

其文件内容为(全部以16进制表示):