- From: Christian Brunschen <cb@df.lth.se>
- Date: Wed, 2 Jun 1999 16:01:25 +0200 (CEST)
- To: www-svg@w3.org
Greetings.
Having just read the latest draft SVG spec, I cannot help but wonder one
thing.
In section 15.5.4, the built-in Filter Effects are listed, with this
little paragraph as a lead-in:
``The following is a catalog of the individual processing nodes proposed.
All filters operate on linear premultiplied RGBA samples. Filters which
work more naturally on non premultiplied data (ColorMatrix and
ComponentTransfer) will temporarily undo and redo premultiplication as
specified.''
Since RGBA rasters can not store sample values with infinite resolution,
the combination of premultipluying and the un-premultiplying pixels is
almost guaranteed to introduce inaccuracies at some places. Assuming an
8-bit-per-sample representation, a simple example is one where the
original pixel is painted with an RGBA value of 3,5,7,127 - a very dark
shade, with a 50% coverage. The resulting pre-multiplied pixel would
contain values something like 1,2,3,127 - and un-pre-multiplying would
result in 2,4,6,127, with each of the RGB samples being markedly different
from the original. Basically, pre-multiplication guarantees a loss of
information.
I would further like to suggest that pre-multiplied alpha is not the best
choice for the default alpha handling for, for instance, the
'DisplacementMap' Filter:
-- begin quote --
NodeType DisplacementMap
Image Inputs 2
Attributes scale
x-channel-selector one of R,G,B or A.
y-channel-selector one of R,G,B or A.
Description Uses Input2 to spatially displace Input1,
similar to the Photoshop displacement filter. This is
the transformation to be performed:
P'(x,y) <- P( x + scale * XC(x,y), y + scale * YC(x,y) )
where P(x,y) is the source image, Input1, and P'(x,y) is
the destination. XC(x,y) and YC(x,y) are the component
values of the designated by the x-channel-selector and
y-channel-selector. For example, to use the R component
of Image2 to control displacement in x and the G component
of Image2 to control displacement in y, set
x-channel-selector to "R" and y-channel-selector to "G".
Comments The displacement map defines the inverse of the mapping
performed.
Implementation
issues This filter can have arbitrary non-localized
effect on the input which might require substantial
buffering in the processing pipeline. However with this
formulation, any intermediate buffering needs can be
determined by scale which represents the maximum
displacement in either x or y.
-- end quote --
If I want to displace something according to the 'R' and 'G' channels of
an image I have constructed, it is not necessarily obvious that I want the
pre-multiplied-alpha Red and Green channels.
Furthermore, if I definitely want to use the _non_premultiplied-alpha Red
and Green channels from my image, I cannot get at them easily.
The lead-in paragraph states that ``Filters which
work more naturally on non premultiplied data (ColorMatrix and
ComponentTransfer) will temporarily undo and redo premultiplication as
specified'' which appears based in the assumption that for _all other
filters_, pre-multiplied-alpha is the `more natural' state of affairs. So
let's take a look at the different filters defined (these are in my
personal opinion, of course):
Filter 'Most Natural' Comment
ColorMatrix non-premultiplied explicitly stated in the
description
Color N/A has no inputs
ComponentTransfer non-premultiplied explicitly stated in the
description
Composite premultiplied? could easily be written
to handle non-premultiplied
while maintaining fidelity
of output; or could be stated
to require premultiplied
alpha
DiffuseLighting N/A uses only the Alpha channel,
does not care about wether RGB
are premultiplied or not
DisplacementMap I'm not sure As I discussed above, I don't
but it feels like see how premultiplied could be
non-premultiplied seen as 'more natural' here
would be better anyway
GaussianBlur non-premultiplied for maximum fidelity in the
resulting blurred image
Image N/A has no inputs
Merge premultiplied? premultiplied preferred for
performance reasons, but could
use non-premultiplied with the
same fidelity (like Composite)
Morphology non-premultiplied to ensure fidelity in the
resulting image
Offset N/A doesn't care about the colors
of the pixels it shifts
SpecularLighting N/A only uses the Alpha channel
Tile N/A doesn't care
Turbulence non-premultiplied to ensure fidelity, or else
the values to be added also
have to be premultiplied, lest
non-opaque pixels receive an
unproportionally large change
So, in summary, of the 14 filters in the spec, 2 _definitely_ need
non-premultiplied Alpha (already in the spec), 4 more seem to me to
probably be better off with non-premultiplied, 6 simply don't care, and
only 2 can really make a demand on premultiplied - Composite and Merge. So
I would interpret this to mean that non-premultiplied would be overall
'more natural' than premultiplied.
Again, this is all in my own opinion.
Anyway, my main argument for _not_ premultiplying RGN with A is that of
maintaining fidelity, of not losing resolution in the RGB channels just
because they happen to have a not-fully-opaque A value.
The main argument for premultiplied Alpha would be performance, unless I
am mistaken: Compositing an image with pre-multiplied Alpha onto another
saves one multiplication per pixel over Compositing the same image
non-premultiplied.
However, consider the case of a graphic that gets offset, a ColorMatrix
filter applied, then offset again (stupid example, but bear with me):
Premultiplied Alpha
* Graphic renders to RGBA matrix : premultiplications take place here
* Offset: shifts pixels around
* ColorMatrix: _Un_premultiply, perform the filter, then _Re_premultiply
* Offset: shift pixels around
* Merge: composite to destination
Multiplications take place in three places: Once when the graphic is
rendered to the RGBA matrix, then when Un-premultiplying before the
ColorMatrix filter can do its job, then re-premultiplying afterwards.
Now, with non-premultiplied Alpha:
* Graphic renders to RGBA matrix
* Offset: shifts pixels around
* ColorMatrix: perform the filter
* Offset: shift pixels around
* Merge: multiply RGB with A, then composite to destination
There's only one place where RGB samples are multiplied with A, and that's
at the very end when the resulting image is to be composited onto the
background.
Note also that in the non-premultiplied case, the ColorMatrix filter can
access the actual RGB values rendered by the Graphic, rather than the
'pre-multiplied, then un-pre-multiplied' values offered with the current
scheme.
For those cases where a certain image will be used pre-multiplied more
than once, it would be easy to define a filter which premultiplies RGB
with A on an image:
-- begin suggestion --
NodeType PreMultiply
Image Inputs 1
Attributes none
Description multiplies each of the R, G and B channels with the A
channel
Comments a very common operation
Implementation
issues none, really
-- end suggestion --
which could be used whenever needed, for whatever reason.
So, in summary, I am questioning the use of premultiplied alpha as the
default representation for RGBA images in filter effects.
Best regards
// Christian Brunschen
Received on Wednesday, 2 June 1999 10:01:28 UTC