您的位置:首页 > 其它

BMP文件格式解析

2013-01-30 12:03 204 查看

一. BMP文件存储格式:



typedef struct tagBITMAPFILEHEADER {

        WORD    bfType;

        DWORD   bfSize;                            // 用字节表示的整个文件的大小

        WORD    bfReserved1;

        WORD    bfReserved2;

        DWORD   bfOffBits;                        // 从文件开始到位图数据开始之间的图像像素数据的偏移量

} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER{

        DWORD      biSize;

        LONG       biWidth;

        LONG       biHeight;

        WORD       biPlanes;

        WORD       biBitCount;                     // 每个像素占的位数(bit数)

        DWORD      biCompression;

        DWORD      biSizeImage;              // 用字节数表示的位图数据的大小。该数必须是4的倍数

        LONG       biXPelsPerMeter;

        LONG       biYPelsPerMeter;

        DWORD      biClrUsed;                  // 位图实际使用的颜色数. 

        DWORD      biClrImportant;

} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

typedef struct tagRGBQUAD {

        BYTE    rgbBlue;

        BYTE    rgbGreen;

        BYTE    rgbRed;

        BYTE    rgbReserved;

} RGBQUAD;

typedef RGBQUAD FAR* LPRGBQUAD;

字段说明: google一下.

二. 一些字段说明

BITMAPINFOHEADER.biBitCount:

每个像素占的位数(bit数)

1  单色位图(实际上可有两种颜色,缺省情况下是黑色和白色。你可以颜色表自己定义这两种颜色)

4  16 色位图

8  256 色位图

16  16bit 高彩色位图

24  24bit 真彩色位图

32  32bit 增强型真彩色位图

BITMAPINFOHEADER.biClrUsed:

实际使用的颜色数. 当BITMAPINFOHEADER.biBitCount为1, 4, 8, 16时, bmp图片会有一个颜色表, 理论的颜色表个数是2的biBitCount次方, 但如果实际使用到的颜色表数没那么多, 那么biClrUsed就记录实际的颜色表数量.

该值大于0而且小与理论数才有效.

bmp像素数据

biBitCount为1, 4, 8, 16时, 像素数据记录的是颜色在颜色表中的索引, 而不是真正的颜色值.

biBitCount为24, 32时, 像素数据记录的是真正的颜色值(RGB值).

三. bmp数据提取

注意各个数据的起始位置(文件偏移)

// 位图文件头提取

Memcpy(pTar1, filePtr, sizeof(BITMAPFILEHEADER));

// 位图信息头提取

Memcpy(pTar2, filePtr + sizeof(BITMAPFILEHEADER), sizeof(BITMAPINFOHEADER));

// 位图颜色表提取

颜色表数量 = pow(2.0, BITMAPINFOHEADER.biBitCount);

if(BITMAPINFOHEADER.biClrUsed != 颜色表数量 && 

BITMAPINFOHEADER.biClrUsed != 0)

{

         颜色表数量 = BITMAPINFOHEADER.biClrUsed;

}

Memcpy(pTar3, filePtr + sizeof(BITMAPFILEHEADER) + BITMAPINFOHEADER.biSize, 

颜色表数量 * sizeof(RGBQUAD) ;

// 像素数据的提取

Memcpy(pTar4, filePtr + BITMAPFILEHEADER.bfOffBits, BITMAPINFOHEADER.biSizeImage);

字节数计但是我发现有些bmp文件的biSizeImage为0, 所以最好自己计算像素数据的长度.

四. bmp像素数据长度的计算

操作系统为了效率问题, 所以bmp像素数据中, 每一行所占字节数必须是4的倍数.

例如: 一张24位的110*90的bmp图片. 

首先24位, 也就是一个像素占24 / 8 = 3个字节, 一行占110 * 3 = 330字节, 330不是4的倍数, 补充为330 + 2 = 332, 也就一行占332字节, 所以像素数据长度是332* 90 = 29880字节

一行所占字节数计算

unsigned int nBytePerLine = (BITMAPINFOHEADER.biWidth * BITMAPINFOHEADER.biBitCount + 7) / 8;

nBytePerLine = (nBytePerLine + 3) / 4 * 4;

BITMAPINFOHEADER.biSizeImage == nBytePerLine * BITMAPINFOHEADER.biHeight

五. 关于BITMAPINFO

typedef struct tagBITMAPINFO {

    BITMAPINFOHEADER    bmiHeader;

    RGBQUAD             bmiColors[1];

} BITMAPINFO, FAR *LPBITMAPINFO, *PBITMAPINFO;

RGBQUAD             bmiColors[1]; // 有点难理解?

其实在解析BMP存储格式时, 并不需要这个结构. 只是在bmp显示时需要用到,

例如 SetDIBitsToDevice其中一个参数就是要传递一个BITMAPINFO指针.

这个结构作为指针用就可以了

BITMAPINFO* p = (BITMAPINFO*)(filePtr + sizeof(BITMAPFILEHEADER));

六. 其他

Bmp格式还有压缩, 上下倒转等问题, 我暂时不需要那么深入, 以后再学习.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: