绘图不可或缺的画笔Paint-滤镜篇
Posted 花花young
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了绘图不可或缺的画笔Paint-滤镜篇相关的知识,希望对你有一定的参考价值。
前言
在Android中需要通过graphics类来显示2D图形,在Graphics中包括了Canvas(画布)、Paint(画笔)、Color(颜色)、Bitmap(图像)等常用的类。Paint在自定义控件用的极其多,通过使用Paint可以根据你的想法画出各种各样的图案。
滤镜效果对图像进行一定的过滤加工处理。使用Paint设置滤镜效果。
1.Alpha滤镜处理
MaskFilter
(1)模糊遮罩滤镜(BlurMaskFilter)
(2)浮雕遮罩滤镜(EmbossMaskFilter)
2.颜色RGB的滤镜处理
ColorMatrix
(1)ColorMatrixColorFilter:色彩矩阵的颜色顾虑器。
(2)LightingColorFilter:过滤颜色和增强色彩的方法。(光照颜色过滤器)
(3)PorterDuffColorFilter:图形混合滤镜(图形学的一个理论飞跃)滤镜的所有处理效果都是通过颜色矩阵的变换实现的。
Part 1、Alpha滤镜处理
(1)模糊遮罩滤镜(BlurMaskFilter)
/**
* radius:模糊的半径
* style:
* BlurMaskFilter.Blur.NORMAL
* BlurMaskFilter.Blur.INNER
* BlurMaskFilter.Blur.OUTER
* BlurMaskFilter.Blur.SOLID
*/
paint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));
canvas.drawBitmap(mBitmap, 0, 0, paint);
效果~
注意在绘制图像的时候要关闭硬件加速,否则没有任何效果
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
(2)浮雕遮罩滤镜(EmbossMaskFilter)
/**
* direction, 指定长度为xxx的数组标量[x,y,z],用来指定光源的位置
* ambient, 指定周边背景光源(0~1)
* specular, 指镜面反射系数
* blurRadius 指定模糊半径
*/
paint.setMaskFilter(new EmbossMaskFilter(new float[]30, 30, 30, 1f, 60, 80));
canvas.drawBitmap(mBitmap, 400f, 0f, paint);
效果~
Part 2、颜色RGB的滤镜处理
(1)ColorMatrixColorFilter:色彩矩阵的颜色顾虑器
paint.setColorFilter(new ColorMatrixColorFilter(matrix));
这里颜色的变化是由matrix来决定的,该Matrix为5*5的矩阵
的第一行参数abcde决定了图像的红色成分,第二行参数fghij决定了图像的绿色成分,第三行参数klmno决定了图像的蓝色成分,第四行参数pqrst决定了图像的透明度,第五列参数ejot是颜色的偏移量。
下面来说一下常见的矩阵
反相效果
ColorMatrix matrix = new ColorMatrix(new float[]
-1, 0, 0, 0, 255,
0, -1, 0, 0, 255,
0, 0, -1, 0, 255,
0, 0, 0, 1, 0,
);
颜色增强(可以起到变亮的效果)
ColorMatrix matrix = 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 matrix = 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, 1f, 0,
);
效果~
去色的原理:只要将RGB三个通道的信息设置成一样的,即R=G=B,那图像就会变成了灰色,并且为了保证图像的亮度不变,同一个通道的R+G+B=1,如0.213+0.715+0.072=1;RGB=0.213, 0.715, 0.072; 三个数字是根据色彩光波频率及色彩心理学计算出来的。当然你也可以直接调用ColorMatrix的方法来设置
//饱和度设置(1,是原来不变;0灰色;>1增加饱和度)
matrix.setSaturation(10);
复古效果
ColorMatrix matrix = 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, 1f, 0,
);
效果~
你也可以通过缩放、旋转、平移来实现颜色的变化
ColorMatrix matrix = new ColorMatrix();
matrix.setScale(1, 1, 1.4f, 1);
//饱和度设置(1,是原来不变;0灰色;>1增加饱和度)
matrix.setSaturation(10);
/**
* axis,代表绕哪一个轴旋转,0,1,2
* (0红色轴,1绿色,2蓝色)
* degrees:旋转的度数
*/
matrix.setRotate(0, 30);
//设置颜色过滤器
paint.setColorFilter(new ColorMatrixColorFilter(matrix));
(2)LightingColorFilter:过滤颜色和增强色彩的方法
/**
* mul,multiply相乘 ---缩放
* add,相加---平移
*/
paint.setColorFilter(new LightingColorFilter(0x00ff00, 0xff0000));
效果~
(3)PorterDuffColorFilter:图形混合滤镜
要学习PorterDuffColorFilter就不得不了解下PorterDuff.Mode的属性
private static final Xfermode[] sModes =
/** [0, 0] */
new PorterDuffXfermode(PorterDuff.Mode.CLEAR),//在该区域里什么都不显示
/** [Sa, Sc] */
new PorterDuffXfermode(PorterDuff.Mode.SRC),//在该区域里只显示原图
/** [Da, Dc] */
new PorterDuffXfermode(PorterDuff.Mode.DST),//在该区域里只显示目标图
/** [Da, Sc * Da + (1 - Sa) * Dc] */
new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP),//在该区域显示目标图并且相交部分显示原图
/** [Sa, Sa * Dc + Sc * (1 - Da)] */
new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP),//在该区域显示原图并且相交部分显示目标图
/** [Sa * Da, Sc * Da] */
new PorterDuffXfermode(PorterDuff.Mode.SRC_IN),//在该区域只显示相交区域且显示相交部分的原图
/** [Sa * Da, Sa * Dc] */
new PorterDuffXfermode(PorterDuff.Mode.DST_IN),//在该区域只显示相交区域且显示相交部分的目标图
/** [Sa * Da, Sc * Dc] */
new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),//在该区域只显示相交区域且显示两种的叠加颜色
/** [Sa * (1 - Da), Sc * (1 - Da)] */
new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT),//在该区域显示非相交部分的原图
/** [Da * (1 - Sa), Dc * (1 - Sa)] */
new PorterDuffXfermode(PorterDuff.Mode.DST_OUT),//在该区域显示非相交部分的目标图
/** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */
new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER),//在该区域全部显示且原图在目标图的上方
/** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */
new PorterDuffXfermode(PorterDuff.Mode.DST_OVER),//在该区域全部显示且目标图在原图的上方
/** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */
new PorterDuffXfermode(PorterDuff.Mode.XOR),//在该区域全部显示并且相交部分显示透明
/** [Sa + Da - Sa*Da,Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
new PorterDuffXfermode(PorterDuff.Mode.DARKEN),//在该区域全部显示且相交部分的颜色变深
/** [Sa + Da - Sa*Da,Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN),//在该区域全部显示且相交部分的颜色变亮
/** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
new PorterDuffXfermode(PorterDuff.Mode.SCREEN),//在该区域全部显示且相交部分滤掉原图的颜色
/** Saturate(S + D) */
new PorterDuffXfermode(PorterDuff.Mode.ADD),//在该区域全部显示且相交部分饱和度相加
new PorterDuffXfermode(PorterDuff.Mode.OVERLAY)//在该区域全部显示且相交部分为叠加的颜色
;
接下来使用PorterDuffColorFilter来实现圆形图片(上篇是使用的是渲染器Shader)
关键代码
@Override
protected void onDraw(Canvas canvas)
//super.onDraw(canvas);//屏蔽掉父类的onDraw方法
Bitmap blank = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas drawCanvas = new Canvas(blank);
drawCanvas.drawBitmap(ivBitmap, 0, 0, circlePaint);
mode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
circlePaint.setXfermode(mode);
drawCanvas.drawBitmap(CircleBit, 0, 0, circlePaint);
circlePaint.setXfermode(null);
以上是关于绘图不可或缺的画笔Paint-滤镜篇的主要内容,如果未能解决你的问题,请参考以下文章