Ghostscript Color Replacement Control

Michael Vrhel·December 27, 2022

GhostscriptPDF Color
Ghostscript Color Replacement Control

Ghostscript provides several approaches to customize the color management of rendered pages. For example, these approaches include:

  • Overriding of source ICC profiles
  • Specification of source object dependent destination ICC profiles
  • Specification of rendering intents
  • Use of proofing profiles

Even with these various methods, there are situations where a developer may desire a finer level of control. Such an option exists using the special operations procedure used by devices. This procedure was developed to provide an easy way to add functionality to the device API without having to introduce new methods. Special operations are invoked in various parts of the source code using a command such as:

/* Check if target supports alpha */
supports_alpha = dev_proc(target, dev_spec_op)(target, gxdso_supports_alpha, NULL, 0);

As described by the comment, this call checks if the target device supports the inclusion of an alpha channel in its output. The device procedure dev_spec_op is invoked with the keyword gxdso_supports_alpha, which is used by the device to switch to a particular operation. For a given keyword, a device may respond to, ignore, or pass the call to another device. Details on special operations are contained in the file gxdevsop.h. The two parameters in the call after the keyword are used to pass a pointer to data that is needed for a particular keyword call.

In Ghostscript, the color management of all non-image colors is handled through a call to the function gx_remap_ICC, which is contained in the file gsicc.c. In this function, calls are made to the color management module to transform source color to destination colors using ICC profiles. Recently, a special operations call was added to the beginning of this function to provide developers the option of performing custom color handling. The code is given by:

       /* Try color replacement. If successful (>0) then no
       ICC color management for this color. */
    if (dev_proc(pgs->device, dev_spec_op)(pgs->device,
        gxdso_replacecolor, ¶m, sizeof(color_replace_t)) > 0)
        return 0;

The keyword for the special operations is gxdso_replacecolor. Note that a pointer to a color_replace_t object is passed through the method. Also note that if this method returns a value greater than zero, then the method performed a successful color replacement for the source color and gx_remap_ICC will return a value of zero indicating to the caller that the color mapping was successful.

Ghostscript provides a sample device implementation using gxdso_replacecolor in the PSD device, which creates Adobe Photoshop output images. The implementation is found in the file gdevpsd.c in the function:

    static int psd_spec_op(gx_device *dev_, int op, void *data, int datasize)

There is a section of code that is disabled in the function unless ENABLE_COLOR_REPLACE is set to nonzero. To enable the code section, use #define ENABLE_COLOR_REPLACE 1 at the top of the file, where it is set to zero by default.

If one of the PSD devices, such as psdcmyk or psdcmyk16, is specified as the output device, the code within the code section

    if (op == gxdso_replacecolor && dev_->color_info.num_components >= 4) {}

may perform a mapping on the source color to the device destination color if the special operation gxdso_replacecolor is invoked and the target device is CMYK based (possibly also with spot colors). This code that does the mapping is simply a demo code and not meant to illustrate a commercial use. The sample will perform color mappings if the source color is RGB, CMYK, or CIELAB and a vector-based object is being filled. If the source color is CMYK, then the demo code looks for certain source CMYK colors to set, and it also performs a color inversion of other colors. If the source is RGB, the code inverts the colors and sets the K values in CMYK to no ink. If the source color is CIELAB, an output value is created using K-only that is based upon the luminance input value of the color.

If there is transparency present in the source file, it is possible that the target color space has changed since transparency groups in PDF files can specify a color space into which objects are drawn. Care needs to be exercised for such cases. The demonstration code shows an example of handling this, where a color mapping is not performed if the current state is a transparency group that is not CMYK based. It is straightforward to do something more sophisticated here, if desired. For example, if the final target device is CMYK based, but the current transparency group is RGB based, then it is necessary to set RGB output colors rather than CMYK output colors.

With the successful setting of the output colors, the function returns true. If the function does not set the output color, then the function returns false. This information is used by the calling function in gx_remap_ICC as described above.

The above information provides a roadmap for adding color replacement capability to your Ghostscript device. If you have any questions about the use of this feature, please reach out to us. We are on Discord: #ghostscript.