Android图片的处理一般是将图片转成位图(Bitmap)来的处理,位图包含着一张图片的所有数据。图片实际上是由很多个单一颜色的点阵组成的,这些点越小图片就越细腻,点的颜色是由色值ARGB,即透明度、红、绿、蓝四个分量决定。而整张图片的处理实际上就是对这些点的分量做调整。
Android系统中提供一个用于调整颜色的矩阵ColorMatrix,这是一个4x5的数字矩阵。而颜色的色值则保存在一个4x1的矩阵中。色值的区间为[0,255]。以下是ColorMatrix部分注解
/**
* 4x5 matrix for transforming the color and alpha components of a Bitmap.
* The matrix can be passed as single array, and is treated as follows:
*
*
* [ a, b, c, d, e,
* f, g, h, i, j,
* k, l, m, n, o,
* p, q, r, s, t ]
*
*
* When applied to a color [R, G, B, A]
, the resulting color
* is computed as:
*
*
*
* R' = a*R + b*G + c*B + d*A + e;
* G' = f*R + g*G + h*B + i*A + j;
* B' = k*R + l*G + m*B + n*A + o;
* A' = p*R + q*G + r*B + s*A + t;
*
*
* That resulting color [R', G', B', A']
* then has each channel clamped to the 0
to 255
* range.
*
*/
由此上面注释我们可以知颜色矩阵m,和颜色分量矩阵C。
即新的颜色分量C’是颜色矩阵m乘以颜色分量矩阵新加一列值为1的5x1的矩阵所得的4x1矩阵,矩阵乘法公式可看注解
private float[] mColorMatrix = new float[20];
private Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.mipmap.maidou);
public void reset() {
final float[] a = mArray;
Arrays.fill(a, 0);
a[0] = a[6] = a[12] = a[18] = 1;
}
private Bitmap setImageMatrix(Bitmap bitmap){
reset();
Bitmap bmp = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), Bitmap.Config.ARGB_8888);
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.set(mColorMatrix);
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
canvas.drawBitmap(bitmap,0,0,paint);
return bmp;
}
由于Android系统不允许直接对原图做修改,因此先创建一个副本图片,再通过ColorMatrix的set方法设置颜色矩阵,使用Paint类的setColorFilter()方法,传入一个带有ColorMatrix对象的ColorMatrixColorFilter对象,使用这支修饰过的画笔在Canvas上绘制原图,从而使颜色矩阵作用在原图上。
我们使用照相机时往往能看到不同的照相效果,如:灰度、怀旧等其实也是通过改变图像的色值来显示效果。而改变色值不同的效果有不同的颜色矩阵,举例有:灰度效果(a)、图像反转(b)、怀旧效果(c)、高饱和度(d)
再回来看ColorMatrix类,其实除了直接设置矩阵的值外,该类还封装了一些API来快速调整矩阵参数,如:通过setRotate()方法设置色调、setSaturation()方法设置饱和度、setScale()方法设置亮度。这些方法使用起来很简单
public static Bitmap handleImageEffect(Bitmap bitmap,float rotate,float saturation,float scale){
// 创建副本,用于将处理过的图片展示出来而不影响原图,Android系统也不允许直接修改原图
Bitmap bmp = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint();
// 修改色调,即色彩矩阵围绕某种颜色分量旋转
ColorMatrix rotateMatrix = new ColorMatrix();
// 0,1,2分别代表像素点颜色矩阵中的Red,Green,Blue分量
rotateMatrix.setRotate(0,rotate);
rotateMatrix.setRotate(1,rotate);
rotateMatrix.setRotate(2,rotate);
// 修改饱和度
ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(saturation);
// 修改亮度,即某种颜色分量的缩放
ColorMatrix scaleMatrix = new ColorMatrix();
// 分别代表三个颜色分量的亮度
scaleMatrix.setScale(scale,scale,scale,1);
//将三种效果结合
ColorMatrix imageMatrix = new ColorMatrix();
imageMatrix.postConcat(rotateMatrix);
imageMatrix.postConcat(saturationMatrix);
imageMatrix.postConcat(scaleMatrix);
paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
canvas.drawBitmap(bitmap,0,0,paint);
return bmp;
}
以上便是三个方法简单的使用,由于ColorMatrix类方法比较少,也比较容易看懂,可以自行看源码:
色调调节setRotate(int axis, float degrees):
其中第一个参数axis是固定可选的,为0、1、2,分别表示改变Red、Green、Blue三个颜色分量,第二个参数degrees表示旋转角度,由旋转角度通过三角函数变换得到不同的矩阵,其中a为角度,单位为°。
invSat = 1 - sat
R = 0.213f * invSat
G = 0.715f * invSat
B = 0.072f * invSat
当饱和度sat为0时图片显灰度。
亮度调节setScale(float rScale, float gScale, float bScale,float aScale):
其矩阵为: