滤镜效果大家肯定都知道,毕竟现在相机这么牛,一般都有这个功能。
不废话,开搞!
所谓滤镜效果,就是对一张图像的颜色进行特定处理(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);
原图
首先在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);
● style---SOLID
paint2.setMaskFilter(new BlurMaskFilter(60, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(bitmap,50,150,paint2);
● style---OUTER
paint2.setMaskFilter(new BlurMaskFilter(60, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(bitmap,50,150,paint2);
● style---INNER
paint2.setMaskFilter(new BlurMaskFilter(60, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(bitmap,50,150,paint2);
(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);
2、颜色RGB的滤镜处理
首先需要大家掌握一些矩阵运算的基本知识(这个大家有点线性代数基础的都会懂的)--乘法
再看一下颜色矩阵乘法
该矩阵意思就是将图中颜色(RGBA)透明度变成它原来的一半,但是我们会发现,这种算法只能乘,如果我们有相加的需求,这种明显是不适用的。所以,应该在四阶色彩变换矩阵上增加一个“哑元坐标”,来实现所列的矩阵运算。
(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);
● 反相效果 -- 底片效果(就是将每个像素都变成它的相反的值)
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);
● 缩放运算---乘法 -- 颜色增强(此处将每个色值都乘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);
● 黑白照片
去色原理:只要把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);
● 发色效果---(比如红色和绿色交换)
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);
● 复古效果
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);
● 颜色通道过滤(此处过滤红色)
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);
● 增加饱和度
ColorMatrix colorMartrix = new ColorMatrix();
colorMartrix.setSaturation(2f);
paint2.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
canvas.drawBitmap(bitmap,50,150,paint2);
● 颜色旋转
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);
● 颜色矩阵叠加效果(红色值加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);
(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)
(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);
混合算法:[0, 0]
● SRC
paint2.setColorFilter(new PorterDuffColorFilter(Color.argb(175,140,90,200), PorterDuff.Mode.SRC));
canvas.drawBitmap(bitmap,50,150,paint2);
混合算法:[Sa, Sc]
● DST
paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.DST));
canvas.drawBitmap(bitmap,50,150,paint2);
混合算法:[Da, Dc]
● SRC_OVER
paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SRC_OVER));
canvas.drawBitmap(bitmap,50,150,paint2);
混合算法:[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);
混合算法:[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);
混合算法:[Sa * Da, Sc * Da]
● DST_IN
paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.DST_IN));
canvas.drawBitmap(bitmap,50,150,paint2);
混合算法:[Sa * Da, Sa * Dc]
● SRC_OUT
paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SRC_OUT));
canvas.drawBitmap(bitmap,50,150,paint2);
混合算法:[Sa * (1 - Da), Sc * (1 - Da)]
● DST_OUT
paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.DST_OUT));
canvas.drawBitmap(bitmap,50,150,paint2);
混合算法:[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);
混合算法:[Sa, Sa * Dc + Sc * (1 - Da)]
● SRC_ATOP
paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.CLEAR));
canvas.drawBitmap(bitmap,50,150,paint2);
混合算法:[Da, Sc * Da + (1 - Sa) * Dc]
● XOR
paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.XOR));
canvas.drawBitmap(bitmap,50,150,paint2);
混合算法:[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);
混合算法:[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);
混合算法:[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);
混合算法:[Sa * Da, Sc * Dc]
● SCREEN
paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SCREEN));
canvas.drawBitmap(bitmap,50,150,paint2);
混合算法:[Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]
● ADD
paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.ADD));
canvas.drawBitmap(bitmap,50,150,paint2);
混合算法:Saturate(S + D)
● OVERLAY
paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.OVERLAY));
canvas.drawBitmap(bitmap,50,150,paint2);
混合算法:
个人觉得很全了,差不多可以满足大部分滤镜效果
版权声明:个人原创,若转载,请注明出处