ColorMatrix介绍
ColorMatrix 是一个用于操作位图颜色分量的 4x5 矩阵类。常用于图像的颜色变换、饱和度调整、灰度处理、反转色、颜色通道旋转等操作。为什么 ColorMatrix 必须是 4x5 的矩阵形式呢?是为了支持颜色和 alpha 通道的线性变换,矩阵形式如下:
[ a, b, c, d, e, //表示的红色R
f, g, h, i, j, //表示的绿色G
k, l, m, n, o, //表示的蓝色B
p, q, r, s, t ] //表示颜色的透明度A
这可以看作一个线性变换 + 平移,对一个颜色 [R, G, B, A] 应用此矩阵后,新的颜色 [R', G', B', A'] 的计算方式如下:
R' = a*R + b*G + c*B + d*A + e
G' = f*R + g*G + h*B + i*A + j
B' = k*R + l*G + m*B + n*A + o
A' = p*R + q*G + r*B + s*A + t
这表示每个输出分量都可以由输入的 RGBA 和常数项共同线性组合而成。其中,前 4 列对应于输入的 R、G、B、A 通道的乘法系数;第 5 列表示一个偏移量(即常数项),可以用于亮度调整、反转色等非线性变换。先给出一个原图如下:
后面对图片的操作都是基于此图,比如做颜色反转:
val invert = ColorMatrix(
floatArrayOf(
-1f, 0f, 0f, 0f, 255f, // Red 通道:-R + 255
0f, -1f, 0f, 0f, 255f, // Green 通道:-G + 255
0f, 0f, -1f, 0f, 255f, // Blue 通道:-B + 255
0f, 0f, 0f, 1f, 0f // Alpha 通道:保持不变
)
)
mImgView.colorFilter = ColorMatrixColorFilter(invert)
为什么上述设置可以做到颜色反转,以 R 通道为例:
- 如果 R = 0 → 输出R' = 255
- 如果 R = 255 → 输出R' = 0
- 如果 R = 100 → 输出R' = 155
这样就实现了颜色取反:反转 = 255 - 原值,上述代码效果如下:
核心方法详解与示例
1. reset() - 重置为单位矩阵
public void reset()
将当前矩阵重置为单位矩阵(无变换),示例:
val matrix: ColorMatrix = ColorMatrix()
matrix.reset()
单位矩阵的形式如下:
1f, 0f, 0f, 0f, 0f, // Red 输出 = R * 1 + 0 = R 0f, 1f, 0f, 0f, 0f, // Green 输出 = G * 1 + 0 = G 0f, 0f, 1f, 0f, 0f, // Blue 输出 = B * 1 + 0 = B 0f, 0f, 0f, 1f, 0f // Alpha 输出 = A * 1 + 0 = A
该矩阵下不对图像进行任何变换,即:输出颜色 = 原始颜色,完全保持图像原样。
2. setScale() - 设置通道缩放
public void setScale(float rScale, float gScale, float bScale, float aScale)
设置通道缩放,参数rScale, gScale, bScale, aScale 分别对应缩放红、绿、蓝、透明度通道,如:
val matrix = ColorMatrix()
matrix.setScale(1f, 1f, 1f, 0.5f) //让alpha半透明
其他调用方式示例:
变亮: setScale(1.5f, 1.5f, 1.5f, 1f)
变暗: setScale(0.5f, 0.5f, 0.5f, 1f)
泛红: setScale(2f, 1f, 1f, 1f)
去除某个颜色通道: setScale(1f, 0f, 1f, 1f)
设置半透明: setScale(1f, 1f, 1f, 0.5f)
3. setSaturation() - 设置饱和度
public void setSaturation(float sat)
设置图像的饱和度: 0 = 灰度,1 = 原图,>1 = 更鲜艳,如:
val matrix = ColorMatrix()
matrix.setSaturation(0f) // 变成灰度图像
4. setRotate() - 颜色通道旋转
public void setRotate(int axis, float degrees)
在颜色空间中,围绕某一个颜色通道(R/G/B)轴,对另外两个颜色通道做二维旋转操作,从而达到色调变化的效果。
- axis 参数
| 值 | 含义 | 实际效果 |
|---|---|---|
| 0 | 绕 红色 (R ) 通道旋转 | 改变 绿色 (G) 与 蓝色 (B) 的混合 |
| 1 | 绕 绿色 (G) 通道旋转 | 改变 红色 (R ) 与 蓝色 (B) 的混合 |
| 2 | 绕 蓝色 (B) 通道旋转 | 改变 红色 (R ) 与 绿色 (G) 的混合 |
⚠️ 注意axis不能取除 0、1、2 以外的值,否则会抛出
java.lang.RuntimeException。
- degrees参数(旋转角度)
表示围绕指定颜色通道的角度旋转,单位是角度,支持任意正负角度(如 30f、-90f、360f、720f),会自动按三角函数周期性转换(360°周期)。
那么什么是“围绕颜色通道轴旋转”呢?可以把颜色 [R, G, B, A] 看成一个 4 维向量,
而 ColorMatrix.setRotate(axis, degrees) 是对 RGB 中的两个颜色分量做二维旋转,保留轴向通道不变。
比如:setRotate(0, 90f) 就是绕 R 轴旋转 90°,相当于:红色 R 分量保持不变,对 G 和 B 分量执行二维旋转 90°,二维旋转矩阵:
[x', y'] = [ cos(θ) -sin(θ) ] [x]
[ sin(θ) cos(θ) ] [y]
作用于颜色:
G' = cos(90°) * G - sin(90°) * B = -B
B' = sin(90°) * G + cos(90°) * B = G
R' = R
即:
输入:[R, G, B]
输出:[R, -B, G]
颜色就发生了扭转,产生了新的视觉滤镜效果,再比如:
val matrix = ColorMatrix()
matrix.setRotate(1, 45f) //绕绿色通道旋转 45 度
imageView.colorFilter = ColorMatrixColorFilter(matrix)
上述代码会让 红色 R 与蓝色 B 混合变色,绿色 G 保持不变,整体色调发生偏移。
5. setConcat() - 矩阵乘法(复合变换)
public void setConcat(ColorMatrix a, ColorMatrix b)
组合两个矩阵,先应用 b,再应用 a,示例:
val scale = ColorMatrix().apply { setScale(1.2f, 1.2f, 1.2f, 1f) }
val saturation = ColorMatrix().apply { setSaturation(2.0f) }
val result = ColorMatrix()
result.setConcat(scale, saturation)
先对图像进行“饱和度提升”,再做“亮度缩放”。
6. postConcat() 和 preConcat()
public void postConcat(ColorMatrix postMatrix)
public void preConcat(ColorMatrix preMatrix)
链式拼接变换:
postConcat是 result = postMatrix × thispreConcat是 result = this × postMatrix
示例:
val matrix = ColorMatrix().apply {
setSaturation(0f) //变灰
}
val scale = ColorMatrix().apply {
setScale(2f, 2f, 2f, 1f) //增强亮度
}
matrix.postConcat(scale)
上述代码先执行变灰操作,在执行增强亮度操作。如果改成preConcat,顺序反之。
总结
ColorMatrix 是一个功能强大的图像处理工具。它以 4x5 矩阵的形式,支持 RGB 和 Alpha 通道的线性变换与偏移,可完成色彩增强、去饱和、通道调换、图像反色等高级操作,适合搭配 ColorMatrixColorFilter 使用于 Paint 或 ImageView 等场景。