Home » Blog » Tutorials » SVG Filters for Image Processing

SVG Filters for Image Processing

SVG filters are a useful tool in web development and can even be applied to image processing tasks. They are flexible and the web environment allows their use in many different situations.

Overview

We usually use SVG filters to apply various effects to images. However, my passion for computer graphics algorithms and web development inspired me to write this tutorial.

The abbreviation SVG stands for Scalable Vector Graphics. These are two-dimensional vector images that we describe using an XML-based markup language. As such, they find many uses on our websites and online image applications.

Because SVG files are in plain text, they allow search engines to index and search them better than simple bitmaps. They also allow easy and quick compression and scripting on them.

What are SVG filters?

The <filter> element is an essential part of SVG images. It describes custom filter effects by grouping different XML nodes. Speaking of web development, we should mention that we can attach this element to the CSS filter attribute as well as use it as part of the Canvas Filter API.

Use SVG Filters for Image Processing

This section provides an overview of how to use SVG filters for some of the most popular image processing algorithms. We now have a significant amount of articles covering computer graphics with WebGL/OpenGL and C/C++. However, the SVG element is a handy tool in combination with JavaScript. It gives interesting possibilities to implement some of the graphics algorithms.

It is impossible to cover all the possibilities of SVG elements in a single article. However, in the following points we will try to look at popular graphic filters.

Picture smoothing by SVG Filtering

Smoothing filters are applicable in many cases. They are often used as a nice image effect, for noise reduction, image masking and much more.

Average blur aka Box filter

One of the previous articles covers in details the Average blur filter. Here we will try to implement it using image convolution. For this purpose we will use feConvolveMatrix SVG node.

<svg width="640" height="480" viewBox="0 0 640 480">
  <defs>
    <filter id="filterAverageBlur">
         <feConvolveMatrix
           kernelMatrix="1 1 1 1 1 1 1 1 1"
           order="3 3"
           bias="0"
           divisor="9"
           preserveAlpha="true" />
   </filter>
  </defs>
  <image x="5" y="5" width="300" height="420" preserveAspectRatio="true" 
      xlink:href="https://upload.wikimedia.org/wikipedia/zh/3/34/Lenna.jpg"/>
  <image x="310" y="5" width="300" height="420" preserveAspectRatio="true" 
      filter="url(#filterAverageBlur)" 
      xlink:href="https://upload.wikimedia.org/wikipedia/zh/3/34/Lenna.jpg"/>
</svg>​

Gaussian blur

Best of all, the SVG format specification even provides the feGaussianBlur node.It implements the popular Gaussian filter and is easy to use.

<svg width="640" height="480" viewBox="0 0 640 480">
  <defs>
    <filter id="filterBlur">
      <feGaussianBlur stdDeviation="5"/>
    </filter>
  </defs>
  <image x="5" y="5" width="300" height="420" preserveAspectRatio="true"
      xlink:href="https://upload.wikimedia.org/wikipedia/zh/3/34/Lenna.jpg"/>
  <image x="310" y="5" width="300" height="420" preserveAspectRatio="true" 
      filter="url(#filterBlur)"
      xlink:href="https://upload.wikimedia.org/wikipedia/zh/3/34/Lenna.jpg"/>
</svg>​
Gaussian smooth by SVG filtering
Gaussian smooth by SVG filtering (stdDeviation 5)

Edge detection by SVG Filtering

Edge detection algorithms are an essential part of many image analysis tasks. We already cover some popular edge detectors like Sobel and Prewitt. We will now show how to find image contours using the Laplacian operator without going deep into the theoretical details. For this purpose we will again use the feConvolveMatrix node.

<svg width="640" height="480" viewBox="0 0 640 480">
  <defs>
    <filter id="filterEdges">
      <feConvolveMatrix
         kernelMatrix="0 1 0 1 -4 1 0 1 0"
         order="3 3"
         bias="0"
         divisor="1"
         preserveAlpha="true" />
    </filter>
  </defs>
  <image x="5" y="5" width="300" height="420" preserveAspectRatio="true" 
      xlink:href="https://upload.wikimedia.org/wikipedia/zh/3/34/Lenna.jpg"/>
  <image x="310" y="5" width="300" height="420" preserveAspectRatio="true" 
      filter="url(#filterEdges)" 
      xlink:href="https://upload.wikimedia.org/wikipedia/zh/3/34/Lenna.jpg"/>
</svg>​
Laplacian edge detector by SVG filters
Laplacian edge detector by SVG filtering

Color space conversion by SVG Filtering

One of the previous articles describes how to use the feColorMatrix SVG element to convert RGB to grayscale. We can use this element for various color effects and transformations such as: YCbCr, YUV, etc. In this tutorial, we’ll show how to use feColorMatrix to implement an RGB to YCbCr color space conversion.

<svg width="640" height="480" viewBox="0 0 640 480">
  <defs>
   <filter id="filterRGB2YCbCr">
      <feColorMatrix 
        in="SourceGraphic"
        type="matrix"
        values="0.257   0.504  0.098 0 0.0625
               -0.148  -0.291  0.439 0 0.5
                0.439  -0.368 -0.071 0 0.5
                0       0      0     1 0" />
    </filter>
  </defs>
  <image x="5" y="5" width="300" height="420" preserveAspectRatio="true" 
      xlink:href="https://upload.wikimedia.org/wikipedia/zh/3/34/Lenna.jpg"/>
  <image x="310" y="5" width="300" height="420" preserveAspectRatio="true" 
      filter="url(#filterRGB2YCbCr)" 
      xlink:href="https://upload.wikimedia.org/wikipedia/zh/3/34/Lenna.jpg"/>
</svg>​

Color effects

The popular Hue Rotate color effect is easy to create with SVG (as well as CSS). This is an elegant way to change the colors of an image with a few lines of code.

<svg width="640" height="480" viewBox="0 0 640 480">
  <defs>
    <filter  id="filterHueRotate">
      <feColorMatrix type="hueRotate" values="64"/>
    </filter>
  </defs>
  <image x="5" y="5" width="300" height="420" preserveAspectRatio="true" 
      xlink:href="https://upload.wikimedia.org/wikipedia/zh/3/34/Lenna.jpg"/>
  <image x="310" y="5" width="300" height="420" preserveAspectRatio="true" 
      filter="url(#filterHueRotate)" 
      xlink:href="https://upload.wikimedia.org/wikipedia/zh/3/34/Lenna.jpg"/>
</svg>​
Hue rotate with SVG Filters
Example result of image color change by Hue Rotate

How to use SVG filter with JavaScript

It is possible to use JavaScript in combination with SVG filters. This is a convenient way to apply photo effects in our web applications.
Let’s say we have a picture we want to filter. First we read the image file into a <canvas> element. We then use the filter property of CanvasRenderingContext2D to attach the SVG node.

function drawFrame(source){
  const canvas = document.querySelector("canvas");
  const context = canvas.getContext("2d");
  context.filter = "url(#filterHueRotate)";
  context.drawImage(source, 0, 0);
}

This makes the combination of Canvas with SVG quite powerful. However, the fact that we cannot work with SVG in the Workers leads to an annoying limitation. Fortunately, a new Canvas 2D filtering extension is coming that seems to be able to solve this.

How to chain SVG filters?

Let’s say we want to make a more complex edge detector. To do this, we will combine several SVG filters into one. This is achieved through the in and result node attributes.


<svg width="640" height="480" viewBox="0 0 640 480">
  <defs>
    <filter id="filterEdgesBeta">
      <feGaussianBlur stdDeviation="1.2" result="blur" />
	  <feColorMatrix in="blur"
        type="matrix"
        values="0.33 0.33 0.33 0 0
                0.33 0.33 0.33 0 0
                0.33 0.33 0.33 0 0
                0 0 0 1 0" result="gray"/>
      <feConvolveMatrix in="gray"
         kernelMatrix="0 1 0 1 -4 1 0 1 0"
         order="3 3"
         bias="0"
         divisor="1"
         preserveAlpha="true" />
    </filter>
  </defs>
  <image x="5" y="5" width="300" height="420" preserveAspectRatio="true" 
      xlink:href="https://upload.wikimedia.org/wikipedia/zh/3/34/Lenna.jpg"/>
  <image x="310" y="5" width="300" height="420" preserveAspectRatio="true" 
      filter="url(#filterHueRotate)" 
      xlink:href="https://upload.wikimedia.org/wikipedia/zh/3/34/Lenna.jpg"/>
</svg>​

The filtering algorithm filterEdgesBeta combines the following operations:

  • Image noise reduction by feGaussianBlur with standart devation of 1.2
  • Convert to monochrome by feColorMatrix element
  • Extract image contours by feConvolveMatrix element
SVG Filter Chain - Edge Detector
Example result of edge detection with Gaussian smooth

Considerations

SVG filters are a useful tool for many cases. However, there are some specifics to consider:

  1. Based on the SVG spec, the result of each filter primitive will be clamped within the allowable ranges for colors and opacity values. This can cause problems for some algorithms.
  2. Generally the SVG filters execute on CPU. This is web browser specific, but you might be better off doing sophisticated filtering via WebGL/GLSL.

Useful Resources

Conclusion

The article gives an introduction to SVG filtering and how we can use it in image processing. The guide provides sample snippets of scalable vector graphics with various popular filters.


You can support me at ko-fi.com