W3C home > Mailing lists > Public > public-fx@w3.org > January to March 2013

Re: Filter Effects and High DPI

From: Rik Cabanier <cabanier@gmail.com>
Date: Mon, 18 Mar 2013 10:31:43 -0700
Message-ID: <CAGN7qDDwB-zXPOHhemL6zgWS2nsXPzspjs9tn6dg3JwUNH=iNA@mail.gmail.com>
To: Stephen White <senorblanco@chromium.org>
Cc: "Tab Atkins Jr." <jackalmage@gmail.com>, "public-fx@w3.org" <public-fx@w3.org>
On Mon, Mar 18, 2013 at 7:02 AM, Stephen White <senorblanco@chromium.org>wrote:

> On Sun, Mar 17, 2013 at 10:01 PM, Rik Cabanier <cabanier@gmail.com> wrote:
>> On Fri, Mar 15, 2013 at 12:54 PM, Tab Atkins Jr. <jackalmage@gmail.com>wrote:
>>> On Fri, Mar 15, 2013 at 11:59 AM, Stephen White
>>> <senorblanco@chromium.org> wrote:
>>> > In particular, in Chrome's accelerated implementation, on a high-DPI
>>> > display, we get high-DPI input images from the compositor.  Right now,
>>>  we
>>> > filter the high-DPI image by the original (unscaled) parameter values,
>>> > which, for the filters whose pixel's result depends on more than a
>>> single
>>> > input pixel value (e.g., blur(), drop-shadow()), results in less
>>> blurring
>>> > than would be visible on a non-HighDPI display.  This seems wrong.
>>>  (Last
>>> > time I checked, the non-composited path was downsampling the input
>>> > primitive, giving a non-high-DPI result but correct amounts of blur,
>>> > although that may have been fixed).
>>> This is a bug in our implementation, then.  The values in the
>>> functions are CSS values, so a length of "5px" means 5 CSS pixels, not
>>> 5 hardware pixels.  The browser has to scale that to whatever internal
>>> notion of "pixel" it's using.
>>> > For blur() and drop-shadow(), It would be straightforward to scale the
>>> > parameter values by the devicePixelRatio automatically, and achieve the
>>> > correct amount of blurring without affecting the resolution of the
>>> result.
>>> > Of course, we could downsample the input primitive for all filters,
>>> but that
>>> > would lose the high DPI even for those filters which are unaffected by
>>> this
>>> > problem, e.g., brightness() etc.
>>> >
>>> > However, for the reference filters, in particular feConvolveMatrix,
>>> it's not
>>> > clear what the optimal behaviour is.  It's tempting to simply multiply
>>> the
>>> > kernelUnitLength by the devicePixelRatio, and apply the convolution as
>>> > normal.  However, that also loses high DPI, and incurs the cost of a
>>> > downsample where it otherwise wouldn't be required (also note that
>>> > kernelUnitLength seems to be unimplemented in WebKit, but that's our
>>> > problem).  Would it be a possibility to simply upsample the kernel by
>>> > devicePixelRatio instead, and apply that kernel to the original
>>> unscaled
>>> > image?   (Or perhaps size' = (size - 1) * devicePixelRatio + 1 for odd
>>> > kernel sizes?)   This would result in a similar effect range, while
>>> > preserving the resolution of the source image.
>>> >
>>> > I have no idea if the convolution math is really correct this way,
>>> though.
>>> > I'm guessing not, since if it was, presumably the spec would have
>>> allowed
>>> > its use for kernelUnitLength application in general.
>>> I'm not sufficiently familiar with feConvolveMatrix to know how to
>>> handle it well.  However, if you get a substantially different result
>>> (beyond rendering/scaling artifacts), the implementation is definitely
>>> wrong in some way.  None of SVG or CSS should require knowledge of the
>>> device's DPI.
>> From the Filter Effects spec [1]:
>> Because they operate on pixels, matrix convolutions are inherently
>> resolution-dependent. To make ‘feConvolveMatrix’ produce
>> resolution-independent results, an explicit value should be provided for
>> either the ‘filterRes’ attribute on the ‘filter’element and/or attribute
>> ‘kernelUnitLength’.
>> So, this is a case where the device's DPI is allowed to make a
>> difference. 'FilterRes' [2] should be used if you want device independent
>> output.
>> It seems that for feConvolveMatrix, 'FilterRes' should have been
>> required. (It's weird that 'FilterRes' is not a resolution but a number of
>> device pixels)
> Thanks!  I didn't catch that.
> So it seems the author's options are:
> 1)  Set filterRes, and have the image downsampled before all filtering
> (lo-DPI results)
> 2)  Set kernelUnitLength, and have the image downsampled before
> convolution only (lo-DPI results).
> 3)  Check window.devicePixelRatio, and provide a kernel sized
> appropriately to the DPI (hi-DPI results).
> Does that sound right?

I * think* option 2 will work for both high and low DPIsince it allows you
to specify percentages or css pixel values [1]:

By specifying value(s) for ‘kernelUnitLength’, the kernel becomes defined
in a scalable, abstract coordinate system. If ‘kernelUnitLength’ is not
specified, the default value is one pixel in the offscreen bitmap, which is
a pixel-based coordinate system, and thus potentially not scalable.

It seems that this should work OK for line art but might cause issues for
high dpi images.

Option 3 could use '@media resolution' [2] and switch to a filter for that
particular pixel ratio.

2: http://www.w3.org/blog/CSS/2012/06/14/unprefix-webkit-device-pixel-ratio/
Received on Monday, 18 March 2013 17:32:13 GMT

This archive was generated by hypermail 2.3.1 : Monday, 18 March 2013 17:32:13 GMT