BMP文件格式解析

. BMP文件存储格式:


BMP文件格式解析_第1张图片


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图片会有一个颜色表理论的颜色表个数是2biBitCount次方, 但如果实际使用到的颜色表数没那么多那么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.bfOffBitsBITMAPINFOHEADER.biSizeImage);

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



. bmp像素数据长度的计算


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

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

首先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格式还有压缩上下倒转等问题我暂时不需要那么深入以后再学习.


你可能感兴趣的:(BMP文件格式解析)