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
我们看到在这些混合模式中有SRC
和DST
的区分,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, 0, 0, xfermodePaint);
//依次修改这里的PorterDuff.Mode.ADD为CLEAR...得到下表
xfermodePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
//使用混合模式将SRC bitmap绘制到Bitmap的画布内
resultCanvas.drawBitmap(srcBitmap, 0, 0, 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(0, 0, 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(100, 100, 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 |
CLEAR模式下,画布上的所有内容将被清空 | |
PorterDuff.Mode.SRC |
SRC单独显示SRC Bitmap对象 | |
PorterDuff.Mode.DST |
DST单独现实DST Bitmap对象 | |
PorterDuff.Mode.SRC_OVER |
SRC_OVER,SRC,DST均绘制,同时SRC绘制在DST上 | |
PorterDuff.Mode.DST_OVER |
DST_OVER,SRC,DST均绘制,同时DST绘制在SRC上 | |
PorterDuff.Mode.SRC_IN |
绘制SRC中的重叠部分,其他部分不绘制 | |
PorterDuff.Mode.DST_IN |
绘制DST中的重叠部分,其他部分不绘制 | |
PorterDuff.Mode.SRC_OUT |
绘制SRC重叠部分以外的区域 | |
PorterDuff.Mode.DST_OUT |
绘制DST重叠部分以外的区域 | |
PorterDuff.Mode.SRC_ATOP |
绘制DST所在区域,并绘制SRC中的重叠部分 | |
PorterDuff.Mode.DST_ATOP |
绘制SRC所在区域,并绘制DST中的重叠部分 | |
PorterDuff.Mode.XOR |
绘制SRC,DST重叠部分以外的区域 | |
PorterDuff.Mode.DARKEN |
保留源像素和目标像素的最小分量,计算公式: | |
PorterDuff.Mode.LIGHTEN |
保留源和目的像素的最大组分,计算公式: | |
PorterDuff.Mode.MULTIPLY |
将源像素和目标像素相乘,计算公式: | |
PorterDuff.Mode.SCREEN |
添加源像素和目标像素,然后减去源像素乘以目标像素,计算公式: | |
PorterDuff.Mode.ADD |
将源像素添加到目标像素并饱和结果,计算公式: | |
PorterDuff.Mode.OVERLAY |
根据目标颜色对源像素和目标像素进行乘法或筛选,计算公式: |
原文始发于微信公众号(小海编码日记):View绘制系列(14)-Paint混合模式
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/67871.html