许多应用程序将图像永久存储为文件。例如,绘图应用程序存储图片,电子表格应用程序存储图表,CAD应用程序存储图纸等。
如果您正在编写一个将位图存储在文件中的应用程序,则应使用位图存储中描述的Windows文件格式。为了以此格式存储位图,您必须初始化BITMAPINFO结构(由BITMAPFILEHEADER结构和RGBQUAD结构的数组组成)以及一组调色板索引。
以下示例代码定义了为BITMAPINFOHEADER结构分配内存并初始化成员的函数。
PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd,HBITMAP hBmp){
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
/ *检索位图的颜色格式,宽度和高度。*/
if(!GetObject(hBmp,sizeof(BITMAP),(LPSTR)& bmp))
errhandler("GetObject", hwnd);
/ *将颜色格式转换为位计数。*/
cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
if (cClrBits == 1)
cClrBits = 1;
else if (cClrBits <= 4)
cClrBits = 4;
else if (cClrBits <= 8)
cClrBits = 8;
else if (cClrBits <= 16)
cClrBits = 16;
else if (cClrBits <= 24)
cClrBits = 24;
其他
cClrBits = 32;
/*
为BITMAPINFO结构分配内存。(这个结构
*包含一个BITMAPINFOHEADER结构和一个RGBQUAD数据的数组
*结构。)
*/
if (cClrBits != 24)
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER)+
sizeof(RGBQUAD) * (2^cClrBits));
/*
* 24位/像素格式没有RGBQUAD阵列。
*/
其他
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER));
/ *初始化BITMAPINFO结构中的字段。*/
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = bmp.bmWidth;
pbmi->bmiHeader.biHeight = bmp.bmHeight;
pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
if(cClrBits < 24)
pbmi->bmiHeader.biClrUsed = 2^cClrBits;
/ *如果位图未压缩,请设置BI_RGB标志。*/
pbmi->bmiHeader.biCompression = BI_RGB;
/*
*计算颜色数组中的字节数
*索引并将结果存储在biSizeImage中。
*/
pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) /8
* Pbmi- bmiHeader.biHeight
* cClrBits;
/*
*将biClrImportant设置为0,表示全部
*设备颜色很重要。
*/
pbmi->bmiHeader.biClrImportant = 0;
return pbmi;
}
以下示例代码定义了初始化剩余结构的函数,检索调色板索引数组,打开文件,复制数据,并关闭文件。
void CreateBMPFile(HWND hwnd,LPTSTR pszFile,PBITMAPINFO pbi,
HBITMAP hBMP,HDC hDC)
{
HANDLE hf; /* file handle */
BITMAPFILEHEADER hdr; /* bitmap file-header */
PBITMAPINFOHEADER pbih; /* bitmap info-header */
LPBYTE lpBits; /* memory pointer */
DWORD dwTotal; /* total count of bytes */
DWORD cb; /* incremental count of bytes */
BYTE *hp; /* byte pointer */
DWORD dwTmp;
pbih = (PBITMAPINFOHEADER) pbi;
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
if(!lpBits)
errhandler("GlobalAlloc", hwnd);
/*
*检索颜色表(RGBQUAD数组)和位
*(数组调色板索引)从DIB。
*/
如果(!GetDIBits(hDC,hBMP,0,(WORD)pbih- > biHeight,
lpBits,pbi,DIB_RGB_COLORS))
errhandler("GetDIBits", hwnd);
/ *创建.BMP文件。*/
hf = CreateFile(pszFile,
GENERIC_READ | GENERIC_WRITE,
(DWORD) 0,
(LPSECURITY_ATTRIBUTES) NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hf == INVALID_HANDLE_VALUE)
errhandler("CreateFile", hwnd);
hdr.bfType = 0x4d42; /* 0x42 = "B" 0x4d = "M" */
/ *计算整个文件的大小。*/
hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
pbih- > biSize + pbih- > biClrUsed
* sizeof(RGBQUAD) + pbih->biSizeImage);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
/ *计算颜色索引数组的偏移量。*/
hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
pbih- > biSize + pbih- > biClrUsed
* sizeof (RGBQUAD);
/ *将BITMAPFILEHEADER复制到.BMP文件中。*/
if(!WriteFile(hf,(LPVOID)& hdr,sizeof(BITMAPFILEHEADER),
(LPDWORD)& dwTmp,(LPOVERLAPPED)NULL))
errhandler("WriteFile", hwnd);
/ *将BITMAPINFOHEADER和RGBQUAD数组复制到文件中。*/
if(!WriteFile(hf,(LPVOID)pbih,sizeof(BITMAPINFOHEADER)
+ pbih- > biClrUsed * sizeof(RGBQUAD),
(LPDWORD)& dwTmp,(LPOVERLAPPED)NULL))
errhandler("WriteFile", hwnd);
/ *将颜色索引数组复制到.BMP文件中。*/
dwTotal = cb = pbih->biSizeImage;
hp = lpBits;
while(cb > MAXWRITE){
if(!WriteFile(hf,(LPSTR)hp,(int)MAXWRITE,
(LPDWORD)& dwTmp,(LPOVERLAPPED)NULL))
errhandler("WriteFile", hwnd);
cb-= MAXWRITE;
hp += MAXWRITE;
}
if(!WriteFile(hf,(LPSTR)hp,(int)cb,
(LPDWORD)& dwTmp,(LPOVERLAPPED)NULL))
errhandler("WriteFile", hwnd);
/ *关闭.BMP文件。*/
if(!CloseHandle(hf))
errhandler("CloseHandle", hwnd);
/ *可用内存* /
GlobalFree((HGLOBAL)lpBits);
}