绘图不可或缺的画笔Paint-滤镜篇

Posted 花花young

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了绘图不可或缺的画笔Paint-滤镜篇相关的知识,希望对你有一定的参考价值。

前言

        在Android中需要通过graphics类来显示2D图形,在Graphics中包括了Canvas(画布)、Paint(画笔)、Color(颜色)、Bitmap(图像)等常用的类。Paint在自定义控件用的极其多,通过使用Paint可以根据你的想法画出各种各样的图案。

滤镜效果
对图像进行一定的过滤加工处理。使用Paint设置滤镜效果。
1.Alpha滤镜处理
MaskFilter
    (1)模糊遮罩滤镜(BlurMaskFilter)
    (2)浮雕遮罩滤镜(EmbossMaskFilter)
2.颜色RGB的滤镜处理
ColorMatrix

    (1)ColorMatrixColorFilter:色彩矩阵的颜色顾虑器。
    (2)LightingColorFilter:过滤颜色和增强色彩的方法。(光照颜色过滤器)
    (3)PorterDuffColorFilter:图形混合滤镜(图形学的一个理论飞跃)滤镜的所有处理效果都是通过颜色矩阵的变换实现的。


Part 1、Alpha滤镜处理

(1)模糊遮罩滤镜(BlurMaskFilter)

        /**
         * radius:模糊的半径
         * style:
         * BlurMaskFilter.Blur.NORMAL
         * BlurMaskFilter.Blur.INNER
         * BlurMaskFilter.Blur.OUTER
         * BlurMaskFilter.Blur.SOLID
         */
        paint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));
        canvas.drawBitmap(mBitmap, 0, 0, paint);
效果~


注意在绘制图像的时候要关闭硬件加速,否则没有任何效果

       setLayerType(View.LAYER_TYPE_SOFTWARE, null);
(2)浮雕遮罩滤镜(EmbossMaskFilter)

        /**
         * direction, 指定长度为xxx的数组标量[x,y,z],用来指定光源的位置
         * ambient, 指定周边背景光源(0~1)
         * specular, 指镜面反射系数
         * blurRadius 指定模糊半径
         */
        paint.setMaskFilter(new EmbossMaskFilter(new float[]30, 30, 30, 1f, 60, 80));
        canvas.drawBitmap(mBitmap, 400f, 0f, paint);
效果~



Part 2、颜色RGB的滤镜处理

(1)ColorMatrixColorFilter:色彩矩阵的颜色顾虑器

        paint.setColorFilter(new ColorMatrixColorFilter(matrix));

这里颜色的变化是由matrix来决定的,该Matrix为5*5的矩阵

的第一行参数abcde决定了图像的红色成分,第二行参数fghij决定了图像的绿色成分,第三行参数klmno决定了图像的蓝色成分,第四行参数pqrst决定了图像的透明度,第五列参数ejot是颜色的偏移量。

下面来说一下常见的矩阵

反相效果

        ColorMatrix matrix = new ColorMatrix(new float[]
                -1, 0, 0, 0, 255,
                0, -1, 0, 0, 255,
                0, 0, -1, 0, 255,
                0, 0, 0, 1, 0,
        );
颜色增强(可以起到变亮的效果)

        ColorMatrix matrix = new ColorMatrix(new float[]
                1.2f, 0, 0, 0, 0,
                0, 1.2f, 0, 0, 0,
                0, 0, 1.2f, 0, 0,
                0, 0, 0, 1.2f, 0,
        );
效果~

黑白效果

        ColorMatrix matrix = 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, 1f, 0,
        );
效果~

 去色的原理:只要将RGB三个通道的信息设置成一样的,即R=G=B,那图像就会变成了灰色,并且为了保证图像的亮度不变,同一个通道的R+G+B=1,如0.213+0.715+0.072=1;RGB=0.213, 0.715, 0.072; 三个数字是根据色彩光波频率及色彩心理学计算出来的。当然你也可以直接调用ColorMatrix的方法来设置

        //饱和度设置(1,是原来不变;0灰色;>1增加饱和度)
        matrix.setSaturation(10);

复古效果

        ColorMatrix matrix = 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, 1f, 0,
        );
效果~

你也可以通过缩放、旋转、平移来实现颜色的变化

        ColorMatrix matrix = new ColorMatrix();
        matrix.setScale(1, 1, 1.4f, 1);
        //饱和度设置(1,是原来不变;0灰色;>1增加饱和度)
        matrix.setSaturation(10);
        /**
         * axis,代表绕哪一个轴旋转,0,1,2
         * 	(0红色轴,1绿色,2蓝色)
         * degrees:旋转的度数
         */
        matrix.setRotate(0, 30);
        //设置颜色过滤器
        paint.setColorFilter(new ColorMatrixColorFilter(matrix));
(2)LightingColorFilter:过滤颜色和增强色彩的方法

        /**
         * mul,multiply相乘 ---缩放
         * add,相加---平移
         */
        paint.setColorFilter(new LightingColorFilter(0x00ff00, 0xff0000));
效果~


(3)PorterDuffColorFilter:图形混合滤镜

要学习PorterDuffColorFilter就不得不了解下PorterDuff.Mode的属性

private static final Xfermode[] sModes = 
            /** [0, 0] */
            new PorterDuffXfermode(PorterDuff.Mode.CLEAR),//在该区域里什么都不显示 
            /** [Sa, Sc] */
            new PorterDuffXfermode(PorterDuff.Mode.SRC),//在该区域里只显示原图  
            /** [Da, Dc] */
            new PorterDuffXfermode(PorterDuff.Mode.DST),//在该区域里只显示目标图  
            /** [Da, Sc * Da + (1 - Sa) * Dc] */
            new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP),//在该区域显示目标图并且相交部分显示原图  
            /** [Sa, Sa * Dc + Sc * (1 - Da)] */
            new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP),//在该区域显示原图并且相交部分显示目标图  
            /** [Sa * Da, Sc * Da] */
            new PorterDuffXfermode(PorterDuff.Mode.SRC_IN),//在该区域只显示相交区域且显示相交部分的原图  
            /** [Sa * Da, Sa * Dc] */
            new PorterDuffXfermode(PorterDuff.Mode.DST_IN),//在该区域只显示相交区域且显示相交部分的目标图  
            /** [Sa * Da, Sc * Dc] */
            new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),//在该区域只显示相交区域且显示两种的叠加颜色  
            /** [Sa * (1 - Da), Sc * (1 - Da)] */
            new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT),//在该区域显示非相交部分的原图  
            /** [Da * (1 - Sa), Dc * (1 - Sa)] */
            new PorterDuffXfermode(PorterDuff.Mode.DST_OUT),//在该区域显示非相交部分的目标图  

            /** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */
            new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER),//在该区域全部显示且原图在目标图的上方  
            /** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */
            new PorterDuffXfermode(PorterDuff.Mode.DST_OVER),//在该区域全部显示且目标图在原图的上方  
            /** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */
            new PorterDuffXfermode(PorterDuff.Mode.XOR),//在该区域全部显示并且相交部分显示透明 
            /** [Sa + Da - Sa*Da,Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
            new PorterDuffXfermode(PorterDuff.Mode.DARKEN),//在该区域全部显示且相交部分的颜色变深  
            /** [Sa + Da - Sa*Da,Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
            new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN),//在该区域全部显示且相交部分的颜色变亮  
            /** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
            new PorterDuffXfermode(PorterDuff.Mode.SCREEN),//在该区域全部显示且相交部分滤掉原图的颜色
            /** Saturate(S + D) */
            new PorterDuffXfermode(PorterDuff.Mode.ADD),//在该区域全部显示且相交部分饱和度相加  
            new PorterDuffXfermode(PorterDuff.Mode.OVERLAY)//在该区域全部显示且相交部分为叠加的颜色  
    ;
接下来使用PorterDuffColorFilter来实现圆形图片(上篇是使用的是渲染器Shader)


关键代码

@Override
protected void onDraw(Canvas canvas) 
        //super.onDraw(canvas);//屏蔽掉父类的onDraw方法
        Bitmap blank = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas drawCanvas = new Canvas(blank);
        drawCanvas.drawBitmap(ivBitmap, 0, 0, circlePaint);
        mode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
        circlePaint.setXfermode(mode);
        drawCanvas.drawBitmap(CircleBit, 0, 0, circlePaint);
        circlePaint.setXfermode(null);



以上是关于绘图不可或缺的画笔Paint-滤镜篇的主要内容,如果未能解决你的问题,请参考以下文章

绘图不可或缺的画笔Paint-渲染篇

android绘图之Paint(1)

Android自己定义View画家(画布)Canvas与画笔Paint的应用——绘图涂鸦板app的实现

三个绘图工具类详解

Android Paint以及ColorFilter等

Android Paint和Color类介绍