2012-07-27 134 views
2

我正在編輯一些使用GDI +的舊GDI代碼,並且在繪製具有透明背景的BMP文件時遇到了問題。舊的GDI代碼沒有使用任何明顯的額外代碼來繪製背景透明,所以我想知道如何使用GDI +實現這一點。如何使用GDI繪製透明BMP +

我當前的代碼看起來像這樣

HINSTANCE hinstance = GetModuleHandle(NULL); 
bmp = Gdiplus::Bitmap::FromResource(hinstance, MAKEINTRESOURCEW(IDB_BMP)); 
Gdiplus::Graphics graphics(pDC->m_hDC); 
graphics.DrawImage(&bmp, posX, posY); 

我也試圖通過克隆方法,並通過繪製位圖到新創建的一個創造,從資源的新位圖,但也沒有幫助。兩次我使用PixelFormat32bppPARGB。

然後我試圖使用alpha混合,但這種方式,整個圖像變得透明,不僅背景:

Gdiplus::ColorMatrix clrMatrix = { 
    1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 
    0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 
    0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 
    0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 
    0.0f, 0.0f, 0.0f, 0.0f, 1.0f 
}; 

Gdiplus::ImageAttributes imgAttr; 
imgAttr.SetColorMatrix(&clrMatrix); 

graphics.DrawImage(&bmp, destRect, 0, 0, width(), height(), Gdiplus::UnitPixel, &imgAttr); 

透明度信息已包含在圖像中,但我沒有線索如何在繪製圖像時應用它。如何實現這一目標?

回答

1

最簡單的解決方案是使用BMP以外的格式。

您需要位包含阿爾法數據,並且您需要位圖以具有阿爾法數據的格式。當您使用GDI +加載BMP時,即使BMP具有Alpha通道,它也將始終使用不帶alpha的格式。我相信數據存在於圖像位中,但沒有被使用。

克隆或繪製到PixelFormat32bppPARGB位圖時出現的問題是GDI +會將圖像數據轉換爲新格式,這意味着丟棄alpha數據。

假設它正確加載位,您需要做的是將位直接複製到另一個具有正確格式的位圖。你可以用Bitmap::LockBitsBitmap::UnlockBits來做到這一點。 (請確保您鎖定每個位與其天然像素格式,因此沒有轉換完成。)

+1

好吧,這似乎真的舊的GDI能夠在沒有任何額外的代碼的情況下繪製這樣的圖像,而新的GDI +無法做同樣的工作,而不需要額外的繁重的工作......悲傷但真實 – sigy 2012-07-30 09:01:25

+0

正如答案所示,GDI + *可以做到這一點,只需使用支持Alpha通道的圖像格式(如PNG)即可。 [我毫不懷疑你*可以將alpha數據存儲在BMP文件中,但你不應該這樣做。這不正常。如果它有效,它會因爲GDI中的錯誤而起作用,並且你不應該依賴它。] – BrainSlugs83 2015-01-13 13:28:18

0

逾期答案,但:

ImageAttributes imAtt;  
imAtt.SetColorKey(Color(255,255,255), Color(255,255,255), ColorAdjustTypeBitmap); 

將使white (255,255,255)透明上使用與此圖像屬性的任何位圖。

0

我有同樣的問題。透明BMP沒有正確顯示,不幸的是,PNG不能直接從資源中加載(除了添加相當多的代碼將其複製到流中並從流中加載它們)。我想避免這個代碼。
我使用的位圖也只使用兩種顏色(背景和徽標)。擁有一個alpha通道意味着我需要用更高的顏色深度來保存它們,而不是隻有2位的顏色深度。

埃文的回答正是是我一直在尋找:-)

而不是白色,我使用的是左上角像素爲透明色的顏色:

Gdiplus::Color ColourOfTopLeftPixel; 
Gdiplus::Status eStatus = m_pBitmap->GetPixel(0, 0, &ColourOfTopLeftPixel); 
_ASSERTE(eStatus == Gdiplus::Ok); 

// The following makes every pixel with the same colour as the top left pixel (ColourOfTopLeftPixel) transparent. 
Gdiplus::ImageAttributes ImgAtt; 
ImgAtt.SetColorKey(ColourOfTopLeftPixel, ColourOfTopLeftPixel, Gdiplus::ColorAdjustTypeBitmap);