Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SVG blur filter edge artifacts

When I apply blur filter to svg image it blurs edges so they become little transparent (see left sample). What I want is to blur it without such artifact (see right sample). I solved this by hack: just copying same flipped image and placed them for 4 sides.

Is there any better way?

Note that I can't just make image bigger on 5-10%; size should be the same as original image.

Here is my svg:

...
<filter id="blur">
 <feGaussianBlur in="SourceGraphic" stdDeviation="4"></feGaussianBlur>
</filter>
...
<g filter="url(#blur)">
  <image xlink:href="cathedral.jpg"></image>
</g>

enter image description here

like image 831
Plastic Rabbit Avatar asked Jun 25 '14 19:06

Plastic Rabbit


1 Answers

This is a good hack for having a crisp border that uses feComponentTransfer to increase the opacity of the edges to 1.0, but it also requires you to clip the filter to the size of the filtered element (using the filter sizing attributes in the filter element) - if you don't do this, you'll see an overflow of newly opaque blur & black background spilling outside the original image.

<filter id="blur" x="0%"
 y="0%" width="100%" height="100%">
 <feGaussianBlur in="SourceGraphic" stdDeviation="4"/>
  <feComponentTransfer>
      <feFuncA type="discrete" tableValues="1 1"/>
   </feComponentTransfer>
</filter>
...
<g filter="url(#blur)">
  <image xlink:href="cathedral.jpg"></image>
</g>

If you don't have a square input (let's say your photo is circular), then you need to use a feComposite "in" to clip the output to the area of the input rather than using filter dimensions. But feComposites are a little slow right now and can't yet be used as part of a CSS filter, so the above method is preferable for square inputs.

Note that this won't work on images with variable opacity/alpha channel - it will convert everything to 100% opacity.

Another variant is to use an feColorMatrix to do the same thing, some browsers seem to have GPU accelerated this operation, so it might be faster than feComponentTransfer

<filter id="blur" x="0%"
 y="0%" width="100%" height="100%">
 <feGaussianBlur in="SourceGraphic" stdDeviation="4"/>
 <feColorMatrix type="matrix"  values="1 0 0 0 0
                                       0 1 0 0 0 
                                       0 0 1 0 0 
                                       0 0 0 0 1"/>
</filter>
...
<g filter="url(#blur)">
  <image xlink:href="cathedral.jpg"></image>
</g>
like image 118
Michael Mullany Avatar answered Nov 20 '22 22:11

Michael Mullany