Table of Contents

1概述

feColorMatrix 元素用于将图像的像素值进行矩阵变换。

颜色矩阵是一个 5x4 的矩阵,我们可以用上面这个工具来方便大家生成理想的颜色变换矩阵。

其中第一行是红色通道,第二行是绿色通道,第三行是蓝色通道,第四行是透明度通道。

[r1r2r3r4r5g1g2g3g4g5b1b2b3b4b5a1a2a3a4a5]\begin{bmatrix} r1 & r2 & r3 & r4 & r5 \\ g1 & g2 & g3 & g4 & g5 \\ b1 & b2 & b3 & b4 & b5 \\ a1 & a2 & a3 & a4 & a5 \\ \end{bmatrix}

如下所示,我用案例表明了每一层颜色矩阵的取值。

index.html
1
<!-- 此时表示保留原图,啥都不变 -->
2
<feColorMatrix type="matrix" values="
3
1 0 0 0 0 <!-- 红色通道:原图的红色组成部分 -->
4
0 1 0 0 0 <!-- 绿色通道:原图的绿色组成部分 -->
5
0 0 1 0 0 <!-- 蓝色通道:原图的蓝色组成部分 -->
6
0 0 0 1 0" <!-- Alpha通道:原图的透明度组成部分 -->
7
/>

矩阵乘法公式为

[rgba]=[r1r2r3r4r5g1g2g3g4g5b1b2b3b4b5a1a2a3a4a5]X[RGBA1]\begin{bmatrix} r` \\ g` \\ b` \\ a` \\ \end{bmatrix} = \begin{bmatrix} r1 & r2 & r3 & r4 & r5 \\ g1 & g2 & g3 & g4 & g5 \\ b1 & b2 & b3 & b4 & b5 \\ a1 & a2 & a3 & a4 & a5 \\ \end{bmatrix} X \begin{bmatrix} R \\ G \\ B \\ A \\ 1 \end{bmatrix}

翻译一下就是:

  • 新的红色通道 = (旧红色 x r1) + (旧绿色 x r2) + (旧蓝色 x r3) + (旧透明度 x r4) + (偏移量 r5)
  • 新的绿色通道 = (旧红色 x g1) + (旧绿色 x g2) + (旧蓝色 x g3) + (旧透明度 x g4) + (偏移量 g5)
  • 新的蓝色通道 = (旧红色 x b1) + (旧绿色 x b2) + (旧蓝色 x b3) + (旧透明度 x b4) + (偏移量 b5)
  • 新的透明度通道 = (旧红色 x a1) + (旧绿色 x a2) + (旧蓝色 x a3) + (旧透明度 x a4) + (偏移量 a5)

feColorMatrix 主要通过 type 属性来定义不同的颜色操作模式

  • matrix 完整的矩阵变换模式,可以通过该方法来实现最精确的颜色控制
  • saturate 饱和度模式,取值范围 0 ~ 1,0 表示完全去色,1 表示完全不改变
  • hueRotate 色相旋转模式,用于调整图像的色相,取值范围 0 ~ 360,0 表示完全不改变,360 表示完全旋转一圈
  • luminanceToAlpha 亮度到透明度模式,用于将图像的亮度转换为透明度,取值范围 0 ~ 1,0 表示完全透明,1 表示完全不透明

饱和度、色相旋转、透明度的表现与 css filter 的表现与取值都是一致的,因此我们这里不再使用案例来演示,我们主要学习 matrix 模式。

我们通过如下案例来感受不同的颜色操作模式

预览
index.tsx
1
{/* 只保留红色通道 */}
2
<filter id="92demo01_matrix_red">
3
<feColorMatrix type="matrix" values="
4
1 0 0 0 0
5
0 0 0 0 0
6
0 0 0 0 0
7
0 0 0 1 0"
8
/>
9
</filter>
10
11
{/* 只保留绿色通道 */}
12
<filter id="92demo01_matrix_green">
13
<feColorMatrix type="matrix" values="
14
0 0 0 0 0
15
0 1 0 0 0
16
0 0 0 0 0
17
0 0 0 1 0"
18
/>
19
</filter>
20
21
{/* 只保留蓝色通道 */}
22
<filter id="92demo01_matrix_blue">
23
<feColorMatrix type="matrix" values="
24
0 0 0 0 0
25
0 0 0 0 0
26
0 0 1 0 0
27
0 0 0 1 0"
28
/>
29
</filter>

2实践:spotify 风格

Spotify 双色调风格是一种适合品牌化的风格。我们可以使用 2 次颜色转换来实现该效果。

首先将原图转为灰色,然后将高光映射会另外一种颜色:例如亮粉、荧光绿、深紫色等。从而让多张图片呈现出统一的风格。

预览
index.html
1
<svg width="0" height="0" style="position: absolute;">
2
<filter id="92demo03_matrix_spotify">
3
<!-- 步骤1: 将图片转为灰度,但为了保留细节,我们混合RGB通道 -->
4
<feColorMatrix type="matrix" result="gray" values="
5
1 0 0 0 0
6
1 0 0 0 0
7
1 0 0 0 0
8
0 0 0 1 0" />
9
10
<!-- 步骤2: 颜色映射
11
我们将灰度值映射到两个特定颜色:
12
颜色A (深紫): R:44 G:20 B:180 (#2c14b4)
13
颜色B (荧光粉): R:255 G:55 B:160 (#ff37a0)
14
原理:利用最后一列作为基础色(暗部),利用前三列作为增量(亮部)
15
-->
16
<feColorMatrix type="matrix" in="gray" values="
17
0.82 0 0 0 0.17
18
0.13 0 0 0 0.07
19
-0.07 0 0 0 0.70
20
0 0 0 1 0" />
21
</filter>
22
</svg>

3实践:高斯模糊液态融合

在前面,我们学习了 css 的高斯模糊与对比度增强的结合可是实现液态融合效果。但是那种方案只能应用于简单的场景,颜色与预期的颜色不一致,会因为对比度增强导致颜色失真。

因此,我们这里需要使用 feColorMatrix 来实现更精确的颜色控制。

具体的原理在备注中注明,大家可以结合代码与备注进行理解。

预览
index.html
1
<svg width="0" height="0" style="position: absolute;">
2
<filter id="92demo04_matrix_gooey">
3
<!-- 1. 高斯模糊 -->
4
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
5
<!-- 2. Alpha 对比度增强 -->
6
<!--
7
a_4 (18): 放大 Alpha 值 (让模糊部分变清晰)
8
a_5 (-7): 减去偏移量 (切掉太淡的边缘)
9
公式: A' = A * 18 - 7
10
-->
11
<feColorMatrix in="blur" type="matrix" values="
12
1 0 0 0 0
13
0 1 0 0 0
14
0 0 1 0 0
15
0 0 0 18 -7" result="goo" />
16
<!-- 3. (可选) 将原图叠在上面,保证内容清晰 -->
17
<feComposite in="SourceGraphic" in2="goo" operator="atop"/>
18
</filter>
19
</svg>

4实践:自定义颜色

这里分享的一个案例是利用滤镜给白底黑字的扫描件或图标上色。详细原理请看备注

预览
index.tsx
1
<svg width="0" height="0">
2
<filter id="92demo05_matrix">
3
{/*
4
反转 Alpha:
5
让原来的白色变透明,黑色变实体。
6
这对于处理白底黑字的扫描件或图标非常有用。
7
A' = A * -1 + 1
8
*/}
9
<feColorMatrix type="matrix" values="
10
1 0 0 0 0
11
0 1 0 0 0
12
0 0 1 0 0
13
-1 0 0 1 0"
14
/>
15
16
{/* 给实体部分上色 (例如变成深红色) */}
17
<feColorMatrix type="matrix" values="
18
0 0 0 0 0.8
19
0 0 0 0 0.1
20
0 0 0 0 0.1
21
0 0 0 1 0"
22
/>
23
</filter>
24
</svg>

如果你的图片不是纯色的黑白,又灰色过渡,可以使用 亮度权重 来计算,从而使边缘更平滑

下面的变换矩阵是将上面案例中的矩阵合二为一,可以得到同样的效果,拆分是为了更好的理解。你也可以在最开始的颜色编辑器中,调出最适合你图片的变换矩阵。

index.tsx
1
<svg width="0" height="0" style="position: absolute;">
2
<filter id="text-mask-smooth">
3
<feColorMatrix type="matrix" values="
4
0 0 0 0 0.8
5
0 0 0 0 0.1
6
0 0 0 0 0.1
7
-0.21 -0.72 -0.07 1 0 "
8
/>
9
</filter>
10
</svg>
专栏首页
到顶
专栏目录