在自定义控件中最熟悉的就是Paint,Canvas,path,Matrix等,要想炫酷效果这几个类必不可少。Paint.setColorFilter(ColorFilter filter):设置颜色过滤器,可以通过颜色过滤器过滤掉对应的色值.这样可以是图片颜色千变万化,没有做不到的颜色,只有你想不到的颜色。
ColorMatrixColorFilter:这是一个很重要的类,通过颜色矩阵(ColorMatrix)对图像中的色值进行改变。
图片颜色加载到内存中是一个个像素点agba,agb是颜色,a是透明度。ColorMatrix是一个4*5的矩阵,也是一维数组[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t]
ColorMatrix 的第一行参数abcde决定了图像的红色成分,第二行参数fghij决定了图像的绿色成分,第三行参数klmno决定了图像的蓝色成分,第四行参数pqrst决定了图像的透明度,第五列参数ejot是颜色的偏移量。
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;
通过以上公式的分析可得到,R1,G1,B1,A1分量值取决于他们的系数和最后加部分的偏移量(e,j,o,t).可得出如下结论:
1、第一行的a,b,c,d,e用来决定新的颜色值中的R的值(红色)---a,b,c,d为系数,e则为偏移量(offset),若a=1;b,c,d都为0,e为任意值(0-N),这就可以的得到:R1=R+e(若e=0,则R1=R),那就得出了,影响单个红色变化的有两个因素:一个是系数a,另一个则是偏移量(offset)e.所以当我们想控制单个红色的值话就可以从控制这两个变量值即可。e为偏移量,当我的a系数定了后,其他的b,c,d参数为0,当修改e的值后就会改变红色这个单个颜色的深浅程度,可以这样理解前面几个系数(a,b,c,d)用来配色的,而e后面偏移量则是用来控制颜色整体的深浅程度的
2、第二行f,g,h,i,j用来决定新的颜色值中的G的值(绿色)---f,g,h,i,j为系数,j则为偏移量(offset),若f=1;g,h,i都为0,j为任意值(0-N),这就可以的得到:G1=G+j(若j=0,则G1=G),那就得出了,影响单个绿色变化的有两个因素:一个是系数f,另一个则是偏移量(offset)j.所以当我们想控制单个绿色的值话就可以从控制这两个变量值即可。j为偏移量,当我的f系数定了后,其他的g,h,i参数为0,当修改j的值后就会改变绿色这个单个颜色的深浅程度,可以这样理解前面几个系数(f,g,h,i)用来配色的,而j后面偏移量则是用来控制颜色整体的深浅程度的
3、第三行的k,l,m,n,o用来决定新的颜色值中的B的值(蓝色)---k,l,m,n为系数o则为偏移量(offset),若k=1;l,m,n都为0,o为任意值(0-N),这就可以的得到:B1=B+o(若o=0,则B1=B),那就得出了,影响单个蓝色变化的有两个因素:一个是系数k,另一个则是偏移量(offset)o.所以当我们想控制单个蓝色的值话就可以从控制这两个变量值即可。o为偏移量,当我的k系数定了后,其他的l,m,n参数为0,当修改o的值后就会改变蓝色这个单个颜色的深浅程度,可以这样理解前面几个系数(k,l,m,n)用来配色的,而o后面偏移量则是用来控制颜色整体的深浅程度的
4、第四行的p,q,r,s,t用来决定新的颜色值中的A的值(透明度)---p,q,r,s为系数,t则为偏移量(offset),若p=1;q,r,s都为0,t为任意值(0-N),这就可以的得到:A1=A+t(若t=0,则A1=A),那就得出了,影响单个透明度变化的有两个因素:一个是系数p,另一个则是偏移量(offset)t.所以当我们想控制单个透明度的值话就可以从控制这两个变量值即可。t为偏移量.
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(bitmap, 0, 50, paint);
float[] floats = {
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0
};
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.set(floats);
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
canvas.drawBitmap(bitmap, 0, bitmap.getHeight() + 100, paint);
}
最简单的一段代码,显示俩张图片,第一张是正常显示图片,第二张是通过改变颜色矩阵中的值后显示的效果。
下面这张图是改变的R,G的颜色增量
float[] floats = {
1, 0, 0, 0, 100,
0, 1, 0, 0, 100,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0
};
我们吧红色成分增加2倍,效果
float[] floats = {
2, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0
};
我们吧绿色成分增加2倍,效果
float[] floats = {
1, 0, 0, 0, 0,
0, 2, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0
};
上面提到每行都是控制一个颜色,我们这样来修改
float[] floats = {
1, 0, 2, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0
};
看效果就知道都是控制的红色的份量。
除了自己去修改那个颜色矩阵外,android官方还给出一些调整图片的色光属性封装的API,主要用于修改色调(setRotate)、饱和度(setSaturation)、亮度(setScale),主要就是方便开放者使用,简化流程。
1、修改色调的API(setRotate)
colorMatrix.setRotate(axis, degrees);//第一参数可传入:0,1,2(0,1,2分别代表red,green,blue三种颜色的处理),第二个就是需要处理的值
public void setRotate(int axis, float degrees) {
reset();
double radians = degrees * Math.PI / 180d;
float cosine = (float) Math.cos(radians);
float sine = (float) Math.sin(radians);
switch (axis) {
// Rotation around the red color
case 0:
mArray[6] = mArray[12] = cosine;
mArray[7] = sine;
mArray[11] = -sine;
break;
// Rotation around the green color
case 1:
mArray[0] = mArray[12] = cosine;
mArray[2] = -sine;
mArray[10] = sine;
break;
// Rotation around the blue color
case 2:
mArray[0] = mArray[6] = cosine;
mArray[1] = sine;
mArray[5] = -sine;
break;
default:
throw new RuntimeException();
}
}
查看代码就知道每一个值代表的意思。
下面来设置setRotate这个值看看效果。
ColorMatrix colorMatrix = new ColorMatrix();
// colorMatrix.set(floats);
colorMatrix.setRotate(1,190);
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
canvas.drawBitmap(bitmap, 0, bitmap.getHeight() + 100, paint);
修改色调API(setSaturation)注意:当饱和度的颜色变为0的时候图片就变为灰色的图片了
setSaturation(0),这个时候是灰色,这不就是以前的黑白照片效果
修改亮度的API(setScale)当三原色如果是以相同的比例混合的话,就会显示出白色
colorMatrix.setScale(1,2,2,1);
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;
}
setScale最终修改的就是矩阵中的R G B颜色份量。
LightingColorFilter,用于颜色过滤,paint.setColorFilter(new LightingColorFilter(0xffff00ff,0xffff0000));十六进制颜色值分别是A,R,G,B。这段代码就是过滤掉绿色,并再添加红色。
效果图: