使用Image.FromHbitmap時丟失Alpha信息的解決方案

原文地址:https://blog.csdn.net/zzstack/article/details/52297120

在使用Image.FromHbitmap創建Image時,會丟失Alpha信息(或者說GDI+在使用HBITMAP創建Bitmap時都不會攜帶Alpha信息)。可以使用下面代碼來解決:

Bitmap* CreateBitmapFromHBITMAP(IN HBITMAP hBitmap)
{
    BITMAP bmp = { 0 };
    if ( 0 == GetObject(hBitmap, sizeof(BITMAP), (LPVOID)&bmp) )
    {
        return FALSE;
    }
     
    // Although we can get bitmap data address by bmp.bmBits member of BITMAP 
    // which is got by GetObject function sometime,
    // we can determine the bitmap data in the HBITMAP is arranged bottom-up 
    // or top-down, so we should always use GetDIBits to get bitmap data.
    BYTE *piexlsSrc = NULL;
    LONG cbSize = bmp.bmWidthBytes * bmp.bmHeight;
    piexlsSrc = new BYTE[cbSize];
     
    BITMAPINFO bmpInfo = { 0 };
    // We should initialize the first six members of BITMAPINFOHEADER structure.
    // A bottom-up DIB is specified by setting the height to a positive number, 
    // while a top-down DIB is specified by setting the height to a negative number.
    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biWidth = bmp.bmWidth;
    bmpInfo.bmiHeader.biHeight = bmp.bmHeight; // 正數,說明數據從下到上,如未負數,則從上到下
    bmpInfo.bmiHeader.biPlanes = bmp.bmPlanes;
    bmpInfo.bmiHeader.biBitCount = bmp.bmBitsPixel;
    bmpInfo.bmiHeader.biCompression = BI_RGB;
     
    HDC hdcScreen = CreateDC(L"DISPLAY", NULL, NULL,NULL);
    LONG cbCopied = GetDIBits(hdcScreen, hBitmap, 0, bmp.bmHeight, 
                        piexlsSrc, &bmpInfo, DIB_RGB_COLORS);
    DeleteDC(hdcScreen);
    if ( 0 == cbCopied )
    {
        delete [] piexlsSrc;
        return FALSE;
    }
     
    // Create an GDI+ Bitmap has the same dimensions with hbitmap
    Bitmap *pBitmap = new Bitmap(bmp.bmWidth, bmp.bmHeight, PixelFormat32bppPARGB);
     
    // Access to the Gdiplus::Bitmap's pixel data
    BitmapData bitmapData;
    Rect rect(0, 0, bmp.bmWidth, bmp.bmHeight);
    if ( Ok != pBitmap->LockBits(&rect, ImageLockModeRead, 
            PixelFormat32bppPARGB, &bitmapData) )
    {
        SAFE_DELETE(pBitmap);
        return NULL;
    }
     
    BYTE *pixelsDest = (BYTE*)bitmapData.Scan0;
    int nLinesize = bmp.bmWidth * sizeof(UINT);
    int nHeight = bmp.bmHeight;
     
    // Copy pixel data from HBITMAP by bottom-up.
    for ( int y = 0; y < nHeight; y++ )
    {
        // 從下到上覆制數據,因爲前面設置高度時是正數。
        memcpy_s( 
             (pixelsDest + y * nLinesize), 
             nLinesize, 
             (piexlsSrc + (nHeight - y - 1) * nLinesize), 
             nLinesize);
    }
     
    // Copy the data in temporary buffer to pBitmap
    if ( Ok != pBitmap->UnlockBits(&bitmapData) )
    {
        delete pBitmap;
    }
     
    delete [] piexlsSrc;
    return pBitmap;
}

參考文獻:

1.http://stackoverflow.com/questions/335273/how-to-create-a-gdiplusbitmap-from-an-hbitmap-retaining-the-alpha-channel-inf

2.http://blog.csdn.net/leehong2005/article/details/8607581

3.http://www.cnblogs.com/yedaoq/p/3579036.html

4.http://www.cnblogs.com/yedaoq/p/3587913.html

5.http://stackoverflow.com/questions/9275738/convert-hbitmap-to-bitmap-preserving-alpha-channel

6.http://stackoverflow.com/questions/4627376/use-native-hbitmap-in-c-sharp-while-preserving-alpha-channel-transparency
---------------------
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章