How to save bitmap to file?

 

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

 
  • lumo

    hi,
    i am trying to use this code for a screenshot function in my program…
    somewhere i get lost, cause i cant even get it working with an “dumb” generated data pool
    so this is what i try to save (note that w= width and h = height, i get this from screen resolution)

    cout

  • lumo

    awesome, my text got cropped…

  • Gerard

    Many thanks Sarath.

    It worked perfectly first time.

  • p

    Thanks for the help!

    Page was indirectly useful for solving a problem I was having.

  • Ahmed

    Thankx

  • J

    I never imagined writing a BMP would be so simple. All I needed was the header information and basic file structure, and I adapted my own Save function. It works great so far, thanks!

  • Jimmy jones

    I am a novice Win32 via C++ programmer, and I have been trying to learn about DIB’s
    for a program that I’m creating. At some point I was going to have to learn about how to save bitmaps, but I couldn’t find any simple examples. Your example has completely simplified the process, and saved me a lot of grief trying to sort out more complex examples just to even begin saving bmps.

    THANK YOU!

  • gl

    cheers.

  • http://massey.ac.nz Shujjat Khan

    Thank You brother……
    It worked really well………………

  • http://www.visualcsamples.blogspot.com Moha

    can u put pics?

  • Jim

    Thanks, cut and paste worked like a dream.

  • TW

    What should be the format for pBitmapBits? I have 4 channels of RGB and alpha, each with 16 bit color, how should I format it so I can pass to pBitmapBits? Can you give an example how this function should be called?

  • TW

    Hi,
    Thanks for your posting.
    I tried, but how come your code didn’t save the COLOR INDEX ARRAY?
    I found my color wrong, may be that’s why? Please advise.

    TW

  • ced

    thanks a lot for this so simple function ….. that works! Thanks