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] 可以看到,它可能有多种情况,需要实际计算。
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

看到这里的童鞋快奖励自己一口辣条吧!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容