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 - SaDa, Sc(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)]取較暗的透明值,色值計算相對複雜。
LIGHTEN[Sa + Da - SaDa, 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]可以看到,它可能有多種情況,需要實際計算。
ADDSaturate(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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章