[cairo] Spot colors (and CMYK)

Bill Spitzak spitzak at gmail.com
Thu Feb 18 10:53:39 PST 2010

Russell Shaw wrote:

> Because of CRT and camera imperfections, some blue and green pixels
> may be slightly lit. Also, ambient light reflecting off the monitor
> screen adds some blue and green. The "red" phosphor may have a spectral
> output that has some blue and green overlap in it too. We'll call these
> imperfections "colour leakage".
> This means the total red is not of full saturation, and thus means
> the CRT cannot cover the full gamut of ideal tristimulous. It is
> limited to the gamut defined by ITU-R BT.709-5.

Actually the real problem is not color spill, but the fact that the 
"ideal" color that is supposed to be emitted by the CRT is not fully 
saturated. However the result is exactly as you describe: the volume of 
color space covered by 0-1 indexes (the "gamut") is smaller than the 
volume of visible colors.

Light reflecting off the monitor adds a constant color to the viewing. 
In our work I have found a handy coincidence in the description of sRGB: 
due to the linear segment, if you instead plotted the gamma curve it 
would intersect the vertical axis at .00083. I don't think this was 
planned, but this vertical offset is approximately the reflection of the 
very finest high-contrast lcd monitors in a dark room. I have tried 
removing the linear segment from our sRGB->linear sRGB conversion, this 
has resulted in better composites of dark areas, which indicates that 
users have adjusted their images to compensate for ambient light 
(unfortunately this also picks up filter ringing inserted by software so 
I did not do this permanently).

> Storing negative values in sRGB is clearly a nonsense hack (square roots
> and all that).

True, and this is the biggest problem with saying "unclamped sRGB". 
Microsoft with their scRGB definition have said that the conversion of 
values greater than one follow the gamma curve, and negative numbers are 
encoded as -f(-x). From previous experience with Microsoft standards I 
am sure they thought about this for about 10 seconds, but unless we can 
find a persuasive argument for different math I think using Microsoft's 
definition is now the safest.

It is also certainly true that composites are useless for these 
out-of-gamut colors. Conversion to linear is needed before compositing 
math. This is exactly what Nuke does. However I can warn you that there 
are serious consequences that are going to hit a library used for vector 
graphics like Cairo much worse than they hit Nuke. The problem is that 
an awful lot of compositing relies on the "perceptually uniform" math 
being done, the most obvious is the result of drawing the same-thickness 
lines (or letters) in black or white on the opposite background. If the 
antialiasing is done "correctly" in linear space, the user thinks the 
white lines are far thinner or fainter than the black ones. But wrong 
antialiasing done in sRGB looks "correct". Also users do not expect 
their carefully painted partially-transparent overlay from Photoshop 
will produce visible artifacts when composited.

I do not have a solution to these problems. I wish I did. Linearizing 
only outside the 0-1 range kind of works but the discontinuous slope at 
0 and 1 produced artifacts.

> To process images from a source covering the full gamut, the linear RGB
> pixel values may be less than 2x as that from a ITU-R BT.709-5 source.
> See the upper-right CIE 1931 xy chromaticity diagram:
> http://en.wikipedia.org/wiki/SRGB

You need to get linear sRGB values of -.5 to cover the CIE horseshoe. 
Values greater than 1 are useful for high dynamic range (specifying 
colors brighter than the display can do) and is very useful in itself, 
the only integer-based HDR format I am familiar with (Cineon) goes up to 
approximately 16. Microsoft's scRGB integer format goes up to 7.5. Most 
HDR is done in floating point.

> Also, to avoid loss of resolution, sRGB in 8 bits/pixel should become
> 16 bits/pixel when converting to linear RGB (an x^1/2.4 type operation).

I very strongly recommend that if you use 16 bits, you use floating 
point in the ILM "half" format. This format is handled natively by 
graphics cards. Integers are very poor for storing linear color information.

The linear portion of the sRGB definition with a slope of 1/12.92 does 
mean that you must add 4 bits to get all n-bit values of sRGB into 
different linear values. So 12 bits in theory works. If you use pure 
gamma functions then you require an infinite number of bits to 
accurately store the linear value in an integer as the slope is zero 
near zero.

> Cairo can operate on this linear data, then convert it back to sRGB
> for monitor display. No ICC profile needed.

This is pretty much the same as I was thinking, although exactly how the 
compositing is done may vary. In my scheme the compositing is done in 
any space convenient for the device, provided the gamma is somewhat 
similar to sRGB, enough that the "photoshop composite" I listed above 
works with artifacts too small for humans to see. Alternatives are to 
force sRGB composites, or force linear sRGB composites as you suggest.

> Some printers may print a spot colour such as "shiny metallic silver".
> Obviously cairo cannot do any mathematically sensible merging of
> this colour with general synthesizeable RGB colours.

This I think is the main purpose of "spot colors". Spot colors that have 
an XYZ or RGB "equivalent" do not need to be part of Cairo's api. The 
spot color api is to explicitly say "I want this ink deposited here". It 
is by definition device-specific. I also think C,M,Y,K are "spot colors" 
as far as this is concerned, apparently all CMYK data is either "use the 
trivial conversion to sRGB" or "inks on this specific printer". The 
first means the application can convert it, the second requires the spot 
color api.

More information about the cairo mailing list