美文网首页
Android 图层混合模式PorterDuff.Mode

Android 图层混合模式PorterDuff.Mode

作者: 刘小厨 | 来源:发表于2020-03-31 17:51 被阅读0次

    Android 图层混合模式 PorterDuff.Mode

    PorterDuff.Mode它是将所绘制的图形的像素与Canvas中对应位置的像素按照一定规则进行混合,形成新的像素值,从而更新Canvas中最终的像素颜色值.
    PorterDuff.Mode共有18种
    Android 中使用 图层混合模式常见的地方有三种:

    1. 组合渲染ComposeShader (详见: Android Paint总结)

    2. 画笔: Paint.setXfermode()

    3. 颜色过滤器: PorterDuffColorFilter

    本文主要简单说下第二种 画笔: Paint.setXfermode()

    PorterDuff.Mode

    每一个图层混合模式代表一种规则,根据每种规则计算混合之后的透明通道值和颜色值
    使用图层混合模式有几个需要注意的点:

    图层混合模式仅作用于src源图像

    意思是:以下面谷歌的demo中的第一个为例使用的模式为PorterDuff.Mode.CLEAR
    ,源图像src为矩形图 目标图为圆形图dst,PorterDuff.Mode.CLEAR表示清除所有颜色值和透明通道,我们从效果可以看到,目标图dst只有与源图像src相交的地方才会有影响

    禁用硬件加速

    原因: 在Android api 14之后,图层混合的有些api是不支持硬件加速的,系统的硬件加速是默认开启的,所以在使用图层混合模式之前,禁用掉硬件加速 ,方式如下:

    //禁止硬件加速
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    

    离屏绘制

    原因: 在不采用离屏绘制的情况下,控件的背景会影响图层混合模式的计算结果,导致得到期望之外的效果
    我们看下使用/不使用 离屏绘制的区别:


    使用离屏绘制.gif 不使用离屏绘制.gif

    通过使用离屏绘制(离屏缓冲),把要绘制的内容单独绘制在缓冲层,保证Xfermode的使用不会出现错误的结果

    离屏绘制有两种使用方式,一般使用第一种方式就足够了:

    • Canvas.saveLayer() 可以做短时的离屏绘制,在绘制之前保存 ,绘制之后结束,使用方式如下:
     int saveId= canvas.saveLayer(0, 0, width, height, Canvas.ALL_SAVE_FLAG);
                    canvas.translate(x, y);
                    canvas.drawBitmap(mDstB, 0, 0, paint);//绘制操作
                    paint.setXfermode(xfermode);//设置xfermode
                    canvas.drawBitmap(mSrcB, 0, 0, paint);//绘制操作
                    paint.setXfermode(null); //用完清除
                    canvas.restoreToCount(saveId);//图层恢复
    
    • View.setLayerType() 直接把整个View都绘制在离屏缓冲中,使用如下:
    setLayerType(LAYER_TYPE_HARDWARE,paint);//使用GPU缓冲
    setLayerType(LAYER_TYPE_SOFTWARE,paint);//使用一个Bitmap缓冲
    

    下面我们直接看下 谷歌的 demo->Xfermodes.java
    效果图如下:

    Xfermodes.png

    看下PorterDuff.Mode各种模式以及代表的意思:

    //其中Sa全称为Source alpha表示源图的Alpha通道;Sc全称为Source color表示源图的颜色;Da全称为Destination alpha表示目标图的Alpha通道;Dc全称为Destination color表示目标图的颜色,[...,..]前半部分计算的是结果图像的Alpha通道值,“,”后半部分计算的是结果图像的颜色值。
        //效果作用于src源图像区域
        private static final Xfermode[] sModes = {
                //所绘制不会提交到画布上
                new PorterDuffXfermode(PorterDuff.Mode.CLEAR),
                //显示上层绘制的图像
                new PorterDuffXfermode(PorterDuff.Mode.SRC),
                //显示下层绘制图像
                new PorterDuffXfermode(PorterDuff.Mode.DST),
                //正常绘制显示,上下层绘制叠盖
                new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER),
    
                //上下层都显示,下层居上显示
                new PorterDuffXfermode(PorterDuff.Mode.DST_OVER),
                //取两层绘制交集,显示上层
                new PorterDuffXfermode(PorterDuff.Mode.SRC_IN),
                //取两层绘制交集,显示下层
                new PorterDuffXfermode(PorterDuff.Mode.DST_IN),
                //取上层绘制非交集部分,交集部分变成透明
                new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT),
    
                //取下层绘制非交集部分,交集部分变成透明
                new PorterDuffXfermode(PorterDuff.Mode.DST_OUT),
                //取上层交集部分与下层非交集部分
                new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP),
                //取下层交集部分与上层非交集部分
                new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP),
                //去除两图层交集部分
                new PorterDuffXfermode(PorterDuff.Mode.XOR),
    
                //取两图层全部区域,交集部分颜色加深
                new PorterDuffXfermode(PorterDuff.Mode.DARKEN),
                //取两图层全部区域,交集部分颜色点亮
                new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN),
                //取两图层交集部分,颜色叠加
                new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),
                //取两图层全部区域,交集部分滤色
                new PorterDuffXfermode(PorterDuff.Mode.SCREEN),
    
                //取两图层全部区域,交集部分饱和度相加
                new PorterDuffXfermode(PorterDuff.Mode.ADD),
                //取两图层全部区域,交集部分叠加
                new PorterDuffXfermode(PorterDuff.Mode.OVERLAY)
        };
    

    小案例:刮刮卡

    相关文章

      网友评论

          本文标题:Android 图层混合模式PorterDuff.Mode

          本文链接:https://www.haomeiwen.com/subject/pjnwyhtx.html