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>
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>
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>
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
Considerations
SVG filters are a useful tool for many cases. However, there are some specifics to consider:
- 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.
- 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
- How to use media file with Canvas? – FIVEKO
- The Upcoming CanvasFilter API
- Filter Effects Specification – W3C
- SVG filter element – MDN
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.
WEB APPLET
See how it works in the browser!