bmp图像文件格式超详解

365网址经常打不开 📅 2025-07-22 11:02:50 👤 admin 👁️ 9752 ❤️ 842
bmp图像文件格式超详解

0 BMP简介

BMP(Bitmap-File)图形文件,又叫位图文件,是Windows采用的图形文件格式,在Windows环境下运行的所有图像处理软件都支持BMP图像文件格式。Windows系统内部各图像绘制操作都是以BMP为基础的。一个BMP文件由四部分组成:

BMP文件的数据按照从文件头开始的先后顺序分为四个部分:

文件头(bmp file header):提供文件的格式、大小等信息

信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息

调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表

位图数据(bitmap data):图像的像素值可以是RGB值,也可以是调色板的索引值。如果使用了调色板,那像素值就是调色板的索引值,可以根据像素值得到调色板索引值,然后根据调色板索引值找到相应的颜色,该颜色即为像素的颜色,如果用RGB值表示位图数据,那位图就没有调色板。通常8位深及8位深以下的图像会用到调色板,8位深以上的就不用调色板了,因为8位深以上的图像再使用调色板内存开销就会很大,直接使用RGB值存储,更节省内存。 以16位深图像为例,共有2^16=65536种颜色,如果使用调色板,调色板的大小就是262144字节,然后每个像素用16位表示,假设是一个100像素 * 100像素的图像,那么图像大小就是(100 * 16 +31)/32 * 4 * 100=20000字节,而如果使用RGB值来存储,低5位表示蓝色,中间5位表示绿色,高5位表示红色,最高1位保留位,即每像素用2字节来表示,图像的大小就是(100 * 16 +31)/ 32 * 4 * 100=20000字节,节省了调色板高达262144字节的空间!图像大小计算方式参考bmp图像大小计算方式

一个BMP文件可以用如下代码表示:

typedef struct tagBITMAP_FILE{

BITMAPFILEHEADER bitmapheader;//文件头

BITMAPINFOHEADER bitmapinfoheader;//信息头

PALETTEENTRY palette[256];//调色板(可选)

UCHAR *buffer; //UCHAR 大小1字节(同C语言的unchar),指向图像数据信息

} BITMAP_FILE;

图像文件的底层全都是二进制形式,存储和读取都是以字节位单位的,所以图像数据要么是char* 存储,要么是unchar* 存储,为什么图像数据要用unchar*表示?

如果是char* 存储,那文件的每一个字节都是一个char,最高位是符号位无法表示图像像素信息,这肯定是不行的,比如1bit图像,文件中的某一个字节为00110011,最高位0本应该是表示白色,现在表示符号位就无法表示图像信息了,所以用unchar* 更为合适。且使用unchar* 文件中的每一个字节都是一个unchar,一个unchar的取值对应8位深图像的颜色索引,一个unchar的取值范围在0~255之间刚好对应8位深图像调色板0 ~ 255的颜色索引。

1 文件头

typedef struct tagBITMAPFILEHEADER { // bmfh

WORD bfType; //占2字节

DWORD bfSize; //占4字节

WORD bfReserved1; //占2字节

WORD bfReserved2; //占2字节

DWORD bfOffBits; //占4字节

} BITMAPFILEHEADER;

以1张1bit灰度图像为例来介绍文件头、信息头、调色板和图像数据: 1:0x424D->bfType: BM 2:0x0004a8e2->bfSize: 305378B(278KB) 打开文件属性,可以看到文件大小计算无误

3:0x00000000->bfReserved1和bfReserved2:共4字节的保留字节,全设为0 4:0x0000003e->bfOffBits: 偏移量大小为62字节(14字节的文件头+40字节的信息头+8字节的调色板)

2 信息头

typedef struct tagBITMAPINFOHEADER{ // bmih

DWORD biSize;

LONG biWidth; //4字节

LONG biHeight;

WORD biPlanes;

WORD biBitCount

DWORD biCompression;

DWORD biSizeImage;

LONG biXPelsPerMeter;

LONG biYPelsPerMeter;

DWORD biClrUsed;

DWORD biClrImportant;

} BITMAPINFOHEADER;

1:0x00000028->biSize=40字节 2:0x0000040f->biWidth=1039像素 3:0x00000909->biHeight=2313像素 4:0x0001->biPlanes=1 5:0x000a->biBitCount=1

通过图片检测计算无误 6:0x00000000->biCompression=0(没有压缩) 7:0x0004a8a4->biSizeImage=305316字节 我们可以通过LineBytes = (width * bitCount + 31) / 32 * 4计算来验证biSizeImage的大小是否正确,关于LineBytes = (width * bitCount + 31) / 32 * 4的原理可参考bmp图像大小计算方式 每行字节数为:(1039 * 1+31)/32 * 4=132B 图像大小为132 * 2313 = 305316B 由上述计算方式可知biSizeImage的大小正确 8:0x00000000->biXPelsPerMeter=0 9:0x00000000->biYPelsPerMeter=0 10:0x00000000->biCirUsed = 0 11:0x00000000->biClrImportant=0

注意biSize、bfSize、biSizeImage三者的区别: biSize是信息头的大小,通常占40字节,bfSize是整个图像文件的大小,包括文件头+信息头+调色板(可选)+图像大小,biSizeImage是整个图像的大小。我们之前算的biSizeImage=305316,bfSize = 305378 = 文件头(14)+信息头(40)+调色板(8)+biSizeImage(305316)。

3 调色板

通常8位深及以下bmp图像使用调色板,8位深以上使用RGB。

可以使用C++预定义的结构体来定义调色板

typedef struct tagRGBQUAD {

BYTE rgbBlue;

BYTE rgbGreen;

BYTE rgbRed;

BYTE rgbReserved;

} RGBQUAD;

具体定义方式如下:

//定义一个1bit图像的调色板

//1bit图像只有2种颜色

RGBQUAD colors1[2];//定义调色板

//实现调色板

//每个分量占8位,所以1个颜色占4字节

colors1[0].rgbBlue = 0; // 黑色

colors1[0].rgbGreen = 0;

colors1[0].rgbRed = 0;

colors1[0].rgbReserved = 0;

colors1[1].rgbBlue = 255; // 白色

colors1[1].rgbGreen = 255;

colors1[1].rgbRed = 255;

colors1[1].rgbReserved = 0;

上面测试的图像为1bit图像,其中文件头占14字节,信息头占40字节,而文件头到实际数据之间的偏移量却为62字节,是因为文件头和信息头后面还有8字节的调色板。

注意:当rgb三个值都相等时,对应的颜色是灰色

上面基本把调色板及相关取色策略梳理清楚了,接着回到我们之前1位深图像的例子。

该图像是1bit图像,所以肯定是调色板图像,每个像素值占1位,表示调色板索引号,蓝色方框的8字节就是调色板信息,后面的信息就是图像数据信息了,比如0xFF,对应的二进制就是11111111,表示这8个像素每个像素都是调色板中索引号为1的颜色。

由于位图信息头中的图像高度是正数,所以位图数据在文件中的排列顺序是从左下角到右上角,以行为主序排列的。

相关推荐

门中门防盗门优缺点
365bet体育在线总站

门中门防盗门优缺点

📅 07-15 👁️ 8919
八字空亡是什么意思?空亡在四柱上有什么作用?
365bet最新备用

八字空亡是什么意思?空亡在四柱上有什么作用?

📅 07-14 👁️ 9865
funbike单车押金怎么退 funbike退押金方法一览
365bet最新备用

funbike单车押金怎么退 funbike退押金方法一览

📅 06-30 👁️ 4485