PorterDuffXfermode学习笔记

来源:互联网 发布:it学校 编辑:程序博客网 时间:2024/06/05 18:22

PorterDuffXfermode是什么

PorterDuffXfermode是一种规则
PorterDuffXfermode是一种颜色混合的规则
PorterDuffXfermode用于实现新绘制的像素(SRC)与Canvas上对应位置已有的像素(DEST)按照混合规则进行颜色混合。

记住:先绘制的图形为DEST

这个混合规则一个基本的知识点是,一个图片是由a和c组成的,a表示透明度,c表示color,其实这个规则,就是利用DEST的a和c的值与SRC的a和c进行计算得到的(即:Sa 、Da、Sc 、Da这四个值的混合运算)

简单讲,你用canvas先绘制一个黄色的圆形,再错位绘制一个蓝色方形,如果不使用PorterDuffXfermode规则的话,你只能得到两个效果,要么圆形覆盖方形,要么方形覆盖圆形,相交的部分要么是圆形的黄色,要么是方形的蓝色。

按照上述简单规则混合得到的效果太单一了,所以出现了PorterDuffXfermode模式

Android在绘图时会先检查该画笔Paint对象有没有设置Xfermode,如果没有设置Xfermode,那么直接将绘制的图形覆盖Canvas对应位置原有的像素;如果设置了Xfermode,那么会按照Xfermode具体的规则来更新Canvas中对应位置的像素颜色。

使用方法

离屏绘制:我们需要把绘制的核心代码放在saveLayer()和restoreToCount()之间即可。

//★禁用硬件加速:setLayerType(View.LAYER_TYPE_SOFTWARE, null);  //★新建图层      int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);        //★TODO 核心绘制代码        //1.画DEST图形       canvas.drawCircle(r, r, r, paint);       //2.给Paint设置PorterDuffXfermode       paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));          //3.绘制SRC图形       canvas.drawRect(r, r, r * 2.7f, r * 2.7f, paint);       //4.最后将画笔去除Xfermode       paint.setXfermode(null);  //★还原图层  canvas.restoreToCount(layerId);

Google官方图片的误读(略)

关于18种模式的解读(选择两个理解)

我们关心的区域

图片来自于启舰大神的博客
图片和文字均来自于启舰大神的博客

所以如上图所示,我们在计算源图像所在区域效果图时,需要着重关注两个区域:
1、如图标示区域一:区域一是源图像和目标图像的相交区域,由于在这个区域源图像和目标图像像素都不是空白像素,所以可以明显看出颜色的计算效果。
2、如图标示区域二:在区域二中,源图像所在区域的目标图像是空白像素,所以这块区域所表示的意义就是,当某一方区域是空白像素时,此时的计算结果。

总而言之:我们在下面的各个模式计算时,只需要关注图示中的区域一和区域二;其中区域一表示当源图像和目标图像像素都不是空白像素时的计算结果,而区域二则表示当某一方区域是空白像素时,此时的计算结果。

Mode.SRC

从公式中也可以看出,在处理源图像所在区域的相交问题时,全部以源图像显示
所以示例图像为:

Mode.SRC_IN

计算公式为:[Sa * Da, Sc * Da]
在这个公式中结果值的透明度和颜色值都是由Sa,Sc分别乘以目标图像的Da来计算的。所以当目标图像为空白像素时,计算结果也将会为空白像素。
示例图像为:

大家注意SRC_IN模式与SRC模式的区别,一般而言,是在相交区域时无论SRC_IN还是SRC模式都是显示源图像,而唯一不同的是,当目标图像是空白像素时,在SRC_IN所对应的区域也将会变成空白像素;

其实更严格的来讲,SRC_IN模式是在相交时利用目标图像的透明度来改变源图像的透明度和饱和度。当目标图像透明度为0时,源图像就完全不显示。

AvoidXfermode

AvoidXfermode的用法看这里这里:简单说这个!AvoidXfermode指的是正选(Mode.TARGET),或者反选(Mode.AVOID)指定的颜色值,而这个颜色只有一定容差。
最后用画笔所设置的颜色将其替换

第一个参数opColor:一个16进制的AARRGGBB的颜色值; 第二个参数tolerance:表示容差,比如你要选择#ff0000的颜色,但是容许选择与这个颜色色值相近的颜色,这个相近的范围就是容差第三个参数mode:取值有两个Mode.TARGET和Mode.AVOID;这里我们先知道Mode.TARGET的意义就可以了,Mode.TARGET表示将指定的颜色替换掉 public AvoidXfermode(int opColor, int tolerance, Mode mode) 

用法类似:

//★禁用硬件加速:setLayerType(View.LAYER_TYPE_SOFTWARE, null);  //★设置画笔颜色,这个颜色将去替换你通过AvoidXfermode所选中的颜色mPaint.setColor(Color.RED);//★新建图层    int layerID = canvas.saveLayer(0,0,width,height,mPaint,Canvas.ALL_SAVE_FLAG);        //★TODO 核心绘制代码         canvas.drawBitmap(mBmp,null,new Rect(0,0,width,height),mPaint);          mPaint.setXfermode(new AvoidXfermode(Color.WHITE,100, AvoidXfermode.Mode.TARGET));          canvas.drawRect(0,0,width,height,mPaint);  //★还原图层canvas.restoreToCount(layerID);  

学到的其他知识点

画一个倒影图像

BmpSRC = BitmapFactory.decodeResource(getResources(),R.drawable.dog,null);  Matrix matrix = new Matrix();  matrix.setScale(1F, -1F);  // 生成倒影图  BmpRevert = Bitmap.createBitmap(BmpSRC, 0, 0, BmpSRC.getWidth(), BmpSRC.getHeight(), matrix, true);