View绘制系列(14)-Paint混合模式

Paint混合模式

前文中我们在绘制时所有的坐标都是经过精确计算的,但是在现实应用场景中,我们不能百分之百的保证所绘制的每个图像都是独立互不相交的,我们也有可能会遇到下图中的情形:

View绘制系列(14)-Paint混合模式

这时可能需要保留重合区域,也有可能保留其他区域,怎么去定制呢?使用XferMode即可。

关于Paint.setXferMode的官网说明如下:

Set or clear the transfer mode object. A transfer mode defines how source pixels (generate by a drawing command) are composited with the destination pixels (content of the render target).

PorterDuffXfermode is the most common transfer mode.

其是用来设置混合模式(直译过渡模式)的,混合模式指的是使用Canvas绘图方法绘制的元素与画布上已有内容的渲染组合方式。PorterDuffXfermode是最常用的混合模式对象。

PorterDuffXfermode只有一个含参的构造函数PorterDuffXfermode(PorterDuff.Mode mode),mode可选值有:

  • PorterDuff.Mode.CLEAR

  • PorterDuff.Mode.SRC

  • PorterDuff.Mode.DST

  • PorterDuff.Mode.SRC_OVER

  • PorterDuff.Mode.DST_OVER

  • PorterDuff.Mode.SRC_IN

  • PorterDuff.Mode.DST_IN

  • PorterDuff.Mode.SRC_OUT

  • PorterDuff.Mode.DST_OUT

  • PorterDuff.Mode.SRC_ATOP

  • PorterDuff.Mode.DST_ATOP

  • PorterDuff.Mode.XOR

  • PorterDuff.Mode.DARKEN

  • PorterDuff.Mode.LIGHTEN

  • PorterDuff.Mode.MULTIPLY

  • PorterDuff.Mode.SCREEN

  • PorterDuff.Mode.ADD

  • PorterDuff.Mode.OVERLAY

我们看到在这些混合模式中有SRCDST的区分,DST指的是先绘制的原始图片,SRC指的是我们将应用混合模式绘制的新图片,使用XferMode时应注意在新图层或者画布上做操作,在Android中常见的画布获取方式有两种:

  • onDraw函数中的canvas对象,在这里明显不适用

  • 使用Bitmap构造Canvas对象,相当于对Bitmap对象进行绘制

这里我们使用Bitmap的方式获取画布,并在该画布上进行XferMode的混合工作,完成后将Bitmap使用canvas.drawBitmap绘制在自定义View内,完整的onDraw代码如下:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    //获取先绘制的Bitmap对象,即DST Bitmap
    Bitmap dstBitmap = makeDst(getWidth()/2,getWidth()/2);
    //获取采用混合模式绘制的Bitmap对象,即SRC bitmap
    Bitmap srcBitmap = makeSrc(getWidth(),getWidth()/2);

    //使用Bitmap方式获取画布,创建一个和View大小相同的Bitmap对象
    Bitmap bitmap = createBitamp(getWidth(), getHeight());
    Canvas resultCanvas = new Canvas(bitmap);
    //获取Bitmap的Canvas画布对象
    Paint xfermodePaint = new Paint();
    //使用Bitmap的画布对象绘制DST bitmap
    resultCanvas.drawBitmap(dstBitmap, 00, xfermodePaint);
    //依次修改这里的PorterDuff.Mode.ADD为CLEAR...得到下表
    xfermodePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
    //使用混合模式将SRC bitmap绘制到Bitmap的画布内
    resultCanvas.drawBitmap(srcBitmap, 00, xfermodePaint);

    Paint paint = new Paint();
    //绘制混合结果到View上
    canvas.drawBitmap(bitmap,0,0,paint);
}

    //创建一个圆形bitmap,作为dst图
    private Bitmap makeDst(int width, int height) {
        Bitmap bm = createBitamp(width, height);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(0xFFFFCC44);
        c.drawOval(new RectF(00, width / 3 * 2, height / 3 * 2), p);
        return bm;
    }

    // 创建一个矩形bitmap,作为src图
    private Bitmap makeSrc(int width, int height) {
        Bitmap bm = createBitamp(width, height);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(0xFF66AAFF);
        c.drawRect(100100, width, height, p);
        return bm;
    }

    private Bitmap createBitamp(int w, int h){
        return Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    }

依次使用PorterDuffXfermode的各模式绘制效果,见下表:

混合模式 Paint.Style.STROKE 备注
PorterDuff.Mode.CLEAR

View绘制系列(14)-Paint混合模式

CLEAR模式下,画布上的所有内容将被清空
PorterDuff.Mode.SRC

View绘制系列(14)-Paint混合模式


SRC单独显示SRC Bitmap对象
PorterDuff.Mode.DST

View绘制系列(14)-Paint混合模式


DST单独现实DST Bitmap对象
PorterDuff.Mode.SRC_OVER

View绘制系列(14)-Paint混合模式

SRC_OVER,SRC,DST均绘制,同时SRC绘制在DST上
PorterDuff.Mode.DST_OVER

View绘制系列(14)-Paint混合模式

DST_OVER,SRC,DST均绘制,同时DST绘制在SRC上
PorterDuff.Mode.SRC_IN

View绘制系列(14)-Paint混合模式


绘制SRC中的重叠部分,其他部分不绘制
PorterDuff.Mode.DST_IN

View绘制系列(14)-Paint混合模式


绘制DST中的重叠部分,其他部分不绘制
PorterDuff.Mode.SRC_OUT

View绘制系列(14)-Paint混合模式


绘制SRC重叠部分以外的区域
PorterDuff.Mode.DST_OUT

View绘制系列(14)-Paint混合模式


绘制DST重叠部分以外的区域
PorterDuff.Mode.SRC_ATOP

View绘制系列(14)-Paint混合模式


绘制DST所在区域,并绘制SRC中的重叠部分
PorterDuff.Mode.DST_ATOP

View绘制系列(14)-Paint混合模式


绘制SRC所在区域,并绘制DST中的重叠部分
PorterDuff.Mode.XOR

View绘制系列(14)-Paint混合模式


绘制SRC,DST重叠部分以外的区域
PorterDuff.Mode.DARKEN

View绘制系列(14)-Paint混合模式


保留源像素和目标像素的最小分量,计算公式:

View绘制系列(14)-Paint混合模式

PorterDuff.Mode.LIGHTEN

View绘制系列(14)-Paint混合模式


保留源和目的像素的最大组分,计算公式:

View绘制系列(14)-Paint混合模式

PorterDuff.Mode.MULTIPLY

View绘制系列(14)-Paint混合模式


将源像素和目标像素相乘,计算公式:

View绘制系列(14)-Paint混合模式

PorterDuff.Mode.SCREEN

View绘制系列(14)-Paint混合模式


添加源像素和目标像素,然后减去源像素乘以目标像素,计算公式:

View绘制系列(14)-Paint混合模式

PorterDuff.Mode.ADD

View绘制系列(14)-Paint混合模式


将源像素添加到目标像素并饱和结果,计算公式:

View绘制系列(14)-Paint混合模式

PorterDuff.Mode.OVERLAY

View绘制系列(14)-Paint混合模式


根据目标颜色对源像素和目标像素进行乘法或筛选,计算公式:

View绘制系列(14)-Paint混合模式


原文始发于微信公众号(小海编码日记):View绘制系列(14)-Paint混合模式

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/67871.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!