Android 濾鏡效果和顏色通道過濾

當今是靠臉吃飯的時代,平時的人像、風景照、美食照等都須要加上一款優美的濾鏡,才能讓照片更加精緻,更加吸引人,這樣的照片可以讓你在朋友圈更加出衆,別具一格。canvas

所以一個智能手機固然少不了一款美顏APP,在商店中有衆多的美顏APP,例如我比較喜歡的:Snapseed、InterPhoto、美顏相機和美人相機等等。這些相機都擁有很是美和優秀的濾鏡,正由於有這些優秀的濾鏡,才能讓你的照片變得更美,所以做爲開發者的咱們須要瞭解這些濾鏡是怎麼作出來的,通常都是經過Android自帶的濾鏡處理、OpenGL處理或者經過顏色RGB的濾鏡處理。本文咱們不介紹OpenGL,由於OpenGL確實是一個很強大的圖像處理技術。數組

Android的濾鏡效果就是對圖像進行必定的過濾加工處理,通常的使用Paint設置濾鏡效果分爲兩類:bash

一、Android自帶的濾鏡效果,而該濾鏡效果能夠分爲:

1)模糊遮罩濾鏡(BlurMaskFilter);ide

2)浮雕遮罩濾鏡(EmbossMaskFilter)。函數

二、顏色RGB的濾鏡處理,能夠經過ColorMatrix設置。

經過Android的濾鏡效果和顏色通道過濾這兩種方式,能夠對圖像作出很好的濾鏡效果,接下來學習下如何處理濾鏡。post

Android自帶的濾鏡效果

Android的濾鏡處理使用paint.setMaskFilter(maskfilter)方法設置,其中能夠設置BlurMaskFilter和EmbossMaskFilter這兩款濾鏡,而這兩款濾鏡都是繼承MaskFilter這個基類。學習

BlurMaskFilter

BlurMaskFilter:即模糊遮罩濾鏡,經過該濾鏡可使圖像呈現模糊效果。ui

使用:

public class MaskFilterView extends View {

    private int progress = 10;
    private Paint paint;

    public MaskFilterView(Context context) {
        super(context);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    }

    public MaskFilterView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //須要關閉硬件加速(沒有關閉則沒效果)
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);

        paint.setColor(Color.RED);
        RectF r = new RectF(100, 100, 300, 300);
        /**模糊遮罩濾鏡效果
         * BlurMaskFilter.Blur.INNER
         * BlurMaskFilter.Blur.NORMAL
         * BlurMaskFilter.Blur.OUTER
         * BlurMaskFilter.Blur.SOLID
         */
		paint.setMaskFilter(new BlurMaskFilter(progress, BlurMaskFilter.Blur.NORMAL));
        canvas.drawRect(r , paint);

    }


    public void setProgress(int progress) {
        if (progress <= 0){
            return;
        }
        this.progress = progress;
        postInvalidate();
    }
}
複製代碼

Activity:this

public class MaskFilterActivity extends AppCompatActivity {

    private SeekBar mSeekBar;
    private MaskFilterView mFilterView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mask_filter);
        mSeekBar = (SeekBar)this.findViewById(R.id.seekBar);
        mFilterView = (MaskFilterView)this.findViewById(R.id.my_view);
        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                mFilterView.setProgress(progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }
}
複製代碼

效果圖: spa

View.png

在MaskFilterView的onDraw方法中,首先須要new一個BlurMaskFilter對象,咱們看下其構造方法:

public BlurMaskFilter(float radius, Blur style)

radius:模糊的半徑,值越大模糊就越擴散。

style:模糊濾鏡使用的類型,總共有四種類型能夠選擇,它們分別是:

1)INNER:在圖像內部產生模糊;

2)NORMAL:將整個圖像模糊掉;

3)OUTER:在Alpha邊界外產生一層模糊,並且將本來的圖像變透明。

4)SOLID:在圖像的Alpha外邊界產生一層與Paint顏色一致的模糊效果,但不影響圖像自己。

注意:這裏咱們須要須要關閉硬件加速,不然沒效果。

上圖效果中咱們使用了INNER,接下來咱們看看其餘三種效果。

NORMAL:
paint.setMaskFilter(new BlurMaskFilter(progress, BlurMaskFilter.Blur.NORMAL));
canvas.drawRect(r , paint);
複製代碼

View

OUTER:
paint.setMaskFilter(new BlurMaskFilter(progress, BlurMaskFilter.Blur.OUTER));
canvas.drawRect(r , paint);
複製代碼

View

SOLID:
paint.setMaskFilter(new BlurMaskFilter(progress, BlurMaskFilter.Blur.SOLID));
canvas.drawRect(r , paint);
複製代碼

View

以上即是模糊遮罩濾鏡的使用了,下面咱們看看浮雕遮罩濾鏡的使用效果。

EmbossMaskFilter

EmbossMaskFilter(浮雕遮罩濾鏡)讓圖像呈現一種凹凸不平的面具效果。

使用

paint.setMaskFilter(new EmbossMaskFilter(new float[]{30,30,30}, 0.2f, 20, progress));
canvas.drawBitmap(bitmap, 100, 300, paint);
複製代碼

EmbossMaskFilter效果圖

使用的時候,須要new一個EmbossMaskFilter對象,並經過paint.setMaskFilter方法設置,咱們主要看EmbossMaskFilter的構造方法參數。

public EmbossMaskFilter(float[] direction, float ambient, float specular, float blurRadius)
複製代碼

direction:指定長度爲xxx的數組標量[x,y,z],用來指定光源的位置;

ambient:指定周邊背景光源(0~1);

specular:指鏡面反射係數;

blurRadius:指定模糊半徑。

注意:使用EmbossMaskFilter一樣須要關閉硬件加速,不然沒效果。

顏色RGB的濾鏡處理

顏色RGB的濾鏡處理是經過ColorMatrix來實現的,即顏色矩陣,而後將ColorMatrix設置到ColorMatrixColorFilter,經過setColorFilter方法設置ColorMatrixColorFilter,這樣就完成了設置顏色過濾器。setColorFilter還能夠設置全部ColorFilter的子類,包括LightingColorFilter和PorterDuffColorFilter。

ColorMatrix顧名思義就是顏色矩陣,那麼濾鏡的全部處理效果都是經過顏色矩陣的變換實現的。因此須要讀者可以熟悉基本的矩陣運算方法。若是讀者目前還不認識矩陣,怎麼辦?不要緊,接下來咱們簡單介紹下矩陣,以及基本的運算方法。讀者能夠自行參考百度百科。

矩陣

定義:

m×n矩陣

矩陣加法:

矩陣加法

矩陣減法:

矩陣減法

矩陣乘法:

矩陣乘法

第一個矩陣A的第一行,與第二個矩陣B的第一列的數字分別相乘,獲得的結果相加,最終的值作爲結果矩陣的第(1,1)位置的值(即第一行,第一列)。 一樣,A矩陣的第一行與B矩陣的第二列的數字分別相乘而後相加,獲得的值做爲結果矩陣第(1,2)位置的值(即第一行第二列)。

色彩矩陣: 通常的色彩矩陣使用四階表示,也就是RGBA

四階色彩矩陣

半透明的色彩矩陣,如:

半透明

Android色彩矩陣使用五階矩陣

色彩五階矩陣

在四階矩陣的基礎上,增長一階,而第五階表示偏移量,上圖表示紅色份量值更改成原來的2倍,綠色份量增長100(1*100+100);

ColorMatrix的使用

調用紅色(R),綠色增長兩倍。

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //須要關閉硬件加速(沒有關閉則沒效果)
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        paint.setColor(Color.RED);
        ColorMatrix matrix = new ColorMatrix(new float[]{
				0,0,0,0,0,
				0,1,0,0,200,
				0,0,1,0,0,
				0,0,0,1,0,
		});
        paint.setColorFilter(new ColorMatrixColorFilter(matrix ));
        canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);
    }
複製代碼

效果圖

先new一個ColorMatrixColorFilter對象,並把ColorMatrix設置進去,setColorFilter方法把ColorMatrixColorFilter對象設置進去就能夠完成設置顏色過濾器。

反相效果
ColorMatrix matrix = new ColorMatrix(new float[]{
				-1,0,0,0,255,
				0,-1,0,0,255,
				0,0,-1,0,255,
				0,0,0,1,0,
		});
paint.setColorFilter(new ColorMatrixColorFilter(matrix ));
canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);
複製代碼

效果圖

顏色加強

顏色加強:能夠起到一個變亮的效果,經過矩陣縮放方式。

ColorMatrix matrix = new ColorMatrix(new float[]{
				1.2f,0,0,0,0,
				0,1.2f,0,0,0,
				0,0,1.2f,0,0,
				0,0,0,1.2f,0,
		});
paint.setColorFilter(new ColorMatrixColorFilter(matrix ));
canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);
複製代碼

效果圖.png

黑白圖片

去色原理:只要把RGB三通道的色彩信息設置成同樣;即:R=G=B,那麼圖像就變成了灰色,而且,爲了保證圖像亮度不變,同一個通道中的R+G+B=1。 如:0.213+0.715+0.072=1;也就是RGB分別爲:0.213,0.715,0.072; 三個數字是根據色彩光波頻率及色彩心理學計算出來的。

ColorMatrix matrix = new ColorMatrix(new float[]{
                0.213f, 0.715f, 0.072f, 0, 0,
                0.213f, 0.715f, 0.072f, 0, 0,
                0.213f, 0.715f, 0.072f, 0, 0,
                0, 0, 0, 1f, 0,
        });
paint.setColorFilter(new ColorMatrixColorFilter(matrix ));
canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);
複製代碼

效果圖.png

髮色效果

髮色效果:如紅色和綠色交換——把第一行和第二行交換。

ColorMatrix matrix = new ColorMatrix(new float[]{
			0,1f,0,0,0,
			1f,0,0,0,0,
			0,0,1f,0,0,
			0,0,0,1f,0,
		});
paint.setColorFilter(new ColorMatrixColorFilter(matrix ));
canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);
複製代碼

效果圖.png

復古風格
ColorMatrix matrix = new ColorMatrix(new float[]{
				1/2f,1/2f,1/2f,0,0,
				1/3f,1/3f,1/3f,0,0,
				1/4f,1/4f,1/4f,0,0,
				0,0,0,1f,0,
			});
paint.setColorFilter(new ColorMatrixColorFilter(matrix ));
canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);
複製代碼

效果圖.png

色彩運算

ColorMatrix色彩矩陣,除了以上直接設置矩陣的方式,還可使用ColorMatrix類的方法來設置進行色彩運算:

1)色彩的縮放運算(matrix.setScale):也就是四階矩陣RGBA對應的乘法運算。

ColorMatrix matrix = new ColorMatrix();
//setScale(float rScale, float gScale, float bScale, float aScale)
matrix.setScale(2, 2, 2f, 1);
paint.setColorFilter(new ColorMatrixColorFilter(matrix ));
canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);
複製代碼

效果圖.png

上圖中RGB都方法原來的兩倍。

2)色彩的平移運算,也就是矩陣加法運算。

ColorMatrix的API

經過上面的學習咱們知道ColorMatrix其強大之處在於經過矩陣運算能夠實現顏色通道過濾,咱們有必要學習ColorMatrix的API。

構造方法

構造方法.png

三個構造方法,能夠不須要參數,能夠傳一個float數組(矩陣),也能夠ColorMatrix對象做爲參數。

看下ColorMatrix()方法裏面的reset()方法。

/**
     * Set this colormatrix to identity:
     * <pre>
     * [ 1 0 0 0 0   - red vector
     *   0 1 0 0 0   - green vector
     *   0 0 1 0 0   - blue vector
     *   0 0 0 1 0 ] - alpha vector
     * </pre>
     */
    public void reset() {
        final float[] a = mArray;
        Arrays.fill(a, 0);
        a[0] = a[6] = a[12] = a[18] = 1;
    }
複製代碼

該方法主要是初始化一個矩陣,並且將RGBA都設置爲1。

set方法

set

提供兩個set方法,能夠設置float數組(矩陣),也能夠設置ColorMatrix對象,跟構造方法對應起來。

matrix.set(new float[]{
                1/2f,1/2f,1/2f,0,0,
                1/3f,1/3f,1/3f,0,0,
                1/4f,1/4f,1/4f,0,0,
                0,0,0,1f,0,
        });
paint.setColorFilter(new ColorMatrixColorFilter(matrix ));
canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);
複製代碼

效果圖.png

setScale方法

設置色彩的縮放函數,上面已經介紹過該方法了.

setRotate

該方法是色彩旋轉函數

setRotate

axis:表明繞哪個軸旋轉,0,1,2 (0紅色,1綠色,2藍色);

degrees:旋轉的度數。

該函數已經作好了矩陣的設置和運算了。

matrix.setRotate(0,progress);
paint.setColorFilter(new ColorMatrixColorFilter(matrix ));
canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);
複製代碼

效果圖.png

setSaturation

setSaturation:設置飽和度

setSaturation

方法內部已經運算好的了,咱們只須要傳一個float類型參數sat。

sat:1表示是原來不變,0表示灰色;若是大於1增長飽和度。

matrix.setSaturation(progress);
paint.setColorFilter(new ColorMatrixColorFilter(matrix ));
canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);
複製代碼

效果圖.png

效果圖.png

setRGB2YUV

效果圖.png

RGB轉成YUV,對應的還有一個方法setYUV2RGB,也就是YUV轉成RGB。

setConcat
setConcat(ColorMatrix matA, ColorMatrix matB):將顏色矩陣matA和matB複合,至關與對圖片進行matA矩陣處理再進行矩陣matB處理。

matrixA.preConcat(ColorMatrix prematrix):等價於setConcat(matrixA, prematrix)

matrixA.postConcat(ColorMatrix postmatrix):等價於setConcat(prematrix,matrixA)
複製代碼

ColorFilter

ColorFilter做爲顏色過濾器,有三個子類來實現顏色過濾: 1)ColorMatrixColorFilter:即色彩矩陣的顏色過濾器,配合ColorMatrix使用。 2)LightingColorFilter:即光照顏色過濾器,能過濾顏色和加強色彩的方法。 3)PorterDuffColorFilter:即圖形混合濾鏡,該是圖形學的一個理論飛躍。

上文中已經使用過了ColorMatrixColorFilter,而且配合ColorMatrix使用。接下來主要介紹LightingColorFilter和PorterDuffColorFilter。

LightingColorFilter

光照顏色過濾器,也就是ColorMatrixColorFilter的簡化版本。

public LightingColorFilter(@ColorInt int mul, @ColorInt int add) {
        mMul = mul;
        mAdd = add;
    }
複製代碼

經過構造方法設置過濾顏色,參數解析:

mul:multiply,也就是乘法 ;

add:加法,也就是顏色偏移量。

paint.setColorFilter(new LightingColorFilter(0x00ff00, 0xff0000));
canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);
複製代碼

效果圖.png

PorterDuffColorFilter
public PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
        mColor = color;
        mMode = mode;
    }
複製代碼

color:源顏色, mode:色彩的混合模式:

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:取兩圖層所有區域,交集部分變爲透明色。

paint.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, null, new RectF(0, 0, 400, 400*bitmap.getHeight()/bitmap.getWidth()), paint);
複製代碼

效果圖.png
相關文章
相關標籤/搜索