SVG 过滤器将 alpha 值映射到表中的 RGB 值?

标签 svg svg-filters

我了解如何使用feComponentTransfer使用tabletableValues调整RGBA值。

但是有没有办法使用 alpha 值作为输入来调整 R、G 或 B 值(例如)?

为什么?假设我合成了许多半透明形状,导致这些形状重叠的地方产生不同的不透明度。我想使用这些不透明度值通过基于每个像素的不透明度的查找表来调整 RGB。

gray scale ellipse, squares, and text overlapping

例如,在this image中椭圆、正方形和文本均使用 alpha 0.1 绘制。重叠区域具有较高的 alpha 值。

如何将 alpha 0.1 的图像中的每个像素映射到 rgba(255,0,0,1) 以及将 alpha 0.2 的所有像素映射到 rgba(0,255,0,1) (并在抗锯齿边缘上的这两个 alpha 值之间插入替换颜色)?更多颜色将分配给所有其他 alpha 值(最多 1)。

很容易制作这样的查找表。

但是如何使用 svg 滤镜应用于图像?

最佳答案

您可以实现它,但这是一个多步骤的过程,您必须自己了解性能和可维护性。

我的示例代码将不透明度值划分为四个等距范围:0.2...0.4...0.6...0.8...1。范围 0...0.2 映射到透明度。

对于四个颜色范围中的每一个,您需要组合三个过滤器基元:

  • 接听SourceAlpha作为输入,并应用 <feComponentTransfer>到 alpha channel ,类型为 discrete这样只有一个范围映射到 opacity="1"
  • <feFlood> 填充过滤区域以指定的颜色
  • 将第一个和第二个结果与 <feComposite> 结合起来和operator="in" ,这样只有映射的值才被着色

然后,将所有不同的单色部分与<feMerge>合并在一起。 .

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="200">
  <linearGradient id="sourceGradient" x1="0" x2="1" y1="0" y2="0">
    <stop style="stop-color:#000000;stop-opacity:0" offset="0" />
    <stop style="stop-color:#000000;stop-opacity:1" offset="1" />
  </linearGradient>
  <filter id="filter">
    <feComponentTransfer in="SourceAlpha" result="step1">
      <feFuncA type="discrete" tableValues="0 1 0 0 0"/>
    </feComponentTransfer>
    <feFlood flood-color="rgb(255,0,0)" />
    <feComposite operator="in" in2="step1" result="color1" />
    <feComponentTransfer in="SourceAlpha" result="step2">
      <feFuncA type="discrete" tableValues="0 0 1 0 0"/>
    </feComponentTransfer>
    <feFlood flood-color="rgb(255,255,0)" />
    <feComposite operator="in" in2="step2" result="color2" />
    <feComponentTransfer in="SourceAlpha" result="step3">
      <feFuncA type="discrete" tableValues="0 0 0 1 0"/>
    </feComponentTransfer>
    <feFlood flood-color="rgb(0,255,0)" />
    <feComposite operator="in" in2="step3" result="color3" />
    <feComponentTransfer in="SourceAlpha" result="step4">
      <feFuncA type="discrete" tableValues="0 0 0 0 1"/>
    </feComponentTransfer>
    <feFlood flood-color="rgb(0,0,255)" />
    <feComposite operator="in" in2="step4" result="color4" />
    <feMerge>
      <feMergeNode in="color1" />
      <feMergeNode in="color2" />
      <feMergeNode in="color3" />
      <feMergeNode in="color4" />
    </feMerge>
  </filter>
  <rect fill="url(#sourceGradient)" x="50" y="25" width="300" height="50" id="rect" />
  <use xlink:href="#rect" y="100" filter="url(#filter)" />
</svg>

interpolate the replacement colors between those two alpha values on the anti-aliased edges

我不确定我是否理解这一点,但是type="table"对于连续规模的组件转移结果。合并后的结果在大多数地方的不透明度都低于 1,因此您需要一些最后步骤来再次提高不透明度。

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="200">
  <linearGradient id="sourceGradient" x1="0" x2="1" y1="0" y2="0">
    <stop style="stop-color:#000000;stop-opacity:0" offset="0" />
    <stop style="stop-color:#000000;stop-opacity:1" offset="1" />
  </linearGradient>
  <filter id="filter" x="0" y="0" width="1" height="1">
    <feComponentTransfer in="SourceAlpha" result="step1">
      <feFuncA type="table" tableValues="0 1 0 0 0"/>
    </feComponentTransfer>
    <feFlood flood-color="rgb(255,0,0)" />
    <feComposite operator="in" in2="step1" result="color1" />
    <feComponentTransfer in="SourceAlpha" result="step2">
      <feFuncA type="table" tableValues="0 0 1 0 0"/>
    </feComponentTransfer>
    <feFlood flood-color="rgb(255,255,0)" />
    <feComposite operator="in" in2="step2" result="color2" />
    <feComponentTransfer in="SourceAlpha" result="step3">
      <feFuncA type="table" tableValues="0 0 0 1 0"/>
    </feComponentTransfer>
    <feFlood flood-color="rgb(0,255,0)" />
    <feComposite operator="in" in2="step3" result="color3" />
    <feComponentTransfer in="SourceAlpha" result="step4">
      <feFuncA type="table" tableValues="0 0 0 0 1"/>
    </feComponentTransfer>
    <feFlood flood-color="rgb(0,0,255)" />
    <feComposite operator="in" in2="step4" result="color4" />
    <feMerge result="merged">
      <feMergeNode in="color1" />
      <feMergeNode in="color2" />
      <feMergeNode in="color3" />
      <feMergeNode in="color4" />
    </feMerge>
    <feComponentTransfer  in="SourceAlpha" result="capped">
      <feFuncA type="discrete" tableValues="0 1 1 1 1"/>
    </feComponentTransfer>
    <feComposite operator="atop" in="merged" in2="capped" />
  </filter>
  <rect fill="url(#sourceGradient)" x="50" y="25" width="300" height="50" id="rect" />
  <use xlink:href="#rect" y="100" filter="url(#filter)" />
</svg>

关于SVG 过滤器将 alpha 值映射到表中的 RGB 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53783625/

相关文章:

javascript - jQuery 单击不是在 SVG <g> 上触发,而是在子元素上触发

d3.js - SVG 过滤器中的 feTurbulence 可以旋转吗?

html - 用于模糊图像的 Svg

svg - PhantomJS 不尊重 SVG 颜色插值过滤器

javascript - 使用 JS 操作对象

javascript - 使用 Snap.svg 带有箭头标记的动画路径

javascript - 查找 svg 路径元素的中心

javascript - 使用 d3 js 引用不同的元素集

Safari 中的 SVG 高斯模糊意外地使图像变亮

css - 在 safari 和移动浏览器中的图像上使用 <feGaussianBlur/> 的奇怪人工制品