使用SVG过滤器替换一种颜色



是否可以拍摄IMG图片,并将一种确切的颜色替换为另一种颜色,比如#fff到#000,同时保持所有其他颜色不变?SVG过滤器的颜色矩阵可能有帮助吗?

这对于Canvas来说是微不足道的。也可以使用SVG,但它很复杂。以下方法适用于传统的完全不透明图像。首先,使用长ComponentTransfer(256个成员的tableValues数组中唯一的"1"的索引应该与r、g和b替换值匹配)将每个通道中的每个不匹配颜色值转换为零,将每个匹配颜色值转化为1。然后使用颜色矩阵将除白色像素外的所有像素的alpha归零。您将结果用作目标颜色的feFlood的遮罩,并将结果合成在原始图形上。例如,以下代码将特定颜色rgb(87、78、29)替换为蓝色。

<svg width="600px" height="600px" viewBox="0 0 600 600">
<defs>
<filter id="color-replace" color-interpolation-filters="sRGB">
<!-- Replace rgb(87,78,29) with blue. -->
<feComponentTransfer >
<feFuncR type="discrete" tableValues="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"/>
<feFuncG type="discrete" tableValues="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"/>
<feFuncB type="discrete" tableValues="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"/>
</feComponentTransfer>
<feColorMatrix type="matrix" values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
1 1 1 1 -3" result="selectedColor"/>
<feFlood flood-color="blue"/>
<feComposite operator="in" in2="selectedColor"/>
<feComposite operator="over" in2="SourceGraphic"/>
</filter>
</defs>
<g filter="url(#color-replace)">
<rect  x="50" y="50" height="100" width="100" fill="rgb(86,77,28)"/>
<rect  x="250" y="50" height="100" width="100" fill="rgb(86,77,29)"/>
<rect  x="450" y="50" height="100" width="100" fill="rgb(86,78,29)"/>
<rect  x="50" y="250" height="100" width="100" fill="rgb(87,77,29)"/>
<rect  x="250" y="250" height="100" width="100" fill="rgb(87,78,29)"/>
<rect  x="450" y="250" height="100" width="100" fill="rgb(87,78,30)"/>
<rect  x="50" y="450" height="100" width="100" fill="rgb(88,78,30)"/>
<rect  x="250" y="450" height="100" width="100" fill="rgb(88,79,29)"/>
<rect  x="450" y="450" height="100" width="100" fill="rgb(88,79,30)"/>
</g>
</svg>

更新:

如果你想用不透明度小于1的颜色替换原始颜色,那么你需要采取额外的步骤-在替换之前删除选定的颜色。你可以通过这种方式扩展过滤器来实现这一点。

<--snipping first half of filter -->
<feColorMatrix type="matrix" values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
1 1 1 1 -3" result="selectedColor"/>
<feComposite operator="out" in="SourceGraphic" result="notSelectedColor"/>
<feFlood flood-color="blue" flood-opacity="0.5"/>
<feComposite operator="in" in2="selectedColor"/>
<feComposite operator="over" in2="notSelectedColor"/>
</filter>

最新更新