W3C home > Mailing lists > Public > public-fx@w3.org > October to December 2013

Re: [filter-effects] resolution dependent filter primitives

From: Michael Mullany <michael@sencha.com>
Date: Tue, 5 Nov 2013 00:12:13 -0800
Message-ID: <CABTYPJnoHvB=pkVqs2KcJkQ7n8L6ZQ-u7fQ87pDdijeNqcj90Q@mail.gmail.com>
To: Dirk Schulze <dschulze@adobe.com>
Cc: "public-fx@w3.org" <public-fx@w3.org>, www-svg list <www-svg@w3.org>
On Mon, Nov 4, 2013 at 10:30 PM, Dirk Schulze <dschulze@adobe.com> wrote:

> On Nov 5, 2013, at 1:01 AM, Michael Mullany <michael@sencha.com> wrote:
> On Mon, Aug 26, 2013 at 9:28 PM, Dirk Schulze <dschulze@adobe.com> wrote:
>> Hi,
>> This is a follow up on Stephen White's mail "Filter Effects and High
>> DPI"[2]
>> The Filter Effects spec[1] has a couple of filter primitives that are
>> resolution dependent. Namely: feConvolutionMatrix, feDiffuseLighting,
>> feSpecularLighting and feCustom.
>> With removing 'filterRes', there is just 'kernelUnitLength' that can be
>> used to "hard code" a resolution for a primitive. 'filterRes' defined the
>> resolution for the whole filter chain which reduced or increased pixel
>> density for each filter primitive instead of one. This either caused
>> unnecessary oversampling of filter operations but more often: unnecessary
>> reduction of quality. With 'kernelUnitLength' the affect of over- or
>> undersampling can be localized to exactly one primitive where the primitive
>> values can not be scaled for resolution independent results.
>> If 'kernelUnitLength' is not set, all the primitives in the introduction
>> may depend on the device pixel ratio and are therefore platform dependent.
>> This is actually hardly a "retina" vs "normal" screen problem. SVG is
>> scalable by nature and therefore you can see the problem on any screen
>> today. Open the following example in a browsers and resize the window:
>> http://www.w3.org/Graphics/SVG/Test/20110816/svg/filters-conv-01-f.svg
>> You'll see that you don't have consistent results. If you make the window
>> smaller, the top left image gets more blurry and the top right image more
>> sharpen. Same happens if you zoom into a page where one of the above
>> primitives was applied.
>> We could create stable results by default. UAs could set
>> 'kernelUnitLength' such that the kernel size is always relative to a CSS
>> pixel in the current local coordinate system of the filtered object. This
>> is something that is nearly impossible to determine for the author if he
>> wants to use the same filter on different objects. With the auto calculated
>> 'kernelUnitLength' the proportion of the filter chain result looks always
>> the same across platforms but might be more pixelated on one platform and
>> less pixelated on another one.
>> It is unclear what is better for the users:
>> * best results that are highly platform dependent and indeed differ
>> significantly, or
>> * platform independent results that might be pixelated.
>> During my research I couldn't find one SVG example where the above
>> primitives are used in combination of either 'filterRes' or
>> 'kernelUnitLength'. Not even in the SVG test suite. That means these
>> examples in the web out there are all suffering from device and zoom
>> dependent filter results.
>> I would even suggest removing 'kernelUnitLength' as well and choose one
>> of the above two ways (high DPI but resolution dependent results, or
>> pixelated proportion stable results). Or let the author choose between one
>> of the two options and have one as fallback.
>> Does anyone have a comment?
> I got around to doing a thorough testing of feDiffuseLighting +
> fePointLight cross browser and generated a test page for people to play
> with.
> The page is here: http://codepen.io/mullany/pen/wKJeu (note this takes a
> while to render in IE10 due to lack of support for objectBoundingBox units
> for kernelUnitLength)
> It's not very surprising that there is not much content using these
> settings because they don't work consistently cross browser. Here's what I
> found:
>    - kernelUnitLength: supported by IE10, Firefox (no support in Safari
>    or Chrome)
>    - filterRes: supported by Chrome, Safari, Firefox (no support in IE10)
>    - primitiveUnits = userSpaceOnUse -> supported everywhere
>    - primitiveUnits = objectBoundingBox -> supported by Firefox,  (no
>    support in Safari, Chrome, IE10: units are interpreted as userSpace units)
>       - This makes kernelUnitLengths specified in OBB units cause very
>       very long render times in browsers (aka IE10) that support
>       kernelUnitLength, but don't support objectBoundingBox units - because it
>       thinks I'm asking for a very small kernelUnitLength
> This test page raised one or two notes for the current spec:
>    - The spec is not clear what Z position units are calculated relative
>    to, when primitiveUnits = objectBoundingBox -> X? Y? Some average thereof?
>    - The spec is not clear that surfaceScale units are in pixels, not in
>    primitiveUnits (or if they're supposed to be primitiveUnits, it should say
>    that - no browser currently supports this)
>  In any case, the use case I'm running into is not a high dpi vs. low dpi
> problem (because OBB units should be able to solve this, I think?) Instead,
> it's the fact that Firefox (specifically) chooses a fast, low quality
> default for lighting effects which are too coarse to use in image filters.
> The mozilla implementor has told me to use a higher filterRes, but since
> all positions are scaled by the ratio of filterRes to default filterRes
> (aka when you double the filterRes, the X, Y and Z positions of your image
> source are also scaled up by 2x), you end up with what is effectively a new
> unit system just for lightsource positions that has nothing to do with any
> other unit system (unless you also reduce the kernelUnitLength to
> compensate).  [As an aside, the practical effect of this in Firefox was no
> increase in quality (and I've filed a bug against that)].
> It would all be a lot simpler if there was an attribute similar to
> shape-rendering (filter-rendering?) that would allow optimizeSpeed vs.
> optimizeQuality for these primitives.
> I need to verify your test case. All arguments are supposed to be pixels
> and therefore are just integer and floats (floats for oversampling) and
> don’t have px, cm or any other length value.

Just to clarify, the following lighting related units are defined in
primitiveUnits, not pixels in both the SVG 1.1 spec and the current filter
effects 1.0 draft

   - kernelUnitLength in feDiffuseLighting & feSpecularLighting
   -  X, Y,Z in fePointlight
   -  X, Y, Z, PointsAtX, PointsAtY, PointsAtZ, in feSpotlight

> I agree that Firefox implemented some values like stdDeviation from
> feGaussianBlur relative to the value of primitiveUnits. A reason why WebKit
> did it as well. Not sure if that was the initial intension of the spec
> though. I rather think that primitiveUnits should just be taken into
> account for x,y,width and height of the subregions, but kernelUnitLength is
> indeed one use case where it makes sense to have it relative to
> primitiveUnits. I’ll add an issue to the spec.

In both SVG 1.1, and in the current filter effects 1.0 draft - stdDeviation
for GaussianBlur as well as kernelUnitLength for feDiffuseLighting and
feSpecularLighting are all defined as primitiveUnits. From the specs:

 stdDeviation = "*<number-optional-number>
The standard deviation for the blur operation. If two
are provided, the first number represents a standard deviation value along
the x-axis of the coordinate system established by attribute
the ‘filter’ <http://www.w3.org/TR/SVG/filters.html#FilterElement> element.
in combination with the other attributes, defines an implicit pixel grid in
the filter effects coordinate system (i.e., the coordinate system
established by the

> That said, your conclusion that WebKit and Blink do not support
> primtitiveUnits in general is not correct. in the cases described above,
> both engines should take primitiveUnits into account.

I should have been clearer - I was talking solely about the context of the
test page - meaning that they don't currently support
primitiveUnits=objectBoundingBox specifically for fePointlight X,Y,Z
positions. No generalization was intended (although I also know that
feSpotlight positions also do not currently support objectBoundingBox units
in Chrome or Webkit)

> I compare Z to the value of z on transform-origin or perspective-origin
> from CSS Transforms. You can not have percentage values there because you
> don’t know how they would be relative to the x and y dimension. Therefore,
> Z should always operate in userSpaceOnUse. I'll add an issue to the spec.

I think I inappropriately slandered the draft spec wrt its definition of Z
-> The spec currently states:

   "Z location for the light source in the coordinate system established by
attribute ‘primitiveUnits’<http://www.w3.org/TR/filter-effects/#FilterElementPrimitiveUnitsAttribute>
the <filter> <http://www.w3.org/TR/filter-effects/#FilterElement> element,
assuming that, in the initial coordinate
the positive Z-axis comes out towards the person viewing the content and
assuming that one unit along the Z-axis equals one unit in X and

one unit in X and Y is in turn defined as " sqrt((*actual-width*)**2 + (

I can see many use cases where you want X, Y and Z of a pointlight source
defined in objectBoundingBox units, so you can apply the same filter to a
bunch of differently sized content for example for consistent embossing,
without having to recalculate Z units . So the current spec language seems
fine to me.

> filterRes was deprecated and removed from the spec. It is just
> kernelUnitLength that is left.
> I am not convinced if it is worth it to keep kernelUnitLength. You never
> know how kernelUnitLength is relative to device units OR to your object,
> see previous discussions. So you are better on with having high DPI results
> but platform dependent or you want to have it exactly depending on your
> userSpaceInUse coordinates which probably will reduce quality. Of course,
> if you put it in userSpaceOnUse, there are cases where you could
> ridiculously increase the pixel density and the browser may need to reduce
> it again or runs out of memory. Example:
> <g transform=“scale(0.0001)”>
> <g filter=“url(#filter)”>
> <rect transform=“scale(100)” width=“1000” height=“1000"/>
>  </g>
> </g>
> The resulting rect size would be 100x100, yet the filtered object would be
> 100000x100000.
> So even if we add a flag to switch between device pixels and
> userSpaceOnUse, it would still just be a hint for the UA.

Given that it's already implemented in both Firefox and IE10+, I'd vote for
retaining kernelUnitLength as the way to poke the UA to do the "right
thing" however the developer/author chooses to define that, rather than
introducing a new attribute.

> Greetings,
> Dirk
>> Greetings,
>> Dirk
>> [1] http://dev.w3.org/fxtf/filters/
>> [2] http://lists.w3.org/Archives/Public/public-fx/2013JanMar/0149.html
> --
> www.sencha.com
> "Amazing Apps with Web Technologies"

"Amazing Apps with Web Technologies"
Received on Tuesday, 5 November 2013 08:13:12 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 19:49:47 UTC