[cairo] Spot colors (and CMYK)

Francois Robert frobert at atex.com
Fri Jan 15 04:17:13 PST 2010

Bill Spitzak wrote :
> For spot colors the spot color is recovered by looking up the sRGB color. 
> This assumes a 1:1 mapping >between spot color and sRGB. Another channel is 
> used to transfer this information.

Actually, a spot color (or rather a 'colorant' or an 'ink') is identitified by a human-readable name. The proposed structure may be fine for rendering a spot color(ant) on an RGB device. On a PS or a PDF device, the name must be passed (along with alternate colorspace etc...) So the definition details of a spot color that aims to be passed-through to a PS or a PDF backend unfortunately requires more than just some RGB equivalent. (but being unfamilliar with the code, that may be stored elsewhere already ?)

To understand why a name is needed, it helps understand what happens at print time:

In offset printing (or similar, eg. laser printing), unlike video, it is not possible to specify a 'pixel intensity'. On each point of the paper, either there is ink or there is not. There cannot be 50% ink. Fortunately, the human brain offers a workaround with optical illusions, referred as 'optical mix': If the ink is deposited in small enough discrete clumps on a reflective background, the brain averages things out and what determines the perceived color is the (local) percentage of the paper area covered with ink. So what is needed is a binary map of where to deposit ink and where not to. Such a bitmap is called a 'separation'. This bitmap is produced at resolution above 1200 dpi (2400 and 3600 dpi being common too). A RIP (Raster Image Processor) is the software responsible for producing this bitmap. 
The exact way the ink gets distributed on the bitmap is determined by the 'halftnoning' (or 'screening') logic. What drives the ink distribution for a given halftone is a quantity akin to a single RGB component called 'tint' in Postscript. (only that 0 means minimum coverage, and 1 means maximum coverage. I did not write 0% and 100% because halftoning may decide otherwise).
All of this business of separation is largely hidden from people that deal with RGB video output. (unless you are on the monitor hardware side of things and need to manipulate what loosely amounts to a Red, Green and Blue 'separations', with the difference that it is possible to have continous values)

Sooooo.... back to the name thing :
One separation is produced for each ink. But, unlike RGB which has three components, there are many more inks that may be used simultaneously... The way inks are identified is thus by name (the label on the ink bottle). Each ink has some properties: For usual dyes, it may be a L*a*b* triplet under some predefined viewing conditions, or some cruder RGB or CMYK approximation. If your PS code asks your RIP for a known colorant (matched by name), the RIP will produce a dedicated separation for that ink. However, if no such colorant is available to the RIP, some other approximate rendering may be possible, using the other inks of the device. In that case, the RIP will replace a separation for the inexisting ink with modification of the separations of other inks, to approximate the missing ink color.
Both Postscript and PDF have provisions for that logic : They can request a colorant by name and specify a fallback mecanism in case it is not available. It is the RIP that ultimately decides which separations to produce.  (ok, I am assuming in-RIP separation for the sake of simplicity. Older techniques required to execute a Postscript program several times in different context to produce one separation per run, but I digress).

To give you an idea of what is involved, here is a Postscript (level 2) example (conceptually identical in PDF):

[ /Separation
  (Grün) % A colorant name (case sensitive, 8-bit char, encoding unspecified)
  /DeviceCMYK % alternate colorspace used in case the device does not have the requested colorant
  { 0 1 index 0 } bind % a 'tint proc' to convert from tint to alternate colorspace
] setcolorspace

0.5 setcolor % requested tint
0 0 100 110 rectfill % paint something

We can mix inks too: Here we print in Grün and black, with CMYK fallback:
[ /DeviceN
  [ /Black % colorant names
  /DeviceCMYK % alternate colorspace
  { 0 1 index
    4 3 roll 
  } bind % tint proc
] setcolorspace

0.1 0.3 setcolor % requested tints
0 0 100 110 rectfill % paint something

Note that Postcript Level 3 allows to configure a RIP and declare the available colorants for in-RIP separation :
<< /SeparationColorNames
  [ (Grün) (PANTONE 185 U)
  /Separations true % enable in-RIP sep.
>> setpagedevice

Hope this helps

More information about the cairo mailing list