Scaled filters
-
bobsammers
- Posts: 8
- Joined: Fri Jun 07, 2013 10:48 pm
Scaled filters
Hi,
I've created a custom filter: just a drop shadow (offset, blur, merge; offset and blur have identical X and Y parameters). It isn't behaving as I'd expect / wish.
If I have a shape whose size and / or aspect ratio has been altered, the filter does not apply the same as it would to shapes which have not undergone scaling. As an example, the attached picture shows two rectangles which started off as identical squares before being scaled and (after scaling) had the same filter applied. As you can see, the shadow is much more pronounced at the end of the rectangles, even though X and Y should be treated the same by the filter. If I draw a rectangle from scratch to be the same shape as one of these examples and apply the filter, the results are as I'd expect: similar blurring down the bottom and side of the object.
Looking at the XML it seems objects are defined at a whatever original sizes / scale the artist uses and then have a transformation matrix applied to them to cope with later scaling. Presumably, my filter is applied before this transform and I want it to be applied afterwards.
Can I do this? I suppose I need to either apply the filter post-matrix or somehow apply the transformation matrix to the shape permanently (as if it hadn't been scaled since it was defined), so the filter does its rendering on the final shape, rather than the initial shape.
I'm new to Inkscape and not exactly an accomplished graphic artist either, so forgive me if I've missed / misunderstood something obvious. I'm using the latest stable (0.48.4).
Thanks for any help,
Bob
I've created a custom filter: just a drop shadow (offset, blur, merge; offset and blur have identical X and Y parameters). It isn't behaving as I'd expect / wish.
If I have a shape whose size and / or aspect ratio has been altered, the filter does not apply the same as it would to shapes which have not undergone scaling. As an example, the attached picture shows two rectangles which started off as identical squares before being scaled and (after scaling) had the same filter applied. As you can see, the shadow is much more pronounced at the end of the rectangles, even though X and Y should be treated the same by the filter. If I draw a rectangle from scratch to be the same shape as one of these examples and apply the filter, the results are as I'd expect: similar blurring down the bottom and side of the object.
Looking at the XML it seems objects are defined at a whatever original sizes / scale the artist uses and then have a transformation matrix applied to them to cope with later scaling. Presumably, my filter is applied before this transform and I want it to be applied afterwards.
Can I do this? I suppose I need to either apply the filter post-matrix or somehow apply the transformation matrix to the shape permanently (as if it hadn't been scaled since it was defined), so the filter does its rendering on the final shape, rather than the initial shape.
I'm new to Inkscape and not exactly an accomplished graphic artist either, so forgive me if I've missed / misunderstood something obvious. I'm using the latest stable (0.48.4).
Thanks for any help,
Bob
- Attachments
-

- Example.png (5.26 KiB) Viewed 2427 times
Re: Scaled filters
Welcome aboard!
Something that might help: open the inkscape preferencies panel, and at the transformations section set optimised.
Something that might help: open the inkscape preferencies panel, and at the transformations section set optimised.
-
bobsammers
- Posts: 8
- Joined: Fri Jun 07, 2013 10:48 pm
Re: Scaled filters
Thanks for your help, Lazur.
Unfortunately, the "Optimized" setting is already set (presumably it's been this way since I installed Inkscape). Shame, as the description of this setting sounds like it should do exactly what I need.
Unfortunately, the "Optimized" setting is already set (presumably it's been this way since I installed Inkscape). Shame, as the description of this setting sounds like it should do exactly what I need.
Re: Scaled filters
One workaround for this is to put your object(s) into a group, and then apply the filter to the group. So long as you enter the group in order to scale the objects themselves (as opposed to scaling the group) then the filter should appear as you expect, since it's applying to the un-transformed coordinates of the group rather than the transformed coordinates of the objects within.
Re: Scaled filters
Hello:
I've noted that using the interpolate extension to a path, it generates a group of paths. But the interpolated paths doesn't have the transformation attribute.
So, Try to duplicate your path. Select both and apply the interpolate extension with 1 step an checked the option:"duplicate path".
Well, after that you will have to erase the unnecessary paths ...
...,jajaja, sorry, nevermind it's a too complicated method.
Greetings
I've noted that using the interpolate extension to a path, it generates a group of paths. But the interpolated paths doesn't have the transformation attribute.
So, Try to duplicate your path. Select both and apply the interpolate extension with 1 step an checked the option:"duplicate path".
Well, after that you will have to erase the unnecessary paths ...
...,jajaja, sorry, nevermind it's a too complicated method.
Greetings
If you have problems:
1.- Post a sample (or samples) of your file please.
2.- Please check here:
http://tavmjong.free.fr/INKSCAPE/MANUAL/html/index.html
3.- If you manage to solve your problem, please post here your solution.
1.- Post a sample (or samples) of your file please.
2.- Please check here:
http://tavmjong.free.fr/INKSCAPE/MANUAL/html/index.html
3.- If you manage to solve your problem, please post here your solution.
-
bobsammers
- Posts: 8
- Joined: Fri Jun 07, 2013 10:48 pm
Re: Scaled filters
Thanks so much, Xav, that work's perfectly and is appealingly straightforward.
Hulf, I tried to experiment with your technique too but for the particular object I'm interested in, I couldn't make interpolate do anything. I assume you meant "Extensions -> Generate from Path -> Interpolate...". I suspect it's because it's not a path, but "Path -> Object to Path" is not apparently doing anything to help and I don't understand the difference between a path and an object in order to understand why that might be. It could easily be for some other reason. I obviously need to do some reading up.
The application of these filters seems inconsistent to me. I'm curious: is this down to ambiguity in the SVG specification, an Inkscape idiosyncrasy or is it by design for some reason I can't fathom? To my mind, you should get a result you can predict from what you can see on the screen, rather than what is in the history of the object to which you apply a filter.
Hulf, I tried to experiment with your technique too but for the particular object I'm interested in, I couldn't make interpolate do anything. I assume you meant "Extensions -> Generate from Path -> Interpolate...". I suspect it's because it's not a path, but "Path -> Object to Path" is not apparently doing anything to help and I don't understand the difference between a path and an object in order to understand why that might be. It could easily be for some other reason. I obviously need to do some reading up.
The application of these filters seems inconsistent to me. I'm curious: is this down to ambiguity in the SVG specification, an Inkscape idiosyncrasy or is it by design for some reason I can't fathom? To my mind, you should get a result you can predict from what you can see on the screen, rather than what is in the history of the object to which you apply a filter.
Re: Scaled filters
As far as I understand it's from the svg specification.
Similar problem appears with the strokes, as in the specification they can be scaled differently in horizontal and vertical directions.
http://www.w3.org/TR/SVG/render.html
http://www.w3.org/TR/SVG/filters.html
Similar problem appears with the strokes, as in the specification they can be scaled differently in horizontal and vertical directions.
3.5 How elements are rendered
Individual graphics elements are rendered as if each graphics element represented its own group; thus, the effect is as if a temporary separate canvas is created for each graphics element. The element is first painted onto the temporary canvas (see Painting shapes and text and Painting raster images below). Then any filter effects specified for the graphics element are applied to create a modified temporary canvas. The modified temporary canvas is then composited into the background, taking into account any clipping, masking and object opacity settings on the graphics element.
http://www.w3.org/TR/SVG/render.html
http://www.w3.org/TR/SVG/filters.html
-
bobsammers
- Posts: 8
- Joined: Fri Jun 07, 2013 10:48 pm
Re: Scaled filters
Thanks for the links, Lazur. They do seem to suggest SVG as the source of this, but I wonder if it's possible to argue that the spec is ambiguous and, further, that Inkscape has taken the wrong interpretation?
The 'primitiveUnits' attrib. is not defined in my XML and I can't see any way of doing so in Inkscape, so 'userSpaceOnUse' is going to be in force.
I think this is an ambiguity, because the coord system in "place when the filter element is referenced" could be the height and width before or after any transform attribute (which would be a sibling to the 'style' attribute referencing the filter). If so, for consistency of filters across the canvas, should Inkscape assume that *after* the transform is the best place to apply it?
primitiveUnits = "userSpaceOnUse | objectBoundingBox"
Specifies the coordinate system for the various length values within the filter primitives and for the attributes that define the filter primitive subregion.
If primitiveUnits="userSpaceOnUse", any length values within the filter definitions represent values in the current user coordinate system in place at the time when the ‘filter’ element is referenced (i.e., the user coordinate system for the element referencing the ‘filter’ element via a ‘filter’ property)...
If attribute ‘primitiveUnits’ is not specified, then the effect is as if a value of userSpaceOnUse were specified.
The 'primitiveUnits' attrib. is not defined in my XML and I can't see any way of doing so in Inkscape, so 'userSpaceOnUse' is going to be in force.
I think this is an ambiguity, because the coord system in "place when the filter element is referenced" could be the height and width before or after any transform attribute (which would be a sibling to the 'style' attribute referencing the filter). If so, for consistency of filters across the canvas, should Inkscape assume that *after* the transform is the best place to apply it?
Re: Scaled filters
The only thing I know about inkscape coordinate system is that it is upside down compared to the specs,
so some transformation must always be involved.
so some transformation must always be involved.
Re: Scaled filters
I don't think the "problem" is due to the width and height before/after transforming, it's that Inkscape applies the filter first, then applies the transform to the filtered object. In this case the transform says that the object should be stretched more in one direction that the other, so the shadow is also stretched more in one direction than the other.
But I think this is the right thing to do. Consider a filter chain other than one that creates a drop shadow - something that adds some texture to an object, for example. Now consider a different transform other than stretching - such as rotation. I think most people would expect the texture to rotate with the object, not to stay fixed to its original orientation.
For simple primitives, such as rectangles and circles, there's one other workaround for this issue. Rather than changing the size of the object using the
transformation handles, you can use the
or
tools to modify the object directly. This doesn't add a transform attribute to the SVG file, so the filter is applied directly to the new object size.
But I think this is the right thing to do. Consider a filter chain other than one that creates a drop shadow - something that adds some texture to an object, for example. Now consider a different transform other than stretching - such as rotation. I think most people would expect the texture to rotate with the object, not to stay fixed to its original orientation.
For simple primitives, such as rectangles and circles, there's one other workaround for this issue. Rather than changing the size of the object using the
transformation handles, you can use the
or
tools to modify the object directly. This doesn't add a transform attribute to the SVG file, so the filter is applied directly to the new object size.-
bobsammers
- Posts: 8
- Joined: Fri Jun 07, 2013 10:48 pm
Re: Scaled filters
Sorry, Xav, I didn't express myself very clearly: that's what I meant.
I see your point - sometimes it wouldn't make much sense for the filter to operate post-transform. That sounds to me like an argument for being able to choose the order of filter / transform application, since there are also situations where I think the transform should be applied first (like drop shadow, or even some operations on textured objects - widening a shape with filter-created flames, perhaps?).
Because the order of attributes in XML isn't guaranteed to be preserved during processing, the most obvious route to determine the order in which these things should be applied isn't open. I suppose a flag could be added to SVG to determine which was applied first. Alternatively (since at the moment transforms are applied second), an Inkscape tool which removed the transform attribute after applying the matrix to the original coords (for complex objects - thanks for pointing out that primitives can already be resized in this way, I didn't know) would achieve the same goal.
Of course, if this hasn't been addressed yet, I must be in the minority of people for whom this seems important (and it is, indeed, only a 'problem'
)!
Thanks for everyone's help.
Bob
I see your point - sometimes it wouldn't make much sense for the filter to operate post-transform. That sounds to me like an argument for being able to choose the order of filter / transform application, since there are also situations where I think the transform should be applied first (like drop shadow, or even some operations on textured objects - widening a shape with filter-created flames, perhaps?).
Because the order of attributes in XML isn't guaranteed to be preserved during processing, the most obvious route to determine the order in which these things should be applied isn't open. I suppose a flag could be added to SVG to determine which was applied first. Alternatively (since at the moment transforms are applied second), an Inkscape tool which removed the transform attribute after applying the matrix to the original coords (for complex objects - thanks for pointing out that primitives can already be resized in this way, I didn't know) would achieve the same goal.
Of course, if this hasn't been addressed yet, I must be in the minority of people for whom this seems important (and it is, indeed, only a 'problem'
Thanks for everyone's help.
Bob
Re: Scaled filters
bobsammers wrote:
Because the order of attributes in XML isn't guaranteed to be preserved during processing, the most obvious route to determine the order in which these things should be applied isn't open.
It's not a matter of order of attribute. You could define a fill attribute after a stroke attribute, this won't change the behaviour of rendering engine : it will fill the shape then it will stroke it.
Specs say the transform will be applied after the filter. That's all.
You can't (in svg1) change the rendering order : fill then stroke then markers then filter then transform.
But you can cheat by embedding your shape in a group and applying the transform onto the shape and the filter onto the group.
-
bobsammers
- Posts: 8
- Joined: Fri Jun 07, 2013 10:48 pm
Re: Scaled filters
v1nce wrote:You could define a fill attribute after a stroke attribute
You could do this but it has to mean exactly the same things as defining them the other way around, according to XML rules. That was my point
v1nce wrote:Specs say the transform will be applied after the filter. That's all.
Do they? I spent some time looking for this and I couldn't find anything that specified the order.
v1nce wrote:You can't (in svg1) change the rendering order : fill then stroke then markers then filter then transform.
That's (at least partly) a consequence of the choice of these things as sibling attributes. If they were elements within the object tag, rather than attributes of it, the order could be used (if the spec wished) to control order of application.
v1nce wrote:But you can cheat by embedding your shape in a group and applying the transform onto the shape and the filter onto the group.
Yes - this is what I've done, at Xav's suggestion.
Re: Scaled filters
bobsammers wrote:v1nce wrote:Specs say the transform will be applied after the filter. That's all.
Do they? I spent some time looking for this and I couldn't find anything that specified the order.v1nce wrote:You can't (in svg1) change the rendering order : fill then stroke then markers then filter then transform.
That's (at least partly) a consequence of the choice of these things as sibling attributes. If they were elements within the object tag, rather than attributes of it, the order could be used (if the spec wished) to control order of application.
I think the confusion (which I'll admit I probably contributed to) is in thinking of this as being two separate steps, and that applying them in the opposite order would have a different effect. In practice the spec actually states that the transform attribute introduces a new coordinate system (http://www.w3.org/TR/SVG/coords.html ):
A new user space (i.e., a new current coordinate system) can be established at any place within an SVG document fragment by specifying transformations in the form of transformation matrices or simple transformation operations such as rotation, skewing, scaling and translation.
So it's not so much that the filter is being applied first, as that the filter is being applied in the new coordinate system introduced by the transform. Whether it's implemented as "render filtered version, then transform" or "transform coordinate system, then render filter" would not have any real effect on the outcome.
bobsammers wrote:v1nce wrote:But you can cheat by embedding your shape in a group and applying the transform onto the shape and the filter onto the group.
Yes - this is what I've done, at Xav's suggestion.
I don't think I'd even really call this a cheat. I suspect that if you asked the SVG working group, they would probably state explicitly that if you want the filter applied to the non-transformed coordinate space then the answer is to put the transformed element into a <g> and apply the filter to that.
-
bobsammers
- Posts: 8
- Joined: Fri Jun 07, 2013 10:48 pm
Re: Scaled filters
Xav wrote:...it's not so much that the filter is being applied first, as that the filter is being applied in the new coordinate system introduced by the transform. Whether it's implemented as "render filtered version, then transform" or "transform coordinate system, then render filter" would not have any real effect on the outcome.
Isn't this more or less semantics? I'm sure it can be useful to think of transforms in a variety of ways, but I don't see that saying a transform mediates between coordinate systems is really any different to saying it modifies an object's scale (or rotation, or whatever).
Whichever way you look at it, it's easy to conceive of applying the filter before or after the transform (in one or the other coordinate system, for example). I don't think it's valid to say the attributes of the object apply to the object entirely in its own coordinate system because the transform attribute itself necessarily violates this. Having said this, I see that the coord system viewpoint (which the SVG spec clearly chooses to use) does lend itself to your interpretation much better.
v1nce wrote:But you can cheat by embedding your shape in a group and applying the transform onto the shape and the filter onto the group.
Xav wrote:I don't think I'd even really call this a cheat. I suspect that if you asked the SVG working group, they would probably state explicitly that if you want the filter applied to the non-transformed coordinate space then the answer is to put the transformed element into a <g> and apply the filter to that.
Noobily, I've only just come to appreciate that you can have a group of one object (I was hacking the XML and then realised that Inkscape will happily create one from Object -> Group. I thought I'd tried this earlier, but clearly not!). Given this, my pleading for extensions / modifications to the SVG spec seems somewhat extravagant. I'd agree with Xav, I think. It might be a bit clunky, but it does enable a straight choice of when to apply the filter and therefore means a more esoteric solution is redundant: no doubt the SVG spec writers are aware of this.
I've enjoyed this discussion: it's made me think about the underlying representation of the illustration I've been working on much more than I would have done and it's taken all of it for me to realise single-object groups were possible! Thanks again to all contributors (and esecially Xav).
Re: Scaled filters
bobsammers wrote:Whichever way you look at it, it's easy to conceive of applying the filter before or after the transform (in one or the other coordinate system, for example). I don't think it's valid to say the attributes of the object apply to the object entirely in its own coordinate system because the transform attribute itself necessarily violates this. Having said this, I see that the coord system viewpoint (which the SVG spec clearly chooses to use) does lend itself to your interpretation much better.
What I was saying is that the spec defines the transform attribute as creating a new coordinate system for the object, so essentially there is no "one or the other coordinate system", there's just the one. The "other" coordinate system is that of the object's parent - which of course brings us back round to using a <g>. In other words there is no ambiguity about which order to perform the operations in, because the SVG spec does define it, even if it's not worded as clearly as it could be.
As for the attributes, it is valid to say that they apply to the object in its own post-transform coordinate system, because that's what the spec says:
The ‘transform’ attribute is applied to an element before processing any other coordinate or length values supplied for that element. In the element
<rect x="10" y="10" width="20" height="20" transform="scale(2)"/>
the x, y, width and height values are processed after the current coordinate system has been scaled uniformly by a factor of 2 by the ‘transform’ attribute.
In summary: The SVG spec does define what should happen, and Inkscape appears to follow the spec as it should. Whether the end result follows the "principle of least surprise" depends very much on the actual filter in question - I can see how it would be unexpected in the example given at the start of this thread, but I can also see how it would be equally unexpected if a "pattern" filter didn't rotate with the object.
-
bobsammers
- Posts: 8
- Joined: Fri Jun 07, 2013 10:48 pm
Re: Scaled filters
Xav wrote:...it is valid to say that they apply to the object in its own post-transform coordinate system, because that's what the spec says:The ‘transform’ attribute is applied to an element before processing any other coordinate or length values supplied for that element. In the element
<rect x="10" y="10" width="20" height="20" transform="scale(2)"/>
the x, y, width and height values are processed after the current coordinate system has been scaled uniformly by a factor of 2 by the ‘transform’ attribute.
In summary: The SVG spec does define what should happen, and Inkscape appears to follow the spec as it should.
Ah - got you. Yes, of course, you're correct.
Xav wrote:Whether the end result follows the "principle of least surprise" depends very much on the actual filter in question - I can see how it would be unexpected in the example given at the start of this thread, but I can also see how it would be equally unexpected if a "pattern" filter didn't rotate with the object.
I agree.
I'd like to modify my earlier complaint to be that the available method for choosing when to apply a filter (which is clearly an important ability) is unintuitive. As a newbie, I should probably just accept this as part of the learning curve, but it would be nice if Inkscape (or SVG) offered some readily discoverable method to apply a post-transform filter. For example: single-object, filter-only groups treated as special cases and having obvious options within Inkscape to apply filters (and potentially other attributes) to these groups; a tool which permanently transforms an object to the parent coord system (thereby removing the transform attrib.).
