位图格式
令人高兴的是,要自己写一个调用位图的函数,有一个Win32结构的位图头文件可以利用。读取这个头文件的信息,用fread()这样简单的函数就可以了。所有的位图文件都有这样一个头文件,它包含了位图的全部信息。BITMAPFILEHEADER就是这个头文件结构的名字,下面是它的原形:
typedef struct tagBITMAPFILEHEADER { // bmfh WORD bfType; // file type - must be "BM" for bitmap DWORD bfSize; // size in bytes of the bitmap file WORD bfReserved1; // must be zero WORD bfReserved2; // must be zero DWORD bfOffBits; // offset in bytes from the BITMAPFILEHEADER // structure to the bitmap bits } BITMAPFILEHEADER; | 我就不详细介绍这些成员了,因为注释里已经说得很清楚了,只要使用fread()读取它们就可以了。注意要检测bfType成员是否等于字符“BM”,若是,说明你正在处理一个有效的位图。在此之后,有另一个头文件需要读取,它包含位图的尺寸、压缩类型等图象信息。以下是它的结构:
typedef struct tagBITMAPINFOHEADER{ // bmih DWORD biSize; // number of bytes required by the structure LONG biWidth; // width of the image in pixels LONG biHeight; // height of the image in pixels WORD biPlanes; // number of planes for target device - must be 1 WORD biBitCount; // bits per pixel - 1, 4, 8, 16, 24, or 32 DWORD biCompression; // type of compression - BI_RGB for uncompressed DWORD biSizeImage; // size in bytes of the image LONG biXPelsPerMeter; // horizontal resolution in pixels per meter LONG biYPelsPerMeter; // vertical resolution in pixels per meter DWORD biClrUsed; // number of colors used DWORD biClrImportant; // number of colors that are important } BITMAPINFOHEADER; | 只有几个成员需要解说一下。第一个,注意压缩格式。大多数的位图你都需要做解压缩的操作。最普通的位图压缩格式是run-length编码(RLE),但只能应用于4-bit或8-bit图象,在此情况时,成员biCompression将分别是BI_RLE4和BI_RLE8,我们就不讨论这种压缩格式了,但它真的很简单,很容易理解,你如果要了解它是不会有任何麻烦的。
第二个,对于高色彩的位图,biClrUsed和biClrImportant这两个成员通常设置为0,所以不用太在意它们。对于BI_RGB这种未压缩格式的位图,成员biSizeImage也将被设置为0。最后,针对我们的目的,其它的结构成员都不是很重要的,我们只需要注意位图的长、宽和色彩的深度(biWidth、biHeight、biBitCount)。
读取完了这些头文件的信息后,如果位图是8-bit或者以下色彩深度的(也就是调色板模式),调色板的信息会紧跟在这些信息之后。也许出乎你的意料,调色板的信息不是存储在PALETTEENTRY结构中,而是在RGBQUAD结构中。RGBQUAD结构如下:
typedef struct tagRGBQUAD { // rgbq BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved; } RGBQUAD; | 不要问我为什么红、绿、蓝以倒序方式排列,事实就是这样!读取RGBQUAD中的数据,把数据传递给DirectDraw调色板的数组。记得要把每个PALETTEENTRY的peFlag设置成PC_NOCOLLAPSE。
之后呢(调色板信息不一定存在,因为高彩模式下就没有),你将发现图象位(image bits),你可能会想到建立一个指针,在内存中分配足够的空间来控制这些图象位数据,然后读取它们。对极了,我正要这样干。假设把存储在BITMAPINFOHEADER结构中的信息头文件称作info,你的图象位指针称作fptr,实施的代码如下:
UCHAR* buffer = (UCHAR*)malloc(info.biSizeImage); fread(buffer, sizeof(UCHAR), info.biSizeImage, fptr); | 要记住,在一些情况下,biSizeImage的值可能为0,所以有必要在上面的代码运行前检测它一下。如果它被设置为0,你将不得不计算图象由多少个象素构成,每个象素需要多少个字节。
写你自己的位图调用函数,并非什么难事儿。但你觉得不需要,就用我们开始介绍的方法好了。这个话题告一段落,下面让我们看看DirectDraw的精华:使用位块传输。
|
|