濾鏡效果

濾鏡效果大家肯定都知道,畢竟現在相機這么牛,一般都有這個功能。
不廢話,開搞!

所謂濾鏡效果,就是對一張圖像的顏色進行特定處理(ARGB)

準備工作

創建一個繼承于View的類,然后

//寫3個私有成員變量
private Paint paint;//用于原圖的畫筆
private Paint paint2;//用于濾鏡的畫筆
private Bitmap bitmap;//圖像

//在構造函數中初始化一下
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.shuaige);

接下來的操作將都在onDraw中進行,并且要關閉硬件加速先

setLayerType(View.LAYER_TYPE_SOFTWARE,null);

原圖

shuaige.jpg

首先在onDraw中把原圖畫出來

//畫出原圖
canvas.drawBitmap(bitmap,50,50,paint);
//畫板位置向下平移
canvas.translate(0,500);

1、Alpha濾鏡處理

Alpha濾鏡效果主要通過MaskFilter類進行處理,MaskFilter擁有兩個子類BlurMaskFilter和EmbossMaskFilter,BlurMaskFilter用來繪制模糊陰影,EmbossMaskFilter用來用來實現浮雕立體效果

(1)BlurMaskFilter

首先看一下BlurMaskFilter的構造方法

/**
* @param radius 陰影的半徑
* @param style  
*               NORMOL -- 整個圖像都被模糊掉
*               SOLID -- 圖像邊界外產生一層與Paint顏色一致陰影效果,不影響圖像的本身
*               OUTER -- 圖像邊界外產生一層陰影,并且將圖像變成透明效果
*               INNER -- 在圖像內部邊沿產生模糊效果
*/
BlurMaskFilter(float radius, Blur style)

接下來看看它們的效果

● style---NORMOL

paint2.setMaskFilter(new BlurMaskFilter(60, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830211237.png

● style---SOLID

paint2.setMaskFilter(new BlurMaskFilter(60, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830213038.png

● style---OUTER

paint2.setMaskFilter(new BlurMaskFilter(60, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830213251.png

● style---INNER

paint2.setMaskFilter(new BlurMaskFilter(60, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830213443.png

(2)EmbossMaskFilter

首先看一下EmbossMaskFilter的構造方法

/**
* @param direction  指定光源的位置,長度為xxx的數組標量[x,y,z]
* @param ambient    環境光的因子 (0~1),越接近0,環境光越暗
* @param specular   鏡面反射系數 越接近0,鏡面反射越強
* @param blurRadius 模糊半徑 值越大,模糊效果越明顯
*/
EmbossMaskFilter(float[] direction, float ambient, float specular, float blurRadius)

接下來看看它們的效果

new float[]{2,2,2}, 0.1f, 10, 60

paint2.setMaskFilter(new EmbossMaskFilter(new float[]{2,2,2},0.1f,10,60));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830214650.png

2、顏色RGB的濾鏡處理

首先需要大家掌握一些矩陣運算的基本知識(這個大家有點線性代數基礎的都會懂的)--乘法


舉證乘法.png

再看一下顏色矩陣乘法


顏色矩陣乘法.gif

該矩陣意思就是將圖中顏色(RGBA)透明度變成它原來的一半,但是我們會發現,這種算法只能乘,如果我們有相加的需求,這種明顯是不適用的。所以,應該在四階色彩變換矩陣上增加一個“啞元坐標”,來實現所列的矩陣運算。
啞元坐標.gif

(1)ColorMatrix

顏色RGB的濾鏡處理主要通過ColorMatrix這個顏色矩陣類來完成,下面一起來看看具體代碼和顯示

● 平移運算---加法(就是將某個顏色值增加一個固定的值,此處是將綠色的值加了100)

ColorMatrix colorMartrix = new ColorMatrix(new float[]{
                1, 0,0,0,0,
                0,1,0,0,100,
                0,0,1,0,0,
                0,0,0,1,0
        });
paint2.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830223456.png

● 反相效果 -- 底片效果(就是將每個像素都變成它的相反的值)

ColorMatrix colorMartrix = new ColorMatrix(new float[]{
                -1, 0,0,0,255,
                0,-1,0,0,255,
                0,0,-1,0,255,
                0,0,0,1,0
        });
paint2.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830224810.png

● 縮放運算---乘法 -- 顏色增強(此處將每個色值都乘1.4倍)

ColorMatrix colorMartrix = new ColorMatrix(new float[]{
                1.4f, 0,0,0,0,
                0,1.4f,0,0,0,
                0,0,1.4f,0,0,
                0,0,0,1,0
        });

//或者
//ColorMatrix colorMartrix = new ColorMatrix();
//colorMartrix.setScale(1.2f,1.2f,1.2f,1);

paint2.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830225334.png

● 黑白照片

去色原理:只要把R G B 三通道的色彩信息設置成一樣,那么圖像就會變成灰色,同時為了保證圖像亮度不變,同一個通道里的R+G+B =1。

ColorMatrix colorMartrix = 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,1,0
        });
paint2.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830225729.png

● 發色效果---(比如紅色和綠色交換)

ColorMatrix colorMartrix = new ColorMatrix(new float[]{
                0,1,0,0,0,
                1, 0,0,0,0,
                0,0,1,0,0,
                0,0,0,1,0
        });
paint2.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830230034.png

● 復古效果

ColorMatrix colorMartrix = 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,1,0
        });
paint2.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830230303.png

● 顏色通道過濾(此處過濾紅色)

ColorMatrix colorMartrix = new ColorMatrix(new float[]{
                1, 0,0,0,0,
                0,0,0,0,0,
                0,0,0,0,0,
                0,0,0,1,0
        });
paint2.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830230630.png

● 增加飽和度

ColorMatrix colorMartrix = new ColorMatrix();
colorMartrix.setSaturation(2f);
paint2.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830231845.png

● 顏色旋轉

ColorMatrix colorMartrix = new ColorMatrix();
//setRotate參數
//aixs-- 0 紅色軸,1,綠色,2,藍色
//degrees -- 旋轉的角度
colorMartrix.setRotate(0,10f);
paint2.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830232406.png

● 顏色矩陣疊加效果(紅色值加100,另外再各個顏色增強)

ColorMatrix colorMartrix1 = new ColorMatrix(new float[]{
                1, 0,0,0,100,
                0,1,0,0,0,
                0,0,1,0,0,
                0,0,0,1,0
        });
 ColorMatrix colorMartrix2 = new ColorMatrix(new float[]{
                1.4f, 0,0,0,0,
                0,1.4f,0,0,0,
                0,0,1.4f,0,0,
                0,0,0,1.4f,0
        });
colorMartrix.setConcat(colorMartrix1,colorMartrix2);
paint2.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截圖20170830233123.png

(2)LightingColorFilter

LightingColorFilter主要是可以對顏色值一次性的進行乘和加,但是這里只是修改RGB值,首先看一看LightingColorFilter的構造方法。

/**
*mul   顏色值乘的倍數
*add   顏色值增加的值
*/
LightingColorFilter(int mul, int add)

下面看看具體應用

//表示將原有的顏色值先乘0x00ff00,再加0xff0000
paint2.setColorFilter(new LightingColorFilter(0x00ff00,0xff0000));
canvas.drawBitmap(bitmap,50,150,paint2)
QQ截圖20170830235335.png

(3)PorterDuffColorFilter

PorterDuffColorFilter可以用于顏色與原圖像混合疊加的效果
首先開看一看PorterDuffColorFilter的構造方法

/**
*color 進行疊加的顏色
*mode 疊加的模式
*/
PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode)

再來看看疊加模式PorterDuff.Mode有哪些

public enum Mode {
        /** [0, 0] */
        CLEAR       (0),
        /** [Sa, Sc] */
        SRC         (1),
        /** [Da, Dc] */
        DST         (2),
        /** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */
        SRC_OVER    (3),
        /** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */
        DST_OVER    (4),
        /** [Sa * Da, Sc * Da] */
        SRC_IN      (5),
        /** [Sa * Da, Sa * Dc] */
        DST_IN      (6),
        /** [Sa * (1 - Da), Sc * (1 - Da)] */
        SRC_OUT     (7),
        /** [Da * (1 - Sa), Dc * (1 - Sa)] */
        DST_OUT     (8),
        /** [Da, Sc * Da + (1 - Sa) * Dc] */
        SRC_ATOP    (9),
        /** [Sa, Sa * Dc + Sc * (1 - Da)] */
        DST_ATOP    (10),
        /** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */
        XOR         (11),
        /** [Sa + Da - Sa*Da,
             Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
        DARKEN      (16),
        /** [Sa + Da - Sa*Da,
             Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
        LIGHTEN     (17),
        /** [Sa * Da, Sc * Dc] */
        MULTIPLY    (13),
        /** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
        SCREEN      (14),
        /** Saturate(S + D) */
        ADD         (12),
        OVERLAY     (15);

        Mode(int nativeInt) {
            this.nativeInt = nativeInt;
        }

        /**
         * @hide
         */
        public final int nativeInt;
    }

這里一共有17種疊加模式,接下來我將以藍色為疊加顏色,然后展示所有疊加效果。

這里需要注意 這里我們的bitmap屬于目標圖片(DST),Color.argb(175,140,90,200)屬于源圖片(SRC)
再來看看疊加規則
[] : [展示的透明度, 展示的顏色值]
Sa:源圖片的透明度
Sc:源圖片的顏色值
Da:目標圖片的透明度
Dc:目標圖片的顏色值

● CLEAR

paint2.setColorFilter(new PorterDuffColorFilter(Color.argb(175,140,90,200), PorterDuff.Mode.CLEAR));
canvas.drawBitmap(bitmap,50,150,paint2);
CLEAR 效果
混合算法:[0, 0]

● SRC

paint2.setColorFilter(new PorterDuffColorFilter(Color.argb(175,140,90,200), PorterDuff.Mode.SRC));
canvas.drawBitmap(bitmap,50,150,paint2);
SRC 效果
混合算法:[Sa, Sc]

● DST

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.DST));
canvas.drawBitmap(bitmap,50,150,paint2);
DST 效果
混合算法:[Da, Dc]

● SRC_OVER

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SRC_OVER));
canvas.drawBitmap(bitmap,50,150,paint2);
SRC_OVER 效果
混合算法:[Sa + (1 - Sa)Da, Rc = Sc + (1 - Sa)Dc]

● DST_OVER

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.CLEAR));
canvas.drawBitmap(bitmap,50,150,paint2);
DST_OVER 效果
混合算法:[Sa + (1 - Sa)Da, Rc = Dc + (1 - Da)Sc]

● SRC_IN

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap,50,150,paint2);
SRC_IN 效果
混合算法:[Sa * Da, Sc * Da]

● DST_IN

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.DST_IN));
canvas.drawBitmap(bitmap,50,150,paint2);
DST_IN 效果
混合算法:[Sa * Da, Sa * Dc]

● SRC_OUT

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SRC_OUT));
canvas.drawBitmap(bitmap,50,150,paint2);
SRC_OUT效果
混合算法:[Sa * (1 - Da), Sc * (1 - Da)]

● DST_OUT

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.DST_OUT));
canvas.drawBitmap(bitmap,50,150,paint2);
DST_OUT 效果
混合算法:[Da * (1 - Sa), Dc * (1 - Sa)]

含義參考 SRC_OUT

● DST_ATOP

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.DST_ATOP));
canvas.drawBitmap(bitmap,50,150,paint2);
DST_ATOP 效果
混合算法:[Sa, Sa * Dc + Sc * (1 - Da)]

● SRC_ATOP

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.CLEAR));
canvas.drawBitmap(bitmap,50,150,paint2);
SRC_ATOP 效果
混合算法:[Da, Sc * Da + (1 - Sa) * Dc]

● XOR

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.XOR));
canvas.drawBitmap(bitmap,50,150,paint2);
XOR 效果
混合算法:[Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]

● DARKEN

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.DARKEN));
canvas.drawBitmap(bitmap,50,150,paint2);
DARKEN 效果
混合算法:[Sa + Da - SaDa,Sc(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)]

● LIGHTEN

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.LIGHTEN));
canvas.drawBitmap(bitmap,50,150,paint2);
LIGHTEN 效果
混合算法:[Sa + Da - SaDa, Sc(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)]

● MULTIPLY

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.MULTIPLY));
canvas.drawBitmap(bitmap,50,150,paint2);
MULTIPLY 效果
混合算法:[Sa * Da, Sc * Dc]

● SCREEN

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SCREEN));
canvas.drawBitmap(bitmap,50,150,paint2);
SCREEN 效果
混合算法:[Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]

● ADD

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.ADD));
canvas.drawBitmap(bitmap,50,150,paint2);
ADD 效果
混合算法:Saturate(S + D)

● OVERLAY

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.OVERLAY));
canvas.drawBitmap(bitmap,50,150,paint2);
OVERLAY 效果
混合算法:

個人覺得很全了,差不多可以滿足大部分濾鏡效果

版權聲明:個人原創,若轉載,請注明出處
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容