前言:在这篇笔记中,引用了别人博客之中的相关内容,在此附上相关链接,以作为参考资料。
1、BMP 文件格式详解
2、BMP 文件结构
BMP 图片编码
1、数据结构
位图文件整体通常由文件头、信息表、颜色表、图像数据四个部分的字节连续组成。其中颜色表在部分的图片文件之中,可省略。
组成 | 类型简介 |
---|---|
位图文件头(bitmapFileHeader) | 固定大小为 14 个字节,其中包含 Bmp 图片类型,以及文件大小和位图起始位置等信息 |
位图信息头(bitmapInformationHeader) | 固定大小为40个字节,用于说明位图的尺寸等信息 |
彩色表/调色板(colorTable) | 固定大小为4个字节,用于图片色彩值的映射情况(部分省略) |
位图数据(bitmapData) | 真实存储的图像数据 |
2、位图文件头
字段名 | 大小(单位:字节) | 描述 |
---|---|---|
bfType | 2 | 用于说明文件类型,Bmp 文件类型前的头两个字节指明必须是0x424D,即字符串“BM”;否则认为不是标准的 Bmp。 但在文件读取的时候,低位在前,因此其读取出来的真实数据即为:&H4D42 |
bfSize | 4 | 用于说明文件的整体大小,包括这14个字节,以字节为单位 |
bfReserved1 | 2 | 保留属性,设置为0 |
bfReserved2 | 2 | 保留属性,设置为0 |
bfOffsetBytes | 4 | 位图数据区在 Bmp 文件中的位置偏移量,此时的偏移量不得小于 54 字节(即只包含位图文件头、位图信息头),其不为固定数据常量 |
3、位图信息头
字段名 | 大小(单位:字节) | 描述 |
---|---|---|
biSize | 4 | 信息头大小,其为固定字节常量,40 |
biWidth | 4 | 指明图像宽度信息 |
biHeight | 4 | 指明图像高度信息 |
biPlanes | 2 | 位平面数,必须为1 |
biBitCount | 2 | 说明每像素的位数。常用的值为1(黑白二色图)、4(16色图)、8(256色)、24(真彩色图)或32(新的.bmp格式支持32位色) |
biCompression | 4 | 压缩类型,当值为 0 表示不压缩,1 表示RLE8压缩,2 表示RLE4压缩,3 表示每个像素值由指定的掩码决定 |
biSizeImage | 4 | 压缩图像大小字节数 biSizeImage = lineBytes(真实行字节数) × biHeight,其中 lineBytes 必须是 4 的整倍数,(不是biWidth(图像的宽度),而是lineBytes,表示大于或等于 biWidth 的,最接近 4 的整倍数) |
biXPelsPerMeter | 4 | 水平分辨率,单位是每米的象素个数 |
biYPelsPerMeter | 4 | 垂直分辨率,单位是每米的象素个数 |
biClrUsed | 4 | 位图实际用到的色彩数,如果该值为零,则用到的颜色数为2^biBitCount |
biClrImportant | 4 | 本位图中重要的色彩数,如果该值为零,则认为所有的颜色都是重要的 |
注解1:为何是 lineBytes,而不是 biWidth ?
答:操作系统默认的扫描的最小单位是 4 字节,如果数据对齐满足这个值的话,可以加快数据的获取速度。因此,BMP 图像顺应了这个要求,要求每行的数据的长度必须是 4 的倍数,如果不够需要进行比特填充(以 0 填充),这样可以达到按行的快速存取。此时,位图数据区的像素个数就未必是 图片宽 × 图片高,因为每行可能还需要进行比特填充。
注解2:lineBytes 的相关计算公式:
1、lineBytes = (biWidth * biBitCount + 31) / 32 * 4
2、解释:
①、计算未进行填充时一行数据所占的位数:biWidth * biBitCount
②、将位数转换为未对齐时一行数据所占的字节数:(biWidth * biBitCount + 7) / 8(进位取整)
③、进行计算对齐时一行数据所占的字节单元数(单位:4Byte):[(biWidth * biBitCount + 7) / 8 + 3]) / 4(同样需要进一步的进位取整,可将上述步骤②的结果值作为一个整体变量来进行运算)
④、公式整理、化简:lineBytes = (biWidth * biBitCount + 31) / 32 * 4
4、颜色表
字段名 | 大小(单位:字节) | 描述 |
---|---|---|
rgbBlue | 1 | 该颜色的蓝色分量 |
rgbGreen | 1 | 该颜色的绿色分量 |
rgbRed | 1 | 该颜色的红色分量 |
rgbAlpha | 1 | 该颜色的通明分量,当不为 32 位真彩图的时候,该值为 0 |
- 调色板其实是一张映射表,标识颜色索引号与其代表的颜色的对应关系。
- 它在文件中的布局就像一个二维数组 palette[N][4],其中N表示总的颜色索引数,每行的四个元素分别表示该索引对应的 B、G、R和 Alpha 的值,每个分量占一个字节。
- 如不设透明通道时,Alpha为0。
- 24位真彩色是无调色板部分的,位图信息头(bitBmpInfoHeader)后直接是位图数据。
5、图像数据
-
字节要求:每一行的字节数必须是4的整倍数,如果不是,则需要补齐。如 241 补齐为 244.
-
读取顺序:一般来说,BMP文件的数据从下到上,从左到右的。也就是说,从文件中最先读到的是图象最下面一行的左边第一个象素,然后是左边第二个象素……接下来是倒数第二行左边第一个象素,左边第二个象素……依次类推 ,最后得到的是最上面一行的最右一个象素。
-
存储方式:24位真彩色图,按照 B、G、R 的顺序来存储每个像素的各颜色通道的值,一个像素的所有颜色分量值都存完后才存下一个像素,不进行交织存储。32位数据,按照 B、G、R、A 的顺序存储,其余与24位位图的方式一样。
6、结构体示例
#ifndef __BmpFormat_H
#define __BmpFormat_H
typedef unsigned char uint_8; // 一个字节
typedef unsigned short uint_16; // 两个字节
typedef unsigned int uint_32; // 四个字节
// 位图文件头,固定大小为 14 个字节,用于判断 Bmp 图片类型,以及文件大小和位图起始位置等
typedef struct BITMAPFILEHEADER {
uint_16 bfType; // 文件类型,Bmp 文件类型前的头两个字节指明必须是0x424D,即字符串“BM”;否则认为不是标准的 Bmp 文件类型
uint_32 bfSize; // 说明文件的大小,包括这14个字节,以字节为单位
uint_16 bfReserved1; // 保留,设置为0
uint_16 bfReserved2; // 保留,设置为0
uint_32 bfOffsetBytes; // 说明从 位图文件头(BITMAPFILEHEADER)结构开始到实际的图像数据之间的字节偏移量,以字节为单位
} bitBmpFileHeader;
//位图信息头,固定大小为40个字节,用于说明位图的尺寸等信息
typedef struct BITMAPINFOHEADER {
uint_32 biSize; // 信息头大小
uint_32 biWidth; // 图像宽度
uint_32 biHeight; // 图像高度
uint_16 biPlanes; // 位平面数,必须为1
uint_16 biBitCount; // 每像素位数。常用的值为1(黑白二色图), 4(16色图), 8(256色), 24(真彩色图)或32(新的.bmp格式支持32位色)
uint_32 biCompression; // 压缩类型:有效的值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS(都是一些Windows定义好的常量)
uint_32 biSizeImage; // 压缩图像大小字节数 biSizeImage=biWidth’ × biHeight,biWidth’必须是4的整倍数,(所以不是biWidth,而是biWidth’,表示大于或等于biWidth的,最接近4的整倍数)
uint_32 biXPelsPerMeter; // 水平分辨率,单位是每米的象素个数
uint_32 biYPelsPerMeter; // 垂直分辨率,单位是每米的象素个数
uint_32 biClrUsed; // 位图实际用到的色彩数,如果该值为零,则用到的颜色数为2^biBitCount
uint_32 biClrImportant; // 本位图中重要的色彩数,如果该值为零,则认为所有的颜色都是重要的。
} bitBmpInfoHeader;
/****************************************************************************************************************************************
* 调色板信息,4个字节
* 说明:调色板其实是一张映射表,标识颜色索引号与其代表的颜色的对应关系。
* 它在文件中的布局就像一个二维数组palette[N][4],其中N表示总的颜色索引数,每行的四个元素分别表示该索引对应的 B、G、R和 Alpha 的值,每个分量占一个字节。
* 如不设透明通道时,Alpha为0。
* 真彩色是无调色板部分的,位图信息头(bitBmpInfoHeader)后直接是位图数据。
****************************************************************************************************************************************/
typedef struct BITMAPRGBAlpha {
uint_8 rgbBlue; // 该颜色的蓝色分量
uint_8 rgbGreen; // 该颜色的绿色分量
uint_8 rgbRed; // 该颜色的红色分量
uint_8 rgbAlpha; // 该颜色的透明分量
} bmpColorPalette;
/****************************************************************************************************************************************
* 位图数据信息 - bitmapData
* 字节要求:每一行的字节数必须是4的整倍数,如果不是,则需要补齐。如 241 补齐为 244.
* 读取顺序:一般来说,BMP文件的数据从下到上,从左到右的。也就是说,从文件中最先读到的是图象最下面一行的左边第一个象素,
然后是左边第二个象素……接下来是倒数第二行左边第一个象素,左边第二个象素……依次类推 ,最后得到的是最上面一行的最右一个象素。
* 存储方式:24位真彩色图,按照 B、G、R 的顺序来存储每个像素的各颜色通道的值,一个像素的所有颜色分量值都存完后才存下一个像素,不进行交织存储。
32位数据,按照 B、G、R、A 的顺序存储,其余与24位位图的方式一样。
****************************************************************************************************************************************/
#endif // !__BmpFormat_H