参考
上面使用了setColorFilter中使用ColorMatrixColorFilter包装的ColorMatrix;
setColorFilter
Paint的setColorFilter的API如下:
public ColorFilter setColorFilter(ColorFilter filter)
ColorFilter这个类没啥实现,靠子类来实现一些效果:
ColorMatrixFilter
上篇就是这个;
LightingColorFilter
ColorMatrix很强大,但使用起来比较麻烦;Android提供了光照颜色过滤器,可以简单的完成色彩过滤
和色彩增强
功能,这就是LightingColorFilter
;
构造函数
// mul乘法,add加法。mul和add取值都是0xRRGGBB,没有透明度,
// LightingColorFilter只针对RGB色值起作用
public LightingColorFilter(int mul, int add)
比如,当前有一个颜色值为(r,g,b),对它应用LightingColorFilter(mul, add)效果后的颜色值为:
结果R值 = (r*mul.R+add.R)%255; // % 255就是不超过255
结果G值 = (g*mul.G+add.G)%255;
结果B值 = (b*mul.B+add.B)%255;
也就是原来的色值 乘以 mul
对应的色值, 再 加上 add
对应的色值;
因为 mul 与 add 取值都是0xRRGGBB类型的值,即mul和add中都是包含了R、G、B分量的;
以红色为例:mul.R是对当前红色值进行放大的倍数
;而add.R则表示对当前红色增加的数值
;它们对应ColorMatrix的位置如下:
利用mul
进行颜色值放大并不好控制,所以更多的是用来过滤颜色
,即当对应的颜色值取0时,就不会将对应的颜色显示出来;
而把要显示出来的颜色对应的mul值设置为ff,即255;从公式中可以知道设置为255不会对原始的这个颜色分量产生任何影响。所以这样就可以把想要的颜色给显示出来,把不想要的颜色给过滤掉;
示例代码 - 显示绿色
// 绘制原始位图
canvas.drawBitmap(bitmap, null, Rect(0, 0, 250, 250 * bitmap.height / bitmap.width), paint)
canvas.translate(260f, 0f)
val paint2 = Paint(Paint.ANTI_ALIAS_FLAG)
// mul参数设置为0x00ff00,即把绿色显示出来,把R和B过滤掉
// add参数全部设置为0,即没有对原始图像色彩做任何改变
paint2.colorFilter = LightingColorFilter(0x00ff00,0x000000)
canvas.drawBitmap(bitmap, null, Rect(0, 0, 250, 250 * bitmap.height / bitmap.width), paint2)
加深蓝色
// mul参数设置为0xffffff,即没有对颜色做任何改变;add参数设置为0x0000f0,
// 即在每个像素的蓝色值在原来基础上增加0xf0,让原来的图像变得更蓝;
paint2.colorFilter = LightingColorFilter(0xffffff,0x0000f0)
参考源博客;
PorterDuffColorFilter
PorterDuff颜色滤镜,也叫图形混合滤镜;其名称是Tomas Proter和Tom Duff两个人名的缩写,他们提出的图形混合的概念极大地推动了图形图像学的发展;
构造
public PorterDuffColorFilter(int color, PorterDuff.Mode mode)
参数:
- color:0xAARRGGBB类型的颜色值;
- mode:混合模式,枚举值有18个,表示各种图形混合模式,有:
- Mode.CLEAR
- Mode.SRC
- Mode.DST
- Mode.SRC_OVER
- Mode.DST_OVER
- Mode.SRC_IN
- Mode.DST_IN
- Mode.SRC_OUT
- Mode.DST_OUT
- Mode.SRC_ATOP
- Mode.DST_ATOP
- Mode.XOR
- Mode.DARKEN
- Mode.LIGHTEN
- Mode.MULTIPLY
- Mode.SCREEN
- Mode.OVERLAY
- Mode.ADD
在这里与filter相关的有6个:
- Mode.ADD(饱和度相加)
- Mode.DARKEN(变暗)
- Mode.LIGHTEN(变亮)
- Mode.MULTIPLY(正片叠底)
- Mode.OVERLAY(叠加)
- Mode.SCREEN(滤色)
示例代码:叠底
// 绘制原始位图
canvas.drawBitmap(bitmap, null, Rect(0, 0, 250, 250 * bitmap.height / bitmap.width), paint)
val paint2 = Paint(Paint.ANTI_ALIAS_FLAG)
canvas.translate(260f, 0f)
paint2.colorFilter = PorterDuffColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY) // 正片叠底
canvas.drawBitmap(bitmap, null, Rect(0, 0, 250, 250 * bitmap.height / bitmap.width), paint2)
以红色为原色进行的PorterDuffColorFilter6个效果:
其他模式
除了上面的六个Mode,还有其它的三组Mode;
第一组:清空模式
- Mode.CLEAR;
- Mode.XOR;
这里表现的效果时,清空了原图;
第二组:目标图像模式
在Mode模式中,有一组DST相关的模式,DST所代表的意义就是被应用模式的图像
,即上面的图;
- Mode.DST;
- Mode.DST_IN
- Mode.DST_OUT
- Mode.DST_OVER
- Mode.DST_ATOP
几个模式在PorterDuffColorFilter的实际应用中,并没什么用
第三组:源图模式
在Mode模式中,有一组SRC相关的模式,SRC表示的颜色值所代表的图像
;
- Mode.SRC
- Mode.SRC_IN
- Mode.SRC_OUT
- Mode.SRC_OVER
- Mode.SRC_ATOP
具体参考原博客,这块我经常搞混了;DST与SRC经常搞混了;
利用SRC,我们可以改变图片的演示,对应一些ICON,只要求一个颜色系,就可以实现多个颜色了;也是V4包中DrawableCompat类添加的一个setLint()
函数所使用实现方法;
setLint示例
将图片改成想要的颜色
resources.getDrawable(R.mipmap.icon_map).mutate().let {
DrawableCompat.setTint(it, Color.GREEN)
setImageDrawable(it)
}
利用setTint就可以把一个图片渲染为不同的颜色,这样就可以支持多主题,在不同的风格和不同的情境下使用不同的颜色的图片。
使用PorterDuffColorFilter着色
// 原图
canvas.drawBitmap(mBmp, null, Rect(0, 0, width, height), mPaint)
canvas.translate(70f, 0f)
mPaint.setColorFilter(PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC))
canvas.drawBitmap(mBmp, null, Rect(0, 0, width, height), mPaint)
canvas.translate(70f, 0f)
mPaint.setColorFilter(PorterDuffColorFilter(Color.GREEN, PorterDuff.Mode.SRC_ATOP))
canvas.drawBitmap(mBmp, null, Rect(0, 0, width, height), mPaint)
canvas.translate(70f, 0f)
mPaint.setColorFilter(PorterDuffColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN))
canvas.drawBitmap(mBmp, null, Rect(0, 0, width, height), mPaint)
canvas.translate(70f, 0f)
mPaint.setColorFilter(PorterDuffColorFilter(Color.GRAY, PorterDuff.Mode.SRC_OVER))
canvas.drawBitmap(mBmp, null, Rect(0, 0, width, height), mPaint)
canvas.translate(70f, 0f)
mPaint.setColorFilter(PorterDuffColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_ATOP))
canvas.drawBitmap(mBmp, null, Rect(0, 0, width, height), mPaint)
SRC相关的模式,只有Mode.SRC_ATOP和SRC_IN能够实现SetTint的功能;
参考源博客解释,后续详细说明 这几个模式;
当然这里也可以通过ColorMatrix
来实现变色的;
如绿色:
// colorMatrix 00FF00
canvas.translate(70f, 0f)
mPaint.colorFilter = ColorMatrixColorFilter(ColorMatrix(floatArrayOf(
0f,0f,0f,0f,0f,
0f,0f,0f,0f,255f,
0f,0f,0f,0f,0f,
0f,0f,0f,1f,0f
)))
PorterDuffColorFilter总结:
- PorterDuffColorFilter只能实现与一个
特定颜色值
的合成; - 通过Mode.ADD(饱和度相加),Mode.DARKEN(变暗),Mode.LIGHTEN(变亮),Mode.MULTIPLY(正片叠底),Mode.OVERLAY(叠加),Mode.SCREEN(滤色)可以实现与指定颜色的复合;
- 通过Mode.SRC、Mode.SRC_IN、Mode.SRC_ATOP能够实现setTint()的功能,可以改变纯色图标的颜色;