Android自定义View之图像的色彩处理

Android自定义View系列

Paint和Canvas为我们提供了丰富的API,使我们可以轻松的自己画一些图。除了可以绘制文字和简单的图形,Paint和Canvas还有一些高级的功能,比如改变图片的颜色和形状等。今天我们就来看看怎么利用Paint和Canvas改变图片的颜色。

改变图片的颜色

我们需要用到Paint和Canvas的新的API

  • Paint设置颜色过滤
paint.setColorFilter(new ColorMatrixColorFilter(ColorMatrix matrix)
复制代码
  • Canvas绘制Bitmap
canvas.drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint)
复制代码

这里出现了一个新东西:ColorMatrix


ColorMatrix
ColorMatrix改变颜色的原理
  • ColorMatrix:即色彩矩阵,是android.graphics包下的一个类,用来处理图片的色彩。
  • 它是一个4*5的数字矩阵,用一个一维数组来保存存储矩阵中的值。
  • 对于每一个像素点都有一个颜色分量矩阵用来保存颜色的RGBA值

颜色矩阵

A=  \begin{bmatrix}    a & b & c & d & e\\    f & g & h & i & j \\    k & l & m & n & o \\    p & q & r & s & t   \end{bmatrix}

颜色分量矩阵,对应的是每个像素的RGBA值

C= \left[  \begin{matrix}    R \\    G  \\    B \\    A \\    1   \end{matrix}  \right]

将颜色矩阵作用于像素的颜色分量矩阵,也就是2个矩阵做乘法

R1 = a*R + b*G + c*B + d*A + e
G1 = f*R + g*G + h*B + i*A + j;
B1 = k*R + l*G + m*B + n*A + o;
A1 = p*R + q*G + r*B + s*A + t;
复制代码

上面2个矩阵相乘以后得到的矩阵就是某个像素点对应的新的RGBA值,也就是变成了R1G1B1A1,这样我们只要改变颜色矩阵里元素的值就能改变像素的颜色值了。

特殊的是,当我们的颜色矩阵为:

A0=  \begin{bmatrix}    1 & 0 & 0 & 0 & 0\\    0 & 1 & 0 & 0 & 0 \\    0 & 0 & 1 & 0 & 0 \\    0 & 0 & 0 & 1 & 0   \end{bmatrix}

像素的RGBA值不变,因此矩阵A0通常作为初始的颜色矩阵。

ColorMatrix的常用API

一般我们都从色调、饱和度和亮度这三个方面来处理图像的色彩,Android系统中的ColorMatrix类已经为我们封装好了对应的API

  • 改变色调:setRotate(int axis, float degrees)
//色调
ColorMatrix hueMatrix = new ColorMatrix();
//0表示对Red的处理
hueMatrix.setRotate(0, hue);
//1表示对Green的处理
hueMatrix.setRotate(1, hue);
//2表示对Blue的处理
hueMatrix.setRotate(2, hue);
复制代码
  • 改变饱和度:setSaturation(float sat)
//饱和度
ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(saturation);
复制代码
  • 改变亮度:setScale(float rScale, float gScale, float bScale, float aScale)
//亮度
ColorMatrix lumMatrix = new ColorMatrix();
lumMatrix.setScale(lum, lum, lum, 1);
复制代码
  • 混合几个矩阵效果:postConcat(ColorMatrix postmatrix)
//组合效果
ColorMatrix bitmapMatrix = new ColorMatrix();
bitmapMatrix.postConcat(hueMatrix);
bitmapMatrix.postConcat(saturationMatrix);
bitmapMatrix.postConcat(lumMatrix);
复制代码

实战:获取灰度图片

日常开发中难免会用到灰度的图片,下面我们看看怎么用今天学的内容来实现。

灰度图片其实很简单,把图片的饱和度降为0就可以了。

(1)首先拿到图片

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ant);
复制代码

(2)拿到图片以后我们就要进行灰度处理了,这里直接将饱和度降为0就行了

//饱和度
ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(0);
复制代码

(3)然后调用Paint和Canvas重新绘图

Bitmap bitmap = Bitmap.createBitmap(bp.getWidth(), bp.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();

paint.setColorFilter(new ColorMatrixColorFilter(saturationMatrix));
canvas.drawBitmap(bp, 0, 0, paint);
复制代码

(4)最后将新得到的Bitmap设置给ImageView就可以了

imageView.setImageBitmap(bitmap);
复制代码

当然,我们也可以直接利用一个长度为20的一维数组来创建颜色矩阵,通过改变一维数组的元素的值来更加细致的控制颜色

比如灰度图片的一维数组为:

private static final float[] GREY = {0.33f,0.59f,0.11f,0,0,0.33f,0.59f,0.11f,0,0,0.33f,0.59f,0.11f,0,0,0,0,0,1,0};
复制代码

得到灰度图片的代码就变成如下

ColorMatrix bitmapMatrix = new ColorMatrix();
bitmapMatrix.set(GREY);

Bitmap bitmap = Bitmap.createBitmap(bp.getWidth(), bp.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();

paint.setColorFilter(new ColorMatrixColorFilter(bitmapMatrix));
canvas.drawBitmap(bp, 0, 0, paint);

复制代码

其实我们查看ColorMatrix的源码可以发现上述2种方式的原理是一样的,只不过ColorMatrix为我们提供了API方便我们使用,而不是每次都要去维护一个一维数组

//ColorMatrix.class
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;
}
复制代码

需要注意的是,同样是灰度图片,灰度的程度也可以不一样,如果要求较高,可以精细地调一调,不过一般都不用。


其他特殊颜色效果处理

研究图像色彩处理的人通过不同的算法将颜色矩阵应用到原图像上,从而得到新的色彩的图像。这里介绍几个常见的颜色效果矩阵

(1)灰度效果

private static final float[] GREY = {0.33f,0.59f,0.11f,0,0,0.33f,0.59f,0.11f,0,0,0.33f,0.59f,0.11f,0,0,0,0,0,1,0};
复制代码

(2)图像反转的效果

private static final float[] REVERSAL = {-1f,0f,0f,1,1,0f,-1f,0f,1,1,0f,0f,-1f,1,1,0,0,0,1,0};
复制代码

(3)去色效果

private static final float[] DECOLORATION = {1.5f,1.5f,1.5f,0,-1,1.5f,1.5f,1.5f,0,-1,1.5f,1.5f,1.5f,0,-1,0,0,0,1,0};
复制代码
总结
  • Android中通过颜色矩阵ColorMatrix来控制图像的颜色,ColorMatrix则是通过作用于像素的RGBA来改变颜色
  • ColorMatrix为我们提供了常用的API,包括色彩、饱和度和亮度的控制
  • Android中不允许直接改变原图,所以我们需要通过原图片来创建新的Bitmap,并以新的Bitmap创建画布Canvas
  • 通过Paint的setColorFilter方法,将颜色矩阵ColorMatrix作用于图像的绘制过程
  • 最后通过Canvas的drawBitmap方法得到新的Bitmap,需要注意的是我们创建Canvas使用的是新Bitmap,而drawBitmap方法中传递的是原始的Bitmap对象,千万别搞错了

欢迎关注我的微信公众号,和我一起每天进步一点点!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值