Fun with color space in Filter Land (verbose)

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.

Given that everyone else on this mailing list figured this out eons ago
(I'm always the last to know), you may wonder why I'm posting this here.
It's because the feComponentTransfer example in the specification,
section 15.11, uses a gradient and filters with different (default) 
color interpolation spaces.  I'd suggest either making them use the
same color space, or adding a foonote that says they are purposely using
different color spaces.
---
J. David Eisenberg  http://catcode.com/

Received on Sunday, 26 August 2001 20:49:33 UTC