滤镜效果

滤镜效果大家肯定都知道,毕竟现在相机这么牛,一般都有这个功能。
不废话,开搞!

所谓滤镜效果,就是对一张图像的颜色进行特定处理(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);

原图

shuaige.jpg

首先在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);
QQ截图20170830211237.png

● style---SOLID

paint2.setMaskFilter(new BlurMaskFilter(60, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截图20170830213038.png

● style---OUTER

paint2.setMaskFilter(new BlurMaskFilter(60, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截图20170830213251.png

● style---INNER

paint2.setMaskFilter(new BlurMaskFilter(60, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截图20170830213443.png

(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);
QQ截图20170830214650.png

2、颜色RGB的滤镜处理

首先需要大家掌握一些矩阵运算的基本知识(这个大家有点线性代数基础的都会懂的)--乘法


举证乘法.png

再看一下颜色矩阵乘法


颜色矩阵乘法.gif

该矩阵意思就是将图中颜色(RGBA)透明度变成它原来的一半,但是我们会发现,这种算法只能乘,如果我们有相加的需求,这种明显是不适用的。所以,应该在四阶色彩变换矩阵上增加一个“哑元坐标”,来实现所列的矩阵运算。
哑元坐标.gif

(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);
QQ截图20170830223456.png

● 反相效果 -- 底片效果(就是将每个像素都变成它的相反的值)

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);
QQ截图20170830224810.png

● 缩放运算---乘法 -- 颜色增强(此处将每个色值都乘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);
QQ截图20170830225334.png

● 黑白照片

去色原理:只要把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);
QQ截图20170830225729.png

● 发色效果---(比如红色和绿色交换)

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);
QQ截图20170830230034.png

● 复古效果

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);
QQ截图20170830230303.png

● 颜色通道过滤(此处过滤红色)

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);
QQ截图20170830230630.png

● 增加饱和度

ColorMatrix colorMartrix = new ColorMatrix();
colorMartrix.setSaturation(2f);
paint2.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
canvas.drawBitmap(bitmap,50,150,paint2);
QQ截图20170830231845.png

● 颜色旋转

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);
QQ截图20170830232406.png

● 颜色矩阵叠加效果(红色值加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);
QQ截图20170830233123.png

(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)
QQ截图20170830235335.png

(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);
CLEAR 效果
混合算法:[0, 0]

● SRC

paint2.setColorFilter(new PorterDuffColorFilter(Color.argb(175,140,90,200), PorterDuff.Mode.SRC));
canvas.drawBitmap(bitmap,50,150,paint2);
SRC 效果
混合算法:[Sa, Sc]

● DST

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.DST));
canvas.drawBitmap(bitmap,50,150,paint2);
DST 效果
混合算法:[Da, Dc]

● SRC_OVER

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SRC_OVER));
canvas.drawBitmap(bitmap,50,150,paint2);
SRC_OVER 效果
混合算法:[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);
DST_OVER 效果
混合算法:[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);
SRC_IN 效果
混合算法:[Sa * Da, Sc * Da]

● DST_IN

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.DST_IN));
canvas.drawBitmap(bitmap,50,150,paint2);
DST_IN 效果
混合算法:[Sa * Da, Sa * Dc]

● SRC_OUT

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SRC_OUT));
canvas.drawBitmap(bitmap,50,150,paint2);
SRC_OUT效果
混合算法:[Sa * (1 - Da), Sc * (1 - Da)]

● DST_OUT

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.DST_OUT));
canvas.drawBitmap(bitmap,50,150,paint2);
DST_OUT 效果
混合算法:[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);
DST_ATOP 效果
混合算法:[Sa, Sa * Dc + Sc * (1 - Da)]

● SRC_ATOP

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.CLEAR));
canvas.drawBitmap(bitmap,50,150,paint2);
SRC_ATOP 效果
混合算法:[Da, Sc * Da + (1 - Sa) * Dc]

● XOR

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.XOR));
canvas.drawBitmap(bitmap,50,150,paint2);
XOR 效果
混合算法:[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);
DARKEN 效果
混合算法:[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);
LIGHTEN 效果
混合算法:[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);
MULTIPLY 效果
混合算法:[Sa * Da, Sc * Dc]

● SCREEN

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.SCREEN));
canvas.drawBitmap(bitmap,50,150,paint2);
SCREEN 效果
混合算法:[Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]

● ADD

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.ADD));
canvas.drawBitmap(bitmap,50,150,paint2);
ADD 效果
混合算法:Saturate(S + D)

● OVERLAY

paint2.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.OVERLAY));
canvas.drawBitmap(bitmap,50,150,paint2);
OVERLAY 效果
混合算法:

个人觉得很全了,差不多可以满足大部分滤镜效果

版权声明:个人原创,若转载,请注明出处
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,888评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,677评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,386评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,726评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,729评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,337评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,902评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,807评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,349评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,439评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,567评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,242评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,933评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,420评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,531评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,995评论 3 377
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,585评论 2 359

推荐阅读更多精彩内容