Re: Linear RBG and feComposite "arithmetic"

On Mon, 10 Sep 2001, Thomas E Deweese wrote:

> >>>>> "TD" == Thomas E Deweese <thomas.deweese@kodak.com> writes:
> 
> >>>>> "JM" == Jim Mork <jmork@jasc.com> writes:
> 
>     Actually this was the problem.  Without the enable-background
> present, you end up 'compositing' the magenta rect with transparent
> black (0, 0, 0, 0). The result of the combine is:
> 
>          (.5, 0, .5, .5)
> 
> Because the operation works on pre-multiplied versions of the
> components when you undo the sRGB->linear you get (using math from
> your previous mail)
> 
>      (0.73, 0, 0.73, 0.5)
> 
>      Note that this violates the Alpha-Premultiplied rules because the
> color channels have values greater than the alpha channel.  Thus these
> values get clipped to the alpha channel value:
> 
>      (0.5, 0, 0.5, 0.5)
> 
>      Ie, a 50% opaque Magenta rectangle...
> 
>      This is then composited with srcOver on top of the cyan rectangle
> in sRGB, the result is:
> 
>      (0.5, 0.5, 1.0, 1.0) 
> 
>      Giving the result you saw.
> 
Is this the same problem that is exhibited in the following (which
shows a problem with Batik, but not in Adobe SVG viewer version 2)
and is a repost of a previous problem:

This one had me confused for several hours.

Consider this rectangle that uses a pure green gradient:

    <defs>
    <linearGradient id="green_grad">
        <stop offset="0%" stop-color="rgb(0%, 0%, 0%)"/>
        <stop offset="100%" stop-color="rgb(0%, 100%, 0%)"/>
    </linearGradient>

    <rect id="green_bar" x="0" y="0" width="200" height="30"
        fill="url(#green_grad)"/>
    </defs>

Now, write a filter to invert the color values with a simple linear
transformation (G' = 1 - G)

    <filter id="invert-filter" filterUnits="objectBoundingBox"
        x="0%" y="0%" width="100%" height="100%">
        <feComponentTransfer in="SourceGraphic">
            <feFuncG type="linear" slope="-1.0" intercept="1.0"/>
        </feComponentTransfer>
    </filter>

And apply it as follows:

    <use xlink:href="#green_bar" transform="translate(0,0)"/>

    <use xlink:href="#green_bar" transform="translate(0,50)"
        filter="url(#invert-filter)"/>

Gape in amazement at the second rectangle, which looks nothing like
the reverse of the first rectangle.

Why?  Because the gradient has been drawn with color-interpolation in
the sRGB space (by default), and the filter has done its work with
color-interpolation-filters in the linearRGB space (which is its
default).

The solution is to write the filter so that it, too, works in the
correct color space:

    <filter id="invert-filter-sRGB" filterUnits="objectBoundingBox"
        color-interpolation-filters="sRGB"
        x="0%" y="0%" width="100%" height="100%">
        <feComponentTransfer in="SourceGraphic">
            <feFuncG type="linear" slope="-1.0" intercept="1.0"/>
        </feComponentTransfer>
    </filter>

apply it,

    <use xlink:href="#green_bar" transform="translate(0,100)" 
        filter="url(#invert-filter-sRGB)"/>

and all is well with the world.  A complete example is available for
download from ftp://catcode.com/pub/svg/filterspace.svg.


---
J. David Eisenberg  http://catcode.com/

Received on Monday, 10 September 2001 11:51:42 UTC