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格式还有压缩, 上下倒转等问题, 我暂时不需要那么深入, 以后再学习.相关文章推荐
- bmp文件格式的解析与显示
- bmp文件格式详细解析
- bmp文件格式详细解析
- BMP文件格式解析
- bmp文件格式详细解析
- BMP文件头格式 bmp文件二进制解析,bmp文件解析,bmp存储格式
- BMP文件格式解析
- BMP文件格式解析
- BMP文件头格式 bmp文件二进制解析
- 2,BMP文件格式解析
- MP3文件格式解析
- pcap文件格式及文件解析
- MP3文件格式解析
- bmp文件格式中rgb555与rgb888之间的转换,24位与16位位图的转换
- mp4文件格式解析(二)
- MP3文件格式解析
- ELF文件格式解析
- 使用Manifest和Attributes类解析形如MANIFEST.MF格式文件内容
- 使用Java解析xml文件为json格式
- [android]Lyric LRC格式文件解析