2

I'm trying to apply a noise effect to an image, however, I struggle to maintain the transparency. Here's a fiddle to illustrate:

https://jsfiddle.net/t1aeyqfu/

#noisy {
  filter: url(#noise);
}

#filter {
  visibility: hidden;
}
<body style="background-color: #aca">
  <img src="https://i.postimg.cc/pr61qLqk/flower.png" id="noisy">
  <svg id="filter">
    <filter id="noise">
      <feTurbulence baseFrequency="0.60" xresult="colorNoise" />
      <feColorMatrix in="colorNoise" type="matrix" values=".33 .33 .33 0 0 .33 .33 .33 0 0 .33 .33 .33 0 0 0 0 0 1 0" result="monoNoise" />
      <feBlend in="SourceGraphic" in2="monoNoise" mode="multiply" />
    </filter>
  </svg>

</body>

My goal is to apply the noise effect only to the parts of the image which are not transparent. (In the above example: No noise outside of the blue flower.)

I got somewhat close using feComposite with out operator, but then the noise inherits the transparency. Applying the SourceAlpha to the result might help, but I can't figure out how.

Thanks for your hints!

2 Answers 2

1

Just clip the noise to the original shape by adding a feComposite/in. The rest stays the same.

#noisy {
  filter: url(#noise);
}

#filter {
  visibility: hidden;
}
<body style="background-color: #aca">
  <img src="https://i.postimg.cc/pr61qLqk/flower.png" id="noisy">
  <svg id="filter">
    <filter id="noise">
      <feTurbulence baseFrequency="0.60" xresult="colorNoise" />
      <feColorMatrix in="colorNoise" type="matrix" values=".33 .33 .33 0 0 .33 .33 .33 0 0 .33 .33 .33 0 0 0 0 0 1 0"/>
      <feComposite operator="in" in2="SourceGraphic" result="monoNoise"/>
      <feBlend in="SourceGraphic" in2="monoNoise" mode="multiply" />
    </filter>
  </svg>

</body>

1
  • 1
    I had tried this as well, but a runaway / broke it. Thanks for the answer, @Michael !
    – svoop
    Commented Nov 22, 2020 at 2:10
0

The filter you are looking for is quite simply a feComposite with operator="out".

#noisy {
  filter: url(#noise);
}

#filter {
  visibility: hidden;
}
<body style="background-color: #aca">
  <img src="https://i.postimg.cc/pr61qLqk/flower.png" id="noisy">
  <svg id="filter">
    <filter id="noise">
      <feTurbulence baseFrequency="0.20" xresult="colorNoise" />
      <feColorMatrix in="colorNoise" type="matrix" values=".33 .33 .33 0 0 .33 .33 .33 0 0 .33 .33 .33 0 0 0 0 0 1 0" result="monoNoise" />
      <feComposite operator="out" in="SourceGraphic" in2="monoNoise"/>
    </filter>
  </svg>

</body>

1
  • I had tried that, but the noise becomes transparent which is not what I intend here.
    – svoop
    Commented Nov 22, 2020 at 2:09

Not the answer you're looking for? Browse other questions tagged or ask your own question.