Paint之Xfermode的18種模式
請尊重原創(chuàng),轉(zhuǎn)載請注明出處【tianyl】的博客
關(guān)于的Android之玩轉(zhuǎn)View目錄
前言
說到Xfermode,實現(xiàn)過圓形圖像的同學(xué)一定不會陌生,雖說之前的Shader篇中介紹了一種用Shader實現(xiàn)圓形圖像的方法,不過使用最廣泛的,還是Xfermode
首先說明一下Xfermode是個什么東西,簡單來講,它就是將一張圖片,根據(jù)另一張圖片,來進(jìn)行一些處理,來達(dá)到想要的顯示效果,而它的處理方式,總共有18種,下面就來介紹一下這些處理方式
1 PorterDuff
PorterDuff.java是android.graphics包下的一個類,它有一個枚舉的子類Mode,這個Mode類就定義了這18種處理方式
因為篇幅原因這里就不放代碼了,直接貼圖片

上圖就是這18種處理模式,下圖是它們的處理結(jié)果(還有兩種新增的模式的圖在后面)

下面來分別介紹它們的處理規(guī)則
1.1 顏色計算說明
首先說明,對于這18種模式,Android都是通過兩張圖片的顏色值進(jìn)行特殊的計算,而得到一張新的圖片進(jìn)行實現(xiàn)的,用數(shù)組[x,y]表示(Sa表示原圖的alpha值,Da表示目標(biāo)圖的alpha值,Sc表示原圖的color值,Dc表示目標(biāo)圖的color值
其中x表示結(jié)果圖片的alpha值,y表示結(jié)果圖片的color值
1.2 PorterDuff.Mode.CLEAR
清除模式
Android源碼中的顏色數(shù)組為[0,0]
很顯然,這個模式下的圖標(biāo)就是什么都沒有,如上圖16種模式中的Clear
1.3 PorterDuff.Mode.SRC
原圖模式
Android源碼中的顏色數(shù)組為[Sa,Sc]
這個模式下的繪制出來的就是原圖
1.4 PorterDuff.Mode.Dst
目標(biāo)圖模式
Android源碼中的顏色數(shù)組為[Da, Dc]
這個模式下的繪制出來的就是目標(biāo)圖
1.5 PorterDuff.Mode.SRC_OVER
原圖覆蓋
Android源碼中的顏色數(shù)組為[Sa + (1 - Sa)*Da, Sc + (1 - Sa)*Dc]
很顯然,如果Sa透明度為1(即完全不透明,那么繪制的是原圖,否則繪制的是目標(biāo)圖,如果是半透明那么兩者都有)
顯示出來的效果就是原圖將目標(biāo)圖覆蓋了
1.6 PorterDuff.Mode.DST_OVER
目標(biāo)圖覆蓋
Android源碼中的顏色數(shù)組為[Sa + (1 - Sa)*Da, Dc + (1 - Da)*Sc]
和SRC_OVER正好相反,就不解釋了
顯示出來的效果就是目標(biāo)圖將原圖覆蓋了
1.7 PorterDuff.Mode.SRC_IN
繪制原圖,但是受目標(biāo)圖的alpha值影響
Android源碼中的顏色數(shù)組為[Sa * Da, Sc * Da]
如果Da(目標(biāo)圖的alpha值)為0,那么數(shù)組的值就是[0,0],所以這個模式只會繪制兩者相交的區(qū)域,并且相交區(qū)域受目標(biāo)圖的alpha值影響
1.8 PorterDuff.Mode.DST_IN
繪制目標(biāo)圖,受原圖alpha值影響
Android源碼中的顏色數(shù)組為[Sa * Da, Sa * Dc]
因為和SRC_IN相反,所以這里也不解釋了
1.9 PorterDuff.Mode.SRC_OUT
繪制原圖,去掉相交部分
Android源碼中的顏色數(shù)組為[Sa * (1 - Da), Sc * (1 - Da)]
很顯然,如果Da(目標(biāo)圖的alpha值)為1,那么數(shù)組值為[0,0],所以只會繪制目標(biāo)圖alpha值不為1的部分,并且最后顏色的也和目標(biāo)圖的alpha的值有關(guān)
1.10 PorterDuff.Mode.DST_OUT
繪制目標(biāo)圖,去掉相交部分
Android源碼中的顏色數(shù)組為[Da * (1 - Sa), Dc * (1 - Sa)]
和SRC_OUT相反,解釋略
1.11 PorterDuff.Mode.SRC_ATOP
主要繪制目標(biāo)圖,如果存在相交部分,則繪制原圖
Android源碼中的顏色數(shù)組為[Da, Sc * Da + (1 - Sa) * Dc]
顯然,alpha的值為Da,所以只繪制目標(biāo)圖,而當(dāng)Sa為1時(完全不透明)color值為Sc * Da,所以相交部分繪制原圖,但是受Da值的影像
1.12 PorterDuff.Mode.DST_ATOP
主要繪制原圖,如果存在相交部分,則繪制目標(biāo)圖
Android源碼中的顏色數(shù)組為[Sa, Sa * Dc + Sc * (1 - Da)]
和SRC_ATOP相反,解釋略
1.13 PorterDuff.Mode.XOR
異或模式,相交部分不繪制,繪制不相交部分
Android源碼中的顏色數(shù)組為[Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
顯然,alpha的值為Sa + Da - 2 * Sa * Da,只有Sa=Da=1的時候,這個值為0,也就是兩者完全不透明并且相交的時候不繪制,除此之外都會繪制
color值受兩者的color值影響,計算公式是:Sc * (1 - Da) + (1 - Sa) * Dc
1.14 PorterDuff.Mode.DARKEN
字面翻譯就是變暗模式,兩者都繪制,并且在兩者相交的位置對顏色進(jìn)行處理(也就是所謂的變暗)
Android源碼中的顏色數(shù)組為[Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)]
alpha值為Sa + Da - Sa*Da,因為alpha的值在0到1之間,所以alpha值是增大的,所以更加不透明了
color值為Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)
1.15 PorterDuff.Mode.LIGHTEN
和DARKEN相反,字面意思就是變亮
Android源碼中的顏色數(shù)組為[Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)]
alpha計算和DARKEN一樣,更加不透明,顏色計算這里取的是max(Sc, Dc),而DARKEN里取的是min(Sc, Dc),我們知道顏色越小就越暗(黑色是000000,白色是ffffff)
1.16 PorterDuff.Mode.MULTIPLY
字面翻譯就是正片疊底,只繪制相交區(qū)域,并處理
Android源碼中的顏色數(shù)組為[Sa * Da, Sc * Dc]
顯然,當(dāng)Sa為0或者Da為0的時候,全透明,只有當(dāng)兩者都不透明時,繪制圖像,color值為Sc * Dc
1.17 PorterDuff.Mode.SCREEN
字面翻譯就是屏幕(說好聽一點叫濾色),繪制所有區(qū)域,并處理
Android源碼中的顏色數(shù)組為[Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]
1.18 PorterDuff.Mode.ADD
疊加飽和度,這個算是后面加的一種模式
官方文檔上的alpha值和color值計算規(guī)則

效果圖如下

1.19 PorterDuff.OVERLAY
疊加模式
官方文檔上的alpha值和color值計算規(guī)則

效果圖如下

由于后兩者ADD模式和OVERLAY是后面加的,所有這里就直接使用Google官方的效果圖展示了
1.20 總結(jié)
到此,關(guān)于Xfermode的18種模式就介紹完了,當(dāng)然,關(guān)于這些模式中的顏色計算和圖片計算,本文都只是說明了一個大概,具體的含義并沒有深究(畢竟我只是一個程序員,不懂美術(shù)啊),如果有同學(xué)對這方面有興趣,可以看一下這篇科普,關(guān)于部分顏色處理公式的物理含義都有解釋
最后,由于這部分內(nèi)容是科普向的內(nèi)容,就不放demo展示了,后續(xù)做一些特效實現(xiàn)吧(ˇ?ˇ)