在C Win32中使用hBitmap = CreateDIBSection()保存.bmp文件

时间:2012-03-07 18:14:38

标签: c file winapi save bmp

我有以下代码。我想用这个信息来创建一个.bmp文件,它显示来自内存的数据,这是一个从framegrabber复制到主内存的图像,有人可以告诉我吗? 谢谢

LPSTR CreateBMP( HWND hAppWnd, int nImageType )

{
    void * pWinGBits = NULL;     int i;     Z_BITMAPINFO zWinGHeader; //用于修改DIB的bitmapinfo

//  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 

}

3 个答案:

答案 0 :(得分:6)

在C中,转换是一个巨大的痛苦,因为您需要手动构建位图。 Here是我过去用过的代码:

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);

如果您被允许使用C ++,则可以使用CImage中的ATL轻松完成此操作(在几行中)。

答案 1 :(得分:1)

CreateDIBSection函数创建一个DIB *,应用程序可以直接写入。该函数为您提供指向位图位值位置的指针。

此调用创建位图图像,为什么要使用该功能?

  • 设备无关位图

答案 2 :(得分:1)

使用win32 api从内存中的图像数据或HBITMAP到图像文件的最简单方法是使用GDI +。只需从图像数据或HBITMAP创建一个Bitmap对象(参见http://msdn.microsoft.com/en-us/library/ms536314%28v=vs.85%29.aspx),然后使用Save方法创建文件(参见http://msdn.microsoft.com/en-us/library/ms535407%28v=vs.85%29.aspx)。如果您无法使用C ++,那么这些方法也可以作为C语言调用的函数存在。