Android高级UI开发(四十二)canva滤镜
一、矩阵简述
1、定义
M*n矩阵。
2、矩阵乘法
它的意思就是将第一个矩阵A的第一行,与第二个矩阵B的第一列的数字分别相乘,得到的结果相加,最终的值做为结果矩阵的第(1,1)位置的值(即第一行,第一列)。
同样,A矩阵的第一行与B矩阵的第二列的数字分别相乘然后相加,结果做为结果矩阵第(1,2)位置的值(即第一行第二列)。
- 矩阵A乘以矩阵B和矩阵B乘以矩阵A的结果是不一样的。
色彩信息的矩阵表示
四阶表示
如果想将色彩(0,255,0,255)更改为半透明时,可以使用下面的的矩阵运算来表示:
真正的运算使用五阶矩阵
考虑下面这个变换:
1、红色分量值更改为原来的2倍;
2、绿色分量增加100;
则使用4阶矩阵的乘法无法实现,所以,应该在四阶色彩变换矩阵上增加一个“哑元坐标”,来实现所列的矩阵运算:
这个矩阵中,分量值用的是100
1*100+100
二、渲染举例
Alpha滤镜处理
1. 实现模糊效果:
-
protected void onDraw(Canvas canvas) {
-
super.onDraw(canvas);
-
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
-
RectF rectF = new RectF(0,100,bitmap.getWidth(),bitmap.getHeight());
-
paint.reset();
-
paint.setColor(Color.RED);
-
-
/**
-
* Create a blur maskfilter.
-
*
-
* @param radius 阴影的半径
-
* @param style NORMOL -- 整个图像都被模糊掉
-
* SOLID -- 图像边界外产生一层与Paint颜色一致阴影效果,不影响图像的本身
-
* OUTER -- 图像边界外产生一层阴影,并且将图像变成透明效果
-
* INNER -- 在图像内部边沿产生模糊效果
-
* @return
-
*/
-
paint.setMaskFilter(new BlurMaskFilter(50, BlurMaskFilter.Blur.NORMAL));
-
canvas.drawRect(rectF,paint);
-
}
模糊效果有以下几种模式:
(1)NORMOL: 整个图形都被模糊,见上面的效果图;
(2)SOLID:图像边界模糊,图形本身保持原样。效果图如下:
(3)OUTER模式:图形边界外产生模糊阴影,图形内变成透明。
(4)INNER:跟SOLID相反,边界内边缘模糊,图像内部无影响。
2. 镜面效果、浮雕效果
-
@Override
-
protected void onDraw(Canvas canvas) {
-
super.onDraw(canvas);
-
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
-
RectF rectF = new RectF(0,100,bitmap.getWidth(),bitmap.getHeight());
-
paint.reset();
-
paint.setColor(Color.RED);
-
-
/**
-
* Create an emboss maskfilter
-
*
-
* @param direction 指定光源的位置,长度为xxx的数组标量[x,y,z]
-
* @param ambient 环境光的因子 (0~1),越接近0,环境光越暗
-
* @param specular 镜面反射系数 越接近0,镜面反射越强
-
* @param blurRadius 模糊半径 值越大,模糊效果越明显
-
*/
-
paint.setMaskFilter(new EmbossMaskFilter(new float[]{50,50,10},1f,0.2f,1000));
-
//canvas.translate(200,0);
-
canvas.drawBitmap(bitmap,200,100,paint);
-
}
这里我们画了一张bitmap图片,在x=200,y=100的屏幕位置。Paint设置maskfilter为EmbossMaskFilter,构造函数的第一个参数代表光源x,y,z分别来自不同方向的光源,x是水平方向,y是垂直方向,z是垂直于手机屏幕的方向照射到屏幕上,数值越大,从各方向上照射过来的光的强度越大,第二个参数ambient环境光因子,值越小图片越暗。第三个参数镜面反射系统,越接近0,图片表面放光越强,视觉上的感受就和镜子在太阳光下一样,镜面越亮,甚至看不清镜子表面。
效果图下:
是不是图片表面有镜面反光的效果。
3. 颜色矩阵
-
protected void onDraw(Canvas canvas) {
-
super.onDraw(canvas);
-
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
-
-
paint.reset();
-
paint.setColor(Color.RED);
-
RectF rectF = new RectF(0,100,bitmap.getWidth(),100+bitmap.getHeight());
-
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
-
1, 0,0,0,0,
-
0,1,0,0,0,
-
0,0,1,0,0,
-
0,0,0,1,0,
-
});
-
-
paint.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
-
canvas.drawBitmap(bitmap,null,rectF,paint);
-
}
第一行的1表示R通道,第二行的1表示G绿色通道,第三行的1表示B蓝色通道,第四行的1表示透明度通道。目前都为1,表示正常显示,效果如下:
如果给绿色通道+100,颜色矩阵如下:
-
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
-
1, 0,0,0,0,
-
0,1,0,0,100,
-
0,0,1,0,0,
-
0,0,0,1,0,
-
});
则整个图片将会绿色更重,效果如下图:
我们接着给蓝色通道+100, 矩阵如下:
-
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
-
1, 0,0,0,0,
-
0,1,0,0,100,
-
0,0,1,0,100,
-
0,0,0,1,0,
-
});
图片将会凸显出蓝色和绿色的混合色,效果如下图:
反相效果,将矩阵改变成如下:
-
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
-
-1, 0,0,0,255,
-
0,-1,0,0,255,
-
0,0,-1,0,255,
-
0,0,0,1,0,
-
});
我们发现RGB的1都变成了-1,这意味着如果原来R的值是100的话,那么现在将变成255+(-100)=155,是255的另一半,所以叫反相。
这时图片的显示效果如下:
要想颜色增强,将矩阵改变成:
-
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
-
1.2f, 0,0,0,0,
-
0,1.2f,0,0,0,
-
0,0,1.2f,0,0,
-
0,0,0,1.2f,0,
-
});
我们发现RGBA4个通道都变成了原来的1.2倍,表现为图片效果则是亮度增加,如下图:
还可以显示黑白照片,只需将RGB三通道中的各颜色值(RGB颜色值)设置相同。为了让图形亮度不变,每一个通道里的RGB值加起来等于1,现在的矩阵如下所示:
-
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
-
0.213f, 0.715f,0.072f,0,0,
-
0.213f, 0.715f,0.072f,0,0,
-
0.213f, 0.715f,0.072f,0,0,
-
0,0,0,1,0,
-
});
第1行,第2行,第3行,这3个通道中的 第一列(R),第二列(G),第三列(B)的值都相等。且每一个通道的RGB值加起来还是1,与原来每一行只有1个1的情况一样,图像的亮度不会变,效果如下:
如果想要发色效果,例如将红色和绿色交换,矩阵如下:
-
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
-
1, 0,0,0,0,
-
1,0,0,0,0,
-
0,0,1,0,0,
-
0,0,0,1,0,
-
});
我们发现第二行的通道中,将绿色为0,红色为1.显示效果如下,颜色有点泛红:
同理,将第三通道中的蓝色和红色交换,矩阵如下:
-
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
-
1, 0,0,0,0,
-
0,1,0,0,0,
-
1,0,0,0,0,
-
0,0,0,1,0,
-
});
这次发出红色的效果更明显些,效果图如下:
如果想要复古效果,矩阵如下:
-
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
-
1/2f,1/2f,1/2f,0,0,
-
1/3f, 1/3f,1/3f,0,0,
-
1/4f,1/4f,1/4f,0,0,
-
0,0,0,1,0,
-
});
显示图片的效果如下:
颜色通道过滤,将绿色通道和蓝色通道清0后的矩阵如下:
-
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
-
1, 0,0,0,0,
-
0,0,0,0,0,
-
0,0,0,0,0,
-
0,0,0,1,0,
-
});
运行出的图片效果只剩红色,效果图如下:
除了直观的修改矩阵中的RGB三行通道中的RGB值,还可以使用API,如下代码:
-
protected void onDraw(Canvas canvas) {
-
super.onDraw(canvas);
-
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
-
RectF rectF = new RectF(0,100,bitmap.getWidth(),bitmap.getHeight());
-
paint.reset();
-
paint.setColor(Color.RED);
-
ColorMatrix colorMartrix = new ColorMatrix();
-
colorMartrix.setScale(1.2f,1.2f,1.2f,1);
-
paint.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
-
canvas.drawBitmap(bitmap,null, rectF,paint);
-
}
-
其中 以下两行代码:
-
ColorMatrix colorMartrix = new ColorMatrix();
-
colorMartrix.setScale(1.2f,1.2f,1.2f,1);
效果同矩阵:
-
ColorMatrix colorMartrix = new ColorMatrix(new float[]{
-
1.2f, 0,0,0,0,
-
0,1.2f,0,0,0,
-
0,0,1.2f,0,0,
-
0,0,0,1.2f,0,
-
});
-
使用如下两行代码还可以设置色彩的饱和度
-
ColorMatrix colorMartrix = new ColorMatrix();
-
colorMartrix.setSaturation(2f);
-
//colorMartrix.setSaturation(0f);
-
当设置为0时,图片变为黑白照片。当设置为2色彩很重,效果如下图所示;
-
还可以旋转颜色,
-
ColorMatrix colorMartrix = new ColorMatrix();
-
colorMartrix.setRotate(0,30); //红色旋转30度
-
colorMartrix.setRotate(1,30);//绿色旋转
-
colorMartrix.setRotate(2,30);//蓝色旋转
效果图如下:
LightingColorFilter,它的构造函数有2个参数:
-
/**
-
* Create a colorfilter that multiplies the RGB channels by one color,
-
* and then adds a second color. The alpha components of the mul and add
-
* arguments are ignored.
-
*/
-
public LightingColorFilter(@ColorInt int colorMultiply, @ColorInt int colorAdd) {
-
mMul = mul;
-
mAdd = add;
-
}
将原矩阵乘以 colorMultiply,然后再加上colorAdd. 假设原来矩阵的颜色值是RGB,经过LightingColorFilter后,R'G'B'的值如下:
-
* Given a source color RGB, the resulting R'G'B' color is computed thusly:
-
* <pre>
-
* R' = R * colorMultiply.R + colorAdd.R
-
* G' = G * colorMultiply.G + colorAdd.G
-
* B' = B * colorMultiply.B + colorAdd.B
-
* </pre>
实例核心代码如下:
-
paint.setColorFilter(new LightingColorFilter(0x00ff00,0x0000ff));
-
canvas.drawBitmap(bitmap,null, rectF,paint);
运行效果如下:
反正绿色增强了(乘绿色),然后蓝色也增强了(加蓝色)。
colorMartrix.setConcat(matA,matB);同时应用两个矩阵的效果,先应用A的效果,然后再应用B的效果。源码注释如下:
如下代码将2个矩阵效果叠加起来,第一个矩阵是原样,第二个矩阵加亮:
-
ColorMatrix colorMartrixA = new ColorMatrix(new float[]{
-
1, 0,0,0,0,
-
0,1,0,0,0,
-
0,0,1,0,0,
-
0,0,0,1,0,
-
});
-
-
-
-
ColorMatrix colorMartrixB = new ColorMatrix(new float[]{
-
1.2F, 0,0,0,0,
-
0,1.2F,0,0,0,
-
0,0,1.2F,0,0,
-
0,0,0,1,1.2F,0,
-
});
-
ColorMatrix colorMartrix = new ColorMatrix();
-
colorMartrix.setConcat(colorMartrixA,colorMartrixB);
-
paint.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
-
canvas.drawBitmap(bitmap,null, rectF,paint);
运行效果图如下:
paint.setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.DARKEN));
可以将红色像素与原图像素以指定的混合模式混合成新的像素。效果图如下:
-
paint.setColorFilter(new PorterDuffColorFilter(Color.argb(255,140,90,200), PorterDuff.Mode.MULTIPLY));
-
canvas.drawBitmap(bitmap,null,rectF,paint);
paint.setColorFilter(new PorterDuffColorFilter(Color.GREEN, PorterDuff.Mode.MULTIPLY));效果如下:
paint.setColorFilter(new PorterDuffColorFilter(Color.BLUE, PorterDuff.Mode.MULTIPLY));效果如下:
paint.setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY));的效果图如下:
我们发现MULTIPLY模式,相当于用透明的红色塑料片 叠加到原图之上 形成的 效果。
文章来源: blog.csdn.net,作者:冉航--小虾米,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/gaoxiaoweiandy/article/details/105308681
- 点赞
- 收藏
- 关注作者
评论(0)