IBigerBiger的成长之路

移动端滤镜开发(一)ColorMatrix实现滤镜效果

关于滤镜开发


本着兴趣与之前项目有一点小小涉及的原因,对移动端的滤镜相关开发有小小的研究,故将相关的内容整理出来,供大家一起交流。

首先我们要了解什么是滤镜?

滤镜最早出现在胶片相机时代,为了保护相机的传感器免受各种环境因素的影响,慢慢发展到后面则出现带各种效果的滤镜,我们常用的滤镜主要有9种,他们分别是:UV镜、偏振镜、中灰镜、中灰渐变镜、反向中灰渐变镜、彩色滤镜、近摄镜以及特殊效果滤镜。它们一般由玻璃(高端产品)、树脂和聚碳酸酯制成。

对于现在数字时代的图片,我们可以通过算法处理来达到以前镜片的效果,这个系列的文章就是对于整个移动端滤镜开发从0到1的过程。

对于滤镜相关开发,我相信大家第一印象就是在自定义View中ColorMatrix可以对图片进行一定的处理从而达到不同的效果,所以开篇就对ColorMatrix进行相关的介绍

一.矩阵

首先我们得了解矩阵这个概念及相关的运算

(1).定义


由 m × n 个数aij排成的m行n列的数表称为m行n列的矩阵,简称m × n矩阵。


图1 矩阵
(2).基本运算

图2 矩阵加法

图3 矩阵减法

图4 矩阵数乘

图5 矩阵乘法

二.Android颜色矩阵

Android中的颜色矩阵是用来表示三原色和透明度的4×5的矩阵

1
2
3
4
[ a, b, c, d, e,
    f, g, h, i, j,
    k, l, m, n, o,
    p, q, r, s, t ]

颜色矩阵的功能划分如下

  • a, b, c, d, e 表示三原色中的红色
  • f, g, h, i, j 表示三原色中的绿色
  • k, l, m, n, o 表示三原色中的蓝色
  • p, q, r, s, t 表示颜色的透明度
  • 第五列用于表示颜色的偏移量

一个颜色则使用[R, G, B, A]的方式进行表示,所以矩阵与颜色的计算方式则为


图6 矩阵与颜色的计算方式

所以通过颜色矩阵我们会对原有的颜色进行改变

通过一个小的例子来实验一下

1
2
3
4
5
6
7
8
9
10
11
12
13
ColorMatrix colorMatrix = new ColorMatrix(new float[]{
0, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 1, 0,
});
canvas.drawBitmap(bitmap, null, new Rect(0, 0, getWidth()/2, getWidth()/2 * bitmap.getHeight() / bitmap.getWidth()), mPaint);
canvas.translate(getWidth()/2, 0);
mPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
canvas.drawBitmap(bitmap, null, new Rect(0, 0, getWidth()/2, getWidth()/2 * bitmap.getHeight() / bitmap.getWidth()), mPaint);

可以看到这边我们设置的颜色矩阵是仅仅保留绿色通道的,所以通过计算得到新的颜色为[0,G,0,A]

接下来看看最后的效果


图7 保留绿色通道效果图

三.颜色处理运算方式

#####(1)setSaturation(设置饱和度)

色彩的饱和度调整其实是对颜色矩阵的第五列进行调整

1
2
3
4
5
6
/**
* 设置矩阵颜色的饱和度
*
* sat 0表示灰度、1表示本身
*/
public void setSaturation(float sat)

ColorMatrix提供的setSaturation函数是对RGB的饱和度都进行调整

其中: 参数float sat:表示把当前色彩饱和度放大的倍数。取值为0表示完全无色彩,即灰度图像(黑白图像);取值为1时,表示色彩不变动;当取值大于1时,显示色彩过度饱和

如图所示


图8 色彩饱和度设置为0

图9 色彩饱和度设置为5

#####(2)setScale (色彩缩放)

1
2
3
4
5
6
7
8
/**
* rScale 表示红色的数值的缩放比例
* gScale 表示绿色的数值的缩放比例
* bScale 表示蓝色的数值的缩放比例
* aScale 表示透明度的数值的缩放比例
*/
public void setScale(float rScale, float gScale, float bScale,float aScale)

ColorMatrix的缩放方法,其实就是根据矩阵的运算规则,对R、G、B、A的数值分别进行缩放操作


图10 色彩缩放

像上面的最开始举的例子其实就是对色彩进行缩放,设置的是单色道的缩放

1
2
// 绿色通道
mColorMatrix.setScale(0,1,0,1);

当然也可以对每个色道进行修改

1
mColorMatrix.setScale(1.2f,1.5f,1.1f,1);

如图所示


图11 色彩缩放

#####(3)setRotate (色彩旋转)

1
2
3
4
5
6
7
8
/**
* 用于色调的旋转运算
* axis=0 表示色调围绕红色进行旋转
* axis=1 表示色调围绕绿色进行旋转
* axis=2 表示色调围绕蓝色进行旋转
*/
public void setRotate(int axis, float degrees)

图12 三原色坐标系

1)围绕红色轴旋转

我们可以根据三原色来建立一个三维向量坐标系,当围绕红色旋转时,我们将红色虚化为一个点,绿色为横坐标,蓝色为纵坐标,旋转θ°。


图13 围绕红色轴旋转坐标系

根据平行四边形法则R、G、B、A各值计算结果:



1
mColorMatrix.setRotate(0,90);

图14 围绕红色轴旋转坐标系90度

2)围绕绿色轴旋转

绿色虚化为一个点,蓝色为横坐标轴,红色为纵坐标轴,旋转θ°。


图15 围绕绿色轴旋转坐标系

根据平行四边形法则R、G、B、A各值计算结果:



1
mColorMatrix.setRotate(1,90);

图16 围绕绿色轴旋转坐标系90度

3)围绕蓝色轴旋转

蓝色虚化为一个点,红色为横坐标轴,绿色为纵坐标轴,旋转θ°。


图17 围绕蓝色轴旋转坐标系

根据平行四边形法则R、G、B、A各值计算结果:




1
mColorMatrix.setRotate(2,90);



图18 围绕蓝色轴旋转坐标系90度

写在后面的话

其实这一篇的ColorMatrix和我们整个的滤镜开发并没有太多的关联,所以这边也就简单的介绍一下了,毕竟用ColorMatrix来实现滤镜效果不能照顾到视频和相机相关,并且对于相对较复杂的滤镜也确实无能为力,所以后面会介绍更加给力的方法来实现滤镜效果,peace~~