版权声明:本文为博主原创文章,未经博主允许不得转载。
本文纯个人学习笔记,由于水平有限,难免有所出错,有发现的可以交流一下。
一、概述
滤镜效果就是对图像进行一定的过滤处理,安卓的颜色值有 32 位整数包含 4 个字节,ARGB 各占一个字节。:A—Alpha值,RGB—颜色值。
过滤主要分为两种,一是对 Alpha 的过滤处理,二是对 RGB 的过滤处理。
二、 Alpha 滤镜处理
MaskFilter 类进行处理,MaskFilter 又分为 BlurMaskFilter 和 EmbossMaskFilter 两种。
1.BlurMaskFilter 用来绘制模糊阴影
/**
* Create a blur maskfilter.
*
* @param radius 阴影的半径
* @param style NORMOL -- 整个图像都被模糊掉
* SOLID -- 图像边界外产生一层与Paint颜色一致阴影效果,不影响图像的本身
* OUTER -- 图像边界外产生一层阴影,并且将图像变成透明效果
* INNER -- 在图像内部边沿产生模糊效果
* @return
*/
public BlurMaskFilter(float radius, Blur style) ;
这是设置模糊半径为50的效果图。从左到右,从上到下,分别是原图、NORMOL 、SOLID 、OUTER 、INNER 。
这是设置模糊半径为100的效果图。从左到右,从上到下,分别是原图、NORMOL 、SOLID 、OUTER 、INNER 。
public class FilterView extends View {
Paint paint;
public FilterView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//硬件加速关闭
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
canvas.drawRect(100, 100, 500, 500, paint);
paint.setMaskFilter(new BlurMaskFilter(100, BlurMaskFilter.Blur.NORMAL));
canvas.drawRect(700, 100, 1100, 500, paint);
paint.setMaskFilter(new BlurMaskFilter(100, BlurMaskFilter.Blur.SOLID));
canvas.drawRect(100, 700, 500, 1100, paint);
paint.setMaskFilter(new BlurMaskFilter(100, BlurMaskFilter.Blur.OUTER));
canvas.drawRect(700, 700, 1100, 1100, paint);
paint.setMaskFilter(new BlurMaskFilter(100, BlurMaskFilter.Blur.INNER));
canvas.drawRect(100, 1300, 500, 1700, paint);
}
}
注:硬件加速必须关闭。
把红色方块换成图片的效果。
public class FilterView extends View {
Paint paint;
Bitmap bitmap;
private int progress;
private Matrix matrix = new Matrix();
public FilterView(Context context) {
super(context);
init();
}
private void init() {
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.timg);
matrix.setScale((float)400/bitmap.getWidth(), (float)400/bitmap.getHeight());
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
canvas.drawBitmap(bitmap, 100, 100, paint);
paint.setMaskFilter(new BlurMaskFilter(50, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(bitmap, 700, 100, paint);
paint.setMaskFilter(new BlurMaskFilter(50, BlurMaskFilter.Blur.SOLID));
canvas.drawBitmap(bitmap, 100, 700, paint);
paint.setMaskFilter(new BlurMaskFilter(50, BlurMaskFilter.Blur.OUTER));
canvas.drawBitmap(bitmap, 700, 700, paint);
paint.setMaskFilter(new BlurMaskFilter(50, BlurMaskFilter.Blur.INNER));
canvas.drawBitmap(bitmap, 100, 1300, paint);
}
}
2、EmbossMaskFilter 实现浮雕效果
模拟光照的照射效果,靠近光的地方偏亮,根据颜色的亮暗,模拟出3D的浮雕效果。
/**
* Create an emboss maskfilter
*
* @param direction 指定光源的位置,长度为xxx的数组标量[x,y,z]
* @param ambient 环境光的因子 (0~1),越接近0,环境光越暗
* @param specular 镜面反射系数 越接近0,镜面反射越强
* @param blurRadius 模糊半径 值越大,模糊效果越明显
*/
public EmbossMaskFilter(float[] direction, float ambient, float specular, float blurRadius);
public class FilterView extends View {
Paint paint;
public FilterView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//硬件加速关闭
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
canvas.drawRect(100, 100, 500, 500, paint);
//光照在平面上,所以较暗
paint.setMaskFilter(new EmbossMaskFilter(new float[]{1,1,0},0.2f,60,80));
canvas.drawRect(700, 100, 1100, 500, paint);
//光照在平面上方
paint.setMaskFilter(new EmbossMaskFilter(new float[]{1,1,1},0.2f,60,80));
canvas.drawRect(100, 700, 500, 1100, paint);
//增强光照强度,越大阴影面积越小
paint.setMaskFilter(new EmbossMaskFilter(new float[]{1,1,1},0.5f,60,80));
canvas.drawRect(700, 700, 1100, 1100, paint);
//减小镜面反射,颜色变淡(感觉1以上区别不大)
paint.setMaskFilter(new EmbossMaskFilter(new float[]{1,1,1},0.2f,0.2f,80));
canvas.drawRect(100, 1300, 500, 1700, paint);
//增大阴影面积
paint.setMaskFilter(new EmbossMaskFilter(new float[]{1,1,1},0.2f,60,160));
canvas.drawRect(700, 1300, 1100, 1700, paint);
}
}
注:一样别忘记关闭硬件加速。
三、 颜色矩阵
1.颜色矩阵概述
颜色矩阵正常是一个四阶的矩阵:
我们前面说到的颜色是 ARGB,但是在矩阵计算的时候是按 RGBA 来的,如把透明度变为一半:
四阶矩阵只支持颜色值的乘除运算,无法进行加减运算,如 R 要增加100,四阶矩阵无法实现。故在四阶色彩变换矩阵上增加一个“哑元坐标”,形成五阶矩阵来进行所有的运行:
注:颜色矩阵也可以用来进行透明度的变化,但更多是应用在 RGB 的变化。
简单的一个示例,透明度变为原来的一半:
public class FilterView extends View {
Paint paint;
public FilterView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//硬件加速关闭
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
canvas.drawRect(100, 100, 500, 500, paint);
//设置颜色矩阵过滤器
paint.setColorFilter(new ColorMatrixColorFilter(new float[]{
1,0,0,0,0,
0,1,0,0,0,
0,0,1,0,0,
0,0,0,0.5f,0
}));
canvas.drawRect(700, 100, 1100, 500, paint);
}
}
2.色彩的平移运算—加法运算
效果:增加特定色彩的饱和度,色彩的反转/反相;增加饱和度。
单独增加图片的绿色:
public class FilterView extends View {
Paint paint;
Bitmap bitmap;
private Matrix matrix = new Matrix();
public FilterView(Context context) {
super(context);
init();
}
private void init() {
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.timg);
matrix.setScale((float)400/bitmap.getWidth(), (float)400/bitmap.getHeight());
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
canvas.drawBitmap(bitmap, 100, 100, paint);
//设置颜色矩阵过滤器
//平移运算--绿色加100
paint.setColorFilter(new ColorMatrixColorFilter(new float[]{
1,0,0,0,0,
0,1,0,0,100,
0,0,1,0,0,
0,0,0,1,0
}));
canvas.drawBitmap(bitmap, 700, 100, paint);
}
}
3.色彩的缩放运算–乘法运算
效果:高亮图片,颜色通道过滤(单独红色、绿色、蓝色)
所有颜色值扩大为2倍:
public class FilterView extends View {
Paint paint;
Bitmap bitmap;
private int progress;
private Matrix matrix = new Matrix();
public FilterView(Context context) {
super(context);
init();
}
private void init() {
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.timg);
matrix.setScale((float)400/bitmap.getWidth(), (float)400/bitmap.getHeight());
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
canvas.drawBitmap(bitmap, 100, 100, paint);
//设置颜色矩阵过滤器
//RGB变为原先2倍
paint.setColorFilter(new ColorMatrixColorFilter(new float[]{
2f,0,0,0,0,
0,2f,0,0,0,
0,0,2f,0,0,
0,0,0,1,0
}));
canvas.drawBitmap(bitmap, 700, 100, paint);
}
}
4.加和乘的结合
反相效果:如 R 的值原先为 x,反相后为 255-x。
public class FilterView extends View {
Paint paint;
Bitmap bitmap;
private int progress;
private Matrix matrix = new Matrix();
public FilterView(Context context) {
super(context);
init();
}
private void init() {
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.timg);
matrix.setScale((float)400/bitmap.getWidth(), (float)400/bitmap.getHeight());
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
canvas.drawBitmap(bitmap, 100, 100, paint);
//设置颜色矩阵过滤器
//颜色反相
paint.setColorFilter(new ColorMatrixColorFilter(new float[]{
-1,0,0,0,255,
0,-1,0,0,255,
0,0,-1,0,255,
0,0,0,1,0
}));
canvas.drawBitmap(bitmap, 700, 100, paint);
}
}
5.黑白照片
**去色原理:**只要把R G B 三通道的色彩信息设置成一样,那么图像就会变成灰色。同时为了保证图像亮度不变,同一个通道里的R+G+B =1。
在安卓中,要实现这个去色原理,采用的是一个估计的矩阵值。
paint.setColorFilter(new ColorMatrixColorFilter(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,
}));
6.发色效果
红色和绿色交换:
矩阵:
paint.setColorFilter(new ColorMatrixColorFilter(new float[]{
0,1,0,0,0,
1,0,0,0,0,
0,0,1,0,0,
0,0,0,1,0
}));
7.复古效果
复古效果跟黑白效果一样,是一个经验矩阵。
paint.setColorFilter(new ColorMatrixColorFilter(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,
}));
8.颜色通道过滤
过滤红色:
矩阵:
paint.setColorFilter(new ColorMatrixColorFilter(new float[]{
1,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,1,0
}));
四、其他 RGB 滤镜处理
Paint.setColorFilter(ColorFilter filter);ColorFilter 还有两个子类 LightingColorFilter 和 PorterDuffColorFilter。
1.LightingColorFilter
LightingColorFilter 只会对颜色进行处理,透明度会被忽略。而且 RGB 的处理一直,能进行加法和乘法运许。
/**
* Create a colorfilter that multiplies the RGB channels by one color,
* and then adds a second color. The alpha components of the mul and add
* arguments are ignored.
*/
public LightingColorFilter(int mul, int add) {
mMul = mul;
mAdd = add;
update();
}
2.PorterDuffColorFilter
PorterDuffColorFilter 穿入一个 ARGB 与一个混合模式,用这个颜色与图片进行混合。(混合模式规则在上一篇)
public PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
mColor = color;
mMode = mode;
update();
}