GDI/GDI+(2): VC中,保存HBITMAP到bmp文件方法

来源:互联网 发布:淘宝虚假交易次数 编辑:程序博客网 时间:2024/05/16 05:56

首先附上一段MSDN的文章,在MSDN搜索GetObject,便可得到这篇文章

Storing an Image

Many applications store images permanently as files. For example, drawing applications store pictures, spreadsheet applications store charts, CAD applications store drawings, and so on.

If you are writing an application that stores a bitmap image in a file, you should use the bitmap file format described inBitmap Storage. To store a bitmap in this format, you must use aBITMAPINFOHEADER, a BITMAPV4HEADER, or aBITMAPV5HEADER structure and an array ofRGBQUAD structures, as well as an array of palette indexes.

The following example code defines a function that uses a BITMAPINFO structure and allocates memory for and initializes members within aBITMAPINFOHEADER structure. Note that theBITMAPINFO structure cannot be used with either aBITMAPV4HEADER or aBITMAPV5HEADER structure.

PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp){     BITMAP bmp;     PBITMAPINFO pbmi;     WORD    cClrBits;     // Retrieve the bitmap color format, width, and height.     if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))         errhandler("GetObject", hwnd);     // Convert the color format to a count of bits.     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;     else cClrBits = 32;     // Allocate memory for the BITMAPINFO structure. (This structure     // contains a BITMAPINFOHEADER structure and an array of RGBQUAD     // data structures.)      if (cClrBits != 24)          pbmi = (PBITMAPINFO) LocalAlloc(LPTR,                     sizeof(BITMAPINFOHEADER) +                     sizeof(RGBQUAD) * (1<< cClrBits));      // There is no RGBQUAD array for the 24-bit-per-pixel format.      else          pbmi = (PBITMAPINFO) LocalAlloc(LPTR,                     sizeof(BITMAPINFOHEADER));     // Initialize the fields in the BITMAPINFO structure.     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 = (1<<cClrBits);     // If the bitmap is not compressed, set the BI_RGB flag.     pbmi->bmiHeader.biCompression = BI_RGB;     // Compute the number of bytes in the array of color     // indices and store the result in biSizeImage.     // For Windows NT, the width must be DWORD aligned unless     // the bitmap is RLE compressed. This example shows this.     // For Windows 95/98/Me, the width must be WORD aligned unless the     // bitmap is RLE compressed.    pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8                                  * pbmi->bmiHeader.biHeight;     // Set biClrImportant to 0, indicating that all of the     // device colors are important.      pbmi->bmiHeader.biClrImportant = 0;      return pbmi;  } 

The following example code defines a function that initializes the remaining structures, retrieves the array of palette indices, opens the file, copies the data, and closes the file.

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);     // Retrieve the color table (RGBQUAD array) and the bits     // (array of palette indices) from the DIB.     if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi,         DIB_RGB_COLORS))     {        errhandler("GetDIBits", hwnd);     }    // Create the .BMP file.     hf = CreateFile(pszFile,                    GENERIC_READ | GENERIC_WRITE,                    (DWORD) 0,                     NULL,                    CREATE_ALWAYS,                    FILE_ATTRIBUTE_NORMAL,                    (HANDLE) NULL);     if (hf == INVALID_HANDLE_VALUE)         errhandler("CreateFile", hwnd);     hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"     // Compute the size of the entire file.     hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +                  pbih->biSize + pbih->biClrUsed                  * sizeof(RGBQUAD) + pbih->biSizeImage);     hdr.bfReserved1 = 0;     hdr.bfReserved2 = 0;     // Compute the offset to the array of color indices.     hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +                     pbih->biSize + pbih->biClrUsed                     * sizeof (RGBQUAD);     // Copy the BITMAPFILEHEADER into the .BMP file.     if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),         (LPDWORD) &dwTmp,  NULL))     {       errhandler("WriteFile", hwnd);     }    // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.     if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)                   + pbih->biClrUsed * sizeof (RGBQUAD),                   (LPDWORD) &dwTmp, ( NULL))         errhandler("WriteFile", hwnd);     // Copy the array of color indices into the .BMP file.     dwTotal = cb = pbih->biSizeImage;     hp = lpBits;     if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL))            errhandler("WriteFile", hwnd);     // Close the .BMP file.      if (!CloseHandle(hf))            errhandler("CloseHandle", hwnd);     // Free memory.     GlobalFree((HGLOBAL)lpBits);}

下面是转载的可以具体实现的方法

//======================================================================//

CFileDialog dlg(false,"*.bmp",NULL,NULL,"*.bmp|*.bmp||");

if (dlg.DoModal()==IDOK)
{
    SaveBitmapToFile(hBitmap,dlg.GetPathName());
    PostQuitMessage(0);
}

//------------保存Bitmap到文件---------------
BOOL SaveBitmapToFile(HBITMAP hBitmap, LPCTSTR lpFileName ) 

HDC hDC; //设备描述表 
int iBits; //当前显示分辨率下每个像素所占字节数 
WORD wBitCount; //位图中每个像素所占字节数 
DWORD dwPaletteSize=0, //定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数 
dwBmBitsSize, 
dwDIBSize, dwWritten; 
BITMAP Bitmap; //位图属性结构 
BITMAPFILEHEADER bmfHdr; //位图文件头结构 
BITMAPINFOHEADER bi; //位图信息头结构 
LPBITMAPINFOHEADER lpbi; //指向位图信息头结构 

HANDLE fh, hDib, hPal,hOldPal=NULL; //定义文件,分配内存句柄,调色板句柄 

//计算位图文件每个像素所占字节数 
HDC hWndDC = CreateDC("DISPLAY",NULL,NULL,NULL); 
hDC = ::CreateCompatibleDC( hWndDC ) ; 
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); 
DeleteDC(hDC); 

if (iBits <= 1) 
wBitCount = 1; 
else if (iBits <= 4) 
wBitCount = 4; 
else if (iBits <= 8) 
wBitCount = 8; 
else if (iBits <= 24) 
wBitCount = 24; 
else 
wBitCount = 24 ; 

//计算调色板大小 
if (wBitCount <= 8) 
dwPaletteSize = (1 << wBitCount) * sizeof(RGBQUAD); 

//设置位图信息头结构 
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap); 
bi.biSize = sizeof(BITMAPINFOHEADER); 
bi.biWidth = Bitmap.bmWidth; 
bi.biHeight = Bitmap.bmHeight; 
bi.biPlanes = 1; 
bi.biBitCount = wBitCount; 
bi.biCompression = BI_RGB; 
bi.biSizeImage = 0; 
bi.biXPelsPerMeter = 0; 
bi.biYPelsPerMeter = 0; 
bi.biClrUsed = 0; 
bi.biClrImportant = 0; 

dwBmBitsSize = ((Bitmap.bmWidth * wBitCount+31)/32) * 4 * Bitmap.bmHeight ; 

//为位图内容分配内存 
hDib = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER)); 
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); 
*lpbi = bi; 

// 处理调色板 
hPal = GetStockObject(DEFAULT_PALETTE); 
if (hPal) 

hDC = ::GetDC(NULL); 
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE); 
RealizePalette(hDC); 


// 获取该调色板下新的像素值 
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, 
(LPSTR)lpbi + sizeof(BITMAPINFOHEADER) 
+dwPaletteSize, 
(LPBITMAPINFO ) 
lpbi, DIB_RGB_COLORS); 

//恢复调色板 
if (hOldPal) 

SelectPalette(hDC, (HPALETTE)hOldPal, TRUE); 
RealizePalette(hDC); 
::ReleaseDC(NULL, hDC); 


//创建位图文件 
fh = CreateFile(lpFileName, GENERIC_WRITE, 
0, NULL, CREATE_ALWAYS, 
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 

if (fh == INVALID_HANDLE_VALUE) 
return FALSE; 

// 设置位图文件头 
bmfHdr.bfType = 0x4D42; // "BM" 
dwDIBSize = sizeof(BITMAPFILEHEADER) 
+ sizeof(BITMAPINFOHEADER) 
+ dwPaletteSize + dwBmBitsSize; 
bmfHdr.bfSize = dwDIBSize; 
bmfHdr.bfReserved1 = 0; 
bmfHdr.bfReserved2 = 0; 
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) 
+ (DWORD)sizeof(BITMAPINFOHEADER) 
+ dwPaletteSize; 

// 写入位图文件头 
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); 

// 写入位图文件其余内容 
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, 
&dwWritten, NULL); 

//清除 
GlobalUnlock(hDib); 
GlobalFree(hDib); 
CloseHandle(fh); 

return TRUE; 

}
原创粉丝点击