MaskFilter是对一个Paint的alpha通道的转换,而ColorFilter则是对每一个RGB通道应用转换 。所有由ColorFilter所派生的类在执行它们的转换时,都会忽略alpha通道。
Android包含三个ColorFilter:
ColorMatrixColorFilter 可以指定一个4×5的ColorMatrix并将其应用到一个Paint中。ColorMatrixes通常在程序中用于对图像进行处理 ,而且由于它们支持使用矩阵相乘的方法来执行链接转换,所以它们很有用。
LightingColorFilter 乘以第一个颜色的RGB通道,然后加上第二个颜色。每一次转换的结果都限制在0到255之间。
PorterDuffColorFilter 可以使用数字图像合成的16条Porter-Duff 规则中的任意一条来向Paint应用一个指定的颜色。
ColorMatrixColorFilter:
ColorMatrix mColorMatrix = new ColorMatrix(new float[]{ .5f, 0, 0, 0, 0, 0, .5f, 0, 0, 0, 0, 0, .5f, 0, 0, 0, 0, 0, 1, 0, }); drawable.setColorFilter(new ColorMatrixColorFilter(mColorMatrix));LightingColorFilter:
drawable.setColorFilter(new LightingColorFilter(0xffff0000, 0xff00ff00));PorterDuffCOlorFilter
drawable.setColorFilter(new PorterDuffColorFilter(0xffff0000, PorterDuff.Mode.ADD));接下来重点讲解PorterDuffColorFilter
1.PorterDuff.Mode.CLEAR
所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC
显示上层绘制图片
3.PorterDuff.Mode.DST
显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER
正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER
上下层都显示。下层居上显示。
6.PorterDuff.Mode.SRC_IN
取两层绘制交集。显示上层。
7.PorterDuff.Mode.DST_IN
取两层绘制交集。显示下层。
8.PorterDuff.Mode.SRC_OUT
取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT
取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP
取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP
取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR
取两层绘制非交集。两层绘制非交集。
13.PorterDuff.Mode.DARKEN
上下层都显示。变暗
14.PorterDuff.Mode.LIGHTEN
上下层都显示。变量
15.PorterDuff.Mode.MULTIPLY
取两层绘制交集
16.PorterDuff.Mode.SCREEN
上下层都显示。
代码如下:
public class Xfermodes extends AppCompatActivity { private static final Xfermode[] sModes = { new PorterDuffXfermode(PorterDuff.Mode.CLEAR),/** [0, 0] */ new PorterDuffXfermode(PorterDuff.Mode.SRC),/** [Sa, Sc] */ //原图 new PorterDuffXfermode(PorterDuff.Mode.DST),/** [Da, Dc] */ //目标图 new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER), /** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */ //原图在上面 new PorterDuffXfermode(PorterDuff.Mode.DST_OVER),/** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */ //目标图在上面 new PorterDuffXfermode(PorterDuff.Mode.DST_IN),/** [Sa * Da, Sc * Da] */ //绘制交集部分,绘制的是目标图 new PorterDuffXfermode(PorterDuff.Mode.SRC_IN), /** [Sa * Da, Sc * Da] */ //绘制交集部分,绘制的是原图 new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT),/** [Sa * (1 - Da), Sc * (1 - Da)] */ //绘制原图(不包括相交部分) new PorterDuffXfermode(PorterDuff.Mode.DST_OUT),/** [Da * (1 - Sa), Dc * (1 - Sa)] */ //绘制目标图(不包括相交部分) new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP),/** [Da, Sc * Da + (1 - Sa) * Dc] */ //相交的部分绘制原图,不想交的部分绘制目标图 new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP), /** [Sa, Sa * Dc + Sc * (1 - Da)] */ //相交的部分绘制目标图,不想交的部分绘制原图 new PorterDuffXfermode(PorterDuff.Mode.XOR),/** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */ //取两个图形绘制的非交集 new PorterDuffXfermode(PorterDuff.Mode.DARKEN),/** [Sa + Da - Sa*Da,Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */ //都显示,相交部分是黑色 new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN), /** [Sa + Da - Sa*Da,Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */ //都显示,相交部分是白色 new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),/** [Sa * Da, Sc * Dc] */ //去两层绘制的交集 new PorterDuffXfermode(PorterDuff.Mode.SCREEN), /** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */ //都显示,交集部分显示透明颜色 new PorterDuffXfermode(PorterDuff.Mode.ADD), /** Saturate(S + D) */ //按饱和度增加来显示 new PorterDuffXfermode(PorterDuff.Mode.OVERLAY) /** Saturate(S + D) */ //叠加, }; private static final String[] sLabels = { "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn", "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Darken", "Lighten", "Multiply", "Screen", "ADD", "OVERLAY" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new SampleView(this)); } static Bitmap makeDst(int w, int h) { Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(bm); Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setColor(0xFFFFCC44); c.drawOval(new RectF(0, 0, w * 3 / 4, h * 3 / 4), p); return bm; } static Bitmap makeSrc(int w, int h) { Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(bm); Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setColor(0xFF66AAFF); c.drawRect(w / 3, h / 3, w * 19 / 20, h * 19 / 20, p); return bm; } class SampleView extends View { private static final int ROW_MAX = 4; // number of samples per row private Bitmap mSrcB; private Bitmap mDstB; private Shader mBG; // background checker-board pattern private static final int W = 64; private static final int H = 64; public SampleView(Context context) { super(context); mSrcB = makeSrc(W, H); mDstB = makeDst(W, H); //这里只是创建一个2*2像素的Bitmap,并为每一个像素设置颜色,tips:数组的长度要和width*height的值保持一致 /* extend: Bitmap.Config.ALPHA_8就是Alpha由8位组成 Bitmap.Config.ARGB_4444就是由4个4位组成即16位 Bitmap.Config.ARGB_8888就是由4个8位组成即32位 Bitmap.Config.RGB_565就是R为5位,G为6位,B位5位共16位 位图位数越高代表其可以存储的颜色信息越多,当然图像也就越逼真 */ Bitmap bm = Bitmap.createBitmap(new int[]{0xFFFFFFFF, 0xFFCCCCCC, 0xFFCCCCCC, 0xFFFFFFFF}, 2, 2, Bitmap.Config.RGB_565); //定义色彩渲染器,模式为x、y轴重复显示 mBG = new BitmapShader(bm, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); Matrix m = new Matrix(); //进行缩放,放大为原来的6倍 m.setScale(6, 6); mBG.setLocalMatrix(m);//设置BitmapShader的本地矩阵 } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.GREEN); Paint labelP = new Paint(Paint.ANTI_ALIAS_FLAG);//抗锯齿 labelP.setTextAlign(Paint.Align.CENTER); Paint paint = new Paint(); paint.setFilterBitmap(false);//不对位图进行滤波处理。 canvas.translate(15, 35); int x = 0; int y = 0; for (int i = 0; i < sModes.length; i++) { paint.setStyle(Paint.Style.STROKE); paint.setShader(null);//不进行渲染 canvas.drawRect(x - 0.5f, y - 0.5f, x + W + 0.5f, y + H + 0.5f, paint); //draw the checker-board pattern paint.setStyle(Paint.Style.FILL); paint.setShader(mBG); canvas.drawRect(x, y, x + W, y + H, paint); //创建一个图层,在图层上演示图形混合后的效果 int sc = canvas.saveLayer(x, y, x + W, y + H, null, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); canvas.translate(x, y); canvas.drawBitmap(mDstB, 0, 0, paint); paint.setXfermode(sModes[i]); canvas.drawBitmap(mSrcB, 0, 0, paint); paint.setXfermode(null); canvas.restoreToCount(sc); //书写文字 canvas.drawText(sLabels[i], x + W / 2, y - labelP.getTextSize() / 2, labelP); x += W + 10; // wrap around when we've drawn enough for one row if ((i % ROW_MAX) == ROW_MAX - 1) { x = 0; y += H + 30; } } } } }以上为APIDemo中的代码,在很多情况都不会使用自定义View
iv = (ImageView) findViewById(R.id.iv); iv.getDrawable().setColorFilter(new PorterDuffColorFilter(0xffff0000, PorterDuff.Mode.ADD));在API21及以上可以使用
iv.getDrawable().setTint(0xffff0000); iv.getDrawable().setTintMode(PorterDuff.Mode.MULTIPLY);