2011-05-09 55 views
1

我通過CreateCompatibleBitmap()創建了一個位圖來捕獲屏幕。 然後我想從這個位圖創建一個新的DIB(在內存中)。如何從現有的HBITMAP(CreateCompatibleBitmap)創建新的HBITMAP(DIB)?

代碼應該是:

HBITMAP ConvertToDIB(HBITMAP ddb) 
{ ... } 

我已經有一些代碼寫一個位圖到一個文件中。但是,我想在內存中使用HBITMAP。

//--------------------------------------------------------------------------- 
void WriteBitmapToFile(HBITMAP bitmap, wchar_t* filename, HDC hDC) 
{ 
    BITMAP bmp; 
    PBITMAPINFO pbmi; 
    WORD cClrBits; 
    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; 

    // create the bitmapinfo header information 
    if (!::GetObjectW(bitmap, sizeof(BITMAP), &bmp)) 
    { 
     return; 
    } 

    // 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. 
    if (cClrBits != 24) 
    pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
    sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< cClrBits)); 
    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. 
    pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) /8 * pbmi->bmiHeader.biHeight * cClrBits; 
    // Set biClrImportant to 0, indicating that all of the 
    // device colors are important. 
    pbmi->bmiHeader.biClrImportant = 0; 

    // now open file and save the data 
    pbih = (PBITMAPINFOHEADER) pbmi; 
    lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); 

    if (!lpBits) 
    { 
     return; 
    } 

    // Retrieve the color table (RGBQUAD array) and the bits 
    if (!GetDIBits(hDC, HBITMAP(bitmap), 0, (WORD) pbih->biHeight, lpBits, pbmi, 
    DIB_RGB_COLORS)) 
    { 
     return; 
    } 

    // Create the .BMP file. 
    hf = CreateFileW(filename, 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); 
} 

最好的問候, 扎克

+0

就發現,在Win32 API > CopyImage() http://msdn.microsoft.com/en-us/library/ms648031( v = vs.85).aspx 可以很好地完成這項工作。 – Zach 2011-05-09 06:59:27

回答

1

如果你只是想HBITMAP轉換成DIB(設備無關位圖),有一個名爲Win32的的GetDIBits GDI函數。

int GetDIBits(
    __in  HDC hdc, 
    __in  HBITMAP hbmp, 
    __in  UINT uStartScan, 
    __in  UINT cScanLines, 
    __out LPVOID lpvBits, 
    __inout LPBITMAPINFO lpbi, 
    __in  UINT uUsage 
); 

這裏的鏈接功能的GetDIBits MSDN上:
http://msdn.microsoft.com/en-us/library/dd144879(v=vs.85).aspx

注意,您必須在調用之前的GetDIBits分配用於lpvBits內存。但是有多少內存應該分配是這裏的另一個問題:
How much memory should be allocated for the DIB data received from HBITMAP using GetDIBits function?