The alternate color management module (ICC-CMM) API allows customer-supplied code to implement ICC profile based color transformations. More...
Files | |
| file | swcmm.h |
| Header file defining the Color management module interface - ICC (ICC-CMM). | |
Data Structures | |
| struct | sw_cmm_instance |
| An instance structure for the CMM API implementation. More... | |
| struct | sw_cmm_init_params |
| Collection structure for initialization parameters. More... | |
| struct | sw_cmm_api |
| The definition of an implementation of the alternate CMM interface. More... | |
Macros | |
| #define | SW_CMM_N_ICC_RENDERING_INTENTS (4) |
| The number of ICC rendering intents. | |
| #define | SW_CMM_N_SW_RENDERING_INTENTS (6) |
| The number of extended rendering intents, including absolute derivations of the ICC perceptual and saturation intents. | |
Typedefs | |
| typedef HqnResult | sw_cmm_result |
| Type of return values from sw_cmm_api functions. More... | |
| typedef void * | sw_cmm_profile |
| An opaque structure defined by the alterate CMM implementation to represent profiles. More... | |
| typedef void * | sw_cmm_transform |
| An opaque structure defined by the alternate CMM implementation to represent transforms. More... | |
| typedef struct sw_cmm_api | sw_cmm_api |
| Type definition of the alternate CMM interface implementation. | |
| typedef struct sw_cmm_instance | sw_cmm_instance |
| An instance structure for the CMM API implementation. More... | |
| typedef struct sw_cmm_init_params | sw_cmm_init_params |
| Collection structure for initialization parameters. | |
Enumerations | |
| enum | { SW_CMM_API_VERSION_20070525 = 2 , SW_CMM_API_VERSION_20070614 , SW_CMM_API_VERSION_20071109 , SW_CMM_API_VERSION_20160324 , SW_CMM_API_VERSION_20160819 , SW_CMM_API_VERSION_20200117 , SW_CMM_API_VERSION_20250922 } |
| Version numbers defined for the CMM API. More... | |
| enum | SW_CMM_RESULT { SW_CMM_SUCCESS = HQN_RESULT_SUCCESS , SW_CMM_ERROR = 1 , SW_CMM_ERROR_IOERROR , SW_CMM_ERROR_MEMORY , SW_CMM_ERROR_INVALID , SW_CMM_ERROR_UNSUPPORTED , SW_CMM_ERROR_VERSION , SW_CMM_SUCCESS_USE_BUILTIN } |
| Return values for sw_cmm_api CMM functions. More... | |
| enum | { SW_CMM_INTENT_PERCEPTUAL = 0 , SW_CMM_INTENT_RELATIVE_COLORIMETRIC , SW_CMM_INTENT_SATURATION , SW_CMM_INTENT_ABSOLUTE_COLORIMETRIC , SW_CMM_INTENT_ABSOLUTE_PERCEPTUAL , SW_CMM_INTENT_ABSOLUTE_SATURATION } |
| Values of rendering intent for use in the intents array as passed to sw_cmm_api::open_transform() and sw_cmm_api::open_transform2(). More... | |
Functions | |
| HqnResult | swcmm_result_translate (sw_cmm_result result) |
| Translate a CMM API-specific error code to a generic HqnResult error code. More... | |
| sw_api_result | SwRegisterCMM (sw_cmm_api *implementation) |
| This routine makes an alternate CMM implementation known to the rip. More... | |
The alternate color management module (ICC-CMM) API allows customer-supplied code to implement ICC profile based color transformations.
When converting a color to the output device, the RIP will create a color pipeline according to the configuration. This pipeline will consist of one or multiple transforms. If an individual transform consists of one of:
it is a candidate for being handled by the Alternate CMM.
Each transform in the color pipeline is treated independently for the purpose of its compatibility with the Alternate CMM. Those transforms that are incompatible are handled by the built-in CMM.
The sw_cmm_api structure type describes an ICC-CMM abstraction (a class). The skin registers a concrete implementation of this structure for each selectable ICC-CMM. The RIP will create an instance structure (a sw_cmm_instance) to represent the configured and selected ICC-CMM in use.
Calls to the ICC-CMM interface follow these stages:
setalternatecmm in a PostScript configuration file. The ICC-CMM is then called to construct an instance object.Each ICC_CMM module is identified by an internal name, for use in configuring the RIP, and an additional UTF-8 name for display purposes.
ICC-CMM modules may be registered at any time after the RIP is started by calling SwRegisterCMM() using an instance of the sw_cmm_api structure. This function performs some validation checks on the API structure, and then registers it in RDR as a named RDR, in the RDR_NAMES_CMMAPI namespace, using the internal name provided in the structure. This internal name is also used to select the ICC-CMM module. You may register ICC-CMM modules in RDR directly before the RIP is started, but doing so will not perform the validation checks that SwRegisterCMM() performs. If you miss out a required callback function pointer, selecting your ICC-CMM may crash the RIP. You may also de-register ICC-CMM modules from RDR by calling SwDeregisterNamedRDR(), if you have access to the pointer and length that the module was registered with.
Before any other calls are made to the ICC-CMM module, the RIP will call the optional sw_cmm_api::init() to initialize data. It is called at most once per module. This call is provided with a parameters structure that contains a pointer to a memory callback API instance. The ICC-CMM module should save the memory callback API instance pointer and use it to allocate any data it needs. It is called lazily before the first call to sw_cmm_api::construct() for the module.
A registered ICC-CMM module is activated by calling the PostScript configuration operator setalternatecmm from a configuration file, using the internal name defined in the sw_cmm_api::info.name field:
The RIP then calls sw_cmm_api::construct() to construct an ICC-CMM module instance (sw_cmm_instance). Normally, only one module has an instance constructed at any one time.
/AlternateCMM key of setpagedevice. This method still works but is now deprecated.When a colorspace is selected, the RIP will create a color pipeline consisting of one or multiple transforms that convert the colorspace to the output colorspace according to the configuration.
For each transform that is compatible with the ICC-CMM, a profile handle will be created for the ICC profiles within that transform. Then a transform handle will be created from the profile handles.
ICC profiles are used by e.g. ICCBased PDF colorspaces, and within the color configuration operators setinterceptcolorspace and setreproduction. If a transform of one or two ICC profiles is found in the color pipeline, the RIP opens the ICC profile(s) by calling sw_cmm_api::open_profile(). The resulting profile handle(s) will be used later when constructing the transform.
If a profile handle is successfully created using sw_cmm_api::open_profile(), it will be later closed when the RIP calls sw_cmm_api::close_profile().
The profile handles for ICC profiles are used to create a transform when the RIP calls sw_cmm_api::open_transform2(), or sw_cmm_api::open_transform().
Prior to creating a transform, the RIP ensures compatibility with the capabilities of the ICC-CMM, as indicated by its optional capabilities. If the transform is not compatible, the built-in CMM is used for that transform.
If an ICC-CMM fails to load an ICC profile, or create a transform, the RIP will optionally use the built-in CMM if the ICC-CMM allows this. Otherwise the current job is aborted.
Transforms opened using sw_cmm_api::open_transform2() will be later closed by calling sw_cmm_api::close_transform().
When required, the RIP will invoke the transform to convert color values by calling sw_cmm_api::invoke_transform().
The RIP may have multiple threads actively converting colors using the same or different transforms. The RIP will optionally serialise calls to guarantee thread-safety with the loss of some performance. The ICC-CMM may choose to perform its own synchronization of threads as necessary.
When the graphics state containing a colorspace goes out of scope, the transforms and profiles associated with them will be closed when the RIP calls sw_cmm_api::close_profile() and sw_cmm_api::close_transform().
When the graphics state containing an alternate CMM configuration goes out of scope, normally when the job has completed, the RIP calls sw_cmm_api::destruct() to destroy the API instance created by sw_cmm_api::construct().
When the RIP shuts down, and after all other calls are made to the ICC-CMM module, the optional sw_cmm_api::finish() is called to allow it to finalize data. The module should free any data it allocated.
The RIP makes extensive use of color caching for performance reasons. As a result:
This pseudocode describes the pattern of calls to the ICC-CMM API when an ICC transform is created. The precise timing of these calls may vary widely due to caching strategies employed by the RIP. It is only the order of calls for any one transform that is fixed.
| typedef struct sw_cmm_instance sw_cmm_instance |
An instance structure for the CMM API implementation.
This is the definition of an alternate CMM instance. The RIP allocates memory for the instances, fills in the implementation and memory instance fields, and calls the implementation's constructor to complete the remaining details. The RIP will construct one instance as a result of using either the setalternatecmm operator, or the setpagedevice operator with the /AlternateCMM key. These are commonly used in the RIP's configuration.
There will normally be at most one CMM instance active on each page. There may be more than one CMM instance active at a time if Harlequin Parallel Pages is in use. While discouraged, it is possible to call setalternatecmm multiple times on the same page; this may result in several CMM instances active on the same page which will have unpredictable results depending on the job structure.
The instance structure may be subclassed to hold private data by defining a subclass structure containing this structure as its first member, and using the size of that structure as the implementation's instance size. Individual methods may then downcast their instance pointer parameters to subclass pointers, and use the private data. e.g.,
The RIP will not touch memory beyond the size of the instance structure for the implementation version registered.
| typedef void* sw_cmm_profile |
An opaque structure defined by the alterate CMM implementation to represent profiles.
The alternate CMM implementation can use this type to supply the RIP with references to opened profiles, which will be used when constructing transforms later.
| typedef HqnResult sw_cmm_result |
Type of return values from sw_cmm_api functions.
This is a subclass of HqnResult that also supports some specific extra error codes generated by sw_cmm_api functions (declared as the SW_CMM_RESULT enumeration). Before assigning to values of HqnResult type or any of its other subclasses, sw_cmm_result values must be converted to change the API specific values to HQN_RESULT_SUCCESS or a monitor UID error code greater than MON_CLASS_ERROR. This can be done by calling the function swcmm_result_translate().
| typedef void* sw_cmm_transform |
An opaque structure defined by the alternate CMM implementation to represent transforms.
The alternate CMM implementation can use this type to supply the RIP with references to opened transforms, which will be used when invoking the transforms to convert colors.
| anonymous enum |
Version numbers defined for the CMM API.
| anonymous enum |
Values of rendering intent for use in the intents array as passed to sw_cmm_api::open_transform() and sw_cmm_api::open_transform2().
The first four of these intents correspond to the standard ICC rendering intents: SW_CMM_INTENT_PERCEPTUAL, SW_CMM_INTENT_RELATIVE_COLORIMETRIC, SW_CMM_INTENT_SATURATION, and SW_CMM_INTENT_ABSOLUTE_COLORIMETRIC.
The remaining two of these intents may also be used if supported by the alternate CMM: SW_CMM_INTENT_ABSOLUTE_PERCEPTUAL, SW_CMM_INTENT_ABSOLUTE_SATURATION. They are absolute variants of Perceptual and Saturation that are derived in the same way that AbsoluteColorimetric is derived from RelativeColorimetric.
| enum SW_CMM_RESULT |
Return values for sw_cmm_api CMM functions.
| Enumerator | |
|---|---|
| SW_CMM_SUCCESS | Success return value for sw_cmm_api methods. |
| SW_CMM_ERROR | Non-specific error, also minimum error value. Please avoid using this if possible. |
| SW_CMM_ERROR_MEMORY | Problem accessing blob. |
| SW_CMM_ERROR_INVALID | Memory allocation failed. |
| SW_CMM_ERROR_UNSUPPORTED | Invalid profile, transform, or params. |
| SW_CMM_ERROR_VERSION | Unsupported configuration. |
| SW_CMM_SUCCESS_USE_BUILTIN | Callback API version is insufficient. May only be returned by a call to sw_cmm_api::invoke_transform() for an ICC transform. If set, the RIP will ignore color values returned by sw_cmm_api::invoke_transform() and use the built-in CMM to perform the ICC transform for this color value. |
| HqnResult swcmm_result_translate | ( | sw_cmm_result | result | ) |
Translate a CMM API-specific error code to a generic HqnResult error code.
| [in] | result | One of the SW_CMM_RESULT values, or an error value greater than MON_CLASS_ERROR. |
| sw_api_result SwRegisterCMM | ( | sw_cmm_api * | implementation | ) |
This routine makes an alternate CMM implementation known to the rip.
It can be called any number of times with different implementations of the alternate CMM API. Within SwRegisterCMM(), sw_cmm_api::init() will be called for the implementation. After that, it will remain dormant until the sw_cmm_api::construct() is called as part of using the setalteratecmm operator or the /AlternateCMM key of the setpagedevice operator. Both the sw_cmm_api::init() and sw_cmm_api::finish() callbacks are set to NULL in many implementations because the alternate CMM has nothing to do at this point.
This function may be called at any time after the RIP is initialized, and before the RIP is shut down.
| [in] | implementation | The API implementation to register. This pointer will be returned through the sw_cmm_api::init() and sw_cmm_api::finish() calls, and also will be in the implementation member field of every instance created, so the pointer can be in dynamically allocated memory. |
Implementations may be subclassed to hold class-specific private data by defining a subclass structure containing the sw_cmm_api structure as its first member. Individual methods may then downcast their implementation pointers to subclass pointers, and use those to get at the class data. e.g.,