bool ImageUtil :: CreateGdiplusBmpFromHBITMAP_Alpha ( HBITMAP hBmp , Gdiplus :: Bitmap ** bmp ) { BITMAP bitmap ; GetObject ( hBmp , sizeof ( BITMAP ), & bitmap ); if ( bitmap . bmBitsPixel != 32) { return false ; } Gdiplus :: Bitmap * pWrapBitmap = Gdiplus :: Bitmap :: FromHBITMAP ( hBmp , NULL ); if ( pWrapBitmap ) { Gdiplus :: BitmapData bitmapData ; Gdiplus :: Rect rcImage (0, 0, pWrapBitmap -> GetWidth (), pWrapBitmap -> GetHeight ()); pWrapBitmap -> LockBits (& rcImage , Gdiplus :: ImageLockModeRead , pWrapBitmap -> GetPixelFormat (), & bitmapData ); * bmp = new Gdiplus :: Bitmap ( bitmapData . Width , bitmapData . Height , bitmapData . Stride , PixelFormat32bppARGB , ( BYTE *) bitmapData . Scan0 ); pWrapBitmap -> UnlockBits (& bitmapData ); delete pWrapBitmap ; return true ; } return false ; }
Gdiplus :: Bitmap * ImageUtil :: 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 ) ) { 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 ; }
bool ImageUtil::SavePng( HBITMAP hBmp, LPCTSTR lpszFilePath ) { DIBSECTION dibsection; int nBytes = ::GetObject( hBmp, sizeof( DIBSECTION ), &dibsection ); Gdiplus::Bitmap* bitmap = 0; if(nBytes != sizeof(DIBSECTION) || dibsection.dsBm.bmBitsPixel != 32) { // Bitmap with plate or non-ARGB(32bpp) bitmap = Gdiplus::Bitmap::FromHBITMAP(hBmp); } else { int width, height, bits_per_pixel, pitch; LPVOID bits; width = dibsection.dsBmih.biWidth; height = abs( dibsection.dsBmih.biHeight ); bits_per_pixel = dibsection.dsBmih.biBitCount; pitch = (((width*bits_per_pixel)+31)/32)*4; //計算行寬,四字節對齊 ATL::CImage::ComputePitch bits = dibsection.dsBm.bmBits; if( dibsection.dsBmih.biHeight > 0 ) { bits = LPBYTE( bits )+((height-1)*pitch); pitch = -pitch; } bitmap = new Gdiplus::Bitmap(width, height, pitch, PixelFormat32bppARGB, static_cast< BYTE* >(bits )); } bool ret = false; CLSID clsid = GetGdiplusEncoderClsid(NULL, &Gdiplus::ImageFormatPNG); if(clsid != CLSID_NULL) { ret = (Gdiplus::Ok == bitmap->Save(lpszFilePath, &clsid, NULL)); } delete bitmap; return ret; }