Outils pour utilisateurs

Outils du site


issue112:inkscape

Ceci est une ancienne révision du document !


Table des matières

1

Last time, we looked at Flood Fill and Turbulence – a pair of primitives that can be used to fill the filter area with, respectively, a flat color or a pseudo-random cloud of colors. But there's a universe of other fills you might like to use, from stripes to polka dots, flowers to butterflies. To cater for such infinite possibilities, the SVG standard provides a way to pull another image into your filter chain, using the Image primitive. This allows you to not only use bitmap images, but can even reference other parts of your SVG file to let you pull your own creations into the filter chain. There's just one little problem: the Inkscape implementation is well and truly broken. Let's start with the bit that does work, at least to some degree: importing an external bitmap image into your filter chain. As usual, we'll begin with a bit of text as the object to which we'll apply the filter. You can, of course, use any type of object, but I find that text gives me a quick and easy way to see how a filter will look when applied to a complex shape, rather than using just a simple rectangle or circle.

Create a filter on the test object using one of the methods described in Part 48, and, if necessary, remove any existing filter primitives. Now add a single “Image” primitive to the filter chain, and take a look at its minimal controls at the bottom of the dialog. The “Source of Image” field will be used to hold the path and filename of an external image file, or the XML id of another element in your image. For now, you should choose an external bitmap image by clicking on the “Image File” button and picking one from your hard drive. We'll use our tried and tested Mona Lisa image, giving us the following output (unfiltered text on the left, filtered on the right) when the filter is created in Inkscape 0.48 (bottom left). Now you don't need to be an expert in renaissance art to notice that the image has been distorted somewhat. Now the same filter created in 0.91 (bottom right).

Well, we've lost the distorted aspect ratio, but it doesn't exactly fill the filter area – although we can do something about that, as we'll see shortly. This change in behaviour could potentially mean that drawings created in 0.48 may not appear the same in 0.91 if they make use of this filter primitive. In 0.48, you're stuck with the default position and size of the image – i.e. stretched to fill the bounding box of the object. The official Inkscape manual makes it sound as though you can at least set the position and size of the image within the filter by using the XML editor, but, despite many attempts, I haven't been able to achieve this. To be fair, the manual does state that the implementation in Inkscape “doesn't correctly position images” – though that seems to be something of an understatement based on my own tests.

2

With 0.91, things fare a little better – though you'll still have to make your way to the XML editor to change the parameters, as they're still not reflected in the GUI. Dig out Part 31 of this series if you need a refresher on how to use the XML editor. The XML element you'll need to modify is the <svg:feImage> which is inside an <svg:filter> in the <svg:defs> section of the file. You can add 'x', 'y', 'width', and 'height' attributes, although, in my tests, none of them took effect until I also added a 'preserveAspectRatio' attribute. In subsequent tests, once such an attribute was already present, I had to change it to a different value and back again for changes in the other attributes to be reflected in Inkscape's canvas. Changing it to an invalid value and back does the trick, so you can just add a single letter to the end of the existing value, click “Set”, remove the letter, then click “Set” again. So just what is a valid value for preserveAspectRatio? A good starting point is the word “none” - that will cause Inkscape to ignore the aspect ratio of the original image, and stretch it to fill the bounding box of the object, resulting in a similar appearance as with version 0.48. But there are other options – lots of them, all similarly and confusingly named! They all start with a lowercase 'x' and are followed immediately by 'Min', 'Mid' or 'Max' (which, for the x direction, basically means left aligned, centered or right aligned), then followed immediately by an uppercase 'Y' and another 'Min', 'Mid' or 'Max' (top, middle or bottom aligned), followed by a space and an optional keyword of 'meet' (scale the image so that it's all visible) or 'slice' (scale the image to fill the bounding box, whilst preserving the aspect ratio, but hide any parts that extend beyond the bounding box – i.e. just show a slice of the image). Confusing, isn't it? Perhaps some examples (below) would help.

No, I don't know why the SVG working group went for the confusingly similar 'Min' and 'Mid', nor why 'x' is lowercase whilst 'Y' is uppercase, nor why they chose the words 'meet' and 'slice' rather than 'scale' and 'crop'. I do know, however, that my examples are just the tip of the iceberg: there are 19 possible combinations, without considering the aforementioned 'x', 'y', 'width' and 'height', which can have a dramatic effect on what actually appears in your filter. Until Inkscape gains a UI to make some sense of this madness, I recommend leaving the advanced options of this filter to the experts. But if you do want your image to be distorted to fit the bounding box, per 0.48, you will have to take a deep breath, roll up your sleeves, and wade into the XML editor to deliver a swift dose of preserveAspectRatio=“none”. There's one last thing worth noting about the Image primitive, when used with external images. By default, Inkscape will put the entire path to your image into the filter UI. In order to keep your drawings more portable I strongly recommend keeping any required images in the same folder as your drawing, and then manually editing the entry in the filter settings to remove the path, leaving just the filename. You might consider embedding your image into your document, rather than keeping it in an external file, but read on

The Image primitive should have one more trick up its sleeve. but, yet again, it's broken. It's possible to select an object (or group) in your Inkscape image and then click the “Selected SVG Element” – at which point the Source of Image box will populate with the ID of the element. In this way, it should be possible to pull any other SVG element into your filter chain… except that it doesn't work. It does appear to function in 0.48, in that a rasterised version of the element is pulled in and stretched to fill the bounding box, but in 0.91 even that limited ability seems to have vanished. So there you have the Image primitive – a filter that promises so much, but delivers so little. The useful parts that work in 0.48 are broken in 0.91, whilst the useful parts from 0.91 require you to wade into the XML editor. Meanwhile, the pitiful UI sits back, laughing at your efforts to attempt something as audacious as setting the position of your image within the bounding box. Let's hope that UI gains a little flesh in a future release, and that the ability to use SVG elements makes a welcome return.

3

That concludes our look at the “fill” primitives in Inkscape. The SVG spec, though, has one other – “Tile” – which lets you feed in the output from another primitive to be repeated (“tiled”) over the whole of the filter region. In order for this to work, the incoming primitive needs to have a filter region that is smaller than the one it's going to be tiled into; but, as Inkscape uses a single filter region definition for the entire filter chain, even if this primitive were to be implemented, it would have no practical effect. It hardly seems fair to have wasted your reading time with a description of one poorly implemented filter, and another that hasn't been implemented at all, so I'll finish this instalment by adding another useful primitive to your toolbox: Morphology. Despite its fancy sounding name, this is a very simple filter: all it does is makes things thicker or thinner. And it does so with the minimum of fuss: there's just a drop-down to select between “erode” (make things thinner) and “dilate” (make things thicker), and a pair of optionally linked “radius” sliders to set the amount of erosion or dilation that will take place. Let's see this filter in action – in each case the first text object is unfiltered, and the second is filtered as described, with a radius of 2.5.

These filters are particularly useful when used with the Composite primitive, often in “In” or “Out” modes. In the following example, I've used a Flood filter to create a translucent white fill, then used a Composite “In” to trim it to the size of my eroded text. A little Gaussian Blur and Offset later, and you've got a filter that gives a 3D appearance to your text. “Out” can work well with dilation, to punch out the center of the dilated image. As a simple case, consider a Morphology primitive that dilates the source, then a Composite Out that leaves only those parts of the image that are outside the original source object. What you're left with is an outline of your object, with a transparent middle. Now, rather than punching out the source object, what if you punch out another dilated version, such that you're removing a small dilation from the core of a large dilation. Merge the original object back in, and you have an outline that surrounds the original, at a distance set by the smaller dilation with a thickness equal to the difference between the inner and outer dilations (you may need to increase the size of the filter region to avoid the result being cropped).

Finally, how about taking the previous idea and stacking it up a little further. You can have several outlines, all at different distances from the original object, then just merge everything together at the end. Things start to get a little complex as you add more outlines, because you're juggling a pair of Morphology primitives and a Composite for each layer of the onion, but, in principle, it's possible to carry on adding as many as you like, so long as you can keep track of them all. Or how about this version, where I've also used Color Matrix primitives in Hue Rotate mode in order to give each outline its own color: It's worth remembering that filters are bitmap operations that take place at the rendering stage. Although you can think of the Morphology primitive as thinning or thickening your image, it's not doing so in a vector sense, but rather by just adding or removing pixels in a bitmap version of your object. With that in mind, it also makes sense that you can apply this primitive to bitmap images imported via the Image primitive. This allows you to hide the fine details of an image by eroding them away, or blotting them out through dilation of adjacent areas, without introducing the sort of softness you would expect if you just blurred the images. In either case, Mona ends up looking somewhat worse for the experience!

Image Credits “La Gioconda” (aka “Mona Lisa”) by Leonardo da Vinci http://en.wikipedia.org/wiki/File:Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg

issue112/inkscape.1472505665.txt.gz · Dernière modification : 2016/08/29 23:21 de d52fr