Saving .bmp file using hBitmap = CreateDIBSection() in C Win32 [duplicate]
Asked Answered
M

3

2

I have the following code. I want to use this information to create one .bmp file that shows the data from memory which is a image copied from a framegrabber into main memory, can somebody please let me? Thank you

LPSTR CreateBMP( HWND hAppWnd, int nImageType )

{
void * pWinGBits = NULL; int i; Z_BITMAPINFO zWinGHeader; // bitmapinfo for cerating the DIB

//  create DC for bitmap.
hDCBits = CreateCompatibleDC( ghDCMain );

switch ( nImageType )
{
    case bayer_filter:
    zWinGHeader.bmiHeader.biSize            = sizeof( BITMAPINFOHEADER );
    zWinGHeader.bmiHeader.biPlanes          = 1;
    zWinGHeader.bmiHeader.biClrImportant    = 0;
    zWinGHeader.bmiHeader.biHeight          = -lYSize;
    zWinGHeader.bmiHeader.biWidth           = lXSize;
    zWinGHeader.bmiHeader.biBitCount        = 32;
    zWinGHeader.bmiHeader.biClrUsed         = 0;//3;
    zWinGHeader.bmiHeader.biCompression     = BI_BITFIELDS;
    zWinGHeader.bmiHeader.biSizeImage       = 0;
    zWinGHeader.bmiColors[0].rgbBlue        = 0x00;
    zWinGHeader.bmiColors[0].rgbGreen       = 0x00;
    zWinGHeader.bmiColors[0].rgbRed         = 0xFF;
    zWinGHeader.bmiColors[0].rgbReserved    = 0x00;

    zWinGHeader.bmiColors[1].rgbBlue        = 0x00;
    zWinGHeader.bmiColors[1].rgbGreen       = 0xFF;
    zWinGHeader.bmiColors[1].rgbRed         = 0x00;
    zWinGHeader.bmiColors[1].rgbReserved    = 0x00;

    zWinGHeader.bmiColors[2].rgbBlue        = 0xFF;
    zWinGHeader.bmiColors[2].rgbGreen       = 0x00;
    zWinGHeader.bmiColors[2].rgbRed         = 0x00;
    zWinGHeader.bmiColors[2].rgbReserved    = 0x00;
    break;

    case color32:
    zWinGHeader.bmiHeader.biSize            = sizeof( BITMAPINFOHEADER );
    zWinGHeader.bmiHeader.biPlanes          = 1;
    zWinGHeader.bmiHeader.biClrImportant    = 0;
    zWinGHeader.bmiHeader.biHeight          = -lYSize;
    zWinGHeader.bmiHeader.biWidth           = lXSize/4;
    zWinGHeader.bmiHeader.biBitCount        = 32;
    zWinGHeader.bmiHeader.biClrUsed         = 0;
    zWinGHeader.bmiHeader.biCompression     = BI_BITFIELDS;
    zWinGHeader.bmiHeader.biSizeImage       = 0;
    zWinGHeader.bmiColors[0].rgbBlue        = 0x00;
    zWinGHeader.bmiColors[0].rgbGreen       = 0x00;
    zWinGHeader.bmiColors[0].rgbRed         = 0xFF;
    zWinGHeader.bmiColors[0].rgbReserved    = 0x00;

    zWinGHeader.bmiColors[1].rgbBlue        = 0x00;
    zWinGHeader.bmiColors[1].rgbGreen       = 0xFF;
    zWinGHeader.bmiColors[1].rgbRed         = 0x00;
    zWinGHeader.bmiColors[1].rgbReserved    = 0x00;

    zWinGHeader.bmiColors[2].rgbBlue        = 0xFF;
    zWinGHeader.bmiColors[2].rgbGreen       = 0x00;
    zWinGHeader.bmiColors[2].rgbRed         = 0x00;
    zWinGHeader.bmiColors[2].rgbReserved    = 0x00;
    break;

    case color24:
    zWinGHeader.bmiHeader.biSize            = sizeof( BITMAPINFOHEADER );
    zWinGHeader.bmiHeader.biPlanes          = 1;
    zWinGHeader.bmiHeader.biClrImportant    = 0;
    zWinGHeader.bmiHeader.biHeight          = -lYSize;
    zWinGHeader.bmiHeader.biWidth           = lXSize/3;
    zWinGHeader.bmiHeader.biBitCount        = 24;
    zWinGHeader.bmiHeader.biClrUsed         = 0;
    zWinGHeader.bmiHeader.biCompression     = BI_RGB;
    zWinGHeader.bmiHeader.biSizeImage       = 0;
    break;

    case color3x16:
    zWinGHeader.bmiHeader.biSize            = sizeof( BITMAPINFOHEADER );
    zWinGHeader.bmiHeader.biPlanes          = 1;
    zWinGHeader.bmiHeader.biClrImportant    = 0;
    zWinGHeader.bmiHeader.biHeight          = -lYSize;
    zWinGHeader.bmiHeader.biWidth           = lXSize/6;
    zWinGHeader.bmiHeader.biBitCount        = 32;
    zWinGHeader.bmiHeader.biClrUsed         = 0;
    zWinGHeader.bmiHeader.biCompression     = BI_BITFIELDS;
    zWinGHeader.bmiHeader.biSizeImage       = 0;
    zWinGHeader.bmiColors[0].rgbBlue        = 0x00;
    zWinGHeader.bmiColors[0].rgbGreen       = 0x00;
    zWinGHeader.bmiColors[0].rgbRed         = 0xFF;
    zWinGHeader.bmiColors[0].rgbReserved    = 0x00;

    zWinGHeader.bmiColors[1].rgbBlue        = 0x00;
    zWinGHeader.bmiColors[1].rgbGreen       = 0xFF;
    zWinGHeader.bmiColors[1].rgbRed         = 0x00;
    zWinGHeader.bmiColors[1].rgbReserved    = 0x00;

    zWinGHeader.bmiColors[2].rgbBlue        = 0xFF;
    zWinGHeader.bmiColors[2].rgbGreen       = 0x00;
    zWinGHeader.bmiColors[2].rgbRed         = 0x00;
    zWinGHeader.bmiColors[2].rgbReserved    = 0x00;
    break;

    case bw1x10:
    //  create bitmap-infoheader.
    zWinGHeader.bmiHeader.biSize        = sizeof( BITMAPINFOHEADER );
    zWinGHeader.bmiHeader.biPlanes      = 1;
    zWinGHeader.bmiHeader.biBitCount    = 8;
    zWinGHeader.bmiHeader.biCompression = BI_RGB;
    zWinGHeader.bmiHeader.biSizeImage   = 0;
    zWinGHeader.bmiHeader.biClrUsed     = 256;
    zWinGHeader.bmiHeader.biClrImportant= 0;
    zWinGHeader.bmiHeader.biHeight      = -lYSize;
    zWinGHeader.bmiHeader.biWidth       = lXSize/2;

    //  create colortable fot bitmap (grayvalues).
    for (i = 0; i < 256; i++) 
    {
        zWinGHeader.bmiColors[i].rgbGreen   = i;
        zWinGHeader.bmiColors[i].rgbBlue    = i;
        zWinGHeader.bmiColors[i].rgbRed     = i;

        zWinGHeader.bmiColors[i].rgbReserved = 0;
    }
    break;

    default:
    case bw8:
    //  create bitmap-infoheader.
    zWinGHeader.bmiHeader.biSize        = sizeof( BITMAPINFOHEADER );
    zWinGHeader.bmiHeader.biPlanes      = 1;
    zWinGHeader.bmiHeader.biBitCount    = 8;
    zWinGHeader.bmiHeader.biCompression = BI_RGB;
    zWinGHeader.bmiHeader.biSizeImage   = 0;
    zWinGHeader.bmiHeader.biClrUsed     = 256;
    zWinGHeader.bmiHeader.biClrImportant= 0;
    zWinGHeader.bmiHeader.biHeight      = -lYSize;
    zWinGHeader.bmiHeader.biWidth       = lXSize;

    //  create colortable fot bitmap (grayvalues).
    for (i = 0; i < 256; i++) 
    {
        zWinGHeader.bmiColors[i].rgbGreen   = i;
        zWinGHeader.bmiColors[i].rgbBlue    = i;
        zWinGHeader.bmiColors[i].rgbRed     = i;

        zWinGHeader.bmiColors[i].rgbReserved = 0;
    }
    break;
}

//  cerate identity palette 
hPal = CreateIdentityPalette( zWinGHeader.bmiColors );

//  get new palette into DC and map into physical palette register.
hOldPal = SelectPalette( ghDCMain, hPal, FALSE);
RealizePalette( ghDCMain );

//  cerate DIB-Section f黵 direct access of image-data.
hBitmap = CreateDIBSection(
    hDCBits,                        //  handle of device context
    (BITMAPINFO *)&zWinGHeader,     //  address of structure containing
                                    //  bitmap size, format and color data
    DIB_RGB_COLORS,                 //  color data type indicator: RGB values
                                    //  or palette indices
    &pWinGBits,                     //  pointer to variable to receive a pointer
                                    //  to the bitmap's bit values
    NULL,                           //  optional handle to a file mapping object
    0                               //  offset to the bitmap bit values within
                                    //  the file mapping object
);  
//  get bitmap into DC .
hOldBitmap = (HBITMAP)SelectObject( hDCBits, hBitmap );
return pWinGBits;           //  return pointer to DIB 

}

Micronesian answered 7/3, 2012 at 18:14 Comment(0)
N
2

The easiest way to go from image data in memory or an HBITMAP to an image file using the win32 api is with GDI+. Just create a Bitmap object from your image data or HBITMAP (see http://msdn.microsoft.com/en-us/library/ms536314%28v=vs.85%29.aspx), then use the Save method to create the file (see http://msdn.microsoft.com/en-us/library/ms535407%28v=vs.85%29.aspx). If you're not able to use C++, those methods also exist as functions callable from C.

Nihhi answered 8/3, 2012 at 6:33 Comment(1)
as I am using C program, I cant use GDI+ to the project. also the GDIFlat didnt work as well :(Micronesian
A
6

In C, the conversion is a huge pain since you need to build the bitmap manually. Here is code that I used in the past that did that:

PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp)
{ 
 BITMAP bmp; 
 PBITMAPINFO pbmi; 
 WORD    cClrBits;
 // Retrieve the bitmap color format, width, and height. 
 if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&amp;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) &amp; ~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) &amp;hdr, sizeof(BITMAPFILEHEADER), 
 (LPDWORD) &amp;dwTmp,  NULL)) 
 {
 return; 
 }

 // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. 
 if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) 
 + pbih->biClrUsed * sizeof (RGBQUAD), 
 (LPDWORD) &amp;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) &amp;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);

If you are allowed to use C++, you can do this a lot easier (in a few lines) using CImage from ATL.

Averil answered 7/3, 2012 at 18:18 Comment(7)
hi there I did add your code, it create the file, but it doesnt show anytihng !!! do you have any idea why?Micronesian
You have an empty bitmap there because you did not populate it yet. All you did was create the bitmap object. What are you expecting to see/trying to achieve?Averil
I have a framegrabber and a camera, which I am able to show a live the images, but I want to save one frame into a .bmp file. but in any way I am attemping to save this .bmp file it doesnt show me anytihng. can you please explain how can I save the data into a .bmp file inorder to show me the image on the file ?Micronesian
As I said, the bitmap you created needs to be populated with contents. Since you are copying from one place to another, maybe you should take a look at BitBlt. In what form do you get the image from the framegrabber?Averil
the image is a 8bit (gray) image, which can be stored in the main memory of the computer by mvfg_getbufptr() function, which return a pointer to the address on the first image in the memoryMicronesian
Your problem is not converting a HBITMAP to a .bmp file then. It is how to transfer the buffer returned to you from that subject to a HBITMAP. Unfortunately that is too specific for me to help you on since I have no experience with the library defining mvfg_getbufptr().Averil
@MikeKwan Where can I get the hdc to save the bitmap?Byelaw
N
2

The easiest way to go from image data in memory or an HBITMAP to an image file using the win32 api is with GDI+. Just create a Bitmap object from your image data or HBITMAP (see http://msdn.microsoft.com/en-us/library/ms536314%28v=vs.85%29.aspx), then use the Save method to create the file (see http://msdn.microsoft.com/en-us/library/ms535407%28v=vs.85%29.aspx). If you're not able to use C++, those methods also exist as functions callable from C.

Nihhi answered 8/3, 2012 at 6:33 Comment(1)
as I am using C program, I cant use GDI+ to the project. also the GDIFlat didnt work as well :(Micronesian
H
1

The CreateDIBSection function creates a DIB* that applications can write to directly. The function gives you a pointer to the location of the bitmap bit values.

This call does not create a bitmap image, why do you want to use that function?

  • Device Independent Bitmap
Hooch answered 7/3, 2012 at 18:19 Comment(1)
well, I have a framegrabber and a camera, and have been trying different solution to save the images from a part of memory to a .bmp file, it in everysolution it created thje images but it doesnt show anytihng, do you have any idea why ?Micronesian

© 2022 - 2024 — McMap. All rights reserved.