Ceci est une ancienne révision du document !
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.
La fois dernière, nous avons regardé Remplissage et Turbulence, deux primitives qui peuvent être utilisées pour remplir les zones de filtrage avec, respectivement, une couleur unie ou un nuage de couleurs pseudo-aléatoires. Mais il y a une foule d'autres remplissages que vous pourriez aimer utiliser, des bandes jusqu'aux pois, des fleurs aux papillons. Pour répondre à ces possibilités infinies, la norme SVG fournit une manière d'insérer une autre image dans votre chaîne de filtrage, en utilisant la primitive Image. Ceci vous permet, non seulement d'utiliser des images bitmap, mais peut aussi faire référence à d'autre parties de votre fichier SVG pour vous permettre d'insérer vos propres créations dans la chaîne de filtrage. Il n'y a qu'un petit problème : l'implémentation dans Inkscape est belle et bien inutilisable.
Commençons avec le peu qui marche, au moins jusqu'à un certain point : l'importation d'une image bitmap externe dans votre chaîne de filtres. Comme d'habitude, nous commencerons avec un peu de texte comme objet auquel appliquer le filtre. Vous pouvez, bien sûr, utiliser n'importe quel type d'objet, mais je trouve que le texte me donne une façon rapide et facile à quoi ressemble le filtre quand il est appliqué à une forme complexe, plutôt que d'utiliser un simple rectangle ou cercle.
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).
Créez un filtre sur l'objet test en utilisant une des méthodes décrites dans la partie 48 et, si nécessaire, enlevez toutes les primitives existantes. Maintenant, ajoutez une seul primitive Image à la chaîne de filtrage, et vérifiez que les contrôles sont au minimum en bas du dialogue. Le champ « Source de l'image » sera utilisé pour déterminer le chemin et le nom de fichier du fichier image externe, ou l'identifiant XML d'un autre élément de votre image. Pour l'instant, vous choisissez une image bitmap externe en cliquant sur le bouton « Fichier image » et en sélectionnant un dans votre disque dur. Nous utiliserons notre image de Mona Lisa déjà essayée et adoptée, nous donnant la sortie suivante (texte non filtré à gauche, filtré à droite) quand le filtre est créé dans Inkscape 0.48 (en bas à gauche).
Maintenant, vous n'avez pas besoin d'être un expert en art de la Renaissance pour noter que l'image est quelque peu déformée. Maintenant, le même filtre créé dans la 0.91 (en bas à droite).
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.
Et bien, nous avons perdu la déformation, mais la zone de filtre n'est pas vraiment remplie - bien que nous puissions le résoudre, nous verrons cela sous peu. Ce changement de comportement pourrait potentiellement signifier que les dessins créés dans la 0.48 pourraient ne pas apparaître comme tels dans la 0.91 si vous utilisiez cette primitive de filtrage.
Dans la 0.48, la position par défaut et la taille de l'image nous sont imposées - c'est-à-dire étirée pour remplir la boîte englobante de l'objet. Le manuel officiel d'Inkscape laisse entendre que vous pouvez au moins régler la position et la taille de l'image dans le filtre en utilisant l'éditeur XML, mais, malgré tous mes essais, je n'ai pas réussi. Pour être honnête, le manuel dit que l'implémentation d'Inkscape « ne positionne pas correctement les images » - ce qui, d'après mes tests, est un euphémisme.
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.
Avec la 0.91, c'est un peu mieux - bien qu'il faille toujours passer par l'éditeur pour modifier les paramètres, car il n'ont pas de réplique dans l'interface utilisateur. Replongez-vous dans la partie 31 de cette série si vous voulez rafraîchir votre mémoire pour éditer du XML. L'élément XML que vous devez modifier est <svg:feImage> qui est dans un <svg:filter> de la section <svg:defs> du fichier. Vous pouvez ajouter les attributs « x », « y », « width » (largeur) et « height » (hauteur), bien que, dans mes tests, aucun d'eux n'ait eu d'effet jusqu'à ce que j'ajoute aussi l'attribut « preserveAspectRatio » (préserver le rapport hauteur/largeur). Dans les tests suivants, un fois qu'un tel attribut a été présent, j'ai dû changer sa valeur et retourner modifier les autres paramètres pour que ça soit pris en compte sur le canevas d'Inkscape. Si vous changez pour une valeur invalide et que ça ne marche pas, vous pouvez juste mettre une lettre à la fin de la valeur existante, cliquer sur « Définir », enlever la lettre et re-cliquer sur « Définir ».
Mais qu'est-ce qu'une bonne valeur pour preserveAspectRatio? Un bon point de départ est le mot « none » (aucun) - qui fera qu'Inkscape ignorera le rapport d'aspect de l'image originale et l'étirera pour remplir la boîte englobante de l'objet, le résultat ressemblant à celui de la version 0.48. Mais il y a d'autres options - beaucoup, toutes avec des noms similaires et déconcertants ! Ils commencent tous par la lettre minuscule « x », immédiatement suivie de « Min », « Mid » ou « Max » (ce qui pour la direction x signifie aligné à gauche, centré ou aligné à droite), suivis par un «Y » majuscule en un autre « Min », « Mid » ou « Max » (aligné en haut, au milieu ou en bas), suivi d'un espace et du mot-clé optionnel « meet » (recadrer l'image pour qu'elle soit entièrement visible) ou « slice » (mettre l'image à l'échelle pour remplir la boîte englobante, tout en préservant le ratio d'aspect, mais en cachant tout ce dépasse de la boîte englobante - c'est-à-dire, afficher qu'une tranche de l'image). Confus, n'est-ce pas ? Quelques exemples (ci-dessous) vont peut-être aider.
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
Non, je ne sais pas pourquoi le groupe de travail SVG en est arrivé à une similarité déroutante de « Min » et « Mid », pas plus que pourquoi « x » est en minuscule alors que « Y » est en majuscule, ni pourquoi il a choisi les mots « meet » et « slide » plutôt que « scale » (échelle) et « crop » (recadrage). Je sais bien, cependant, que mes exemples ne sont que la partie visible de l'iceberg : il y a 19 combinaisons possibles, sans considérer les « x », «Y », « width » et « height » déjà cités, qui peuvent avoir un effet important sur ce qui apparaît dans votre filtre.
Jusqu'à ce qu'Inkscape dispose d'une interface utilisateur qui rende plus compréhensible toute cette folie, je recommande de laisser les options avancées de ce filtre à des experts. Mais si vous voulez déformer votre image pour qu'elle remplisse la boîte englobante, dans la 0.48, vous devrez prendre une grande respiration, remonter vos manches, et intervenir dans l'éditeur XML pour y mettre une rapide dose de preserveAspectRatio=“none”.
Il y a une dernière chose intéressante à noter à propos de la primitive Image, quand vous utilisez des images externes. Par défaut, Inkscape, mettra le chemin complet vers votre image dans l'interface utilisateur. Pour rendre vos dessins plus portables, je vous recommande fortement de conserver les images nécessaires dans le même dossier que votre dessin, et, ensuite, de modifier manuellement la saisie des réglages du filtre pour enlever le chemin, en ne laissant que le nom du fichier. Vous pourriez préférer incorporer votre image dans votre document, plutôt que la garder comme fichier externe, mais lisez la suite.
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.
La primitive Image devrait avoir encore une astuce dans son jeu, mais, une fois encore, c'est hors d'usage. Il est possible de sélectionner un objet (ou un groupe) dans votre image Inkscape et ensuite de cliquer sur « Élément SVG sélectionné » - ce qui remplit la boîte Image Source avec l'identifiant de l'élément. De cette façon, il serait possible d'incorporer n'importe quel autre élément SVG dans votre chaine de filtrage… sauf que ça ne fonctionne pas. Il apparaît que ça marche dans la 0.48, dans laquelle une version pixelisée de votre élément est incorporée et étirée pour remplir la boîte englobante, mais, dans la 0.91, même cette possibilité réduite a disparu.
Vous avez donc la primitive Image - un filtre qui promet beaucoup, mais en donne si peu. La partie utile qui fonctionne dans la 0.48 est hors d'usage dans la 0.91, alors que les parties utilisables de la 0.91 vous obligent à plonger dans l'éditeur XML. Dans le même temps, le triste interface utilisateur baisse les bras, se gaussant de vos efforts pour réaliser quelque chose d'aussi audacieux que régler la position de votre image dans la boîte englobante. Espérons que l'interface utilisateur reprendra quelque vigueur dans une future publication, et que la possibilité d'utiliser les éléments SVG fera un retour bienvenu.
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.
Ceci conclut notre tour des primitives de remplissage d'Inkscape. La spécif. SVG, cependant, en a une autre - Tile (Tuile) - qui vous permet d'alimenter la sortie à partir d'une autre primitive répétée (tuilée) sur la totalité de la région du filtre. Pour qu'elle marche, la primitive d'entrée doit avoir une région de filtre plus petite que celle qui sera tuilée ; mais, comme Inkscape utilise une région de filtre unique pour la totalité de la chaîne de filtrage, même si cette primitive devait être implémentée, elle n'aurait aucun effet visible.
Ça ne parait pas très sympa de vous avoir fait perdre votre temps à lire une présentation d'un filtre aussi pauvrement implémenté, et d'un autre pas du tout implémenté ; aussi, je finirait cet article par une autre primitive utile de la boîte à outils : Morphologie.
En dépit de son joli nom, c'est un filtre très simple : tout ce qu'il fait est de rendre les choses plus épaisses ou plus fines. Et il le fait avec le minimum de chichis : il n'y a qu'une liste déroulante, pour sélectionner « Contracter » (rendre les choses plus fines) ou « Dilater » (les rendre plus épaisses) et une paire des réglettes « Rayon », liées en option, pour ajuster la quantité de finesse ou d'épaisseur appliquée. Regardons ce filtre en action - dans chaque cas, le premier objet texte est non filtré, et le second est filtré comme indiqué, avec un rayon de 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).
Ces filtres sont particulièrement utiles quand ils sont utilisés avec la primitive Composite, souvent en modes « In » ou « Out ». Dans l'exemple suivant, j'ai utilisé un filtre Remplissage pour créer un remplissage blanc translucide, puis j'ai utilisé une Composite « In » pour l'ajuster à la taille de mon texte contracté. Après un peu de Flou gaussien et d'Offset, vous obtenez un filtre qui donne une apparence 3D à votre texte.
« Out » peut bien fonctionner avec la dilatation, pour creuser le centre de l'image dilatée. Comme exemple simple, considérez une primitive Morphologie que dilate la source, puis une Composite « Out » qui ne garde que les parties de cette image qui dépassent de l'objet source d'origine. Il ne reste que le contour de votre objet, avec un milieu transparent.
Maintenant, plutôt que d'enfoncer l'objet source, que ce passe-t-il si vous enfoncer une autre version dilatée, de sorte que vous enlevez une petite excroissance au cœur d'un plus grosse dilatation ? Fusionnez avec l'objet original et vous avez un contour qui entoure l'original, à une distance réglé par la plus petite dilatation, avec une épaisseur égal à la différence entre les dilatations intérieure et extérieure (vous devrez peut-être augmenter la taille de la région du filtre pour éviter que le résultat soit coupé).
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!
Enfin, que se passe-t-il en prenant l'idée précédente et en la complétant un peu plus ? Vous pouvez avoir plusieurs contours, à des distances différentes de l'objet d'origine, que vous fusionner ensuite tous ensemble pour terminer. Plus vous ajoutez de contours, plus les choses deviennent compliquées car vous jonglez avec une paire de primitives Morphologie et une Composite pour chaque couche de l'oignon ; mais, dans le principe, il est possible d'en rajouter autant que vous voulez, tant que vous ne vous perdez pas en route.
Ou, que dire de cette version, où j'ai j'ai utilisé aussi des primitives Matrice des couleurs en mode Décalage de teinte de façon à attribuer une couleur à chaque contour :
Il est bon de se rappeler que les filtres sont des opérations bitmap qui ont lieu pendant la phase de rendu. Bien que vous puissiez penser que la primitive Morphologie rétrécit ou dilate votre image, ce n'est pas réalisé dans un sens vectoriel, mais plutôt en ajoutant ou en retirant des pixels dans une version bitmap de votre objet. En le gardant en tête, il parait possible d'appliquer la primitive à des images bitmap importées via la primitive Image. CE ci vous permet de cacher les détails précis d'une image en les dégradant un peu, ou en les cachant par une dilatation des zones adjacentes, sans introduire la sorte d'adoucissement que vous attendez en floutant les images. Dans un tel cas, Mona se sort bien mal d'un tel essai !
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