Re: [filter-effects] hue-rotate() and saturate() filters

Hello Stephen,

Tuesday, October 15, 2013, 4:11:00 PM, you wrote:

> On Tue, Oct 15, 2013 at 5:37 AM, Dirk Schulze <>wrote:

>  Shouldn't the conversion between RGB and HSL be bijective? So if
> both color spaces are bijective, the algorithm described by
> feColorMatrix must be wrong[1]. Polar coordinates or not, every
> color in HSL should be describable in RGB. And we still do the
> animation on the hue value and not on the RGB values. It also
> depends of course if the definition of hue in Filter Effects is
> equivalent to the definition of hue in HSL. Same (and probably more
> dramatic) for saturate. SVG 1.1 is not very clear about that.

> feColorMatrix does not use HSL, AFAICT it uses what appears to be
> HSY'.

Its just a tilted RGB cube. The problem with calling that HSY is that
people may assume the HSL equations are used to calculate H and S. And
it is Y, not Y'.

Looking at the matrix, and assuming the default value for
color-interpolation-filters is being correctly applied, the
coefficients are computing the luminance and the cube is
rotated around the luminance (black to white) axis.

> So the issue is that some fully-saturated colours go
> out-of-gamut when rotated to the far side of the HSY' colour space.
> So when rotated, they must clip.

Yes, exactly. You can't rotate a cube within the bounding box of the
unrotated cube without clipping.

> E.g., when fully-saturated green is rotated into blue, in HSY'
> space it is actually over-saturated, but clips to fully-saturated
> blue (since the colour is now out-of-gamut). If fully-saturated blue
> is rotated into green, it is under-saturated, and stays that way
> (since it's in-gamut), so that the perceived luminance is preserved.
> So it's not a matter of clipping between two filter stages; it's
> actually clipping caused by the rotation. Imagine a horizontal slice
> on the Y' axis of the HSY' space: fully-saturated blue rotated by
> 180 degrees ends up as a partly-saturated yellow, such as in the
> lower right image here:

> This is due to the CCIR 601 luma computation built into
> feColorMatrix hueRotate (Y = 0.213 R + 0.715 G + 0.072 B).

Note that due to color-interpolation-filters initial value of
linearRGB, it is true luminance (not video luma) that is being
calculated. Also, unlike Rec.601 the values for black and white are 0
and 255 (not 16 and 235).

The primary chromaticities and white point of Rec.709 and sRGB are

Cutting to the chase, given that filter effects uses early clamping,
my conclusion is that feMatrix is useful when type=matrix or
type=luminanceToAlpha but that the hueRotate value is misleading. The
specification should note the undesireable side effects for any
colours which fall outside a sphere in RGB space bunded by and centred
on the RGB cube, and a better option offered (especially as a
shorthand) which gives the more expected results without gross
roundoff error.

The saturate value is also potentially misleading when used in a
filter chain of the form

saturate(s) -> something -> saturate(1/s)

where s > 1.0
again due to the early clipping.

Best regards,

Received on Tuesday, 15 October 2013 15:31:40 UTC