【Android】Android图像处理—图像色彩处理探究

Android图像处理—图像色彩处理探究

本文章主要探究了Android的图像处理中的色彩处理部分的使用

RGBA模型

RGBA是一种缩写,其含义分别是Red、Green、Blue、Aplha。即红、绿、蓝三原色以及透明度四个选项。我们平时所见到的各种颜色不过是这三原色通过不同的比例混合所得,而alpha则可以控制图片的透明度。

下面介绍一些图像处理中重要的三个概念:

  • 色调/色相:物体传递的颜色
  • 饱和度:颜色的纯度,从0%(灰)到100%(饱和)来进行描述
  • 亮度/明度:颜色的相对明暗程度

Android中,系统提供类ColorMatrix来帮助调整图像的三个重要属性

色调

通过setRotate方法来设定整个图像的色调,第一个是需要设定的颜色,其中,0对应R,1对应G,2对应B。这里为了简单,给它设定一样的值hue。

饱和度

通过setSaturation方法来给图像设置饱和度,通过设置值,就可以控制图片的饱和度。

亮度

通过setScale方法来给图像设定亮度,四个参数分别是R亮度,G亮度,B亮度以及透明度亮度。

通过ColorMatrix的方法调整图像效果

下面建立一个Android工程,来开始学习使用图像处理。

主界面

首先,建立一个主菜单,来选择对图片进行的修改。

activity_main.xml

MainActivity.java

三原色调整界面

可以大致分析一下,如果要调整一张图片,要经过这三个步骤:

  1. 获取一张图片
  2. 对图片进行一系列修改
  3. 返回一张图片

因此,不妨设计一个工具类,来进行图像相关的处理,这样可以提高代码的复用性。

这里,用到了Canvas类,canvas类是一个画布类,后面进行的操作都会在画布上进行,而不是在原图上。建立了三个ColorMatrix,进行了不同方面的操作,并用postConcat方法将这些Matrix进行融合。通过setColorFilter方法来修改paint的相关属性,然后在canvas上将图片绘制出来。最后将修改后的图片返回出来。

回到我们的界面。设计是用三个Seekbar来分别控制色相、饱和度、亮度三个属性。

然后编辑PrimaryColorActivity。这里我们定义了一个最大值及中间值,可以让它从中间值开始变化,然后通过一系列方法来分别获取色相、饱和度、亮度的值。

运行后,拖动Seekbar,可以发现,我们成功地改变了图片的各项属性


原理分析——矩阵变换

我们之前用到了ColorMatrix类,众所周知,Matrix是矩阵的意思,所以这里实际上我们是通过操作矩阵来处理图像。Android中提供了如图的颜色矩阵,来帮助我们进行图像效果的处理, 图像中的每一个点都是一个矩阵分量,是由R、G、B、A和1组成:

我们用这个颜色矩阵乘上像素点对应的颜色矩阵分量,就能得到一个新的矩阵R1G1B1A1。如图:

这样,我们就把一个像素点通过颜色矩阵变换成了新的像素点(颜色调整后的效果)。

我们把如图的矩阵称为初始化矩阵,因为它乘上原来的像素点后,仍不变。

下面我们看一下这个矩阵,它在原来矩阵的基础上把两个地方的0变为了100,导致的后果就是原来的R G的值变为了它们加上100的值,也就是每个像素点的R G值都增加了100:

同样的,我们可以看一下这样的一个矩阵,它在原来的初始化矩阵的基础上,把矩阵G上的一个1变为了2,带入后可发现,G变为了原来的两倍,效果就是将整个图像的Green增加了两倍

我们可以发现,颜色矩阵的四行分别控制着像素点的R G B A四个属性,而颜色矩阵的第五列,我们称它为颜色偏移量,它不会直接改变某个颜色的系数,而是在原来的基础上调整整个颜色。

我们要改变一个颜色,不仅仅可以改变偏移量,还可以改变颜色的系数。

用矩阵变换来调整图像效果

我们基于原来的工程,增加一个Activity,并让MainActivity的第二个按钮跳转到此Activity。

首先是布局,我们制作如下的布局,准备在GridLayout中添加20个EditText来代表矩阵,用按钮来应用矩阵。

<

然后,我们修改Activity的代码,动态将EditText添加到GridText,来映射我们的ColorMatrix。通过改变EditText来改变我们的ColorMatrix,使图片效果变化。

可以看到,成功改变了图片效果,效果如图

学到这里,我们便可以解答之前为什么要用这样的参数来改变色相、饱和度和亮度了。以亮度为例,我们来看看setScale方法的源码。可以发现,ColorMatrix在内部也是使用这样一个颜色数组,同时将6的倍数位设置为相应的值,以此来改变亮度,说明我们如果在颜色矩阵中想要改变亮度,只需要将每个颜色的值同时提高即可。

通过这些研究,我们可以这样总结:

图像处理,实际上就是研究不同颜色矩阵对图像的处理效果

比如我们在一些图像处理app中常见的怀旧效果,通过下图的设置方法即可得到


通过像素点进行图像处理

图像经过放大后,会呈现一个个点阵,每一个点实际上就是一个像素点。通过RGB的颜色配比,就可以显示出不同的颜色。

下面是一些对像素点处理形成图像特效的例子:

底片效果

对于ABC三个像素点,求B点的底片效果的算法如下。实际上就是对每个坐标点计算它的反色,即可得到

B.r = 255 – B.r;
B.g = 255 – B.g;
B.b = 255 – B.b;

老照片效果

求老照片效果对像素点的算法如下,其中pixR就是当前像素点的R值,以此类推。

newR = (int)(0.393 * pixR + 0.769 * pixG + 0.189 * pixB);
newG = (int)(0.349 * pixR + 0.686 * pixG + 0.168 * pixB);
newB = (int)(0.272 * pixR + 0.534 * pixG + 0.131 * pixB);

浮雕效果

对于ABC三个点,求B点的浮雕效果的算法如下。

B.r = C.r – B.r + 127;
B.g = C.g – B.g + 127;
B.b = C.b – B.b + 127;

下面,我们就通过对像素点的修改来改变图像的显示效果。

先新建一个新的Activity,并在MainActivity的第三个按钮中加上跳转到它的方法。

加入相应特效方法

我们在ImageUtils中加入几个新方法,分别做不同的处理

反色效果

代码如下,我们在里面新建了一个对应图片的像素的数组,然后通过getPixels方法获取所有像素。
getPixels的第二个参数是代表起点的偏移量,第三个参数是控制读取数组时的行距,一般使用width,后面两个参数代表第一次读取像素点的坐标,倒数第二个参数代表我们从bitmap中读取的宽度,最后一个是读取的高度。
然后我们分别对每个像素点通过Color类的red green blue alpha方法来获取r g b a四个值,并通过算法改变它的rgb值,并通过Color的argb方法转换为新的像素数组。需要注意的是,改变它的rgb值时,需要判断一下有没有超过0-255的限制,有的话则赋值为255或0

老照片效果

其他代码基本与之前的一样,只是算法稍作变动,并且不能在原来的rgb基础上改动:

<

pre class=”line-numbers prism-highlight” data-start=”1″>`

浮雕效果

与之前的差不多,唯一需要注意的是,我们需要用到前一个像素点的颜色,所以需要从1开始循环,然后通过相应算法,获取图片

查看效果

我们在Activity中调用相应方法,查看效果。

效果如图


评 论 区

  1. 还没有任何评论,你来说两句吧

发表评论

%d 博主赞过: