Paint 的ColorFilter(颜色过滤器)和 XFermode(图层混合模式)
ColorFilter-颜色过滤器
顾名思义就是 Paint 画笔的颜色过滤功能。通过 setColorFilter(ColorFilter filter)
方法进行设置,该方法传入了一个 ColorFilter
对象,我们来看下这个是个嘛东东。
/**
* A color filter can be used with a {@link Paint} to modify the color of
* each pixel drawn with that paint. This is an abstract class that should
* never be used directly.
*
* 原意:一个可以作用于 Paint 的颜色过滤器,可以用来修改每一个像素的颜色。
* 这是一个抽象类,不能被直接使用
*
*/
public class ColorFilter {}
注释发现这是一个抽象类(抽象类你不写 abstract
,这么懒么。。),查看这个假的抽象类 ColorFilter
有以下三个子类,我们分别来看。
- 光照色彩过滤器:LightingColorFilter
- 混排颜色过滤器滤器:PorterDuffColorFilter
- 颜色矩阵颜色过滤器:ColorMatrixColorFilter
LightingColorFilter(光照色彩过滤器)
构造函数:
LightingColorFilter(@ColorInt int mul, @ColorInt int add)
其参数 mul
和 add
都是16进制的色彩值0xAARRGGBB,mul 用来和目标像素相乘,add 用来和目标像素相加。具体计算逻辑如下:
R' = R * colorMultiply.R + colorAdd.R
G' = G * colorMultiply.G + colorAdd.G
B' = B * colorMultiply.B + colorAdd.B
你说啥?有点懵逼?来个例子就清楚了,比如我们要去掉每个像素中的绿色,就可以传入 ( mul = 0xff00ff , add = 0x000000)
。脑阔疼,这玩意咋算。
假如原像素 0xabcdef
mul = 0xff00ff
add = 0x000000
其他颜色不变,将绿色至为0,则:
R' = 0xab * mul.0xff + add.0x00
G' = 0xcd * mul.0x00 + add.0x00 = 0
B' = 0xef * mul.0xff + add.0x00
这样,绿色就无情的被抹掉了。下面即为实现效果
PorterDuffColorFilter(混排颜色过滤器滤器)
通过其构造函数,发现接受两个参数,分别是混合的颜色 color
和混合模式 mode
PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode)
其中 color 值为16进制的色彩值0xAARRGGBB。而混合模式系统一共提供了18种混合模式,每个混合模式都有自己的计算方法,每种模式对应的功能我们在 XFermode(图层混合模式) 中已经讲解。具体用法如下:
PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.DARKEN);
mPaint.setColorFilter(porterDuffColorFilter);
invalidate();
ColorMatrixColorFilter(颜色矩阵颜色过滤器)
通过 ColorMatrix
颜色矩阵来操作目标像素,具体 ColorMatrix
可以看 官网解析。具体使用如下
float[] colorMatrix = {
1,0,0,0,0, //red
0,1,0,0,0, //green
0,0,1,0,0, //blue
0,0,0,1,0 //alpha
}
ColorMatrixColorFilter colorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix);
mPaint.setColorFilter(colorMatrixColorFilter);
invalidate();
下面贴上全部代码:
package com.wuba.demo;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.LightingColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.util.AttributeSet;
import android.view.View;
/**
* Author silence.
* Time:2019-08-08.
* Desc:
*/
public class PaintColorFilter extends View {
private Paint mPaint;
private Bitmap mBitmap;
public PaintColorFilter(Context context) {
this(context,null);
}
public PaintColorFilter(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public PaintColorFilter(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
mBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.baybay,options);
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawBitmap(mBitmap,0,0,mPaint);
}
public void reset(){
mPaint.reset();
invalidate();
}
public void lightingColorFilter( int mul, int add){
/**
* 光照色彩过滤器
* LightingColorFilter(@ColorInt int mul, @ColorInt int add)
* mul 和 add 都是16进制的色彩值0xAARRGGBB,mul 用来和目标像素相乘,add 用来和目标像素相加
* R' = R * colorMultiply.R + colorAdd.R
* G' = G * colorMultiply.G + colorAdd.G
* B' = B * colorMultiply.B + colorAdd.B
* eg: 去掉绿色。原像素 0xabcdef , mul 0xff00ff , add 0x000000
* 其他颜色不变,将绿色至为0
* R' = 0xab * mul.0xff + add.0x00
* G' = 0xcd * mul.0x00 + add.0x00 = 0
* B' = 0xef * mul.0xff + add.0x00
*/
LightingColorFilter lightingColorFilter = new LightingColorFilter(mul,add);
mPaint.setColorFilter(lightingColorFilter);
invalidate();
}
public void porterDuffColorFilter(int color){
/**
* 混排颜色过滤器滤器
* PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode)
* color:具体的颜色值,如Color.RED
* mode:指定PorterDuff.Mode 混合模式
*/
PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(color, PorterDuff.Mode.DARKEN);
mPaint.setColorFilter(porterDuffColorFilter);
invalidate();
}
public void colorMatrixColorFilter(float[] colorMatrix){
/**
* 颜色矩阵颜色过滤器
* ColorMatrixColorFilter(@NonNull float[] array)
* array:矩阵数组
* eg:float[] colorMatrix = {
* 1,0,0,0,0, //red
* 0,1,0,0,0, //green
* 0,0,1,0,0, //blue
* 0,0,0,1,0 //alpha
* }
*/
ColorMatrixColorFilter colorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix);
mPaint.setColorFilter(colorMatrixColorFilter);
invalidate();
}
}
XFermode-图层混合模式
将绘制图形中的像素与 Canvas 中的对应位置的像素按照一定规则进行混合,形成新的像素值,从而更新 Canvas 中的颜色值。系统为我们提供了18中混合模式:PorterDuff.Mode 官方文档
public enum Mode {
//绘制内容不提交到 canvas 画布中
CLEAR (0),
//显示上层绘制图像
SRC (1),
//显示下层绘制图像
DST (2),
//正常绘制显示,上下图层 叠盖绘制
SRC_OVER (3),
//上下层都显示,下层居上显示
DST_OVER (4),
//取两层绘制交集,显示上层
SRC_IN (5),
//取两层绘制交集,显示下层
DST_IN (6),
//取上层绘制非交集部分,交集部分变透明
SRC_OUT (7),
//取下层绘制非交集部分,交集部分变透明
DST_OUT (8),
//取上层交集部分与下层非交集部分
SRC_ATOP (9),
//取下层交集部分与上层非交集部分
DST_ATOP (10),
//取去除两个图层交集部分
XOR (11),
//取两个图层全部区域,交集部分颜色加深
DARKEN (16),
//取两个图层全部区域,交集部分颜色点亮
LIGHTEN (17),
//取两个图层交集部分,颜色叠加
MULTIPLY (13),
//取两个图层全部区域,交集部分滤色
SCREEN (14),
//取两个图层全部区域,交集部分饱和度相加
ADD (12),
//取两个图层全部区域,交集部分叠加
OVERLAY (15);
}