Android中图像的色彩特效处理:
Android中色彩特效处理的基础:
Android中对于图片的处理通常使用的是Bitmap(位图),Bitmap中包含了一张图片的所有信息(点阵和颜色值)。点阵是一个包含像素的矩阵,每一个元素对应着图片的一个像素,而每一个像素都由一个颜色矩阵分量来保存该像素点的ARGB信息。颜色值——ARGB分别对应透明度,红色,绿色,蓝色,共同决定了像素点显示的颜色。
在Android中系统使用一个4x5的颜色矩阵(ColorMatrix)来处理图片的色彩效果(以一维数组的形式保存,a,b,c,d,e,f,g……r,s,t)。例如对于图片中的某一点像素,其颜色矩阵分量为C=????????RGBA1????????,而系统的颜色矩阵为A=?????afkpbglqchmrdinsejot?????,那么该像素点最终在屏幕上显示的颜色就是这两个矩阵乘积的结果,即该点最终显示在屏幕上的颜色为R=A?C=?????afkpbglqchmrdinsejot??????????????RGBA1????????=?????R1G1B1A1?????,其中R1=a?R+b?G+c?B+d?A+e?1,其他的G1,B1,A1也是矩阵的运算得出。该点最终显示的颜色就是矩阵R中的ARGB来共同决定的。通常情况下系统颜色矩阵为单位矩阵,即A=?????10000100001000010000?????
这就是Android中对图像的色彩处理的原理,而我们要做的就是通过修改颜色矩阵A来达到修改图片色彩的目的。
在图像处理中常见的三个名词的解释:
色调:色调不是指颜色的性质,而是对一幅绘画作品的整体颜色的概括评价。色调是指一幅作品色彩外观的基本倾向。在明度、纯度、色相这三个要素中,某种因素起主导作用,我们就称之为某种色调。一幅绘画作品虽然用了多种颜色,但总体有一种倾向,是偏兰或偏红,是偏暖或偏冷等等。这种颜色上的倾向就是一副绘画的色调。通常可以从色相、明度、冷暖、纯度四个方面来定义一幅作品的色调。
饱和度:饱和度是指色彩的鲜艳程度,也称色彩的纯度。饱和度取决于该色中含色成分和消色成分(灰色)的比例。含色成分越大,饱和度越大;消色成分越大,饱和度越小。纯的颜色都是高度饱和的,如鲜红,鲜绿;而白色,灰色等是不饱和的颜色。
亮度:亮度是指色彩的亮度或明度。颜色有深浅、明暗的变化。比如,深黄、中黄、淡黄、柠檬黄等黄颜色在明度上就不一样。
Android中色彩特效处理的途径:
知道了Android中色彩的处理办法和一些色彩名词,我们就可以尝试对图像的色彩进行处理了。根据我们前面知道的,色彩最终是由像素点的颜色矩阵和系统的ColorMatrix进行运算得到的。若是不对图片的色彩进行任何修改,则应该是R=A?C=?????10000100001000010000??????????????RGBA1????????=?????RGBA?????,这样图片不发生任何的变动。
由其运算规则可以知道,当我们需要修改RGBA时可以有两种方式:1>修改矩阵的偏移量2>修改矩阵的系数。这两种方式都能有效的改变最终色彩矩阵的值。
1>修改偏移量:
A=?????100001000010000110010000?????
图像的红色和绿色分量增加100,结果是色调更加偏向黄色(红色和绿色混合后得到黄色)
2>修改系数:
A=?????10000200001000010000?????
图像绿色分量的系数变为2,图像的色调更加偏向绿色。
3>使用系统提供的处理色光属性的方法:
- 修改色调:
/*声明一个颜色矩阵*/
ColorMatrix hueMatrix = new ColorMatrix();
/*调用其setRotate()方法修改RGB的值*/
hueMatrix.setRotate(0,hue0);//用0,1,2来代表对R,G,B三色的处理
/** Set the rotation on a color axis by the specified values.
* <code>axis=0</code> correspond to a rotation around the RED color
* <code>axis=1</code> correspond to a rotation around the GREEN color
* <code>axis=2</code> correspond to a rotation around the BLUE color
**/
- 修改饱和度:
//声明一个颜色矩阵
ColorMatrix saturationMatrix = new ColorMatrix();
调用其setSaturation()方法修改饱和度
saturationMatrix.setSaturation(saturation);//0代表灰度,1代表原图,比1越大的颜色越加饱和
/**sat A value of 0 maps the color to gray-scale. 1 is identity.**/
- 修改亮度:
/**public void setScale (float rScale, float gScale, float bScale, float aScale)**/
//当三原色以相同的比例混合时就会出现白色,系统也正是通过这个原理改变亮度
ColorMatrix lumMatrix = new ColorMatrix();
lumMatrix.setScale(lum,lum,lum,1);
- 组合效果:
系统提供了postConcat()方法来对多个矩阵进行计算
ColorMatrix imageMatrix = new ColorMatrix();
imageMatrix.postConcat(hueMatrix);
imageMatrix.postConcat(saturationMatrix);
imageMatrix.postConcat(lumMatrix);
这样就出来了组合效果。
对于这三种方式,其均不能对原图进行修改,而是要把原图复制一份,在副本上进行修改,完成后直接返回显示副本图片。所以我们在修改图片时要先根据原图来获得一个副本
//声明一个原图的副本
Bitmap resultBm = Bitmap.createBitmap(sourceBm.getWidth(), sourceBm.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(resultBm);
Paint paint = new Paint();
//设置已经计算好的颜色矩阵
paint.setColorFilter(new ColorMatrixColorFilter(resultMatrix));
//绘制图片,之后若有需要可以把resultBm返回。
canvas.drawBitmap(sourceBm, 0, 0, paint);
源码下载:
常用颜色矩阵:
- 灰度效果:
?????0.33F0.33F0.33F00.59F0.59F0.59F00.11F0.11F0.11F000010000?????
- 图像反转效果:
??????10000?10000?1011111110?????
- 去色效果:
?????1.5F1.5F1.5F01.5F1.5F1.5F01.5F1.5F1.5F00001?1?1?10?????
在知道了这些图像处理的常见矩阵值之后我们就可以自己写出类似于图片处理软件中的各种滤镜效果了。O(∩_∩)O~
Android中对于像素点的处理:
之前都是对整个图像进行处理,所以常见的就是色调,饱和度,亮度的整体改变,但是有时候需要做更加精细的图像操作,Android中同样为我们提供了便捷的方法。
1.获取图片所有的像素点:
/** pixels int[]-----接受回传的像素点数组,
offset int-----读取的偏移量,
stride int-----在pixels[]中的行间距
x int-----从图片中读取像素点的x坐标
y int-----从图片中读取像素点的y坐标
width int-----每行读取的值
height int------读取的行数
**/
mBitmap.getPixels(pixels,offset ,stride,x,y, width, height);
2.获取每个像素点的ARGB值:
for (int i = 0;i<width*height;i++) {
color = oldPexil[i];
//获取每个像素点的ARGB值
r = Color.red(color);
g = Color.green(color);
b = Color.blue(color);
a = Color.alpha(color);
}
3.对每个像素点进行处理:
for (int i = 0;i<width*height;i++) {
color = oldPexil[i];
//获取每个像素点的ARGB值
r = Color.red(color);
g = Color.green(color);
b = Color.blue(color);
a = Color.alpha(color);
//对像素点进行处理
r = (int) (0.393 * r + 0.769 * g + 0.189 * b);
g = (int) (0.349 * r + 0.686 * g + 0.168 * b);
b = (int) (0.272 * r + 0.543 * g + 0.131 * b);
if (r > 255) {
r = 255;
}else if(r<0){
r = 0;
}
if (g > 255) {
g = 255;
}else if(g<0){
g = 0;
}
if (b > 255) {
b = 255;
}else if(b<0){
b = 0;
}
}
3.合成新的像素点数组并将其应用于图片:
for (int i = 0;i<width*height;i++) {
color = oldPexil[i];
//获取每个像素点的ARGB值
r = Color.red(color);
g = Color.green(color);
b = Color.blue(color);
a = Color.alpha(color);
//对像素点进行处理
r = (int) (0.393 * r + 0.769 * g + 0.189 * b);
g = (int) (0.349 * r + 0.686 * g + 0.168 * b);
b = (int) (0.272 * r + 0.543 * g + 0.131 * b);
if (r > 255) {
r = 255;
}else if(r<0){
r = 0;
}
if (g > 255) {
g = 255;
}else if(g<0){
g = 0;
}
if (b > 255) {
b = 255;
}else if(b<0){
b = 0;
}
//合成新的像素数组
newPexil[i] = Color.argb(a, r, g, b);
}
//将新的像素数组应用于图像
bitmap.setPixels(newPexil, 0, width, 0, 0, width, height);
imageView.setImageBitmap(bitmap);
/**
这里要注意bitmap是根据照片原图得到的一个副本。和之前一样,我们都无法对原图直接进行操作,返回的只是处理后的一个副本。
**/
附一个图像特效的处理库,十分强大,实现了PS中大部分的算法效果,Instagram、美图秀秀、美颜相机、Camera360大部分的滤镜特效。