Skip to main content
Skip table of contents

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:

CODE
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:

CODE
{
  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.

The use of Variant 2 Lookup procedures is only required in specialist use cases.
CODE
% 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:

CODE
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.


JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.