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

来源:互联网 发布:石家庄蓝点网络 编辑:程序博客网 时间:2024/05/17 08:14

前言

        在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)


关键代码

@Overrideprotected 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);}



0 0