Named color lookup examples
This page applies to Harlequin v13.1r0 and later; both Harlequin Core and Harlequin MultiRIP.
This section describes various ways of writing lookup procedures to obtain the replacement solid color for named colors.
Simple example
This simple example defines an NCD, called SimpleNCD, which uses the /DeviceCMYK ColorSpace
:
currentglobal false setglobal
<<
/ColorSpace [/DeviceCMYK]
/Lookup {
% on stack: NCD colorant exch /Colors get exch
% on stack: Colors colorant
2 copy known {
get
true
% on stack: solid-color true
} {
pop pop false
% on stack: false
} ifelse
} bind
/TintTransform { {1 index mul exch} forall pop } bind
/Colors <<
/Orange [ 0 0.45 1 0 ]
/Violet [ 0.8 0.8 0 0 ]
>>
>>
/SimpleNCD exch /NamedColor defineresource pop setglobal
The Lookup procedure looks for colorants that are held within the NCD in a dictionary, here called Colors, which also holds the solid color equivalent CMYK values.
One advantage of this method is that the NCD can be created from a PostScript language fragment as a memory-based resource (that is, the NCD does not need to be obtained from disk as required for the InternalLookup example).
Lookup from a table
Note: This same technique is used by the HqnColorDatabase procset, which provides additional functionality to assist creating a resource from a table. It is recommended that HqnColorDatabase is used instead of this example, which is here for completeness.
This example defines an NCD, called InternalLookup
, which uses the /DeviceCMYK ColorSpace
:
{
currentglobal false setglobal
<<
/linebuff 100 string def
/ColorSpace /DeviceCMYK
/Lookup {
% on stack: NCD colorant
Colors exch 2 copy known {
get
true
% on stack: solid-color true
} {
pop pop false
% on stack: false
} ifelse
} bind
/TintTransform { {1 index mul exch} forall pop } bind
/Colors <<
% This loop converts each pair of lines from the end of
% this resource to a dictionary entry of:
% colorant [ CMYK values ]
{
currentfile //linebuff readline not { pop exit } if cvn
[ % And read in the 4 CMYK values
currentfile token pop
currentfile token pop
currentfile token pop
currentfile token pop
]
} loop
>>
>>
/InternalLookup exch /NamedColor defineresource pop
setglobal
} exec
Orange
0 0.45 1 0 % Stored as: /Orange [ 0 0.45 1 0 ]
Violet
0.8 0.8 0 0 % Stored as: /Violet [ 0.8 0.8 0 0 ]
This example also uses the Colors dictionary to store all colorants and their CMYK equivalent solid colors known to this NCD. This method uses the convenient technique of storing the colorants and their CMYK values in a tabular format at the end of database, and reading it in a loop to populate the Colors dictionary. It is convenient because this tabular format of the color values can often be easily imported from the spreadsheet format used for many spot color libraries.
This method requires that the NCD is contained in its own file, which is normally in the SW/NamedColor directory as normal for a disk-based resource.
Use of Variant 2 Lookup procedures
This example is similar to the SimpleNCD
in Simple example. It shows the use of the Variant 2 Lookup procedure to return a different ColorSpace
and/or TintTransform
from one that is defined by the resource. It shows that both variant 1 (array) and variant 2 (dictionary) forms may be returned for different spots in the same resource.
% Define local interpolation operator to make the use of interpop simpler.
% It interpolates an in-value in range 0-1, over an equally spaced array containing
% out-values. The out-values may be any numbers.
% in-value interp-array interpop out-value
userdict /interpop 1183615869 internaldict /interpop get put
currentglobal false setglobal
<<
% A default used if Lookup returns a dictionary without a ColorSpace entry.
/ColorSpace [/DeviceCMYK]
% A default used if Lookup returns a dictionary without a TintTransform entry.
/TintTransform { {1 index mul exch} forall pop } bind
% A boiler plate Lookup procedure. It returns data for the spot from the Colors
% dictionary.
/Lookup {
% on stack: NCD colorant
exch /Colors get exch
% on stack: Colors colorant
2 copy known {
get
true
% on stack: solid-color true
} {
pop pop false
% on stack: false
} ifelse
} bind
% A dictionary of spots handled by this resource. The value of each is either
% a variant 2 (dictionary) or variant 1 (array) form. It shows some examples
% of how tint transforms of spots may be finely adjusted.
/Colors <<
% Variant 2 (dictionary form) returned by Lookup. ColorSpace is implied
% from the default [/DeviceCMYK].
% This TintTransform is equivalent to the simpler Variant 1 form for Violet
% in the SimpleNCD example.
(Violet) <<
/TintTransform {[0.8 0.8 0 0] {1 index mul exch} forall pop} bind
>>
% Variant 2 (dictionary form) returned by Lookup. ColorSpace is implied
% from the default [/DeviceCMYK].
% The tint transform uses an interpop array to apply a curve to the tint
% value before converting to process. The interpop array is deliberately
% simple with 5 entries for values at 25% intervals.
(Orange) <<
/TintTransform {{0 0.35 0.60 0.85 1} //interpop
[0 0.45 1.0 0] {1 index mul exch} forall pop} bind
>>
% Variant 2 (dictionary form) returned by Lookup. ColorSpace is specified
% as a DeviceN that includes a metallic Silver.
% The tint transform uses interpop arrays to differentially apply a curve
% to the non-zero values after converting to process. The interpop arrays
% are deliberately simple with 5 entries for values at 25% intervals.
% N.B. This is a complex example that is probably better implemented using
% a named color device using the ExternalCMYK example.
(Gold) <<
% Gold is converted to this DeviceN. If Silver isn't a device colorant
% an error will be thrown due to the illegal {null} tint transform.
/ColorSpace [/DeviceN [/Cyan /Magenta /Yellow /Black /Silver] /DeviceCMYK {null}]
/TintTransform {
% The solid color values of Gold in CMYK+Silver: [0.05 0 0.4 0 0.7]
0.05 1 index {0 0.35 0.60 0.85 1} //interpop mul exch
0 exch
0.4 1 index {0 0.30 0.56 0.80 1} //interpop mul exch
0 exch
0.7 1 index {0 0.15 0.40 0.65 1} //interpop mul exch
pop
} bind
>>
% Variant 1 (array form) may be returned by Lookup that uses the ColorSpace and
% TintTransform defined in this NCD.
(Grass) [0.6 0 0.7 0]
>>
>>
/SimpleNCD_Variant2 exch /NamedColor defineresource pop setglobal
External Lookup
It is sometimes desirable to lookup colorants in a more dynamic style than is allowed with the previous methods. It is possible to call out to C code to derive the results for the Lookup procedure using a PostScript language device What is a device?.
For more information see the documentation for named-color-lookup.c which is a fully working example PostScript device that supports five example named color device instances, one each for CMYK, CMYKOGV, XYZ, Lab, and None color spaces. As well as the C code that implements the PostScript Language device, a named color resource is required to call the device. This is a simplified version of the TEST_CMYK resource that works with the CMYK instance which is shipped in the SW/NamedColor/Examples directory of the SDK. To avoid confusion this simplified resource is called ExternalCMYK:
currentglobal false setglobal
20 dict begin
/globalness exch def
/ColorSpace /DeviceCMYK
/NCdevname (%namedcolorCMYK%) def
/NCfullname 256 string def % full name of device+colorant filename
//NCdevname //NCfullname copy pop % initialise device prefix once
/Lookup { % NCD colorant |solid-color true OR false
exch pop
//NCfullname //NCdevname length % c fn dnl
2 copy 5 2 roll % fn dnl c fn dnl
1 index length 1 index sub getinterval % fn dnl c fs
cvs length % fn dnl csl
add 0 exch getinterval % (%namedcolorCMYK%colorant)
% Execute the (%namedcolorCMYK%colorant) string which has the effect
% of opening a ’file’ on the %namedcolorCMYK% device, which then
% returns the solid-color and success status.
currentobjectformat 0 eq {
% Binary scanning is required for this, so change the object
% format temporarily to enable binary scanning.
3 setobjectformat run 0 setobjectformat
} {
run
} ifelse
} bind def
% N.B. It is important that a tint of 0 should map to NO ink, and
% that a tint of 1 should not perturb the solid color. The RIP
% uses the tint value to compute the contributions when blending
% spots together during the overprint and compositing phase
/TintTransform { % tint [C M Y K] |Ct Mt Yt Kt
{ % tint solid
1 index mul exch
} forall
pop
} bind def
currentdict
end
/ExternalCMYK exch /NamedColor defineresource
/globalness get setglobal
This resource is written to work with the %namedcolorCMYK%
device instance. It accepts a colorant name and writes back either a false, or a colorant array and true. This data is in binary format, which has the advantage for the PostScript language device that the emitted string is a fixed length.
This example resource may appear complex, but is mostly boilerplate. OEMs will be mostly concerned with getting the details of the color conversions in the C code.