SVG Filter Primitives for Working with External Images and SVG Fragments

There will be times when the effect you want to add requires an additional image beyond the source graphic. Fortunately SVG provides a way to allow us to load external images inside a filter and make them part of the effect.

Last week I started to cover the details of SVG filter primitives as part of a larger series about filter effects. I began with an overview of SVG filters and then walked through the filter element before talking about filter primitives and some details about their input and output.

Today I want to continue with a couple more filter primitives that both involve working with external images directly inside SVG filters. The first feImage allows you to include external images and SVG fragments and the second, feTile, allows you to tile them.v

The feImage Filter Primitive

The feImage filter primitive allows you to refer to an external image or graphic and load it as the result of the primitive. You can refer to an external image or you can reference another SVG fragment.

If you reference an external image (.jpg, .png, or .svg file) the resource is rendered according to the behavior of the <image> element. Otherwise it’s rendered according to the behavior of the <use> element.

The primitive takes two attributes, xlink:href and preserveAspectRatio.

1
2
xlink:href = <iri> // reference to image source
preserveAspectRatio = [defer] <align> [<meetOrSlice>]

I’ve discussed both of these attributes in an earlier series. xlink:href points to the image and preserveAspectRatio determines whether the aspect ratio of the image should be preserved and if so how.

Since I’ve covered it before, I’ll point you to an earlier post on preserveAspectRatio for details. If you don’t specify a value the default is xMidYMid, which centers the image in the filter effects region and preserves its aspect ratio. You can, if you like, offset the image by setting values for x and y.

Here’s an example that hopefully illustrates how the feImage filter primitive works. I created two filters that both refer to the same external image of Strawberry Fields in Central Park. The only difference in the two filters is the first preserves the aspect ratio and the second doesn’t.

I also created two pairs of identically sized rectangles. In each pair one rectangle will reference a filter and the other is there to show a blue outline for where the rectangle is located.

Finally, notice that I set the filter effects region so that it’s the same size as the rectangles (or squares).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<svg width="100%" height="220" style="outline: 1px solid red">
 <defs>
   <filter id="default" x="0" y="0" width="100%" height="100%">
     <feImage xlink:href="http://www.vanseodesign.com/blog/wp-content/uploads/2013/09/strawberry-fields.jpg" result="strawberry-fields" />
   </filter>

   <filter id="preserved" x="0" y="0" width="100%" height="100%">
     <feImage xlink:href="http://www.vanseodesign.com/blog/wp-content/uploads/2013/09/strawberry-fields.jpg" result="strawberry-fields"  preserveAspectRatio="none" />
   </filter>
 </defs>

 <rect x="10" y="10" width="100" height="100" filter="url(#default)" />
 <rect x="10" y="10" width="100" height="100" fill="none" stroke="#00f" />

 <rect x="120" y="10" width="100" height="100" filter="url(#preserved)" />
 <rect x="120" y="10" width="100" height="100" fill="none" stroke="#00f" />
</svg>

On the left the aspect ratio of the image is preserved. The longer dimension, in this case the width, fills the space from edge to edge and the other dimension is set to preserve the aspect ratio of the image. Because the image in this example isn’t square you can see some empty space above and below.

On the right, the aspect ratio isn’t preserved and the image has been stretched vertically to fill the effects region.

In this example, the image looks fine when it’s stretched to fill the region, but that won’t always be the case. In fact this image is actually much larger than the region it fills and is being compressed a great deal to fit, which I think helps it look ok despite being stretched.

Hopefully you agree it’s rather easy to include the image in the filter and whether or not you want to preserve the aspect ratio will depend on the specifics of your filter and the effect you want to achieve.

The feTile Filter Primitive

The feTile filter primitive does what the name implies. It tiles an input image to fill the target rectangle (defined by the subregion of the feTile primitive) by repeating it in both the x and y directions.

There are no additional attributes beyond those common to most of the primitives so there’s not a lot to learn to work with feTile. The main thing to keep in mind is the coordinates and dimensions of the different regions and the image you want to tile. Hopefully the next two examples will help illustrate.

Here I modified the example from the last section. We’ll stick with one pair of rectangles (one that will get a filter and one to show the initial outline). I sized the Strawberry Fields image in the feImage primitive so it’s 32px by 32px. The size was an arbitrary choice. I just wanted something smaller than the rectangle.

I set preserveAspectRatio to none so that the image would stretch to match the square dimensions of the filter effects region, which, again, is 32px in each direction.

1
2
3
4
5
6
7
8
9
10
<svg width="100%" height="220" style="outline: 1px solid red">
 <defs>
   <filter id="tile" x="0" y="0" width="100%" height="100%">
     <feImage xlink:href="http://www.vanseodesign.com/blog/wp-content/uploads/2013/09/strawberry-fields.jpg" result="strawberry-fields" width="32" height="32" preserveAspectRatio="none" />
   </filter>
 </defs>

 <rect x="10" y="10" width="100" height="100" filter="url(#tile)" />
 <rect x="10" y="10" width="100" height="100" fill="none" stroke="#00f" />
</svg>

You can see the result is a smaller image inside the input element, which is shown by the blue outline.

Now let’s add the feTile primitive. In fact the only change between this and the previous example is the one line of code where I added <feTile in="strawberry-fields" result="tiled" /> You can see there’s not a lot to using this primitive.

1
2
3
4
5
6
7
8
9
10
11
<svg width="100%" height="220" style="outline: 1px solid red">
 <defs>
   <filter id="tile" x="0" y="0" width="100%" height="100%">
     <feImage xlink:href="http://www.vanseodesign.com/blog/wp-content/uploads/2013/09/strawberry-fields.jpg" result="strawberry-fields" width="32" height="32" preserveAspectRatio="none" />
     <feTile in="strawberry-fields" result="tiled" />
   </filter>
 </defs>

 <rect x="10" y="10" width="100" height="100" filter="url(#tile)" />
 <rect x="10" y="10" width="100" height="100" fill="none" stroke="#00f" />
</svg>

Here’s the result, which you can see repeats the image both horizontally and vertically to fill the space. It probably looks like it fits exactly three times in the x and y directions, though it’s actually starting a fourth repetition in each that gets cut after a few pixels.

You can create some interesting patterns, just by changing the size of the image. Here’s the same example with the image set to width=“10” and height=“10” and leaving everything else the same.

That’s a pretty big change for very little work and hopefully shows what you can do with feTile, just by varying the dimensions of whatever image or pattern you decide to tile.

Closing Thoughts

I hope you agree these two primitives are fairly easy to understand and work with. I also hope the last few examples show how filters become more interesting when you combine multiple filter primitives inside the same filter element.

Combining filters is going to be the subject of the next few posts in this series, which will look at several blend and merge filters, feMerge, feComposite, and feBlend. I’ll show you the first next week and the latter two in the weeks after.

Download a free sample from my book, Design Fundamentals.

Leave a Reply

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