1. 程式人生 > >Android靈魂畫家的18種混合模式

Android靈魂畫家的18種混合模式

image

⚠️️ Warning!Warning!前方高能,閱讀本文可能需要3分鐘哦!

有什麼料?

  1. 重新認識神祕的PorterDuffXfermode
  2. 學會正確的使用PorterDuffXfermode
  3. 收穫【兩張示例圖】,幫助你在實際中正確的運用各種混合模式。

解密PorterDuffXfermode

先上兩張示例圖,大家快來儲存啊!

image

image

注:這兩張圖僅用了兩個強大的View完成的。【從未如此驚豔!你好,SuperTextView (v1.1) - http://www.jianshu.com/p/1b91e11e441d】,你值得擁有!

自己繪過圖的筒靴一定見過或者用過mPaint.setXfermode(Xfermode xfermode),它是幹什麼的呢?它的作用就是將畫布上的當前影象(即目標影象DST)和後面需要繪製的影象(即源影象SRC)按照一定的演算法進行混合。簡單點說就是把源影象SRC目標影象DST進行混合。而ProterDuffXfermode繼承自Xfermode,提供了18畫素混合模式的演算法,它們是由Thomas PorterTom Duff在 於1984年7月的一篇名為【《Compositing Digital Images》https://keithp.com/~keithp/porterduff/p253-porter.pdf】

的論文中提出的。這對影象處理來說具有重大的意義。

Xfermode的意義你知道嗎?

在上面的兩張圖中,CoorChice已經向筒靴們展示了使用Xfermode來混合簡單的圖形所達到的效果。

對於一些比較難畫的圖形,如果通過運算座標和尺寸去繪製當然是可以的。但是這些運算將會非常複雜!如果合理的使用Xfermode去將一些簡單的圖形進行混合,同樣可以獲得你所期望的複雜圖形。在CoorChice的這篇文章【從未如此驚豔!你好,SuperTextView (v1.1)http://www.jianshu.com/p/1b91e11e441d】 中,CoorChice向你展示了一個掃光特效,它的兩端有個截斷效果,就是通過Xfermode

完成的。如果靠計算的話,實現起來會稍微費點力。

當然,這些並不能發揮Xfermode的真正威力。如果你使用它對一些圖片進行混合,你會看到Xfermode到底能做什麼不可思議的事!比如,在 《Compositing Design Images》 中就有一個這樣的例子:

image

圖中最後Composite的結果就是前面幾張圖片通過一定組合合成的,這是合成演算法:

(FFire plus (BFire out Plant)) over Darken(Plant, .8) over Stars .

你看,Xfermode就是如此的強大,通過合理的組合,能合成圖片。

再一看張CoorChice用圖片合成的各種效果:

image

哇!這魚飛起來啦!

18種混合模式

《Compositing Degital Images》 中,Thomas PorterTom Duff展示了12中基本的混合模式:
image
我們可以將上圖中的A對應目標影象DSTB對應源影象SRC去理解。通過組合這12種混合模式,足夠實現任意的2D影象合成效果了。十分的強大。對照著上面CoorChice畫的圖理解吧。

也許筒靴們平時都只聽說PorterDuff.Mode是16種模式,因為官方的例子中就出現了16種模式。但事實上,Android提供的混合模式共有18種,筒靴們在上圖中也是能看到滴。就是最後一排的ADDOVERLAY是不常被提到的。

下面CoorChice和大家一起捋一捋這18種混合模式:
在此之前,先說明下各個符號的意義。
在支援透明通道的情況下,一個畫素點通過alpha透明值和RGB色值來描述,即[alpha, rgb]



Sa: Src Alpha,即源影象的透明值

Sc:Src color,即源影象的色值

Da:Dst Alpha,即目標影象的透明值

Dc:Dst color,即目標影象的色值
PorterDuff.Mode 演算法 作用
CLEAR [0, 0] 影象的alpha和rgb值均為0.
SRC [Sa, Sc] 取源影象的值。
DST [Da, Dc] 取目標影象的值。
SRC_OVER [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] 結果是Src蓋在了Dst上。注意alpha值的影響,不一定是這個結果。
DST_OVER [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] 結果是Dst蓋在了Src上。注意alpha值的影響,不一定是這個結果。
SRC_IN [Sa * Da, Sc * Da] 結果是在Src色值不為0的地方,且Dst透明值不為0的地方能看到合成影象。
DST_IN [Sa * Da, Sa * Dc] 結果是在Dst色值不為0的地方,且Src透明值不為0的地方能看到合成影象。
SRC_OUT [Sa * (1 - Da), Sc * (1 - Da)] 結果是在Src色值不為0,且Dst透明值不為1的地方能看到合成影象。
DST_OUT [Da * (1 - Sa), Dc * (1 - Sa)] 結果是在Dst色值不為0,且Src透明值不為1的地方能看到合成影象。
SRC_ATOP [Da, Sc * Da + (1 - Sa) * Dc] 結果是在Src和Dst色值不同時為0,且Dst透明值不為0,且當Src色值為0但Src透明值不為1的地方能看到合成影象。
DST_ATOP [Sa, Sa * Dc + Sc * (1 - Da)] 結果是在Src和Dst色值不同時為0,且Src透明值不為0,且當Dst色值為0但Dst透明值不為1的地方能看到合成影象。
XOR [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] 在不相交的地方按原樣繪製源影象和目標影象,相交的地方受到對應alpha和色值影響。
DARKEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] 取較暗的透明值,色值計算相對複雜。
LIGHTEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] 取較亮的透明值,色值計算相對複雜。
MUTIPLY [Sa * Da, Sc * Dc] 結果是在Src和Dst透明值均不為0,且色值均不為0的地方能看到合成影象。
SCREEN [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] 可以看到,它可能有多種情況,需要實際計算。
ADD Saturate(S + D)
OVERLAY

筒靴們對著上面【Bitmap繪製】圖來看這18種混合模式。

令人困惑的圖

筒靴們可以看到【Bitmap繪製】圖和官方的例子圖是一樣一樣的,但是很多筒靴自己畫出來的效果卻和【Canvas直接繪製】圖是一樣一樣的。嗯,百思不解!有沒有可能是官方的例子錯了呢?

想多了,沒有的。只是筒靴們沒注意到官方標準例子中的細節:
- 首先需要關閉硬體加速。因為硬體加速模式下,渲染是通過GPU完成的,和普通CPU渲染可能有點不一樣,導致了部分合成演算法呈現的效果有差異。你可以看看我的這篇文章【用兩張圖告訴你,為什麼你的App會卡頓?http://www.jianshu.com/p/df4d5ec779c8】,瞭解下View的繪製流程。
- 其次,畫素混合是對兩個區域進行的。官方的示例中,黃圓和藍正方形都是畫在大小和黑色邊框相等的Bitmap上的,然後再將兩個Bitmap的畫素進行混合,此時兩個Bitmap的區域是【完全重合】的。所以得到了標準效果。而很多同學可能沒注意,往往就以為兩個區域大小就是兩個圖形的外接矩形的大小,而它們相交的地方只有1/4。所以得到了“Canvas直接繪製”圖的效果。兩種方式最大的差別在於,【Bitmap繪製】圖中有一部分透明畫素點參與了混合,而【Canvas直接繪製】圖中幾乎沒有。

這是CoorChice寫的示例,就是上面幾幅圖的實現,【Github:https://github.com/chenBingX/CoorChiceLibOne/blob/448cf36e0b33fb667cb4fd5a8d8db2651bf0647e/app/src/main/java/com/chenbing/coorchicelibone/Views/PorterDuffXDemoActivity.java】,大家可以對照的動手感受一下。

總結

  • 抽出空餘時間寫文章分享需要動力,還請各位看官動動小手點個贊,給我點鼓勵
  • 我一直在不定期的創作新的乾貨,想要上車只需進到我的【個人主頁】點個關注就好了哦。發車嘍~

本篇文章向大家詳細的展示了強大的PorterDuffXfermode的正確開啟方式,CoorChice相信以後不會再有筒靴抱怨:我的天吶!這玩意兒有毒!為什麼我合成出來的影象和官方示例不一樣!

參考連結

  1. Api PorterDuff.Mode - https://developer.android.com/reference/android/graphics/PorterDuff.Mode.html
  2. Xfermode in android - http://weishu.me/2015/09/23/Xfermode-in-android/
  3. Compositing Digital Images - https://keithp.com/~keithp/porterduff/p253-porter.pdf

看到這裡的童鞋快獎勵自己一口辣條吧!