2008-12-02 121 views
7

當我使用Bitmap :: FromHBITMAP函數創建新的Gdiplus :: Bitmap時,生成的位圖不透明 - 保留原始HBITMAP的部分透明度。如何從HBITMAP創建Gdiplus ::位圖,保留Alpha通道信息?

有沒有辦法從HBITMAP創建一個Gdiplus :: Bitmap來傳遞alpha通道數據?

+0

你肯定知道的是,HBITMAP有一個Alpha通道開始嗎?例如,你是否將它創建爲具有BI_RGB和32bpp或其他方式的DIB? – 2008-12-03 10:33:44

+0

是的,它確實具有透明度。它使用:: AlphaBlend()函數很好地繪製。 – mackenir 2008-12-03 13:44:43

回答

4

事實證明,當從HBITMAP創建位圖時,GDI +從不會引入Alpha通道。

答案是:

  • 使用GetObject傳遞一個位圖和HBITMAP,得到的寬度和高度(並且如果輸入位圖是一個DIB,像素數據)的輸入HBITMAP的。
  • 用32位PARGB像素格式創建正確大小的位圖。
  • 使用LockBits來獲取新Bitmap的pixelData內存。
  • 如果您從GetObject獲得像素,請使用memcpy複製ARGB值。
  • 在新的位圖上調用UnlockBits。

就我而言,輸入HBITMAP的格式對於從輸入位圖像素數據到新位圖像素數據執行直接memcpy是正確的。

如果您沒有從GetObject獲取輸入像素數據,請使用GetDIBits以正確格式獲取副本。

9

我覺得工作的代碼比指令更加有用,所以:

#include <GdiPlus.h> 
#include <memory> 

Gdiplus::Status HBitmapToBitmap(HBITMAP source, Gdiplus::PixelFormat pixel_format, Gdiplus::Bitmap** result_out) 
{ 
    BITMAP source_info = { 0 }; 
    if(!::GetObject(source, sizeof(source_info), &source_info)) 
    return Gdiplus::GenericError; 

    Gdiplus::Status s; 

    std::auto_ptr<Gdiplus::Bitmap> target(new Gdiplus::Bitmap(source_info.bmWidth, source_info.bmHeight, pixel_format)); 
    if(!target.get()) 
    return Gdiplus::OutOfMemory; 
    if((s = target->GetLastStatus()) != Gdiplus::Ok) 
    return s; 

    Gdiplus::BitmapData target_info; 
    Gdiplus::Rect rect(0, 0, source_info.bmWidth, source_info.bmHeight); 

    s = target->LockBits(&rect, Gdiplus::ImageLockModeWrite, pixel_format, &target_info); 
    if(s != Gdiplus::Ok) 
    return s; 

    if(target_info.Stride != source_info.bmWidthBytes) 
    return Gdiplus::InvalidParameter; // pixel_format is wrong! 

    CopyMemory(target_info.Scan0, source_info.bmBits, source_info.bmWidthBytes * source_info.bmHeight); 

    s = target->UnlockBits(&target_info); 
    if(s != Gdiplus::Ok) 
    return s; 

    *result_out = target.release(); 

    return Gdiplus::Ok; 
}