Important: The information in this document is obsolete and should not be used for new development.
Handling Request Codes
When your component receives a request, it should examine thewhat
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 orCallComponentFunction
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'sCallComponentFunctionWithStorage
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" (page 5-21) describes how to handle a
kComponentOpenSelect
request.- "Releasing Private Storage and Closing the Component Instance" (page 5-21) describes how to handle a
kComponentCloseSelect
request.- "Determining Whether Your CMM Supports a Request" (page 5-21) describes how to handle a
kComponentCanDoSelect
request.- "Providing Your CMM Version Number" (page 5-22) describes how to handle a
kComponentVersionSelect
request.
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 akComponentOpenSelect
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 thewhat
field of the component parameters data structure tokComponentCloseSelect
. 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 valuekComponentCanDoSelect
. 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 thewhat
field of the component parameters data structure to the valuekComponentVersionSelect
. 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" (page 5-22) describes how to handle a
kNCMMInit
request.- "Matching a List of Colors to the Destination Profile's Color Space" (page 5-23) describes how to handle a
kCMMMatchColors
request.- "Checking a List of Colors" (page 5-24) describes how to handle a
kCMMCheckColors
request.
Initializing the Current Component Instance for a Session Involving Two Profiles
The Component Manager calls your CMM with an initialization request, setting thewhat
field of the component parameters data structure tokNCMMInit
. 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 theCWMatchColors
function for your CMM to handle, the Component Manager calls your CMM with a color-matching session request, setting thewhat
field of the component parameters data structure tokCMMMatchColors
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 theCWMatchPixMap
function.Before it calls your CMM with this request, the Component Manager calls your CMM with one of the initialization requests--
kCMMInit
,kNCMMInit
, orkCMMConcatInit
--passing to your CMM in theparams
field of the component parameters data structure the profiles for the color-matching session.In response to the
kCMMMatchColors
request, your CMM should call itsMyCMMatchColors
subroutine by calling the Component Manager'sCallComponentFunctionWithStorage
function and passing it a handle to the storage for this component instance, the component parameters data structure, and the address of yourMyCMMatchColors
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 theCWCheckColors
function for your CMM to handle, the Component Manager calls your CMM with a color gamut-checking session request, setting thewhat
field of the component parameters data structure tokCMMCheckColors
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
, orkCMMConcatInit
--passing to your CMM in theparams
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 itsMyCMCheckColors
subroutine. For example, if you use the Component Manager'sCallComponentFunctionWithStorage
function, you pass it a handle to the storage for this component instance, the component parameters data structure, and the address of yourMyCMCheckColors
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 yourMyCMCheckColors
subroutine an array of typeCMColor
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" (page 5-26) describes how to handle a
kCMMValidateProfile
request.- "Matching the Colors of a Bitmap" (page 5-27) describes how to handle a
kCMMMatchBitmap
request.- "Checking the Colors of a Bitmap" (page 5-28) describes how to handle a
kCMMCheckBitmap
request.- "Matching the Colors of a Pixel Map Image" (page 5-29) describes how to handle the
kCMMMatchPixMap
request.- "Checking the Colors of a Pixel Map Image" (page 5-30) describes how to handle the
kCMMCheckPixMap
request.- "Initializing the Component Instance for a Session Using Concatenated Profiles" (page 5-31) describes how to handle a
kCMMConcatInit
request.- "Creating a Device-Linked Profile and Opening a Reference to It" (page 5-32) describes how to handle a
kCMMNewLinkProfile
request.- "Obtaining PostScript-Related Data From a Profile" (page 5-33) describes how to handle the
kCMMGetPS2ColorSpace
,kCMMGetPS2ColorRenderingIntent
, andkCMMGetPS2ColorRendering
requests.- "Obtaining the Size of the Color Rendering Dictionary for PostScript Printers" (page 5-34) describes how to handle a
kCMMGetPS2ColorRenderingVMSize
request.- "Flattening a Profile for Embedding in a Graphics File" (page 5-35) describes how to handle a
kCMMFlattenProfile
request.- "Unflattening a Profile" (page 5-36) describes how to handle a
kCMMUnflattenProfile
request.- "Supplying Named Color Space Information" (page 5-37) describes how to handle the kCMMGetNamedColorInfo, kCMMGetNamedColorValue, kCMMGetIndNamedColorValue, kCMMGetNamedColorIndex, and kCMMGetNamedColorName requests.
Validating That a Profile Meets the Base Content Requirements
When a ColorSync-supportive application or device-driver calls theCMValidateProfile
function for your CMM to handle, the Component Manager calls your CMM with thewhat
field of the component parameters data structure set tokCMMValidateProfile
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'sCallComponentFunction
function, passing it the component parameters data structure and the address of yourMyCMMValidateProfile
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'sCallComponentFunctionWithStorage
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 yourMyCMMValidateProfile
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 andfalse
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 theCWMatchBitMap
function for your CMM to handle, the Component Manager calls your CMM with thewhat
field of the component parameters data structure set tokCMMMatchBitmap
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'sCallComponentFunctionWithStorage
function, passing it the storage handle for this component instance, the component parameters data structure, and the address of yourMyCMMatchBitmap
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 yourMyCMMatchBitmap
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 oftrue
, 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 previouskNCMInit
,kCMMInit
, orkCMMConcatInit
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 aNULL
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 theCWCheckBitMap
function for your CMM to handle, the Component Manager calls your CMM with thewhat
field of the component parameters data structure set tokCMMCheckBitmap
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'sCallComponentFunctionWithStorage
function, passing it the storage handle for this component instance, the component parameters data structure, and the address of yourMyCMCheckBitmap
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 yourMyCMCheckBitmap
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 oftrue
, 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 yourMyCMCheckBitmap
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 theCWMatchPixMap
function for your CMM to handle, the Component Manager calls your CMM with thewhat
field of the component parameters data structure set tokCMMMatchPixMap
if your CMM supports the request. If your CMM supports this request code, yourMyCMMatchPixMap
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'sCallComponentFunctionWithStorage
function, passing it the storage handle for this component instance, the component parameters data structure, and the address of yourMyCMMatchPixMap
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 yourMyCMMatchPixMap
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 oftrue
, 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 theCWCheckPixMap
function for your CMM to handle, the Component Manager calls your CMM with thewhat
field of the component parameters data structure set tokCMMCheckPixMap
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'sCallComponentFunctionWithStorage
function, passing it the storage handle for this component instance, the component parameters data structure, and the address of yourMyCMCheckPixMap
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 yourMyCMCheckPixMap
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 theCWConcatColorWorld
function for your CMM to handle, the Component Manager calls your CMM with thewhat
field of the component parameters data structure set tokCMMConcatInit
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'sCallComponentFunctionWithStorage
function, passing it the storage handle for this component instance, the component parameters data structure, and the address of yourMyCMConcatInit
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 yourMyCMConcatInit
subroutine a pointer to a data structure of typeCMConcatProfileSet
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. TheprofileSet
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 theCMConcatProfileSet
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, yourMyCMConcatInit
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 theCWNewLinkProfile
function for your CMM to handle, the Component Manager calls your CMM with thewhat
field of the component parameters data structure set tokCMMNewLinkProfile
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'sCallComponentFunctionWithStorage
function, passing it the storage handle for this component instance, the component parameters data structure, and the address of yourMyCMNewLinkProfile
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 yourMyCMNewLinkProfile
subroutine a pointer to a data structure of typeCMConcatProfileSet
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 theprofileSet
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 ofcmNoProfileBase
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
- When the application or device driver calls the
CMGetPS2ColorSpace
function, the Component Manager calls your CMM with akCMMGetPS2ColorSpace
request code. To respond to this request, your CMM must obtain the color space data from a source profile and pass the data to a low-level data-transfer function supplied by the calling application or device driver.- When the application or device driver calls the
CMGetPS2ColorRenderingIntent
function, the Component Manager calls your CMM with akCMMGetPS2ColorRenderingIntent
request code. To respond to this request, your CMM must obtain the color rendering intent from the source profile and pass the data to a low-level data-transfer function supplied by the calling application or device driver.- When the application or device driver calls the
CMGetPS2ColorRendering
function, the Component Manager calls your CMM with akCMMGetPS2ColorRendering
request code. To respond to this request, your CMM must obtain the rendering intent from the source profile's header. Then your CMM must obtain or derive the color rendering dictionary for that rendering intent from the destination profile and pass the CRD data to a low-level data-transfer function supplied by the calling application or device driver.
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
- For
kCMMGetPS2ColorSpace
, see MyCMMGetPS2ColorSpace (page 4-34).- For
kCMMGetPS2ColorRenderingIntent
, see MyCMMGetPS2ColorRenderingIntent (page 4-37).- For
kCMMGetPS2ColorRendering
, see MyCMMGetPS2ColorRendering (page 4-39).
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. ForkCMMGetPS2ColorRendering
, 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 theCMGetPS2ColorRenderingVMSize
function for your CMM to handle, the Component Manager calls your CMM with thewhat
field of the component parameters data structure set tokCMMGetPS2ColorRenderingVMSize
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'sCallComponentFunctionWithStorage
function, passing it the storage handle for this component instance, the component parameters data structure, and the address of yourMyCMMGetPS2ColorRenderingVMSize
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 yourMyCMMGetPS2ColorRenderingVMSize
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 theCMFlattenProfile
function for your CMM to handle, the Component Manager calls your CMM with thewhat
field of the component parameters data structure set tokCMMFlattenProfile
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'sCallComponentFunctionWithStorage
function, passing it the storage handle for this component instance, the component parameters data structure, and the address of yourMyCMMFlattenProfile
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 yourMyCMMFlattenProfile
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 theMyCMMFlattenProfile
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 theCMUnflattenProfile
function, the Component Manager calls your CMM with thewhat
field of the component parameters data structure set tokCMMUnflattenProfile
, if your CMM supports that request code.In response to the
kCMMUnflattenProfile
request code, your CMM should call itsMyCMMUnflattenProfile
function. To do this, your CMM can call the Component Manager'sCallComponentFunctionWithStorage
function, passing it the storage handle for this component instance, the component parameters data structure, and the address of yourMyCMMUnflattenProfile
function. For more information, seeMyCMMFlattenProfile
(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 yourMyCMMUnflattenProfile
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, seeMyColorSyncDataTransfer
(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 suppliedMyColorSyncDataTransfer
function repeatedly to obtain the profile data. Before calling theMyColorSyncDataTransfer
function, yourMyCMMUnflattenProfile
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 theMyColorSyncDataTransfer
function for the final time.Supplying Named Color Space Information
When a ColorSync-supportive application or device driver calls theCMGetNamedColorInfo
function for your CMM to handle, the Component Manager calls your CMM with thewhat
field of the component parameters data structure set tokCMMGetNamedColorInfo 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 thenamedColor2Tag
tag, see the International Color Consortium Profile Format Specification.Your CMM responds similarly for other named color requests:
- The
CMGetNamedColorValue
routine generates a kCMMGetNamedColorValue request, which you respond to in your MyCMMGetNamedColorValue routine. The MyCMMGetNamedColorValue routine returns device and PCS color values from a named color space profile for a specific color name.- The
CMGetIndNamedColorValue
routine generates a kCMMGetIndNamedColorValue request, which you respond to in your MyCMMGetIndNamedColorValue routine. The MyCMMGetIndNamedColorValue routine returns device and PCS color values from a named color space profile for a specific named color index.- The
CMGetNamedColorIndex
routine generates a kCMMGetNamedColorIndex request, which you respond to in your MyCMMGetNamedColorIndex routine. The MyCMMGetNamedColorIndex routine returns a named color index from a named color space profile for a specific color name.- The
CMGetNamedColorName
routine generates a kCMMGetNamedColorName request, which you respond to in your MyCMMGetNamedColorName routine. The MyCMMGetNamedColorName routine returns a named color name from a named color space profile for a specific named color index.