存储图像

【勇芳软件工作室】汉化HomePreviousNext

许多应用程序将图像永久存储为文件。例如,绘图应用程序存储图片,电子表格应用程序存储图表,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);
}