How can I create .bmp file from HBITMAP?
Last Updated on Monday, 31 May 2010 08:35
Written by Simeon Antonov



I get this code from MSDN and make a few changes.
(HBITMAP to bmp)
PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp)
{
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
// Retrieve the bitmap color format, width, and height.
if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
return NULL;
// 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;
}
void CreateBMPFile(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)
return;
// 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))
{
return;
}
// 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)
return;
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))
{
return;
}
// Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
+ pbih->biClrUsed * sizeof (RGBQUAD),
(LPDWORD) &dwTmp, ( NULL)))
return;
// 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))
return;
// Close the .BMP file.
if (!CloseHandle(hf))
return;
// Free memory.
GlobalFree((HGLOBAL)lpBits);
}
//code for saving bitmap
HBITMAP hBitmap;
HDC hdc;
...
PBITMAPINFO pBitmapInfo = CreateBitmapInfoStruct(hBitmap);
CreateBMPFile(_T("c:\\temp\\picture.bmp"), pBitmapInfo, hBitmap, hdc);
%0APBITMAPINFO%20CreateBitmapInfoStruct%28HBITMAP%20hBmp%29%0A%7B%20%0A%20BITMAP%20bmp%3B%20%0A%20PBITMAPINFO%20pbmi%3B%20%0A%20WORD%C2%A0%C2%A0%C2%A0%20cClrBits%3B%0A%20%2F%2F%20Retrieve%20the%20bitmap%20color%20format%2C%20width%2C%20and%20height.%20%0A%20if%20%28%21GetObject%28hBmp%2C%20sizeof%28BITMAP%29%2C%20%28LPSTR%29%26amp%3Bbmp%29%29%20%0A%20return%20NULL%3B%0A%0A%20%2F%2F%20Convert%20the%20color%20format%20to%20a%20count%20of%20bits.%20%0A%20cClrBits%20%3D%20%28WORD%29%28bmp.bmPlanes%20%2A%20bmp.bmBitsPixel%29%3B%20%0A%20if%20%28cClrBits%20%3D%3D%201%29%20%0A%20cClrBits%20%3D%201%3B%20%0A%20else%20if%20%28cClrBits%20%3C%3D%204%29%20%0A%20cClrBits%20%3D%204%3B%20%0A%20else%20if%20%28cClrBits%20%3C%3D%208%29%20%0A%20cClrBits%20%3D%208%3B%20%0A%20else%20if%20%28cClrBits%20%3C%3D%2016%29%20%0A%20cClrBits%20%3D%2016%3B%20%0A%20else%20if%20%28cClrBits%20%3C%3D%2024%29%20%0A%20cClrBits%20%3D%2024%3B%20%0A%20else%20cClrBits%20%3D%2032%3B%20%0A%0A%20%2F%2F%20Allocate%20memory%20for%20the%20BITMAPINFO%20structure.%20%28This%20structure%20%0A%20%2F%2F%20contains%20a%20BITMAPINFOHEADER%20structure%20and%20an%20array%20of%20RGBQUAD%20%0A%20%2F%2F%20data%20structures.%29%20%0A%0A%20if%20%28cClrBits%20%21%3D%2024%29%20%0A%20pbmi%20%3D%20%28PBITMAPINFO%29%20LocalAlloc%28LPTR%2C%20%0A%20sizeof%28BITMAPINFOHEADER%29%20%2B%20%0A%20sizeof%28RGBQUAD%29%20%2A%20%281%3C%3C%20cClrBits%29%29%3B%20%0A%0A%20%2F%2F%20There%20is%20no%20RGBQUAD%20array%20for%20the%2024-bit-per-pixel%20format.%20%0A%0A%20else%20%0A%20pbmi%20%3D%20%28PBITMAPINFO%29%20LocalAlloc%28LPTR%2C%20%0A%20sizeof%28BITMAPINFOHEADER%29%29%3B%20%0A%0A%20%2F%2F%20Initialize%20the%20fields%20in%20the%20BITMAPINFO%20structure.%20%0A%0A%20pbmi-%3EbmiHeader.biSize%20%3D%20sizeof%28BITMAPINFOHEADER%29%3B%20%0A%20pbmi-%3EbmiHeader.biWidth%20%3D%20bmp.bmWidth%3B%20%0A%20pbmi-%3EbmiHeader.biHeight%20%3D%20bmp.bmHeight%3B%20%0A%20pbmi-%3EbmiHeader.biPlanes%20%3D%20bmp.bmPlanes%3B%20%0A%20pbmi-%3EbmiHeader.biBitCount%20%3D%20bmp.bmBitsPixel%3B%20%0A%20if%20%28cClrBits%20%3C%2024%29%20%0A%20pbmi-%3EbmiHeader.biClrUsed%20%3D%20%281%3C%3CcClrBits%29%3B%20%0A%0A%20%2F%2F%20If%20the%20bitmap%20is%20not%20compressed%2C%20set%20the%20BI_RGB%20flag.%20%0A%20pbmi-%3EbmiHeader.biCompression%20%3D%20BI_RGB%3B%20%0A%0A%20%2F%2F%20Compute%20the%20number%20of%20bytes%20in%20the%20array%20of%20color%20%0A%20%2F%2F%20indices%20and%20store%20the%20result%20in%20biSizeImage.%20%0A%20%2F%2F%20For%20Windows%20NT%2C%20the%20width%20must%20be%20DWORD%20aligned%20unless%20%0A%20%2F%2F%20the%20bitmap%20is%20RLE%20compressed.%20This%20example%20shows%20this.%20%0A%20%2F%2F%20For%20Windows%2095%2F98%2FMe%2C%20the%20width%20must%20be%20WORD%20aligned%20unless%20the%20%0A%20%2F%2F%20bitmap%20is%20RLE%20compressed.%0A%20pbmi-%3EbmiHeader.biSizeImage%20%3D%20%28%28pbmi-%3EbmiHeader.biWidth%20%2A%20cClrBits%20%2B31%29%20%26amp%3B%20%7E31%29%20%2F8%0A%20%2A%20pbmi-%3EbmiHeader.biHeight%3B%20%0A%20%2F%2F%20Set%20biClrImportant%20to%200%2C%20indicating%20that%20all%20of%20the%20%0A%20%2F%2F%20device%20colors%20are%20important.%20%0A%20pbmi-%3EbmiHeader.biClrImportant%20%3D%200%3B%20%0A%20return%20pbmi%3B%20%0A%7D%20%0A%0Avoid%20CreateBMPFile%28LPTSTR%20pszFile%2C%20PBITMAPINFO%20pbi%2C%20%0A%20HBITMAP%20hBMP%2C%20HDC%20hDC%29%20%0A%7B%20%0A%20HANDLE%20hf%3B%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%20%2F%2F%20file%20handle%20%0A%20BITMAPFILEHEADER%20hdr%3B%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%20%2F%2F%20bitmap%20file-header%20%0A%20PBITMAPINFOHEADER%20pbih%3B%C2%A0%C2%A0%C2%A0%C2%A0%20%2F%2F%20bitmap%20info-header%20%0A%20LPBYTE%20lpBits%3B%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%20%2F%2F%20memory%20pointer%20%0A%20DWORD%20dwTotal%3B%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%20%2F%2F%20total%20count%20of%20bytes%20%0A%20DWORD%20cb%3B%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%20%2F%2F%20incremental%20count%20of%20bytes%20%0A%20BYTE%20%2Ahp%3B%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%20%2F%2F%20byte%20pointer%20%0A%20DWORD%20dwTmp%3B%20%0A%0A%20pbih%20%3D%20%28PBITMAPINFOHEADER%29%20pbi%3B%20%0A%20lpBits%20%3D%20%28LPBYTE%29%20GlobalAlloc%28GMEM_FIXED%2C%20pbih-%3EbiSizeImage%29%3B%0A%0A%20if%20%28%21lpBits%29%20%0A%20return%3B%20%0A%0A%20%2F%2F%20Retrieve%20the%20color%20table%20%28RGBQUAD%20array%29%20and%20the%20bits%20%0A%20%2F%2F%20%28array%20of%20palette%20indices%29%20from%20the%20DIB.%20%0A%20if%20%28%21GetDIBits%28hDC%2C%20hBMP%2C%200%2C%20%28WORD%29%20pbih-%3EbiHeight%2C%20lpBits%2C%20pbi%2C%20%0A%20DIB_RGB_COLORS%29%29%20%0A%20%7B%0A%20return%3B%0A%20%7D%0A%0A%20%2F%2F%20Create%20the%20.BMP%20file.%20%0A%20hf%20%3D%20CreateFile%28pszFile%2C%20%0A%20GENERIC_READ%20%7C%20GENERIC_WRITE%2C%20%0A%20%28DWORD%29%200%2C%20%0A%20NULL%2C%20%0A%20CREATE_ALWAYS%2C%20%0A%20FILE_ATTRIBUTE_NORMAL%2C%20%0A%20%28HANDLE%29%20NULL%29%3B%20%0A%20if%20%28hf%20%3D%3D%20INVALID_HANDLE_VALUE%29%20%0A%20return%3B%20%0A%20hdr.bfType%20%3D%200x4d42%3B%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%20%2F%2F%200x42%20%3D%20%22B%22%200x4d%20%3D%20%22M%22%20%0A%20%2F%2F%20Compute%20the%20size%20of%20the%20entire%20file.%20%0A%20hdr.bfSize%20%3D%20%28DWORD%29%20%28sizeof%28BITMAPFILEHEADER%29%20%2B%20%0A%20pbih-%3EbiSize%20%2B%20pbih-%3EbiClrUsed%20%0A%20%2A%20sizeof%28RGBQUAD%29%20%2B%20pbih-%3EbiSizeImage%29%3B%20%0A%20hdr.bfReserved1%20%3D%200%3B%20%0A%20hdr.bfReserved2%20%3D%200%3B%20%0A%0A%20%2F%2F%20Compute%20the%20offset%20to%20the%20array%20of%20color%20indices.%20%0A%20hdr.bfOffBits%20%3D%20%28DWORD%29%20sizeof%28BITMAPFILEHEADER%29%20%2B%20%0A%20pbih-%3EbiSize%20%2B%20pbih-%3EbiClrUsed%20%0A%20%2A%20sizeof%20%28RGBQUAD%29%3B%20%0A%0A%20%2F%2F%20Copy%20the%20BITMAPFILEHEADER%20into%20the%20.BMP%20file.%20%0A%20if%20%28%21WriteFile%28hf%2C%20%28LPVOID%29%20%26amp%3Bhdr%2C%20sizeof%28BITMAPFILEHEADER%29%2C%20%0A%20%28LPDWORD%29%20%26amp%3BdwTmp%2C%C2%A0%20NULL%29%29%20%0A%20%7B%0A%20return%3B%20%0A%20%7D%0A%0A%20%2F%2F%20Copy%20the%20BITMAPINFOHEADER%20and%20RGBQUAD%20array%20into%20the%20file.%20%0A%20if%20%28%21WriteFile%28hf%2C%20%28LPVOID%29%20pbih%2C%20sizeof%28BITMAPINFOHEADER%29%20%0A%20%2B%20pbih-%3EbiClrUsed%20%2A%20sizeof%20%28RGBQUAD%29%2C%20%0A%20%28LPDWORD%29%20%26amp%3BdwTmp%2C%20%28%20NULL%29%29%29%20%0A%20return%3B%20%0A%0A%20%2F%2F%20Copy%20the%20array%20of%20color%20indices%20into%20the%20.BMP%20file.%20%0A%20dwTotal%20%3D%20cb%20%3D%20pbih-%3EbiSizeImage%3B%20%0A%20hp%20%3D%20lpBits%3B%20%0A%20if%20%28%21WriteFile%28hf%2C%20%28LPSTR%29%20hp%2C%20%28int%29%20cb%2C%20%28LPDWORD%29%20%26amp%3BdwTmp%2CNULL%29%29%20%0A%20return%3B%20%0A%0A%20%2F%2F%20Close%20the%20.BMP%20file.%20%0A%20if%20%28%21CloseHandle%28hf%29%29%20%0A%20return%3B%20%0A%0A%20%2F%2F%20Free%20memory.%20%0A%20GlobalFree%28%28HGLOBAL%29lpBits%29%3B%0A%7D%0A%0A%0A%2F%2Fcode%20for%20saving%20bitmap%0AHBITMAP%20hBitmap%3B%0AHDC%20hdc%3B%0A...%0APBITMAPINFO%20pBitmapInfo%20%3D%20CreateBitmapInfoStruct%28hBitmap%29%3B%0ACreateBMPFile%28_T%28%22c%3A%5C%5Ctemp%5C%5Cpicture.bmp%22%29%2C%20pBitmapInfo%2C%20hBitmap%2C%20hdc%29%3B%0A