最近在做个人项目时,遇到了这样一个需求,在获取到网络上图片之后,需要对图片的亮度进行一些处理,学习了一下Android中如何通过色彩矩阵处理色调、饱和度和亮度的知识,在这篇博客中记录一下供以后查阅。
Android中对于图片的处理,最常使用到的数据结构是位图——Bitmap,它包含了一张图片所有的数据。这个数据都是由点阵和颜色值组成的,所谓点阵就是一个包含像素的矩阵,每一个元素对应着图片的一个像素。而颜色值——ARGB,分别对应透明度、红、绿、蓝这四个通道分量,它们共同决定了每个像素点显示的颜色,下图就显示了自然界中的色光三原色。
色彩矩阵
在色彩处理中,通常使用一下三个角度来描述一个图像。
- 色调——物体传播的颜色
- 饱和度——颜色的纯度,从0(灰)到100%(饱和)来进行描述
- 亮度——颜色的相对明暗程度
而在Android中,系统使用一个颜色矩阵——ColorMatrix,来处理图像的这些色彩效果。Android中的颜色矩阵是一个4*5的数字矩阵,它用来对图片的色彩进行处理。而对于每个像素点,都有一个颜色分量矩阵来保存颜色的RGBA值,如图所示:
图中矩阵M就是一个4*5的颜色矩阵。在Android中,它会以一维数组的形式来存储,而C则是一个颜色矩阵分量。在处理图像时,使用矩阵乘法运算MC来处理颜色分量矩阵:
根据线性代数中的矩阵乘法运算法则,我们可以发现,颜色矩阵是按一下方式划分的
- 第一行的abcde值用来决定新的颜色值中的R——红色
- 第二行的fghij值用来决定新的颜色值中的G——绿色
- 第三行的klmno值用来决定新的颜色值中的B——蓝色
- 第四行的pqrst值用来决定新的颜色值中的A——透明度
- 矩阵M中的第五列——ejot值分别用来决定每个分量中的offset,即偏移量
以R分量的计算过程为例:
R1 = a*R + b*G + c*B + d*A + e;
令a=1,b、c、d、e都等于0,那么计算结果为R1 = R
同理 令a,g,m,s四个值为1,其他值为0的颜色矩阵不会改变原有颜色值。
如果需要改变原有颜色值的矩阵分量,有两种方法:
- 改变a,g,m,s这四个值,即可使原有颜色值产生相应系数的变化
- 改变偏移量的值,即颜色矩阵中第五列的值
使用ColorMatrix
除了自定义一个冗长的一维数组矩阵来处理图像颜色,Android内部封装了一些API来快速调整生成矩阵,而不用每次都自己去计算矩阵值。
在Anroid中,系统封装了一个类——ColorMatrix,也就是前面说所的颜色矩阵。通过这个类,可以很方便地通过改变矩阵值来处理颜色效果,创建一个ColorMatrix对象非常简单,代码如下所示。
ColorMatrix hueMatrix = new ColorMatrix();
改变色调
直接上方法的源代码: