Android图片色彩处理ColorMatrix

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。

m=afkpbglqchmrdinsejotC=RGBA


即新的颜色分量C’是颜色矩阵m乘以颜色分量矩阵新加一列值为1的5x1的矩阵所得的4x1矩阵,矩阵乘法公式可看注解

C=afkpbglqchmrdinsejotRGBA1=aRfRkRpRbGgGlGqGcBhBmBrBdAiAnAsAejot=RGBA

由此可见新的颜色色值和处理之前的颜色色值之间的关系,矩阵m中各行的前四个分别决定新色值的RGBA,各行的第五个系数为新色值分量的偏移量。初始的颜色矩阵为:

10000100001000010000

在使用时颜色矩阵的值是以一个一维float类型数组的形式来存储的,以下是一个通过ColorMatrix处理Bitmap图片的方法,实际上是ColorMatrix中初始化的矩阵,所以图片没变化,可自己更改数组。

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)

a=0.33F0.33F0.33F00.59F0.59F0.59F00.11F0.11F0.11F000010000b=10000100001011111110

c=0.393F0.349F0.272F00.769F0.686F0.534F00.189F0.168F0.131F000010000d=1.438F0.062F0.062F00.122F1.378F0.122F00.016F0.016F1.483F000010.03F0.05F0.02F0

效果分别为:
Android图片色彩处理ColorMatrix_第1张图片
Android图片色彩处理ColorMatrix_第2张图片
Android图片色彩处理ColorMatrix_第3张图片
Android图片色彩处理ColorMatrix_第4张图片


再回来看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为角度,单位为°。

0=10000cosasina00sina10000100001=cosa0sina00100sina0cosa000010000

2=cosasina00sinacosa00001000010000

饱和度调节setSaturation(float sat):
这个方法只改颜色部分即左上九个参数, 有一定的公式,大致为如下:
R+satRR0GG+satG0BBB+sat000010000

其中:

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):
其矩阵为:

rScaleRR0GgScaleG0BBbScale0000aScale0000

当亮度为0时图片呈黑色。
效果叠加
preConcat(ColorMatrix prematrix)和postConcat(ColorMatrix postmatrix)两个方法分别是将目标效果矩阵放在本矩阵之前和放在本矩阵之后,由于矩阵的乘法一般不满足交换律,因此前后关系会对效果有不同的影响。

你可能感兴趣的:(android)