首先需要介绍的是.bmp文件的存储格式,.bmp文件由四部分组成,文件头部,文件信息头部,调色板和实际的像素信息。文件的这种组织形式类似于一种嵌套形式。
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
头部在磁盘上的存储的形式如上所示,其中第一个成员变量bfType类似于一个魔术字,用于标记文件是一个.bmp文件。而bfSize则是整个文件的大小,而bfOffBits则是用于表明像素信息开始相对于文件头部的偏移量。正因为有这一部分的存在使得.bmp文件的信息头部可以被改变而无需考虑兼容问题。
typedef struct tagBITMAPINFOHEADER{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
文件信息头部的结构如上,第一个成员变量biSize表明文件信息头部的大小,这一个变量可以用于判断.bmp文件的版本(不同的版本文件信息头部可以不同,不过一般默认等于40)。接下来两个成员变量表明图像的宽和高度,这两个变量的单位都是像素。然后接下来的是biPlanes成员变量必须等于1.biBitCount成员变量表明每一个像素值占用多少bit位,一般是等于24;不过该变量需要在biClrUsed等于0的情况下才有效,biClrUsed等于0则表示像素是真彩图,否则需要使用调色板,其中biClrUsed表示调色板总共有多少种颜色。biCompression表示图像是否经过压缩。biSizeImage则是图像中像素点的个数,不过这里不一定等于biWidth*biHeight,在计算biSizeImage之前需要对biWidth进行4字节对齐。biXPelsPerMeter表示分辨率,单位是每米多少个像素点。其实后面几个成员变量完全是为了设备无关性才需要保留的。
下面是一段代码用于二进制图像加载到内存中并且显示出来。注意这里.bmp图像中并没有使用调色板,所以不需要构建调色板,直接创建设备无关位图就可以了。
if (strFileName.IsEmpty())
{
return FALSE;
}
OFSTRUCT of;
HFILE hFile=::OpenFile(strFileName.GetBuffer(),&of,OF_READ);
if (hFile==(HFILE)INVALID_HANDLE_VALUE)
{
return FALSE;
}
BITMAPFILEHEADER bh;
DWORD dwCount;
::ReadFile((HANDLE)hFile,(char*)&bh,sizeof(BITMAPFILEHE