為GDI函式增加透明度處理

2022-03-04 23:48:01 字數 2518 閱讀 2074

使用者對客戶端的ui的要求越來越高,採用alpha通道對前景背景做混合是提高ui質量的重要手段。

ui開發離不開gdi,然後要用傳統的gdi函式來處理alpha通道通常是乙個惡夢:雖然有alphablend這個api可以做alpha混合,但是前提必須是操作的dc中的點陣圖有alpha通道的資料,問題的關鍵在於gdi函式在操作的地方會把原來的alpha通道清空。

使用gdi做alpha混合還要增加透明度關鍵要解決2個問題:

1、需要把內容畫到乙個臨時點陣圖上,同時保護好alpha通道。

2、在於把臨時點陣圖的資料和原位圖做混合,而且不能改變鏤空部分原位圖的alpha通道的值。

在soui的render-gdi中我採用下面的類來實現gdi的半透明。

class

dcbuffer

~dcbuffer()

;bool bret=::alphablend(m_hdc,m_prc->left,m_prc->top,m_nwid,m_nhei,m_hmemdc,m_prc->left,m_prc->top,m_nwid,m_nhei,bf);

::deletedc(m_hmemdc);

::deleteobject(m_hbmp);

//恢復原dc的畫筆,畫刷,字型

::selectobject(m_hdc,m_hcurpen);

::selectobject(m_hdc,m_hcurbrush);

::selectobject(m_hdc,m_hcurfont);

}operator

hdc()

protected

: hdc m_hdc;

hdc m_hmemdc;

hbitmap m_hbmp;

lpbyte m_pbits;

byte m_byalpha;

lpcrect m_prc;

intm_nwid,m_nhei;

bool m_bcopybits;

hgdiobj m_hcurpen;

hgdiobj m_hcurbrush;

hgdiobj m_hcurfont;

};

下面以實現drawtext的半透明為例來分析如何實現gdi函式的半透明。

hresult srendertarget_gdi::drawtext( lpctstr psztext,int

cchlen,lprect prc,uint uformat)

if(cchlen == 0) return

s_ok;

return

s_ok;

}

首先來看如何解決alpha通道的保護問題。

為了在目標hdc上呼叫drawtext繪製文字,先宣告乙個dcbuffer物件:dcbuf。

dcbuffer的建構函式中,我們會建立乙個臨時的32位位圖。

再將原dc中的資料複製到臨時點陣圖中(注意,原位圖也是32位的)。

乙個非常重要的工作在於在呼叫gdi的drawtext之前,dcbuffer會先把臨時點陣圖中alpha通道置為255。這樣做的目的在於標識哪些畫素被drawtext修改過。

在呼叫了::drawtext後,srendertarget_gdi::drawtext會進入dcbuffer的析構函式。

在析構函式中,首先對alpha通道中的值取反,經過這一步操作,被::drawtext清空的點的alpha通道值被修改成255,而那些需要透明的點的alpha值則變成了0。

到這裡已經實現了對alpha通道的保護。

有了前面的基礎,做第二步的alphablend就簡單了,這裡只需要直接呼叫api:alphablend,注意blendfunction中幾個引數的設定。

下面解釋一下為什麼需要做上面的處理就可以實現gdi函式的半透明。

首先如drawtext這樣的gdi函式通常會產生透明效果:即矩形中的一部分點變色,而其它點不變色。

gdi函式只會將那些變色的點的alpha通道清0。我們的目標則是將變色的點的rgb值與目標做alpha混合。

通過將臨時點陣圖中的alpha值做取反處理,被gdi函式修改過的點的alpha變為255,而需要鏤空的點的alpha則變為了0。

此時再呼叫用alphablend做混合,對於那些需要鏤空的點,由於臨時點陣圖的alpha為0,混合後根據alphablend的公式,即不會改變原來的rgb值,也不會改變原來的alpha值。

對於那些被gdi函式改變過的點,由於其alpha值都變成了255,其rgb部分,alphablend會根據blendfunction中指定的alpha值來和原值混合,而alpha部分則被修改為255。

最終達到半透明效果。

注:dcbuffer中copybits這一步有時候不是必須的。不過很多函式如drawtext需要做反鋸齒處理,反鋸齒處理的關鍵也是和背景色做混合,因此從原位圖複製出資料也是很有必要的。

如果用gdi+也可以達到相同的效果,但是gdi+出了名的效率低,不知道gdi函式經過如此處理後效率會不會比gdi+慢,從我目前簡單的測試來看,效果還是很好的,效率也很高,有興趣的朋友可以比較一下。

Canvas 畫素處理之改變透明度

一 定義和用法 getimagedata 方法返回 imagedata 物件,該物件拷貝了畫布指定矩形的畫素資料。注意 imagedata物件不是影象,它規定了畫布上乙個部分 矩形 並儲存了該矩形內每個畫素的資訊。對於imagedata物件中的每個畫素,都存在著四方面的資訊,即rgba值 r 紅色 ...

Canvas 畫素處理之改變透明度

一 定義和用法 getimagedata 方法返回 imagedata 物件,該物件拷貝了畫布指定矩形的畫素資料。注意 imagedata物件不是影象,它規定了畫布上乙個部分 矩形 並儲存了該矩形內每個畫素的資訊。對於imagedata物件中的每個畫素,都存在著四方面的資訊,即rgba值 r 紅色 ...

ie8下透明度處理

css3新增屬性rgba和opacity 0 1 在ie8下無法使用 alpha opacity 0 100 0 100 0是透明 100是不透明。ie下的透明度屬性,子元素會繼承這個透明度。下面有阻斷子元素繼承方法。背景透明,文字不透明。html lang en documenttitle a.r...