Paint 的ColorFilter(顏色過濾器)和 XFermode(圖層混合模式)

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)

其參數 muladd 都是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);

    }

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章