一、Xfermode
Xfermode表明图层的混合形式,用于描绘两个图层之间进行融合时,像素点进行计算的规则。
在API16之前,Xfermode有3个子类:AvoidXfermode、PixelXorXfermode、PorterDuffXfermode。但在API16以后,前两个现已过期,乃至从源码里移除,所以咱们只需学习PorterDuffXfermode
即可。
1.1、PorterDuffXfermode
PorterDuffXfermode
最早是在1984年由Porter和Duff两人发表的论文《Compositing Digital Images》中出现,所以该混合形式也依据作者来命名。
PorterDuffXfermode
结构函数需求指定一个PorterDuff.Mode
,而PorterDuff.Mode在以下地方都会触及:
1、ComposeShader
2、Paint.setXfermode()
3、PorterDuffColorFilter
它供给18种形式可选项:
PorterDuff.Mode | 公式 |
---|---|
PorterDuff.Mode.CLEAR |
alphaout=0alpha_{out} = 0 Cout=0C_{out} = 0 |
PorterDuff.Mode.SRC |
alphaout=alphasrcalpha_{out} = alpha_{src} Cout=CsrcC_{out} = C_{src} |
PorterDuff.Mode.DST |
alphaout=alphadstalpha_{out} = alpha_{dst} Cout=CdstC_{out} = C_{dst} |
PorterDuff.Mode.SRC_OVER |
alphaout=alphasrc+(1−alphasrc)∗alphadstalpha_{out} = alpha_{src} + (1 – alpha_{src}) * alpha_{dst} Cout=Csrc+(1−alphasrc)∗CdstC_{out} = C_{src} + (1 – alpha_{src}) * C_{dst} |
PorterDuff.Mode.DST_OVER |
alphaout=alphadst+(1−alphadst)∗alphasrcalpha_{out} = alpha_{dst} + (1 – alpha_{dst}) * alpha_{src} Cout=Cdst+(1−alphadst)∗CsrcC_{out} = C_{dst} + (1 – alpha_{dst}) * C_{src} |
PorterDuff.Mode.SRC_IN |
alphaout=alphasrc∗alphadstalpha_{out} = alpha_{src} * alpha_{dst} Cout=Csrc∗alphadstC_{out} = C_{src} * alpha_{dst} |
PorterDuff.Mode.DST_IN |
alphaout=alphasrc∗alphadstalpha_{out} = alpha_{src} * alpha_{dst} Cout=Cdst∗alphasrcC_{out} = C_{dst} * alpha_{src} |
PorterDuff.Mode.SRC_OUT |
alphaout=(1−alphadst)∗alphasrcalpha_{out} = (1 – alpha_{dst}) * alpha_{src} Cout=(1−alphadst)∗CsrcC_{out} = (1 – alpha_{dst}) * C_{src} |
PorterDuff.Mode.DST_OUT |
alphaout=(1−alphasrc)∗alphadstalpha_{out} = (1 – alpha_{src}) * alpha_{dst} Cout=(1−alphasrc)∗CdstC_{out} = (1 – alpha_{src}) * C_{dst} |
PorterDuff.Mode.SRC_ATOP |
alphaout=alphadstalpha_{out} = alpha_{dst} Cout=alphadst∗Csrc+(1−alphasrc)∗CdstC_{out} = alpha_{dst} * C_{src} + (1 – alpha_{src}) * C_{dst} |
PorterDuff.Mode.DST_ATOP |
alphaout=alphasrcalpha_{out} = alpha_{src} Cout=alphasrc∗Cdst+(1−alphadst)∗CsrcC_{out} = alpha_{src} * C_{dst} + (1 – alpha_{dst}) * C_{src} |
PorterDuff.Mode.XOR |
alphaout=(1−alphadst)∗alphasrc+(1−alphasrc)∗alphadstalpha_{out} = (1 – alpha_{dst}) * alpha_{src} + (1 – alpha_{src}) * alpha_{dst} Cout=(1−alphadst)∗Csrc+(1−alphasrc)∗CdstC_{out} = (1 – alpha_{dst}) * C_{src} + (1 – alpha_{src}) * C_{dst} |
PorterDuff.Mode.DARKEN |
alphaout=alphasrc+alphadst−alphasrc∗alphadstalpha_{out} = alpha_{src} + alpha_{dst} – alpha_{src} * alpha_{dst} Cout=(1−alphadst)∗Csrc+(1−alphasrc)∗Cdst+min(Csrc,Cdst)C_{out} = (1 – alpha_{dst}) * C_{src} + (1 – alpha_{src}) * C_{dst} + min(C_{src}, C_{dst}) |
PorterDuff.Mode.LIGHTEN |
alphaout=alphasrc+alphadst−alphasrc∗alphadstalpha_{out} = alpha_{src} + alpha_{dst} – alpha_{src} * alpha_{dst} Cout=(1−alphadst)∗Csrc+(1−alphasrc)∗Cdst+max(Csrc,Cdst)C_{out} = (1 – alpha_{dst}) * C_{src} + (1 – alpha_{src}) * C_{dst} + max(C_{src}, C_{dst}) |
PorterDuff.Mode.MULTIPLY |
alphaout=alphasrc∗alphadstalpha_{out} = alpha_{src} * alpha_{dst} Cout=Csrc∗CdstC_{out} = C_{src} * C_{dst} |
PorterDuff.Mode.SCREEN |
alphaout=alphasrc+alphadst−alphasrc∗alphadstalpha_{out} = alpha_{src} + alpha_{dst} – alpha_{src} * alpha_{dst} Cout=Csrc+Cdst−Csrc∗CdstC_{out} = C_{src} + C_{dst} – C_{src} * C_{dst} |
PorterDuff.Mode.ADD |
alphaout=max(0,min(alphasrc+alphadst,1))alpha_{out} = max(0, min(alpha_{src} + alpha_{dst}, 1)) Cout=max(0,min(Csrc+Cdst,1)C_{out} = max(0, min(C_{src} + C_{dst}, 1) |
PorterDuff.Mode.OVERLAY |
alphaout=alphasrc+alphadst−alphasrc∗alphadstalpha_{out} = alpha_{src} + alpha_{dst} – alpha_{src} * alpha_{dst} Cout={2∗Csrc∗Cdst2∗Cdst<dstalphasrc∗dst−2(dst−Csrc)(src−Cdst)otherwiseC_{out} = begin{cases} 2 * C_{src} * C_{dst} & 2 * C_{dst} lt alpha_{dst} \ alpha_{src} * alpha_{dst} – 2 (alpha_{dst} – C_{src}) (alpha_{src} – C_{dst}) & otherwise end{cases} |
各种形式下的作用如下图所示:
-
1、假如原图和方针图巨细共同(图中,两者巨细均占满整个小方格区域):
-
2、假如原图和方针图巨细不共同(图中,两者巨细为可见巨细):
这里能够发现,两种作用是不一样的,谷歌官方给的是第一种,但是,通常情况应该是第二种,具体原因可参考该文章。
比方咱们画一个矩形,应该按第二种作用来考虑,因为源图和方针图巨细不共同;假如画相同巨细的Bitmap,则按第一种做。
在实践应用中,咱们能够从以下三个方面来决议运用哪种形式:
1、方针图画和源图画混合,需不需求生成色彩的叠加特效。假如需求,则从色彩叠加相关形式中挑选,有Mode.ADD(饱和度相加)、Mode.DARKEN(变暗)、Mode.LIGHTEN(变亮)、Mode.MULTIPLY (正片叠底)、Mode.OVERLAY(叠加)、Mode.SCREEN(滤色)。
2、当不需求特效,而需求依据某张图片的通明像素来裁剪时,就需求运用SRC相关形式或DST相关形式了。而SRC相关形式与DST相关形式是相通的,唯一不同的是决议当前哪个图画是方针图画和源图画。
3、当需求清空图画时,运用Mode.CLEAR形式。
1.1、实例:
二、硬件加速
2.1、View的制作模型
1、没有硬件加速:
invalidate the view hierarchy ——> draw the view hierarchy
2、有硬件加速:
invalidate the view hierarchy ——> record and update the display list ——> draw the display list
2.2、敞开硬件加速后的反常
1、制作不正确:可能运用了不支撑硬件加速的操作, 需求封闭硬件加速或许绕过该操作
2、抛出反常:可能运用了不支撑硬件加速的操作, 需求封闭硬件加速或许绕过该操作
2.3、禁用GPU硬件加速
在Android系统中,有4个不同等级的翻开或许封闭硬件加速操作:
1、Application等级:
<application android:hardwareAccelerated="false">
默认为true,用于控制这个app是否敞开硬件加速。
2、Activity等级:
<activity android:hardwareAccelerated="false">
3、Window等级:(只支撑敞开操作)
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
4、View等级:(只支撑封闭操作)
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
LAYER_TYPE_HARDWARE
,运用硬件加速(GPU)进行制作
LAYER_TYPE_SOFTWARE
,运用CPU进行制作
或许布局文件中,指定以下属性:
android:layerType="software"
2.4、检测是否敞开硬件加速
1、view.isHardwareAccelerated()
假如回来true,表明view挂在一个敞开了硬件加速的Window之下,也就意味着,它在制作时,并不一定敞开了硬件加速。
2、canvas.isHardwareAccelerated()
假如回来true,因为着canvas在制作的时候启用了硬件加速,尽量选用此方法来判断是否敞开了硬件加速。