For the last few weeks I’ve been talking about two types of SVG filter primitives. First were those that help us add color effects, like feColorMatrix and feComponentTransfer followed by those that help us add lighting effects, like feDiffuseLighting and feSpecularLighting.
This series on filter primitives is a continuation of a series I began last year that walked through the basics of SVG filters before discussing some simple filter primitives, some for working with external images, and some, such as feMerge, feComposite, and feBlend that combine the results of other filters.
There are a few remaining primitives that didn’t quite fit into easily defined categories and I’ve left them till the end. I want to spend the next few weeks talking about the feMorphology, feTurbulence, feDisplacementMap, and feConvolveMatrix filter primitives. I’ll talk about the first two today and then devote a post to each of the latter two over the next couple of weeks.
The feMorphology Filter Primitive
The feMorphology filter primitive thickens or thins graphic elements, particularly the alpha channel of those elements. It accepts two attributes, operator and radius. The first tells the primitive whether to thicken or thin the graphic and the seconds tell it by how much.
- operator = "erode | dilate”—The value erode makes the graphic thinner and the value dilate makes it thicker. The default is erode.
- radius = “<number-optional-number>”—The value determines how much the graphic is eroded or dilated. If 2 numbers are provided, the first is the x-radius and second is the y-radius. If a single number is provided it’s the radius in both the x and y direction. The default is 0.
One way you can use feMorphology is to thicken or thin text as in the following example. Here I set up three SVG text elements. The first uses no filter. The second and third make use of the feMorphology primitive. I used Palatino as the font in all three and the font-size is set to 2em for all three words.
[code type=html]
<svg width="100%" height="220" style="outline: 1px solid red">
<defs>
<filter id="erode">
<feMorphology operator="erode" radius="0.75" />
</filter>
<filter id="dilate">
<feMorphology operator="dilate" radius="1" />
</filter>
</defs>
<g font-size="2em">
<text x="250" y="40">Unfiltered</text>
<text x="250" y="110" filter="url(#erode)">Erode</text>
<text x="250" y="200" filter="url(#dilate)">Dilate</text>
</g>
</svg>
[/code]
Here’s the result.
A few things I should point out. First is that when using erode you have to watch not to erode too much. Initially I set the erode filter to use a radius of 1.0. Here’s what that looked like.
As you can see there’s not much left of the word. If you want to use erode, you probably want to keep the radius on the smaller side.
Next it might look like Dilate is similar to bolding the word, but they aren’t the same. Below is the word Dilate twice. On top the word is bolded and on the bottom a filter has been applied that dilates the word with a radius of 1.0. You can see the two words display differently.
The feTurbulence Filter Primitive
The feTurbulence primitive uses the Perlin turbulence function to add noise to an image. You can use it to create artificial textures that mimic clouds or marble. It accepts five attributes, type, baseFrequencey, numOctaves, seed, and stitchTiles.
- type = "fractalNoise | turbulence”—Determines whether the filter performs a noise or turbulence function. The fractalNoise type leads to a smoother result and turbulence is the default.
- baseFrequency = “<number-optional-number>”—The first number is x and second is y with a single number representing both. Numbers should be between 0.0 and 1.0. A negative value is an error. The larger the number the more fine-grained the result. 0 is the default.
- numOctaves = “<integer>”—Provides the number of noise functions that are added together when calculating. The larger the number, the more detailed the resulting texture. The default is 1.
- seed = “<number>”—The functions use a pseudo random generator and the seed is the starting number for this generator. The default is 0, but you’ll want to change it at times for greater variety in the result.
- stitchTiles = “stitch | noStitch”—This attribute determines if there’s any attempt to achieve smooth transitions for tiling the resulting image. When a value of stitch is used, the user-agent will adjust the baseFrequency values. The default is noStitch.
I created four rectangles for this example and applied turbulence to the first two and noise to the latter two. I used the same filter for each pair so you can see that the result is produced randomly.
Because I wanted you to see the difference when the same numbers are used, I didn’t include a seed value and as the example doesn’t tile the results I left the stitchTiles attribute out as well.
[code type=html]
<svg width="100%" height="220" style="outline: 1px solid red">
<defs>
<filter id="turbulence">
<feTurbulence type="turbulence" baseFrequency="0.125" numOctaves="2" />
</filter>
<filter id="noise">
<feTurbulence type="fractalNoise" baseFrequency="0.125" numOctaves="2" />
</filter>
</defs>
<rect x="40" y="50" width="100" height="100" filter="url(#turbulence)" />
<rect x="200" y="50" width="100" height="100" filter="url(#turbulence)" />
<rect x="360" y="50" width="100" height="100" filter="url(#noise)" />
<rect x="520" y="50" width="100" height="100" filter="url(#noise)" />
</svg>
[/code]
Here are the results. Again the first two squares call the same turbulence filter primitive and the last two call the fractalNoice filter primitive.
This filter can create some interesting effects. The downside is the effects are random. You have some control, but not absolute control over the final result.
Feel free to copy my examples and play around or if you prefer Matthew Bystedt set up demo where you can use a slider to adjust the baseFrequency and numOctaves values to see how each affects the final graphic.
Closing Thoughts
After some of the primitives we’ve looked at the last few weeks, feMorphology and feTurbulence should be easy to work with. The first works well with line art or text as I showed in the example, while the latter is a bit random, but also a way to add interesting backgrounds.
Next week I’ll talk about the the feDisplacementMap filter primitive, which can be used to create warping effects. The week after I’ll talk about the feConvolveMatrix filter primitive, which can be used to add effects like embossing and beveling. Both use pixel values in an image to alter the pixels in that image.
Download a free sample from my book, Design Fundamentals.