Fun with SVG Filters

I’ve been playing around with SVG Filters lately, and let me tell you, I’ve been having a ton of fun.  The best part is, you don’t have to know a lot about SVG here.  The filters, defined in embedded SVG can be applied to your HTML content with CSS.  Once you figure out what filters are available, and how to configure them, it’s really straightforward.

At present, all the examples here will work in Firefox & Chrome.

This isn’t going to be an exhaustive list of everything you can do with SVG Effects, but hopefully this should whet your appetite.

This is what we’re talking about (Remember, Chrome & Firefox for now):

Check out this Pen!

Defining an SVG Filter

Here is a simple SVG file that defines a Gaussian Blur filter:

<svg width="0%" height="0%" xmlns="http://www.w3.org/2000/svg" version="1.1">
   <filter id="GaussianBlurFilter">
      <feGaussianBlur stdDeviation="10 1"/>
   </filter>
</svg>

 

There are several ways to import SVG into a Web page.  In our case, we want to be able to traverse the SVG DOM itself, so setting the SVG as the source of an IMG tag isn’t going to work.  Instead, we can take the code above and place it directly in the HTML of our page.

We can then apply  the GaussianBlurFilter to any element on the page with the following CSS:

<css-selector> {
   -webkit-filter: url(#GaussianBlurFilter);
   filter: url(#GaussianBlurFilter);
}

It’s as simple as that.

Gaussian Blur

As mentioned above, a Gaussian Blur is defined with the following:

<feGaussianBlur stdDeviation="10 1"/>

Screen Shot 2013-07-13 at 12.37.00 AM

The values provided for the stdDeviation define how much blur should be applied along the x and y axes.  If you only supply one value, it will be used for both x and y.

Convolution

Convolution is the process of manipulating an input image by combining pixels with their neighboring pixels in different ways.  Convolution can be used for edge detection, blurring, embossing and many other classic imaging techniques.

The SVG feConvolveMatrix filter can be used to apply a convolution to any HTML content.  The primary attributes for you to think about are the order and the kernelMatrix.

order – defines size of the kernelMatrix.  An order of “3 3” defines a 3×3 matrix.

kernelMatrix – Here are the basics of convolution.  If you want to learn more, there are many good resources on the Web explaining convolution and giving examples of useful convolution matrices.

If you have a 3×3 matrix like the following:

K1 K2 K3
K4 K5 K6
K7 K8 K9

 

For every pixel on the input image (in our case, the HTML to which the feConvoleMatrix filter is applied), the pixel’s value is multiplied by K5.  The surrounding pixels are multiplied by K1, K2, K3, K4, K6, K7, K8 and K9 respectively.  The multiplication values are then added up and the result is used instead of the original pixel value.

Don’t worry about it too much if you don’t get it.  The point is, you can find many different convolution matrices on the Web, and then just use their values to achieve the desired result.

Edge Detection

For example, if you want to perform edge detection, you can use the following 3×3 convolution matrix:

-1 -1 -1
-1  8 -1
-1 -1 -1

Screen Shot 2013-07-13 at 12.30.37 AM

Emboss

An emboss effect can be achieved with the following 3×3 convolution matrix:

-2 -1  0
-1  1  1
 0  1  2

Screen Shot 2013-07-13 at 12.38.07 AM

Take a look at the CodePen above and view the HTML tab to see how I’ve defined the different SVG convolution filters.

 Color Matrix

The feColorMatrix filter can be used to pre-multiply every pixel by a 5×5 input matrix.  You could make a grayscale filter by using the following matrix:

0.2126 0.7152 0.0722 0 0 
0.2126 0.7152 0.0722 0 0 
0.2126 0.7152 0.0722 0 0 
0      0      0      1 0

and using it in an feColorMatrix as follows:

<filter id="GrayScale">
   <feColorMatrix type="matrix" values="0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0" />
</filter>

What this will effectively do is multiply each RGBA pixel as follows:

R’ = G’ = B’ = R * 0.2126 + G * 0.7152 + B * 0.0722

A’ = A

If you’re wondering why all the crazy fractions, and why we don’t simply multiply each channel by ⅓, it has to do with the cones in your eyes and how they perceive changes in brightness.  A minor change in the greens will greatly alter the brightness of an image, whereas a change in the blues will have a much smaller effect.

Screen Shot 2013-07-15 at 11.51.08 PM The feColorMatrix filter has some shortcuts to create the matrix.  If you want, for instance, to use the input image as an alpha mask, where brighter parts of the image are more transparent than darker parts, you can change the type of the feColorMatrix as follows:

<filter id="LuminanceMask">
  <feColorMatrix type="luminanceToAlpha"/>
</filter>

You can then use CSS to apply the LuminanceMask to an HTML element as follows:

#myelem {
   -webkit-filter: url(#LuminanceMask);
   filter: url(#LuminanceMask);
}

Screen Shot 2013-07-13 at 12.39.08 AM

Gradient Maps

Finally, there is a slightly confusing filter called an feComponentTransfer.  Within the FeComponentTransfer filter you can define individual transfer functions for each of the R, G, B and A channels of an input image.

Each transfer function can remap the channel’s color.  For example, take the following transfer function, which remaps reds:

<filter>
   <feComponentTransfer>
      <feFuncR type="table" tableValues="0 1 0"/>
   </feComponentTransfer>
</filter>

If you think of the red channel of each pixel as having a value ranging from 0 to 1:

01

 

Then the above feFuncR would change that to the following:

A red of 0 would still be 0.  But now a red of 0.5 would be changed to 1, and a red of 1.0 would be changed to 0.  Confusing, but very powerful.

By first applying a grayscale color matrix and then a series of component transfers, we can remap the colors of an input image based on the brightness of that part of the image:

<filter id="GradientMapFilter">
  <!-- Convert to graysclae -->
  <feColorMatrix type="matrix" values="0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0"/> 

  <!-- The result of the feColorMatrix will be fed into the feComponentTransfer -->
  <feComponentTransfer >
    <feFuncR type="table" tableValues="0 1 0 1"/>
    <feFuncG type="table" tableValues="0 0 0.4 1"/>
    <feFuncB type="table" tableValues="0 0 .4 1"/>
  </feComponentTransfer>
</filter>

Screen Shot 2013-07-13 at 12.39.56 AM

X-Ray

An XRay effect is really a specialized gradient map where the component transfer filter inverts reds, greens and blues:

<filter id="XRayFilter">
  <feColorMatrix type="matrix" values="0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0" />
  <feComponentTransfer >
    <feFuncR type="table" tableValues="1 0"/>
    <feFuncG type="table" tableValues="1 0"/>
    <feFuncB type="table" tableValues="1 0"/>
  </feComponentTransfer> 
</filter>

Screen Shot 2013-07-15 at 11.59.09 PM

 

That’s it for now.  I hope you agree that SVG Filters are pretty powerful, and definitely fun to use.

Further Reading

If you want to learn more about SVG Filters, I suggest you take a look at the Filters Spec and good resources such as MDN and Web Platform Docs.

Tagged , , . Bookmark the permalink.

10 Responses to Fun with SVG Filters

  1. Šime Vidas says:

    The prefixed style declarations should come *before* the unprefixed ones. (That’s the general rule. I’m not sure if there exist exceptions to this rule.)

  2. Pingback: Collective #73 | Techno Alchemy

  3. James says:

    Nice article and cool effects. What browsers (mobile and desktop) would these effects be supported in?

  4. Oswald says:

    You might enjoy some of these eye-candy code samples with SVG filters:

    https://code.google.com/p/svg-filters-graphics/

    Oswald

  5. Pingback: Collective #73 | FREE Online Magazine

  6. webhost says:

    really nice tips, i never know this..thanks for sharing

  7. Sean says:

    You are AWESOME!!!

    Edge detect on body + grayscale(100%) and invert(100%) on html

    http://i.imgur.com/EBh3pXG.png

    This CHANGES EVERYTHING!!!!!!

Leave a Reply

Your email address will not be published. Required fields are marked *