使用者對客戶端的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的半透明。
classdcbuffer
~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,intcchlen,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...