- 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