canvas - 使用 SVG 滤镜替换一种颜色

标签 canvas svg svg-filters

是否可以拍摄一张 IMG 图片并将一种确切的颜色替换为另一种颜色,例如将 #fff 替换为 #000,同时保持所有其他颜色不变?也许 SVG 滤镜的颜色矩阵可以提供帮助?

最佳答案

这对于 Canvas 来说是微不足道的。也可以使用 SVG 来完成,但它很复杂。以下方法适用于传统的完全不透明图像。首先,使用长 ComponentTransfer 将每个 channel 中的每个不匹配颜色值转换为 0,并将每个匹配颜色值转换为 1(256 个成员 tableValues 数组中唯一“1”的索引应与您的 r、g 和 b 匹配)替换值)。然后,使用颜色矩阵将除生成的白色像素之外的所有内容的 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>

关于canvas - 使用 SVG 滤镜替换一种颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41639049/

相关文章:

javascript - 如何在 Canvas fillText 中实现自动换行和回车?

javascript - 简单的 d3.js 示例图表开始

actionscript-3 - Actionscript 3 - 导入 SVG 文件

html - 如何将 SVG 效果应用于图像或 div 容器?

html - SVG 滤镜 feFlood 'flood-color' 属性是否支持渐变作为输入?

svg - SVG崩溃Safari

javascript - 图表每次渲染时都会调整大小

javascript - 使用 HTML5 在上传前调整图片大小

javascript - 如何显示用户的矩形的外观?

javascript - 在 Snap.svg 图形上设置 ID 属性