Search code examples
csssvgfiltersvg-filters

SVG filter apply filter only to opaque region


Lets have a filter applied to an image with transparency. I need to have this filter applied only to opaque region, in other words, I guess, where alpha is non-zero. You can see in the example currently transparent region is filled with flood color. Would that be possible?

svg {
  width: 0;
  height: 0;
}
.myFilter {
  filter: url(#myFilter);
}
<svg>
  <defs>
    <filter id="myFilter" x="0" y="0" width="100%" height="100%"
            color-interpolation-filters="sRGB">
      <feFlood flood-color="#3a0339" result="flood"/>
      <feBlend mode="exclusion" in="flood" in2="SourceGraphic"/>
    </filter>
  </defs>
</svg>

<img class="myFilter" src="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png">


Solution

  • You can use an feComposite node to apply the alpha channel of the source graphic to the output of the flood filter:

    svg {
      width: 0;
      height: 0;
    }
    .myFilter {
      filter: url(#myFilter);
    }
    <svg>
      <defs>
        <filter id="myFilter" x="0" y="0" width="100%" height="100%"
                color-interpolation-filters="sRGB">
          <feFlood flood-color="#3a0339" result="flood"/>
          <feComposite in="flood" in2="SourceAlpha" operator="in" result="flood_alpha"/>
          <feBlend mode="exclusion" in="flood_alpha" in2="SourceGraphic"/>
        </filter>
      </defs>
    </svg>
    
    <img class="myFilter" src="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png">