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);
}