Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Advanced Color Imaging on the Mac OS /
Chapter 5 - Developing Color Management Modules / Creating a Color Management Module


Handling Request Codes

When your component receives a request, it should examine the what field of the component parameters data structure to determine the nature of the request, perform the appropriate processing, set an error code if necessary, and return an appropriate function result to the Component Manager.

Your entry point routine can call a separate subroutine to handle each type of request. Chapter 4, "ColorSync Manager Reference for Color Management Modules," in Advanced Color Imaging Reference describes the prototypes for functions your CMM must supply to handle the corresponding ColorSync Manager request codes. The entry routine itself can unpack the parameters from the params parameter to pass to its subroutines, or it can call the Component Manager's CallComponentFunctionWithStorage routine or CallComponentFunction routine to perform these services.

The CallComponentFunctionWithStorage function is useful if your CMM uses private storage. When you call this function, you pass it a handle to the storage for this component instance, the component parameters data structure, and the address of your subroutine handler. Each time it calls your entry point function, the Component Manager passes to your function the storage handle along with the component parameters data structure. For a description of how you associate private storage with a component instance, see "Establishing the Environment for a New Component Instance" (page 5-21). The Component Manager's CallComponentFunctionWithStorage function extracts the calling application's parameters from the component parameters data structure and invokes your function, passing to it the extracted parameters and the private storage handle.

Listing 5-2 shows sample code that illustrates how to respond to the required Component Manager and ColorSync Manager requests. For a complete listing of the sample code on which this listing is based, see the Apple technical note QT05, "Component Manager Version 3.0." This technical note shows how to create a fat component, which is a single component usable for both 68K-based and PowerPC-based systems. The portion of sample code in Listing 5-2 for PowerPC-based systems uses a parameter block data structure to pass parameters. The data structure for this parameter block is generated from a macro in the MixedMode.h header file.

Listing 5-2 A CMM component shell

#include <Types.h>
#include <Quickdraw.h>
#include <Memory.h>
#include <Gestalt.h>
#include <Components.h>
#include <CMMComponent.h>
#if GENERATING68K
#include <A4Stuff.h>
#endif
#define DEBUG 0
#ifndef DEBUG
#define DEBUG 0
#endif
/* component version */
#define CMCodeVersion0
#defineCMVersion  ((CMMInterfaceVersion << 16) | CMCodeVersion)

/* component storage */
struct CMMStorageRecord {ComponentInstanceci;};
typedef struct CMMStorageRecordCMMStorageRecord, **CMMStorageHandle;
#if GENERATINGPOWERPC
   #define CallComponentFunctionWithStorageUniv(storage, params, funcName) \
      CallComponentFunctionWithStorage(storage, params, &funcName##RD)
   #define CallComponentFunctionUniv(params, funcName) \
      CallComponentFunction(params, &funcName##RD)
   #define INSTANTIATE_ROUTINE_DESCRIPTOR(funcName) RoutineDescriptor funcName##RD = \
      BUILD_ROUTINE_DESCRIPTOR (upp##funcName##ProcInfo, funcName)
#else
   #define CallComponentFunctionWithStorageUniv(storage, params, funcName) \
      CallComponentFunctionWithStorage(storage, params,
                                 (ComponentFunctionUPP)funcName)
   #define CallComponentFunctionUniv(params, funcName) \
      CallComponentFunction(params, (ComponentFunctionUPP)funcName)
#endif
enum{
   uppDoComponentOpenProcInfo = kPascalStackBased
      | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
      | STACK_ROUTINE_PARAMETER(1,SIZE_CODE(sizeof(ComponentInstance)))
};
enum {
   uppDoComponentCloseProcInfo = kPascalStackBased
      | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
      | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
      | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ComponentInstance)))
};
enum {
   uppDoComponentCanDoProcInfo = kPascalStackBased
      | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) 
      | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
};
enum {
   uppDoComponentVersionProcInfo = kPascalStackBased
      | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
};
enum {
   uppDoComponentRegisterProcInfo = kPascalStackBased
      | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
};
enum {
   uppDoCMInitProcInfo = kPascalStackBased
      | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
      | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
      | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMProfileHandle)))
      | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(CMProfileHandle)))
};
enum {
   uppDoNCMInitProcInfo = kPascalStackBased
      | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
      | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
      | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMProfileRef)))
      | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(CMProfileRef)))
};
enum {
   uppDoCMMatchColorsProcInfo = kPascalStackBased
      | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
      | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
      | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMColor*)))
      | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(unsigned long)))
};
enum {
   uppDoCMCheckColorsProcInfo = kPascalStackBased
      | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
      | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
      | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMColor*)))
      | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(unsigned long)))
      | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long*))
};
/* function prototypes */
pascal ComponentResult main(ComponentParameters *params, Handle storage);
pascal ComponentResult DoComponentOpen(ComponentInstance self);
pascal ComponentResult DoComponentClose(CMMStorageHandle storage, 
                                 ComponentInstance self);
pascal ComponentResult DoComponentCanDo(short selector);
pascal ComponentResult DoComponentVersion(void);
pascal ComponentResult DoComponentRegister(void);
pascalComponentResult DoCMInit(CMMStorageHandle storage, CMProfileHandle srcProfile,
                        CMProfileHandle dstProfile);
pascalComponentResult DoNCMInit(CMMStorageHandle storage, CMProfileRef srcProfile, 
                        CMProfileRef dstProfile);
pascalComponentResult DoCMMatchColors(CMMStorageHandle storage, CMColor *colorBuf, 
                              unsigned long count);
pascal ComponentResult DoCMCheckColors(CMMStorageHandle storage, CMColor *colorBuf, 
                              unsigned long count, long *gamutResult);
#if GENERATINGPOWERPC
   /* Routine descriptors for component functions */
   INSTANTIATE_ROUTINE_DESCRIPTOR(DoComponentOpen);
   INSTANTIATE_ROUTINE_DESCRIPTOR(DoComponentClose);
   INSTANTIATE_ROUTINE_DESCRIPTOR(DoComponentCanDo);
   INSTANTIATE_ROUTINE_DESCRIPTOR(DoComponentVersion);
   INSTANTIATE_ROUTINE_DESCRIPTOR(DoComponentRegister);
   INSTANTIATE_ROUTINE_DESCRIPTOR(DoCMInit);
   INSTANTIATE_ROUTINE_DESCRIPTOR(DoNCMInit);
   INSTANTIATE_ROUTINE_DESCRIPTOR(DoCMMatchColors);
   INSTANTIATE_ROUTINE_DESCRIPTOR(DoCMCheckColors);
/* PowerPC main component entry point */
   RoutineDescriptor MainRD = BUILD_ROUTINE_DESCRIPTOR(uppComponentRoutineProcInfo,
                                             main);

   ProcInfoType __procinfo = uppComponentRoutineProcInfo;
#endif
pascal ComponentResult main(ComponentParameters *params, Handle storage);
/* Abstract:
      main entry point to CMM Component
   Params:
      params(in) Parameters in form used by Component Manager
      storage(in) Handle to memory to be used by CMM
   Return:
      noErr If successful
         Otherwise System or ColorSync result code
*/
/* This main function must run on all Macs. */
pascalComponentResult main(ComponentParameters *params, Handle storage)
{
   ComponentResultresult;
   short       message;

   #if GENERATING68K
   long     oldA4;
   oldA4 = SetCurrentA4();
   #endif
   message = (*params).what;

   /* selectors < 0 for Component Manager functions */ 
   if (message < 0)
   {
      switch (message)
      {
         case kComponentOpenSelect :
            result = CallComponentFunctionUniv (params, DoComponentOpen);
            break; 
         
         case kComponentCloseSelect :
            result = CallComponentFunctionWithStorageUniv(storage, params,
                                                DoComponentClose);
            break;
         case kComponentCanDoSelect :
            result = CallComponentFunctionUniv(params, DoComponentCanDo);
            break;

         case kComponentVersionSelect :
            result = CallComponentFunctionUniv(params, DoComponentVersion);
            break;

         case kComponentRegisterSelect :
            result = CallComponentFunctionUniv(params, DoComponentRegister);
            break;

         default :
            result = noErr;
            break;
      }
   }
/* selectors >= 0 for CMM functions */ 
   else
   {
      switch (message)
      { 
         case kCMMInit :
            result = CallComponentFunctionWithStorageUniv(storage, params,
                                                DoCMInit);
            break;

         case kNCMMInit :
            result = CallComponentFunctionWithStorageUniv(storage, params,
                                                DoNCMInit);
            break;

         case kCMMMatchColors :
            result = CallComponentFunctionWithStorageUniv(storage, params,
                                                DoCMMatchColors);
            break;

         case kCMMCheckColors :
            result = CallComponentFunctionWithStorageUniv(storage, params, 
                                                DoCMCheckColors);
            break;

         default :
            result = unimpErr;
            break;
      }
   }
   #if GENERATING68K
      SetA4(oldA4);
   #endif
   return result;
}
For more information describing how your CMM component should respond to request code calls from the Component Manager, see "Creating Components" in Inside Macintosh: More Macintosh Toolbox.

Responding to Required Component Manager Request Codes

This section describes some of the processes your CMM can perform in response to the following Component Manager requests that it must handle:

Establishing the Environment for a New Component Instance

When a ColorSync-supportive application or device driver first calls a function that requires the services of your CMM, the Component Manager calls your CMM with a kComponentOpenSelect request to open and establish an instance of your component for the calling program. The component instance defines a unique connection between the calling program and your CMM.

In response to this request, you should allocate memory for any private data you require for the connection. You should allocate memory from the current heap zone. It that attempt fails, you should allocate memory from the system heap or the temporary heap. You can use the SetComponentInstanceStorage function to associate the allocated memory with the component instance.

For more information on how to respond to this request and open connections to other components, see "Creating Components" in Inside Macintosh: More Macintosh Toolbox.

Releasing Private Storage and Closing the Component Instance

To call your CMM with a close request, the Component Manager sets the what field of the component parameters data structure to kComponentCloseSelect. In response to this request code, your CMM should dispose of the storage memory associated with the connection.

Determining Whether Your CMM Supports a Request

Before the ColorSync Manager calls your CMM with a request code on behalf of a ColorSync-supportive application or driver that called the corresponding function, the Component Manager calls your CMM with a can do request to determine if your CMM implements support for the request.

To call your CMM with a can do request, the Component Manager sets the what field of the component parameters data structure to the value kComponentCanDoSelect. In response, you should set your CMM entry point function's result to 1 if your CMM supports the request and 0 if it doesn't.

Providing Your CMM Version Number

To call your CMM requesting its version number, the Component Manager sets the what field of the component parameters data structure to the value kComponentVersionSelect. In response, you should set your CMM entry point function's result to the CMM version number. Use the high-order 16 bits to represent the major version and the low-order 16 bits to represent the minor version. The major version should represent the component specification level; the minor version should represent your implementation's version number.

If your CMM supports the ColorSync Manager version 2.x, your CMM should return the constant for the major version defined by the following enumeration when the Component Manager calls your CMM with the kComponentVersionSelect request code:

enum {
   CMMInterfaceVersion = 1
   };

Responding to ColorSync Manager Required Request Codes

This section describes some of the processes your CMM can perform in response to the following ColorSync Manager requests that it must handle:

Initializing the Current Component Instance for a Session Involving Two Profiles

The Component Manager calls your CMM with an initialization request, setting the what field of the component parameters data structure to kNCMMInit. In most cases the Component Manager calls your CMM with an initialization request before it calls your CMM with any other ColorSync Manager requests.

In response to this request, your CMM should call its MyNCMInit initialization subroutine. For a description of the function prototype your initialization subroutine must adhere to, see MyNCMInit (page 4-10) in Advanced Color Imaging Reference.

Using the private storage you allocated in response to the open request, your initialization subroutine should instantiate any private data it needs for the component instance. Before your entry point function returns a function result to the Component Manager, your subroutine should store any profile information it requires. In addition to the standard profile information, you should store the profile header's quality flags setting, the profile size, and the rendering intent. After you return control to the Component Manager, you cannot use the profile references again.

The kNCMMInit request gives you the opportunity to examine the profile contents before storing them. If you do not support some aspect of the profile, then you should return an unimplemented error in response to this request. For example, if your CMM does not implement multichannel color support, you should return an "unimplemented" error at this point.

The Component Manager may call your CMM with the kNCMMInit request code multiple times after it calls your CMM with a request to open the CMM. For example, it may call your CMM with an initialization request once with one pair of profiles and then again with another pair of profiles. For each call, you need to reinitialize the storage based on the content of the current profiles.

Your CMM should support all seven classes of profiles defined by the ICC. For information on the seven classes of profiles, see "Profile Classes" (page 3-13) in Advanced Color Imaging Reference.

Matching a List of Colors to the Destination Profile's Color Space

When a ColorSync-supportive application or device driver calls the CWMatchColors function for your CMM to handle, the Component Manager calls your CMM with a color-matching session request, setting the what field of the component parameters data structure to kCMMMatchColors and passing you a list of colors to match. The Component Manager may also call your CMM with this request code to handle other cases, for example, when a ColorSync-supportive program calls the CWMatchPixMap function.

Before it calls your CMM with this request, the Component Manager calls your CMM with one of the initialization requests--kCMMInit , kNCMMInit, or kCMMConcatInit --passing to your CMM in the params field of the component parameters data structure the profiles for the color-matching session.

In response to the kCMMMatchColors request, your CMM should call its MyCMMatchColors subroutine by calling the Component Manager's CallComponentFunctionWithStorage function and passing it a handle to the storage for this component instance, the component parameters data structure, and the address of your MyCMMatchColors subroutine. For a description of the function prototype to which your subroutine must adhere, see MyCMMatchColors (page 4-12) in Advanced Color Imaging Reference.

The parameters passed to your CMM for this request include an array of type CMColor containing the list of colors to match and a one-based count of the number of colors in the list.

To handle this request, your CMM must match the source colors in the list to the color gamut of the destination profile, replacing the color value specifications in the myColors array with the matched colors specified in the destination profile's data color space. You should use the rendering intent and the quality flag setting of the source profile in matching the colors. For a description of the color list array data structure, see the section "The Color Union" (page 3-59) in Advanced Color Imaging Reference.

Checking a List of Colors

When a ColorSync-supportive application or device driver calls the CWCheckColors function for your CMM to handle, the Component Manager calls your CMM with a color gamut-checking session request, setting the what field of the component parameters data structure to kCMMCheckColors and passing you a list of colors to check.

Before the Component Manager calls your CMM with the kCMMCheckColors request, it calls your CMM with one of the initialization requests--kCMMInit , kNCMMInit, or kCMMConcatInit --passing to your CMM in the params field of the component parameters data structure the profiles for the color gamut-checking session.

In response to the kCMMCheckColors request, your CMM should call its MyCMCheckColors subroutine. For example, if you use the Component Manager's CallComponentFunctionWithStorage function, you pass it a handle to the storage for this component instance, the component parameters data structure, and the address of your MyCMCheckColors subroutine. For a description of the function prototype to which your subroutine must adhere, see MyCMCheckColors (page 4-14) in Advanced Color Imaging Reference.

In addition to the handle to the private storage containing the profile data, the CallComponentFunctionWithStorage function passes to your MyCMCheckColors subroutine an array of type CMColor containing the list of colors to gamut check, a one-based count of the number of colors in the list, and an array of longs.

To handle this request, your CMM should test the given list of colors against the gamut specified by the destination profile to determine whether the colors fall within a destination device's color gamut. For each source color in the list that is out of gamut, you must set the corresponding bit in the result array to 1.

Responding to ColorSync Manager Optional Request Codes

This section describes some of the processes your CMM can perform in response to the optional ColorSync Manager requests if your CMM supports them. Before the Component Manager calls your CMM with any of these requests, it first calls your CMM with a can do request to determine if you support the specific optional request code. This section includes the following:

Validating That a Profile Meets the Base Content Requirements

When a ColorSync-supportive application or device-driver calls the CMValidateProfile function for your CMM to handle, the Component Manager calls your CMM with the what field of the component parameters data structure set to kCMMValidateProfile if your CMM supports the request.

In response to this request code, your CMM should call its MyCMMValidateProfile subroutine. One way to do this, for example, is by calling the Component Manager's CallComponentFunction function, passing it the component parameters data structure and the address of your MyCMMValidateProfile subroutine. To handle this request, you don't need private storage for ColorSync profile information, because the profile reference is passed to your function. However, if your CMM uses private storage for other purposes, you should call the Component Manager's CallComponentFunctionWithStorage function. For a description of the function prototype to which your subroutine must adhere, see MyCMMValidateProfile (page 4-17) in Advanced Color Imaging Reference.

The CallComponentFunction function passes to your MyCMMValidateProfile subroutine a reference to the profile whose contents you must check and a flag whose value you must set to report the results.

To handle this request, your CMM should test the profile contents against the baseline profile elements requirements for a profile of this type as specified by the International Color Consortium. It should determine if the profile contains the minimum set of elements required for its type and set the response flag to true if the profile contains the required elements and false if it doesn't.

To obtain a copy of the International Color Consortium Profile Format Specification, version 2.x, visit the ICC Web site at the following location:

http://www.color.org/
The ICC also defines optional tags, which may be included in a profile. Your CMM might use these optional elements to optimize or improve its processing. Additionally, a profile might include private tags defined to provide your CMM with processing capability it uses. The profile developer can define these private tags, register the tag signatures with the ICC, and include the tags in a profile.

If your CMM is dependent on optional or private tags, your MyCMMValidateProfile function should check for the existence of these tags also.

Instead of itself checking the profile for the minimum profile elements requirements for the profile type, your MyCMMValidateProfile function may use the Component Manager functions to call the default Apple-supplied CMM and have it perform the minimum defaults requirements validation.

To call the Apple-supplied CMM when responding to a kCMMValidateProfile request from an application, your CMM can use the standard mechanisms applications use to call a component. For information on these mechanisms, see the chapter "Component Manager" in Inside Macintosh: More Macintosh Toolbox.

Matching the Colors of a Bitmap

When a ColorSync-supportive application or device driver calls the CWMatchBitMap function for your CMM to handle, the Component Manager calls your CMM with the what field of the component parameters data structure set to kCMMMatchBitmap if your CMM supports the request. If your CMM supports this request code, your CMM should be prepared to receive any of the bitmap types defined by the ColorSync Manager.

In response to this request code, your CMM should call its MyCMMatchBitmap subroutine. For example, to do this, your CMM may call the Component Manager's CallComponentFunctionWithStorage function, passing it the storage handle for this component instance, the component parameters data structure, and the address of your MyCMMatchBitmap subroutine. For a description of the function prototype to which your subroutine must adhere, see MyCMMatchBitmap (page 4-18) in Advanced Color Imaging Reference.

In addition to the storage handle for private storage for this component instance, the CallComponentFunctionWithStorage function passes to your MyCMMatchBitmap subroutine a pointer to the bitmap containing the source image data whose colors your function must match, a pointer to a callback function supplied by the calling program, a reference constant your subroutine must pass to the callback function when you invoke it, and a pointer to a bitmap in which your function stores the resulting color-matched image.

The callback function supplied by the calling function monitors the color-matching progress as your function matches the bitmap colors. You should call this function at regular intervals. Your MyCMMatchBitmap function should monitor the progress function for a returned value of true, which indicates that the user interrupted the color-matching process. In this case, you should terminate the color-matching process.

To handle this request, your MyCMMatchBitmap function must match the colors of the source image bitmap to the color gamut of the destination profile using the profiles specified by a previous kNCMInit, kCMMInit, or kCMMConcatInit request to your CMM for this component instance. You must store the color-matched image in the bitmap result parameter passed to your subroutine. If you are passed a NULL parameter, you must match the bitmap in place.

For a description of the prototype of the callback function supplied by the calling program, see MyCMBitmapCallBackProc (page 3-170) in Advanced Color Imaging Reference

Checking the Colors of a Bitmap

When a ColorSync-supportive application or device driver calls the CWCheckBitMap function for your CMM to handle, the Component Manager calls your CMM with the what field of the component parameters data structure set to kCMMCheckBitmap if your CMM supports the request. If your CMM supports this request code, your CMM should be prepared to receive any of the bitmap types defined by the ColorSync Manager.

In response to this request code, your CMM should call its MyCMCheckBitmap subroutine. For example, to do this, your CMM may call the Component Manager's CallComponentFunctionWithStorage function, passing it the storage handle for this component instance, the component parameters data structure, and the address of your MyCMCheckBitmap subroutine. For a description of the function prototype to which your subroutine must adhere, see MyCMCheckBitmap (page 4-22) in Advanced Color Imaging Reference.

In addition to the storage handle for private storage for this component instance, the CallComponentFunctionWithStorage function passes to your MyCMCheckBitmap subroutine a pointer to the bitmap containing the source image data whose colors your function must check, a pointer to a callback progress-reporting function supplied by the calling program, a reference constant your subroutine must pass to the callback function when you invoke it, and a pointer to a resulting bitmap whose pixels your subroutine must set to show if the corresponding source color is in or out of gamut.

The callback function supplied by the calling function monitors the color gamut-checking progress. You should call this function at regular intervals. Your MyCMCheckBitmap function should monitor the progress function for a returned value of true, which indicates that the user interrupted the color gamut-checking process. In this case, you should terminate the process.

For a description of the prototype of the callback function supplied by the calling program, see MyCMBitmapCallBackProc (page 3-170) in Advanced Color Imaging Reference

Using the content of the profiles that you stored at initialization time for this component instance, your MyCMCheckBitmap subroutine must check the colors of the source image bitmap against the color gamut of the destination profile. If a pixel is out of gamut, your function must set the corresponding pixel in the result image bitmap to 1. The ColorSync Manager returns the resulting bitmap to the calling application or driver to report the outcome of the check.

For complete details on the MyCMCheckBitmap subroutine parameters and how your MyCMCheckBitmap subroutine communicates with the callback function, see MyCMCheckBitmap (page 4-22) in Advanced Color Imaging Reference.

Matching the Colors of a Pixel Map Image

When a ColorSync-supportive application or device driver calls the CWMatchPixMap function for your CMM to handle, the Component Manager calls your CMM with the what field of the component parameters data structure set to kCMMMatchPixMap if your CMM supports the request. If your CMM supports this request code, your MyCMMatchPixMap function should be prepared to receive any of the pixel map types defined by QuickDraw.

In response to this request code, your CMM should call its MyCMMatchPixMap subroutine. For example, to do this, your CMM may call the Component Manager's CallComponentFunctionWithStorage function, passing it the storage handle for this component instance, the component parameters data structure, and the address of your MyCMMatchPixMap subroutine. For a description of the function prototype to which your subroutine must adhere, see MyCMMatchPixMap (page 4-27) in Advanced Color Imaging Reference.

In addition to the storage handle for private storage for this component instance, the CallComponentFunctionWithStorage function passes to your MyCMMatchPixMap subroutine a pointer to the pixel map containing the source image to match, a pointer to a callback progress-reporting function supplied by the calling program, and a reference constant your subroutine must pass to the callback function when you invoke it.

To handle this request, your MyCMMatchPixMap subroutine must match the colors of the source pixel map image to the color gamut of the destination profile, replacing the original pixel colors of the source image with their corresponding colors expressed in the data color space of the destination profile. The ColorSync Manager returns the resulting color-matched pixel map to the calling application or driver.

The callback function supplied by the calling function monitors the color-matching progress. You should call this function at regular intervals. Your MyCMMatchPixMap function should monitor the progress function for a returned value of true, which indicates that the user interrupted the color-matching process. In this case, you should terminate the process.

For a description of the prototype of the callback function supplied by the calling program, see MyCMBitmapCallBackProc (page 3-170) in Advanced Color Imaging Reference.

Checking the Colors of a Pixel Map Image

When a ColorSync-supportive application or device-driver calls the CWCheckPixMap function for your CMM to handle, the Component Manager calls your CMM with the what field of the component parameters data structure set to kCMMCheckPixMap if your CMM supports the request.

In response to this request code, your CMM should call its MyCMCheckPixMap subroutine. For example, to do this, your CMM may call the Component Manager's CallComponentFunctionWithStorage function, passing it the storage handle for this component instance, the component parameters data structure, and the address of your MyCMCheckPixMap subroutine. For a description of the function prototype to which your subroutine must adhere, see MyCMCheckPixMap (page 4-30) in Advanced Color Imaging Reference.

In addition to the storage handle for private storage for this component instance, the CallComponentFunctionWithStorage function passes to your MyCMCheckPixMap subroutine a pointer to the pixel map containing the source image to check, a QuickDraw bitmap in which to report the color gamut-checking results, a pointer to a callback progress-reporting function supplied by the calling program, and a reference constant your subroutine must pass to the callback function when you invoke it.

Using the content of the profiles passed to you at initialization time, your MyCMCheckPixMap subroutine must check the colors of the source pixel map image against the color gamut of the destination profile to determine if the pixel colors are within the gamut. If a pixel is out of gamut, your subroutine must set to 1 the corresponding pixel of the result bitmap. The ColorSync Manager returns the bitmap showing the color gamut-checking results to the calling application or device driver.

Initializing the Component Instance for a Session Using Concatenated Profiles

When a ColorSync-supportive application or device driver calls the CWConcatColorWorld function for your CMM to handle, the Component Manager calls your CMM with the what field of the component parameters data structure set to kCMMConcatInit if your CMM supports the request.

In response to this request code, your CMM should call its MyCMConcatInit subroutine. For example, to do this, your CMM may call the Component Manager's CallComponentFunctionWithStorage function, passing it the storage handle for this component instance, the component parameters data structure, and the address of your MyCMConcatInit subroutine. For a description of the function prototype to which your subroutine must adhere, see MyCMConcatInit (page 4-25) in Advanced Color Imaging Reference.

In addition to the storage handle for private storage for this component instance, the CallComponentFunctionWithStorage function passes to your MyCMConcatInit subroutine a pointer to a data structure of type CMConcatProfileSet containing an array of profiles to use in a subsequent color-matching or color gamut-checking session. The profiles in the array are in processing order--source through destination. The profileSet field of the data structure contains the array. If the profile array contains only one profile, that profile is a device-linked profile. For a description of the CMConcatProfileSet data structure, see "Concatenated Profile Set Structure" (page 3-49) in Advanced Color Imaging Reference.

Using the storage passed to your entry point function in the CMSession parameter, your MyCMConcatInit function should initialize any private data your CMM will need for a subsequent color session involving the set of profiles. Before your function returns control to the Component Manager, your subroutine should store any profile information it requires. In addition to the standard profile information, you should store the profile header's quality flags setting, the profile size, and the rendering intent. After you return control to the Component Manager, you cannot use the profile references again.

A color-matching or color gamut-checking session for a set of profiles entails various color transformations among devices in a sequence for which your CMM is responsible. Your CMM may use Component Manager functions to call other CMMs if necessary.

There are special guidelines your CMM must follow in using a set of concatenated profiles for subsequent color-matching or gamut-checking sessions. For more information on these guidelines, see MyCMConcatInit (page 4-25) in Advanced Color Imaging Reference.

Creating a Device-Linked Profile and Opening a Reference to It

When a ColorSync-supportive application or device driver calls the CWNewLinkProfile function for your CMM to handle, the Component Manager calls your CMM with the what field of the component parameters data structure set to kCMMNewLinkProfile if your CMM supports the request.

In response to this request code, your CMM should call its MyCMNewLinkProfile subroutine. For example, to do this, your CMM may call the Component Manager's CallComponentFunctionWithStorage function, passing it the storage handle for this component instance, the component parameters data structure, and the address of your MyCMNewLinkProfile subroutine. For a description of the function prototype to which your subroutine must adhere, see MyCMNewLinkProfile (page 4-33) in Advanced Color Imaging Reference.

In addition to the storage handle for private storage for this component instance, the CallComponentFunctionWithStorage function passes to your MyCMNewLinkProfile subroutine a pointer to a data structure of type CMConcatProfileSet containing the array of profiles that will make up the device-linked profile.

To handle this request, your subroutine must create a single device-linked profile of type DeviceLink that includes the profiles passed to you in the array pointed to by the profileSet parameter. Your CMM must create a file specification for the device-linked profile. A device-linked profile cannot be a temporary profile: that is, you cannot specify a location type of cmNoProfileBase for a device-linked profile. For information on how to specify the file location, see "Constants for Profile Location Type" (page 3-10) in Advanced Color Imaging Reference.

The profiles in the array are in the processing order--source through destination--which you must preserve. After your CMM creates the device-linked profile, it must open a reference to the profile and return the profile reference along with the location specification.

Obtaining PostScript-Related Data From a Profile

There are three very similar PostScript-related request codes that your CMM may support. Each of these codes requests that your CMM obtain or derive information required by a PostScript printer from the specified profile and pass that information to a function supplied by the calling program.

When a ColorSync-supportive application or device driver calls the high-level function corresponding to the request code and your CMM is specified to handle it, the Component Manager calls your CMM with the what field of the component parameters data structure set to the corresponding request code if your CMM supports it. Here are the three high-level functions and their corresponding request codes:

In response to each of these request codes, your CMM should call its subroutine that handles the request. For example, to do this, your CMM may call the Component Manager's CallComponentFunctionWithStorage function, passing it the storage handle for this component instance, the component parameters data structure, and the address of your subroutine handler.

For a description of the function prototypes to which your subroutine must adhere for each of these requests, see "ColorSync Manager Reference for Color Management Modules" (page 4-3) in Advanced Color Imaging Reference:

In addition to the storage handle for private storage for this component instance, the CallComponentFunctionWithStorage function passes to your subroutine a reference to the source profile containing the data you must obtain or derive, a pointer to the function supplied by the calling program, and a reference constant that you must pass to the supplied function each time your CMM calls it. For kCMMGetPS2ColorRendering, your CMM is also passed a reference to the destination profile.

To handle each of these requests, your subroutine must allocate a data buffer in which to pass the particular PostScript-related data to the function supplied by the calling application or driver. Your subroutine must call the supplied function repeatedly until you have passed all the data to it. For a description of the prototype of the application or driver-supplied function, see MyColorSyncDataTransfer (page 3-167) in Advanced Color Imaging Reference.

For a description of how each of your subroutines must interact with the calling program's supplied function, see the descriptions of the prototypes for the subroutines in "Application-Defined Functions for the ColorSync Manager" (page 3-166) in Advanced Color Imaging Reference.

Obtaining the Size of the Color Rendering Dictionary for PostScript Printers

When a ColorSync-supportive application or device driver calls the CMGetPS2ColorRenderingVMSize function for your CMM to handle, the Component Manager calls your CMM with the what field of the component parameters data structure set to kCMMGetPS2ColorRenderingVMSize if your CMM supports the request.

In response to this request code, your CMM should call its MyCMMGetPS2ColorRenderingVMSize subroutine. For example, to do this, your CMM may call the Component Manager's CallComponentFunctionWithStorage function, passing it the storage handle for this component instance, the component parameters data structure, and the address of your MyCMMGetPS2ColorRenderingVMSize subroutine. For a description of the function prototype to which your subroutine must adhere, see "ColorSync Manager Reference for Color Management Modules" (page 4-3) in Advanced Color Imaging Reference.

In addition to the storage handle for global data for this component instance, the CallComponentFunctionWithStorage function passes to your MyCMMGetPS2ColorRenderingVMSize subroutine a reference to the source profile identifying the rendering intent and a reference to the destination profile containing the color rendering dictionary (CRD) for the specified rendering intent.

To handle this request, your CMM must obtain or assess and return the maximum VM size for the CRD of the specified rendering intent.

If the destination profile contains the Apple-defined private tag 'psvm', described in the next paragraph, then your CMM may read the tag and return the CRD VM size data supplied by this tag for the specified rendering intent. If the destination profile does not contain this tag, then you must assess the VM size of the CRD.

The CMPS2CRDVMSizeType data type defines the Apple-defined 'psvm' optional tag that a printer profile may contain to identify the maximum VM size of a CRD for different rendering intents.

This tag's element data includes an array containing one entry for each rendering intent and its virtual memory size. For a description of the data structures that define the tag's element data, see "PostScript CRD Virtual Memory Size Tag Structure" (page 3-67) in Advanced Color Imaging Reference.

Flattening a Profile for Embedding in a Graphics File

When a ColorSync-supportive application or device driver calls the CMFlattenProfile function for your CMM to handle, the Component Manager calls your CMM with the what field of the component parameters data structure set to kCMMFlattenProfile if your CMM supports the request.

In response to this request code, your CMM should call its MyCMMFlattenProfile subroutine. For example, to do this, your CMM may call the Component Manager's CallComponentFunctionWithStorage function, passing it the storage handle for this component instance, the component parameters data structure, and the address of your MyCMMFlattenProfile subroutine. For a description of the function prototype to which your subroutine must adhere, see MyCMMFlattenProfile (page 4-45) in Advanced Color Imaging Reference.

In addition to the storage handle for private storage for this component instance, the CallComponentFunctionWithStorage function passes to your MyCMMFlattenProfile subroutine a reference to the profile to be flattened, a pointer to a function supplied by the calling program, and a reference constant your subroutine must pass to the calling program's function when you invoke it.

To handle this request, your subroutine must extract the profile data from the profile, allocate a buffer in which to pass the profile data to the supplied function, and pass the profile data to the function, keeping track of the amount of data remaining to pass.

For a description of the prototype of the function supplied by the calling program, see MyColorSyncDataTransfer (page 3-167) in Advanced Color Imaging Reference. In the same book, see the MyCMMFlattenProfile function (page 4-47) for information on how your subroutine communicates with the function supplied by the calling program.

Unflattening a Profile

When a ColorSync-supportive application or device driver calls the CMUnflattenProfile function, the Component Manager calls your CMM with the what field of the component parameters data structure set to kCMMUnflattenProfile, if your CMM supports that request code.

In response to the kCMMUnflattenProfile request code, your CMM should call its MyCMMUnflattenProfile function. To do this, your CMM can call the Component Manager's CallComponentFunctionWithStorage function, passing it the storage handle for this component instance, the component parameters data structure, and the address of your MyCMMUnflattenProfile function. For more information, see MyCMMFlattenProfile (page 4-47) in Advanced Color Imaging Reference.

In addition to the storage handle for private storage for this component instance, the CallComponentFunctionWithStorage function passes to your MyCMMUnflattenProfile function a pointer to a function supplied by the calling program and a reference constant. Your function passes the reference constant to the calling program's function when you invoke it. The calling program's function obtains the profile data and returns it to your subroutine. For more information on the data transfer function, see MyColorSyncDataTransfer (page 3-167) in Advanced Color Imaging Reference.

To handle this request, your subroutine must create a file in which to store the profile data. You should create the file in the temporary items folder. Your MyCMMUnflattenProfile subroutine must call the supplied MyColorSyncDataTransfer function repeatedly to obtain the profile data. Before calling the MyColorSyncDataTransfer function, your MyCMMUnflattenProfile function must allocate a buffer to hold the returned profile data.

Your MyCMMUnflattenProfile function must identify the profile size and maintain a counter to track the amount of data transferred and the amount of data remaining. This information allows you to determine when to call the MyColorSyncDataTransfer function for the final time.

Supplying Named Color Space Information

When a ColorSync-supportive application or device driver calls the CMGetNamedColorInfo function for your CMM to handle, the Component Manager calls your CMM with the what field of the component parameters data structure set to kCMMGetNamedColorInfo if your CMM supports the request.

In response to this request code, your CMM should call its MyCMMGetNamedColorInfo subroutine. To do this, your CMM might call the Component Manager's CallComponentFunctionWithStorage function, passing it the storage handle for this component instance, the component parameters data structure, and the address of your MyCMMGetNamedColorInfo subroutine.

The MyCMMGetNamedColorInfo function returns information about a named color space from its profile reference. For a description of the function prototype to which your subroutine must adhere, see MyCMMGetNamedColorInfo (page 4-50) in Advanced Color Imaging Reference.

A named color profile has a value of 'nmcl' in the Profile/Device class field of its header. If the source profile passed to your MyCMMGetNamedColorInfo subroutine is a named color profile, you can extract the necessary information to return in the parameters of the MyCMMGetNamedColorInfo routine.

Your CMM can obtain named color information as well as profile header information by reading the namedColor2Tag tag (signature 'ncl2'). This tag's element data includes a count of named colors, the number of device channels, and a prefix and suffix for each named color name. The data also includes the named color names themselves, along with profile coordinate space (PCS) and device color information for each named color. For information on the format of the namedColor2Tag tag, see the International Color Consortium Profile Format Specification.

Your CMM responds similarly for other named color requests:


Previous Book Contents Book Index Next

© Apple Computer, Inc.
13 NOV 1996