1 概述
BMP(Bitmap-File)图片文件格式,又称为 Bitmap (位图)或是 DIB(Device-Independent Device,设备无关位图),是 Windows 系统中广泛使用的图像文件格式。
由于它可以不作任何变换的保存图像像素域的数据,因此成为我们取得 RAW 数据的重要来源。Windows 的图形用户界面(graphical user interfaces)也在它的内建图像子系统 GDI 中对 BMP 格式提供了支持。
BMP 位图文件默认的文件扩展名是 BMP 或者 bmp(有时它也会以 .DIB 或 .RLE 作扩展名)
2 BMP 文件结构
BMP 文件的数据按照从文件头开始的先后顺序分为四个部分:
- 位图文件头(bmp file header): 提供文件的格式、大小等信息
- 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息
- 调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表
- 位图数据(bitmap data):图像数据区
一个常见的 BMP 文件数据表如下:
数据段名称 | 大小(byte) |
---|---|
位图文件头 | 14 |
位图信息头 | 40 |
调色板 | 由 biBitCount 决定 |
位图数据 | 由图片大小和颜色决定 |
2.1 位图文件头
Windows 为 bmp 位图文件图定义了如下的结构体:
typedef struct tagBITMAPFILEHEADER {
UINT16 bfType; // 2 Bytes,文件类型,必须为 "BM",即 0x424D
DWORD bfSize; // 4 Bytes,整个 BMP 文件的大小,单位为字节
UINT16 bfReserved1; // 2 Bytes,保留位置为 0
UINT16 bfReserved2; // 2 Bytes,保留位置为 0
DWORD bfOffBits; // 4 Bytes,文件起始位置到图像位图数据的字节偏移量
} BITMAPFILEHEADER;
以下面普通 24 位位图为例:
以字节向后数:
- 前 1-2 字节:0x424d = ‘BM’,表示这是 Windows 支持的位图格式
- 3 - 6 字节:BMP 图片为小端方式存储,0x002A3036 = 2764854 kb ≈ 2.6M
- 7 - 10 字节:保留为,置为 0
- 11 - 14:0x00000036 = 54,实例 BMP 文件没有调色板,从文件头到位图数据偏移 54 个字节
2.2 位图信息头
位图信息头一般为 40 个字节,各字段含义如表格所示:
变量名 | 大小 | 说明 |
---|---|---|
biSize | 4 Bytes | BMP_INFOHEADER 表示所需要的字节数(以字节为单位) |
biWidth | 4 Bytes | 说明图像的宽度(以像素为单位) |
biHeight | 4 Bytes | 说明图像的高度(以像素为单位) |
biPlanes | 2 Bytes | 为目标设备说明位面数,其值总设置为 1 |
biBitCount | 2 Bytes | 一个像素点占几位,其值可为 1、4、8、16、24 或 32 |
biCompression | 4 Bytes | 图像数据的压缩类型,详解见表后 |
biSizeImage | 4 Bytes | 图像的大小,与压缩类型相关,见下文 |
biXPelsPerMeter | 4 Bytes | 水平分辨率 |
biYPelsPerMeter | 4 Bytes | 垂直分辨率 |
biClrUsed | 4 Bytes | 位图实际使用的调色板索引数,0 表示使用所有的调色板索引 |
biClrImportant | 4 Bytes | 对图像显示有重要影响的颜色索引的数目,如果是 0 表示都重要。 |
biCompression 图像数据的压缩类型
取值范围为:
- BI_RGB 不压缩(最常用)
- BI_RLE8 8 比特游程编码(BLE),只用于 8 位位图
- BI_RLE4 4 比特游程编码(BLE),只用于 4 位位图
- BI_BITFIELDS 比特域(BLE),只用于 16/32 位位图
- BI_JPEG 位图包含 JPEG,只用于打印机
- BI_PNG 位图包含 PNG,只用于打印机
biSizeImage 图像大小与压缩类型相关,当压缩类型为 BI_RGB 不压缩时为 0
以下面的实例分析位图信息头,见蓝色部分:
- 1 - 4 字节:0x00000028 = 40 字节,表示该位图信息头占用 40 个字节。
- 5 - 8 字节:位图宽度为 0x00000500 = 1280 像素
- 9 - 12 字节:位图高度为 0x000002D0 = 720 像素
- 13 - 14 字节:biPlanes,0x0001 值总为 1
- 15 - 16 字节:biBitCount,0x0018 = 24,说明一个像素占用 24 字节,为 24 位位图
- 17 - 20 字节:biCompression,0x00000000 = 0 ,0 表示本图像不压缩
- 21 - 24 字节:biSizeImage,图像大小,因为使用 BI_RGB 不压缩所以值为 0
- 25 - 28 字节:水平分辨率,缺省
- 29 - 32 字节:垂直分辨率,缺省
- 33 - 36 字节:biClrUsed,0 表示使用所有的调色板索引
- 37 - 40 字节:biClrImportant,表示所有颜色索引都重要
2.3 调色板
BMP 调色板结构体可以定义如下:
typedef struct _tagRGBQUAD
{
BYTE rgbBlue; // 指定蓝色强度
BYTE rgbGreen; // 指定绿色强度
BYTE rgbRed; // 指定红色强度
BYTE rgbReserved; // 保留,设置为0
} RGBQUAD;
调色板其实是一张映射表,标识颜色索引号与其代表的颜色的对应关系。它在文件中的布局就像一个二维数组 palette[N][4],其中 N 表示总的颜色索引数,每行的四个元素分别表示该索引对应的 B、G、R 和 Alpha 的值,每个分量占一个字节。如不设透明通道时,Alpha 为 0。
2.4 BMP 位图数据
位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:
- 当 biBitCount = 1 时,8 个像素占 1 个字节;
- 当 biBitCount = 4 时,2 个像素占 1 个字节;
- 当 biBitCount = 8 时,1 个像素占 1 个字节;
- 当 biBitCount = 24 时, 1 个像素占 3 个字节;
当扫描取到一个字节后,以该字节为索引查询相应的颜色,并显示到相应的显示设备上即可。
位图的高度为负数时,扫描顺序相反,从右到左,从上到下,即从右上角扫描到左下角。