Android图像处理ColorMatrix
1.颜色矩阵
可以看如下ColorMatix类的注释
/**
* 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:
* 下面这个4x5的矩阵可以表达,为一张图的颜色以及透明图信息。
* [ 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.计算出来的结果,每个通道都在0-255之间
*
* The sample ColorMatrix below inverts incoming colors by scaling each
* channel by -1, and then shifting the result up by
* 255 to remain in the standard color space.
* 以下是一个反转图片颜色的示例,把各颜色分值都设为-1,再加上255的分量,使它乘出来的颜色值保持再0-255之间
*
* [ -1, 0, 0, 0, 255,
* 0, -1, 0, 0, 255,
* 0, 0, -1, 0, 255,
* 0, 0, 0, 1, 0 ]
*/
颜色矩阵是一个用来表示三原色和透明度的4x5的矩阵,表示为一个数组的形式,一个颜色则使用[R, G, B, A]的方式进行表示,所以矩阵与颜色的计算方式则为
从上述的公式可以看出,颜色矩阵的功能划分如下
a, b, c, d, e 表示三原色中的红色
f, g, h, i, j 表示三原色中的绿色
k, l, m, n, o 表示三原色中的蓝色
p, q, r, s, t 表示颜色的透明度
第五列的e,j,o,t用于表示颜色的偏移量
这个偏移量可以拿来干嘛呢? 当我们想增强某一原色的值又不想影响其他颜色的时候就可以直接加上一个偏移量啦。
2.颜色矩阵在安卓里的定义
Android中的色彩矩阵是用ColorMatrics类来表示的。使用ColorMatrix的方法如下
// 生成色彩矩阵
ColorMatrix colorMatrix = new ColorMatrix(new float[]{
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0,
});
mPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
可以看下面着个demo来演示每个值对图片颜色的影响
简单的用20个EditText来输入矩阵数组的每个值,再把它设到paint上画出来就好了。
private void setMatrix() {
Bitmap bmp = Bitmap.createBitmap(
bitmap.getWidth(),
bitmap.getHeight(),
Bitmap.Config.ARGB_8888);
android.graphics.ColorMatrix colorMatrix =
new android.graphics.ColorMatrix();
//mColorMatrix就是我们从每个EditText里get出来得到的数组
colorMatrix.set(mColorMatrix);
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
canvas.drawBitmap(bitmap, 0, 0, paint);
mImageView.setImageBitmap(bmp);
}
如果我们设置只显示红色通道:
嗯小黄人看起来有点吓人了。。。
同理,只显示绿色通道,蓝色通道也是将其他两个色调置为0。
如果我们只是想增强绿色而不影响其他二原色,这时候偏移量用上啦。
反转图片颜色:
3.ColorMatrix提供的一些方法api
看完了以上直接修改矩阵值来修改颜色的例子之后,当然Android中ColorMatrix是自带了一些函数来帮我们完成一些调整饱和度、色彩旋转等操作的函数,我们就一一来看看
- 1、setSaturation——设置饱和度ColorMatrics给我们提供了一个方法来整体增强图像的饱和度,函数如下:
public void setSaturation(float sat)
其中:
参数float sat:表示把当前色彩饱和度放大的倍数。
/**
* Set the matrix to affect the saturation of colors.
*
* @param sat A value of 0 maps the color to gray-scale. 1 is identity.
*/
public void setSaturation(float sat) {
reset();
float[] m = mArray;
final float invSat = 1 - sat;
final float R = 0.213f * invSat;
final float G = 0.715f * invSat;
final float B = 0.072f * invSat;
m[0] = R + sat; m[1] = G; m[2] = B;
m[5] = R; m[6] = G + sat; m[7] = B;
m[10] = R; m[11] = G; m[12] = B + sat;
}
首先要说明一下
黑白图片的去色原理:只要把RGB三通道的色彩信息设置成一样;即:R=G=B,那么图像就变成了灰色,并且,为了保证图像亮度不变,同一个通道中的R+G+B应该接近1。
在Android中按照0.213 R,0.715 G 和 0.072 B 的比例构成像素灰度值。
所以当取值为0表示完全无色彩,即灰度图像(黑白图像);取值为1时,表示色彩不变动;当取值大于1时,显示色彩过度饱和 。
- 2、setScale——色彩缩放
同样,对于色彩的缩放运算ColorMatrics也已经为我们封装了一个函数:
public void setScale(float rScale, float gScale, float bScale,float aScale)
总共有四个参数,分别对应R,G,B,A颜色值的缩放倍数。
/**
* Set this colormatrix to scale by the specified values.
*/
public void setScale(float rScale, float gScale, float bScale,float aScale) {
final float[] a = mArray;
for (int i = 19; i > 0; --i) {
a[i] = 0;
}
a[0] = rScale;
a[6] = gScale;
a[12] = bScale;
a[18] = aScale;
}
跟进去的源码页很明显,它只是把矩阵对应的颜色分量设一个倍数啦。放大某个原色,就不放效果图了。
- 3、setRotate——色彩旋转
实际就是调整色值
/**
* 将旋转围绕某一个颜色轴旋转
* axis=0 围绕红色轴旋转
* axis=1 围绕绿色轴旋转
* axis=2 围绕蓝色轴旋转
*/
public void setRotate(int axis, float degrees);
这里有两个参数:
int axis:表示围绕哪个轴旋转,取值为0,1,2;取0时表示围绕红色轴旋转;取值1时,表示围绕绿色轴旋转;取值2时,表示围绕蓝色轴旋转;
float degrees:表示旋转的度数
- 4、ColorMatrics相乘
矩阵相乘涉及到三个函数:
public void setConcat(ColorMatrix matA, ColorMatrix matB)
这个函数接收两个ColorMatrix矩阵matA和matB,乘法规则为matA*matB,然后将结果做为当前ColorMatrix的值。(为什么要强调乘法规则为matA*matB?因为矩阵A*矩阵B和矩阵B*矩阵A的结果是不一样的!)
public void preConcat(ColorMatrix prematrix)
假如当前矩阵的A,而preConcat的意思就是将当前的矩阵A乘以prematrix
public void postConcat(ColorMatrix postmatrix)
上面prematrix是当前矩阵A*prematrix;而postConcat函数的意义就是postmatrix*当前矩阵A;这就是一个前乘,一个是后乘的区别!我们上面已经很清楚的讲了,前乘和后乘结果是不一样的!
- 5、getArray()获取当前矩阵数组
前面我们已经用到过getArray函数了,getArray函数的意义就是返回当前ColorMatrics对象中的所保存的矩阵
public float[] getArray()
返回值是float[]数组;
4.常见的一些滤镜效果的实现
1、反色效果
2、黑白
3、怀旧