(九)Paint 滤镜

版权声明:本文为博主原创文章,未经博主允许不得转载。

本文纯个人学习笔记,由于水平有限,难免有所出错,有发现的可以交流一下。

一、概述

滤镜效果就是对图像进行一定的过滤处理,安卓的颜色值有 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();
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值