The previous posts regarding bitmaps are already known to many people. But why still I post these. Nothing! just to keep this information in my blog if it useful to somebody else or easily retrievebale.
A bitmap takes the following format
/* Bitmap storage information ---------------------- | BITMAP FILE HEADER | |--------------------- | BITMAP INFO HEADER | |--------------------- | RGBQUAD ARRAY | |--------------------- | COLOR INDEX ARRAY | ---------------------- */
The above said is the normal format of a bitmap.
To save a bitmap, we should have the following information to write a file.
1. Create a bitmap file header
2. Create Bitmap information header
3. Pixel Data + Color Index array
See the sample code. I explained each step with comments.
void SaveBitmapToFile( BYTE* pBitmapBits, LONG lWidth, LONG lHeight,WORD wBitsPerPixel, LPCTSTR lpszFileName )
{
BITMAPINFOHEADER bmpInfoHeader = {0};
// Set the size
bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
// Bit count
bmpInfoHeader.biBitCount = wBitsPerPixel;
// Use all colors
bmpInfoHeader.biClrImportant = 0;
// Use as many colors according to bits per pixel
bmpInfoHeader.biClrUsed = 0;
// Store as un Compressed
bmpInfoHeader.biCompression = BI_RGB;
// Set the height in pixels
bmpInfoHeader.biHeight = lHeight;
// Width of the Image in pixels
bmpInfoHeader.biWidth = lWidth;
// Default number of planes
bmpInfoHeader.biPlanes = 1;
// Calculate the image size in bytes
bmpInfoHeader.biSizeImage = lWidth* lHeight * (wBitsPerPixel/8);
BITMAPFILEHEADER bfh = {0};
// This value should be values of BM letters i.e 0x4D42
// 0x4D = M 0×42 = B storing in reverse order to match with endian
bfh.bfType=0x4D42;
/* or
bfh.bfType = ‘B’+(‘M’ << 8);
// <<8 used to shift ‘M’ to end
*/
// Offset to the RGBQUAD
bfh.bfOffBits = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER);
// Total size of image including size of headers
bfh.bfSize = bfh.bfOffBits + bmpInfoHeader.biSizeImage;
// Create the file in disk to write
HANDLE hFile = CreateFile( lpszFileName,GENERIC_WRITE, 0,NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
if( !hFile ) // return if error opening file
{
return;
}
DWORD dwWritten = 0;
// Write the File header
WriteFile( hFile, &bfh, sizeof(bfh), &dwWritten , NULL );
// Write the bitmap info header
WriteFile( hFile, &bmpInfoHeader, sizeof(bmpInfoHeader), &dwWritten, NULL );
// Write the RGB Data
WriteFile( hFile, pBitmapBits, bmpInfoHeader.biSizeImage, &dwWritten, NULL );
// Close the file handle
CloseHandle( hFile );
}
You should make sure that the bitmap bits you are passing are of a Device Independent Bitmap (DIB) because a bitmap file is stored as DIB. If you pass bitmap bits of a Device Dependent Bitmap the image pixes you are passing will be stored as upside down in the file. Either you have to create a Device dependent bitmap for drawing and pass it's memory pointer to the Save function I aboved described. Or Create a DDB using CBitmap::CreateCompatibleBitmap() function and do the follownig conversion logic described in micorosft support website. Codeguru has an article on converting DDB to DIB. Please check the links following.
http://support.microsoft.com/kb/80080
http://www.codeguru.com/Cpp/G-M/bitmap/article.php/c1765