濾鏡效果大家肯定都知道,畢竟現在相機這么牛,一般都有這個功能。
不廢話,開搞!
所謂濾鏡效果,就是對一張圖像的顏色進行特定處理(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 效果
混合算法:
個人覺得很全了,差不多可以滿足大部分濾鏡效果
版權聲明:個人原創,若轉載,請注明出處