canvas.drawBitmap(srcBmp, width / 2, height / 2, mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
在saveLayer之前就用绿色画笔填充了背景,效果如下:
那么如果这个时候我们把saveLayer函数去掉,会发生什么呢?
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.GREEN);
canvas.drawBitmap(dstBmp, 0, 0, mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(srcBmp, width / 2, height / 2, mPaint);
mPaint.setXfermode(null);
}
效果如下:
这个时候,区域二居然显示出来了,这完全不符合SRC_IN的算法规则呀,为什么会出现这种情况呢?
1、调用saveLayer的绘图流程:
在调用saveLayer()函数时,会生成一块全新的画布,这块画布的大小就是我们所指定的所要保存区域的大小。新生成的画布是完全透明的,在调用saveLayer函数后所有的绘图都在这上面进行。
在利用Xfermode绘图时,会把之前画布上所有的内容都作为目标图像,而在调用saveLayer函数新生成的画布上,只有dstBmp对应的圆形,所以,除与圆形相交之外的位置都是空白像素。
对于Xfermode而言,在绘图完成之后,会把调用saveLayer函数所产生的透明画布覆盖在原来的画布上面,以形成最终的显示结果。
Xfermode的合成过程如下:
中间的透明画布就是saverLayer()函数自动生成的,最上面的透明图层是通过调用drawBitmap()函数生成的。我们知道,**每次调用canvas.drawXXX系列函数,都会生成一个透明图层来专门绘制这个图形,而每次生成的图层都会叠加到最近的画布上面。**因为我们这里对源图像应用了Xfermode算法,所以在叠加到就近的调用saveLayer()函数生成的画布上时,会进行计算。
正是因为咋使用Xfermode计算时,目标图像是绘制在新建的透明画布上的,所以除图形以外的区域全部都是透明像素,最终显示的结果是正确的。
2、没有saveLayer()函数时的绘图流程
去掉saveLayer后,就不会新建透明画布了,所有的绘图操作就都在原始画布上进行了。
由于先把图形染绿,再绘制了一个圆形,在使用Xfermode时来画源图像的时候,在目标画布上是没有透明像素的,如下所示:
结论为:
调用saveLayer()函数会产生一块全新的透明画布,大小与指定保存区域大小一致,后面的绘图操作都放在这个画布上进行。绘制结束后,会直接覆盖在原始画布上显示。
画布与图层
下面讲述关于画布(Bitmap)、图层(Layer)和Canvas的概念
-
图层(Layer):每次调用canvas.drawXX