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

时间:2018-12-14 16:34:13

标签: svg svg-filters

我看到了如何使用feComponentTransfertabletableValues来调整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过滤器应用于图像?

1 个答案:

答案 0 :(得分:2)

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

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

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

  • 拾取SourceAlpha作为输入,并将<feComponentTransfer>应用于类型为discrete的alpha通道,以使只有一个范围被映射到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>

  

在反锯齿边缘的两个alpha值之间插入替换颜色

我不确定我是否理解这一点,但是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>