BMP图片格式
BMP 位图文件把图像尺寸、像素格式和像素数据放在同一文件中。下面以 Windows 常见的 40 字节 BITMAPINFOHEADER、24 位、BI_RGB 未压缩格式为例;调色板、位域掩码和压缩 BMP 需要按各自格式另外解析。
文件从哪里开始读
常见布局为文件头、DIB 信息头、可选颜色信息、像素数据。文件头中的 bfOffBits给出像素区相对文件起点的偏移,不能一律假定像素从第 54 字节开始。信息头也有多个版本,应先读 biSize 再决定解析方式。参见微软的位图头类型说明。

14 字节文件头
下表偏移以文件起点为零。整数按小端读取:低有效字节在前,例如 36 00 00 00 表示十进制 54。文件开头的两个字节为 42 4D,对应 ASCII 字符 BM。
| 偏移 | 大小 | 字段 | 含义 |
|---|---|---|---|
| 0 | 2 字节 | bfType | 文件标识,数值为 0x4D42 |
| 2 | 4 字节 | bfSize | 文件总大小,单位为字节 |
| 6 | 2 字节 | bfReserved1 | 保留,必须为 0 |
| 8 | 2 字节 | bfReserved2 | 保留,必须为 0 |
| 10 | 4 字节 | bfOffBits | 像素数据的起始偏移 |
字段定义见 BITMAPFILEHEADER。读取二进制文件时还要检查实际长度,不能只信任头部声明的大小。
40 字节信息头
本例信息头紧跟文件头,下表偏移仍从文件起点计算。
| 偏移 | 大小 | 字段 | 本例中的含义 |
|---|---|---|---|
| 14 | 4 字节 | biSize | 信息头本身的大小,为 40 |
| 18 | 4 字节 | biWidth | 有符号整数,图像宽度,单位为像素 |
| 22 | 4 字节 | biHeight | 有符号整数,绝对值为高度,符号决定行方向 |
| 26 | 2 字节 | biPlanes | 必须为 1 |
| 28 | 2 字节 | biBitCount | 每像素位数,本例为 24 |
| 30 | 4 字节 | biCompression | BI_RGB 为 0,表示本例像素未压缩 |
| 34 | 4 字节 | biSizeImage | 像素区大小;未压缩 RGB 允许填 0,需据尺寸计算 |
| 38、42 | 各 4 字节 | biXPelsPerMeter、biYPelsPerMeter | 水平、垂直分辨率,单位为像素/米 |
| 46、50 | 各 4 字节 | biClrUsed、biClrImportant | 使用的颜色数与重要颜色数;本例无颜色表,均为 0 |
字段与方向说明见 BITMAPINFOHEADER。24 位像素以蓝、绿、红(BGR)三个字节存储,每通道 8 位,没有独立的透明度通道。
行对齐和图像方向
24 位像素每行的有效数据是 width × 3 字节,文件中的每行要补齐到 4 字节的整数倍。补齐字节不属于下一个像素。可按下列公式计算行跨度与像素区大小:
1 | stride = ((width * 24 + 31) // 32) * 4 |
例如宽度 3、高度 2:每行像素占 9 字节,需要补 3 字节,行跨度为 12 字节,像素区共 24 字节。在本例没有额外颜色信息、像素偏移为 54 的前提下,文件总大小为 54 + 24 = 78 字节。这是按格式计算的示例值。
对本例的未压缩 RGB,biHeight > 0 表示文件先存最下面一行;biHeight < 0 表示先存最上面一行。每行内部仍从左往右排列。逐行读取时,应同时处理行跨度和高度符号,否则容易出现错行或上下颠倒。相关布局见 BITMAPINFO 的说明。
解析时核对什么
- 确认 BM 标识、信息头大小、位深与压缩类型属于解析器支持的范围。
- 确认宽度为正、高度非零,并限制允许的尺寸,检查乘法和偏移计算是否溢出。
- 确认像素偏移在头部之后且位于文件范围内,再核对
bfOffBits + pixel_bytes不超过实际文件长度。 - 不要把 24 位 BI_RGB 的 BGR 顺序、大小计算或第 54 字节的例子直接套用到调色板、压缩或其他信息头版本。