在使用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.youkuaiyun.com/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