2011-11-19 332 views
3

我試圖增加透明度的HBITMAP對象,但它從來沒有畫任何東西:/HBITMAP增加透明度/ Alpha通道

這是我用來繪製手柄

HDC hdcMem = CreateCompatibleDC(hDC); 
    HBITMAP hbmOld = (HBITMAP) SelectObject(hdcMem, m_hBitmap); 

    BLENDFUNCTION blender = {AC_SRC_OVER, 0, (int) (2.55 * 100), AC_SRC_ALPHA}; // blend function combines opacity and pixel based transparency 
    AlphaBlend(hDC, x, y, rect.right - rect.left, rect.bottom - rect.top, hdcMem, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, blender); 

    SelectObject(hdcMem, hbmOld); 
    DeleteDC(hdcMem); 

的代碼,這是應該添加一個alpha通道到HBITMAP

BITMAPINFOHEADER bminfoheader; 
    ::ZeroMemory(&bminfoheader, sizeof(BITMAPINFOHEADER)); 
    bminfoheader.biSize  = sizeof(BITMAPINFOHEADER); 
    bminfoheader.biWidth  = m_ResX; 
    bminfoheader.biHeight  = m_ResY; 
    bminfoheader.biPlanes  = 1; 
    bminfoheader.biBitCount = 32; 
    bminfoheader.biCompression = BI_RGB; 

    HDC windowDC = CreateCompatibleDC(0); 
    unsigned char* pPixels = new unsigned char[m_ResX * m_ResY * 4]; 

    GetDIBits(windowDC, m_hBitmap, 0, m_ResY, pPixels, (BITMAPINFO*) &bminfoheader, DIB_RGB_COLORS); // load pixel info 

    // add alpha channel values of 255 for every pixel if bmp 
    for (int count = 0; count < m_ResX * m_ResY; count++) 
    { 
     pPixels[count * 4 + 3] = 255; <---- here i've tried to change the value to test different transparency, but it doesn't change anything 
    } 
    SetDIBits(windowDC, m_hBitmap, 0, GetHeight(), pPixels, (BITMAPINFO*) &bminfoheader, DIB_RGB_COLORS); // save the pixel info for later manipulation 

    DeleteDC(windowDC); 

編輯的代碼:

這是我如何創建位圖 代碼我填的是PixelData取出在後面的一些代碼

m_hBuffer = CreateBitmap(m_ResX, m_ResY, 1, 32, nullptr); 
+0

我認爲你必須使用GDI +來設置alpha通道。舊的GDI內容不適用於32位圖像。請參閱:http://stackoverflow.com/questions/3942781/how-to-genrate-a-monochrome-bit-mask-for-a-32bit-bitmap – Mordachai

+1

@Mordachai - 大多數GDI功能都是如此 - 比如BitBlt - 但AlphaBlend(在Win2K中添加)被記錄爲專門支持源圖像中的每像素alpha。 – BrendanMcK

+0

@joeco,你是否嘗試過很多調試來試圖縮小問題的可能性?例如。首先嚐試使用BitBlt,只是爲了確保其餘的代碼和邏輯是好的。也可以嘗試改變阿爾法改變代碼,或許將所有G和B通道設置爲與R通道相同 - 只是爲了確保您的位圖操作代碼是正確的。順便提一句,請注意,AlphaBlend預計源位圖R/G/B將被「預乘」,因此如果您添加了Alpha通道,則可能需要在該階段適當調整R/G/B。 – BrendanMcK

回答

3

這是一個有趣的!

猜猜這是什麼打印出來的?

#include <stdio.h> 

int main() 
{ 
    printf("%d\n", (int) (2.55 * 100)); 
    return 0; 
} 

答案:254 - 255。沒有兩件事情發生在這裏:

  • 浮動往往不準確的 - 即2.55沒有得到通過,代表2.55完全是一個二進制值來表示 - 它可能是什麼比如2.5499963 ...(我剛剛做出來了,但你明白了 - 實際上這個數字表示爲2的小數部分 - 因爲二進制是基數爲2的 - 所以像.5或.25這樣的東西可能完全代表,但大多數其他數字將表示爲近似值,您通常不會注意到這一點,因爲浮點打印例程將轉換回基數10以供顯示,whi ch基本上引入了另一個不精確性,最終取消了第一個:因此,您所看到的作爲分配值或打印輸出值不完全是存儲在存儲器中的表示的值。

  • 投射到int截斷 - 即舍入。

把這些放在一起,你的(2.55 * 100)會讓你254,而不是255 - 你必須讓每像素阿爾法工作的魔法值255。

所以這裏的教訓是堅持純粹的整數。或者,如果您需要將浮點數轉換爲整數,請注意發生的情況並解決該問題(例如,添加.5,然後截斷或使用類似技術。)

順便說一句,這是一種逐行檢查代碼並在每個步驟檢查所有輸入和輸出(在調試時絕不會太偏執的情況)的情況之一可能表明了這個問題;在你進入AlphaBlend之前,當你將鼠標懸停在該參數上(假設使用DevStudio或類似的編輯器)並且意識到某些事情已經結束時,你應該會看到一個254。

+0

我不得不承認,我不知道有關浮動的事情,但它不能解決我的問題:(當我把值設置爲255時,它仍然沒有畫任何東西,我也檢查過再次在msdn上,並在那裏說'當你只想使用每個像素的alpha值時,將SourceConstantAlpha的值設置爲255(不透明)。「,所以如果我沒有錯,就說你只想要255使用per-pixel alpha,這意味着你應該可以同時使用,對吧? – ColmanJ

+0

這可能是問題的一部分。你可能會遇到一些錯誤。如果你有時間逐行執行代碼需要確認哪些位是絕對可行的你是否在這裏獲得了所有API的成功返回值?如果你使用普通BitBlt而不是AlphaBlend,代碼是否工作?使用BitBlt並修改藍色通道,你會看到預期的結果? – BrendanMcK

+0

非常確定它在我的鱈魚e我嘗試添加/更改Alpha通道。 BitBlt的工作方式應該是這樣,或者它只是顯示我的圖像,當我嘗試更改像藍色或全部通道的值時,沒有任何更改視覺效果。並且我已經檢查了返回值並且沒有任何方法失敗 – ColmanJ