Android之玩转View(四):Paint之Xfermode的18种模式

Paint之Xfermode的18种模式

请尊重原创,转载请注明出处【tianyl】的博客

关于的Android之玩转View目录

前言

说到Xfermode,实现过圆形图像的同学一定不会陌生,虽说之前的Shader篇中介绍了一种用Shader实现圆形图像的方法,不过使用最广泛的,还是Xfermode

首先说明一下Xfermode是个什么东西,简单来讲,它就是将一张图片,根据另一张图片,来进行一些处理,来达到想要的显示效果,而它的处理方式,总共有18种,下面就来介绍一下这些处理方式

1 PorterDuff

PorterDuff.java是android.graphics包下的一个类,它有一个枚举的子类Mode,这个Mode类就定义了这18种处理方式

因为篇幅原因这里就不放代码了,直接贴图片


Android之玩转View(四):Paint之Xfermode的18种模式_第1张图片

上图就是这18种处理模式,下图是它们的处理结果(还有两种新增的模式的图在后面)


Android之玩转View(四):Paint之Xfermode的18种模式_第2张图片

下面来分别介绍它们的处理规则

1.1 颜色计算说明

首先说明,对于这18种模式,Android都是通过两张图片的颜色值进行特殊的计算,而得到一张新的图片进行实现的,用数组[x,y]表示(Sa表示原图的alpha值,Da表示目标图的alpha值,Sc表示原图的color值,Dc表示目标图的color值

其中x表示结果图片的alpha值,y表示结果图片的color值

1.2 PorterDuff.Mode.CLEAR

清除模式
Android源码中的颜色数组为[0,0]
很显然,这个模式下的图标就是什么都没有,如上图16种模式中的Clear

1.3 PorterDuff.Mode.SRC

原图模式
Android源码中的颜色数组为[Sa,Sc]
这个模式下的绘制出来的就是原图

1.4 PorterDuff.Mode.Dst

目标图模式
Android源码中的颜色数组为[Da, Dc]
这个模式下的绘制出来的就是目标图

1.5 PorterDuff.Mode.SRC_OVER

原图覆盖
Android源码中的颜色数组为[Sa + (1 - Sa)*Da, Sc + (1 - Sa)*Dc]
很显然,如果Sa透明度为1(即完全不透明,那么绘制的是原图,否则绘制的是目标图,如果是半透明那么两者都有)

显示出来的效果就是原图将目标图覆盖了

1.6 PorterDuff.Mode.DST_OVER

目标图覆盖
Android源码中的颜色数组为[Sa + (1 - Sa)*Da, Dc + (1 - Da)*Sc]
和SRC_OVER正好相反,就不解释了

显示出来的效果就是目标图将原图覆盖了

1.7 PorterDuff.Mode.SRC_IN

绘制原图,但是受目标图的alpha值影响
Android源码中的颜色数组为[Sa * Da, Sc * Da]
如果Da(目标图的alpha值)为0,那么数组的值就是[0,0],所以这个模式只会绘制两者相交的区域,并且相交区域受目标图的alpha值影响

1.8 PorterDuff.Mode.DST_IN

绘制目标图,受原图alpha值影响
Android源码中的颜色数组为[Sa * Da, Sa * Dc]
因为和SRC_IN相反,所以这里也不解释了

1.9 PorterDuff.Mode.SRC_OUT

绘制原图,去掉相交部分
Android源码中的颜色数组为[Sa * (1 - Da), Sc * (1 - Da)]
很显然,如果Da(目标图的alpha值)为1,那么数组值为[0,0],所以只会绘制目标图alpha值不为1的部分,并且最后颜色的也和目标图的alpha的值有关

1.10 PorterDuff.Mode.DST_OUT

绘制目标图,去掉相交部分
Android源码中的颜色数组为[Da * (1 - Sa), Dc * (1 - Sa)]
和SRC_OUT相反,解释略

1.11 PorterDuff.Mode.SRC_ATOP

主要绘制目标图,如果存在相交部分,则绘制原图
Android源码中的颜色数组为[Da, Sc * Da + (1 - Sa) * Dc]

显然,alpha的值为Da,所以只绘制目标图,而当Sa为1时(完全不透明)color值为Sc * Da,所以相交部分绘制原图,但是受Da值的影像

1.12 PorterDuff.Mode.DST_ATOP

主要绘制原图,如果存在相交部分,则绘制目标图
Android源码中的颜色数组为[Sa, Sa * Dc + Sc * (1 - Da)]

和SRC_ATOP相反,解释略

1.13 PorterDuff.Mode.XOR

异或模式,相交部分不绘制,绘制不相交部分
Android源码中的颜色数组为[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

字面翻译就是变暗模式,两者都绘制,并且在两者相交的位置对颜色进行处理(也就是所谓的变暗)
Android源码中的颜色数组为[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源码中的颜色数组为[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

字面翻译就是正片叠底,只绘制相交区域,并处理
Android源码中的颜色数组为[Sa * Da, Sc * Dc]

显然,当Sa为0或者Da为0的时候,全透明,只有当两者都不透明时,绘制图像,color值为Sc * Dc

1.17 PorterDuff.Mode.SCREEN

字面翻译就是屏幕(说好听一点叫滤色),绘制所有区域,并处理
Android源码中的颜色数组为[Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]

1.18 PorterDuff.Mode.ADD

叠加饱和度,这个算是后面加的一种模式
官方文档上的alpha值和color值计算规则


Android之玩转View(四):Paint之Xfermode的18种模式_第3张图片

效果图如下


Android之玩转View(四):Paint之Xfermode的18种模式_第4张图片

1.19 PorterDuff.OVERLAY

叠加模式
官方文档上的alpha值和color值计算规则


Android之玩转View(四):Paint之Xfermode的18种模式_第5张图片

效果图如下


Android之玩转View(四):Paint之Xfermode的18种模式_第6张图片

由于后两者ADD模式和OVERLAY是后面加的,所有这里就直接使用Google官方的效果图展示了

1.20 总结

到此,关于Xfermode的18种模式就介绍完了,当然,关于这些模式中的颜色计算和图片计算,本文都只是说明了一个大概,具体的含义并没有深究(毕竟我只是一个程序员,不懂美术啊),如果有同学对这方面有兴趣,可以看一下这篇科普,关于部分颜色处理公式的物理含义都有解释

最后,由于这部分内容是科普向的内容,就不放demo展示了,后续做一些特效实现吧(ˇˍˇ)

你可能感兴趣的:(Android之玩转View(四):Paint之Xfermode的18种模式)