![]() |
PATH![]() |
![]() ![]() |
Using lists and dialog boxes, you can provide choices that influence the color-matching process. For example, you can offer any of the following:
CMIterateColorSyncFolder
.The ColorSync Manager supports the four standard rendering intents defined by the ICC--perceptual, relative colorimetric, saturated, and absolute colorimetric. Every profile supports these four intents, which are commonly used to match the colors of a source image to the color gamut of the destination device in the most optimum way for the type of image. These intents are described in detail in Rendering Intents .
If the source profile is embedded with the image, the source profile specifies the rendering intent to be used. However, if the source profile is not available and the system profile must be used as the source profile, you should allow the user to select the rendering intent to be used.
Note
Starting with ColorSync 2.5, your application can call
CMGetDefaultProfileBySpace
to obtain an appropriate source profile for matching, rather than using the default system profile. However, you may still wish to allow the user to specify a rendering intent.
To allow users to choose the rendering intent most appropriate for color matching a graphical image, you can provide a pop-up menu or a dialog box identifying the rendering intent options available. By providing a description of the available rendering intents, you can help a user select the rendering intent that best maintains important aspects of the image.
Color professionals and technically-sophisticated users are likely to be familiar with the ICC terms for rendering intent and the gamut-matching strategies they represent. If your application is aimed at novice users, however, you may prefer to use a simplified terminology based on the typical image content associated with a rendering intent, as described in Table 2-1 . For example, you might note the following:
After the user selects the intent to be used, you must modify the renderingIntent field of the system profile's header to reflect the choice. To put the rendering intent chosen by the user in the profile header, follow these steps:
Identifying the Current System Profile describes how to do this.
You call the function
CMGetProfileHeader
, passing the profile reference, to obtain the profile's header. The function returns the profile header using a union of type
CMAppleProfileHeader
. You can use this function for both ColorSync 1.0 profiles and version 2.x profiles.
For a version 2.x profile, you use the data structure
CM2Header
. For a version 1.0 profile, you use the
CMHeader
data structure. For more information on profile headers, see
Profile Header
.
To assign a rendering intent to the system profile header's renderingIntent field, use the constants defined by the following enumeration:
enum {
cmPerceptual = 0,
cmRelativeColorimetric = 1,
cmSaturation = 2,
cmAbsoluteColorimetric = 3
};
These constants are described in Rendering Intent Values for Version 2.x Profiles .
After you assign the rendering intent, you must replace the header by calling the function
CMSetProfileHeader
. You can use this function to set a header for a version 1.0 or a version 2.x ColorSync profile. You pass the header using the union
CMAppleProfileHeader
.
You can now use the system profile to create a color world for the color-matching process. For information on how to create a color world, see Creating a Color World to Use With the General Purpose Functions .
IMPORTANT
When you call CMSetProfileHeader , the profile header is modified temporarily. The rendering intent change is discarded when you call the function
CMCloseProfile
. To preserve the change, you must call the functionCMUpdateProfile
.
Listing 4-1 includes code that uses the cmSaturation constant to set the rendering intent for a profile.
The ColorSync Manager provides a feature, called the quality flags settings, that controls the quality of the color-matching process in relation to the time required to perform the match. This feature, which is not a standard feature defined by the ICC profile format specification, works by letting you manipulate certain bits of the profile header's flags field. There are three quality flag settings: normal, draft, and best. For a description of the profile header's flags field, see Quality Flag Values for Version 2.x Profiles .
Normal mode is the default setting. Color matching using draft mode takes the least time and produces the least exact results. Color matching using best mode takes the longest time but produces the finest results.
Users sometimes want to produce review drafts of images quickly before expending the time to produce the best-quality final copy. Your interface can allow them this flexibility by offering a dialog box that provides the three options.
After the user selects the color-matching quality, you can use the selection to set the appropriate bits of the source profile's flags field. To set the color-matching quality chosen by the user, follow these steps:
Obtaining Profile References describes how to do this.
You call the function
CMGetProfileHeader
, passing the profile reference, to obtain the profile's header. The function returns the profile header using a union of type
CMAppleProfileHeader
.
The flags field of the source profile header is a long word coded in big-endian notation. Big-endian notation is a means of encoding data in which the first byte within 16-bit and 32-bit quantities is the most significant. The ICC profile consortium reserves the first 2 bits of the low word for its own use. The least significant 2 bits of the high word constitute the quality flag settings used to specify the quality for the color matching. The bit definitions for the flags field are shown in Figure 5-1 .
To evaluate and interpret the current setting of the quality flags bits, you can take these steps, in order:
enum
{
cmNormalMode = 0,
cmDraftMode = 1,
cmBestMode = 2
};
These constants are described in Flag Mask Definitions for Version 2.x Profiles .
To set the quality flag, you can use the constants defined by the enumeration provided by the ColorSync Manager and shown in step 3.
After you set the
flags
field based on the user's selection, you must replace the header by calling the function
CMSetProfileHeader
. You pass the header using the union
CMAppleProfileHeader
.
You can now use the source profile to create a color world for the color-matching process. For information on how to create a color world, see Creating a Color World to Use With the General Purpose Functions .
IMPORTANT
When you call CMSetProfileHeader , the profile header is modified temporarily. Changes to the flags field are discarded when you call the function
CMCloseProfile
. To preserve the change, you must call the functionCMUpdateProfile
.
Listing 4-1 shows how to set the system profile's quality flag to best mode for producing the highest-quality color-matched image. It also sets the rendering intent to saturation before setting up a color world based on the modified system profile and the printer profile.
The
MySetHeader
function shown in
Listing 4-1
initializes the
CMProfileRef
data structures it will use for the system profile and the printer profile before it calls the following two functions--the ColorSync Manager function
CMGetSystemProfile
to obtain a reference to the system profile and its own function
MyGetPrinterProfile
to obtain a reference to the profile for its printer.
The
source profile (in this case, the system profile), not the printer profile, determines the quality mode and the rendering intent to be used in color matching the image to the destination printer. Now that it has a reference to the system profile, the code can obtain the profile's header. It does this by calling the function
CMGetProfileHeader
, specifying the reference it obtained to the system profile.
Using the kSpeedAndQualityFlagMask constant it defined earlier, the code clears the quality mode bits of the system profile's flags field. Then it sets the quality mode bits to cmBestMode to specify best mode quality for color matching. The least significant 2 bits of the flags field's high word constitute the quality flag. After setting the quality flag, the code sets the system profile header's renderingIntent field to cmSaturation .
Now that the code has modified the system profile's header to indicate the user's selections, it calls the
CMSetProfileHeader
function to write the profile header to the profile. Because the driver code intends to use the values the user selected only to color match the image to be printed, it does not permanently preserve the header field changes by calling
CMUpdateProfile
to write the changes to the profile. When the code closes its reference to the system profile after having built the color world, the system profile's header modifications are discarded.
The code calls the NCWNewColorWorld function, passing the temporarily modified system profile, to create the color world. It then closes its references to both the system and printer profiles and color matches the image before sending it to the printer. When it no longer needs the color world, the code calls the CWDisposeColorWorld function to close the color world and release the memory it uses. Finally, the code tests to ensure that the profile references are closed.
Listing 4-1 Modifying a profile header's quality flag and setting the rendering intent
void MySetHeader(void);
CMError MyGetPrinterProfile(CMProfileRef *printerProf);
/* for CM2Header.profileVersion */
#define kMajorVersionMask 0XFF000000
/* two bits used to specify speed & quality */
/* must be shifted left 16 bits in flag's long word */
#define kSpeedAndQualityFlagMask 0X00000003
void MySetHeader(void)
{
CMError cmErr;
CMProfileRef sysProf;
CMAppleProfileHeader sysHeader;
CMProfileRef printerProf;
CMWorldRef cw;
sysProf = NULL;
printerProf= NULL;
cw = NULL;
cmErr = CMGetSystemProfile(&sysProf);
if (cmErr == noErr)
{
cmErr = MyGetPrinterProfile(&printerProf);
}
if (cmErr == noErr)
{
cmErr = CMGetProfileHeader(sysProf, &sysHeader);
}
if (cmErr == noErr)
{
/* clear the current quality and then set it to best */
sysHeader.cm2.flags &= ~(kSpeedAndQualityFlagMask << 16);
sysHeader.cm2.flags |= (cmBestMode << 16);
/* set rendering intent to saturation */
sysHeader.cm2.renderingIntent = cmSaturation;
cmErr = CMSetProfileHeader(sysProf, &sysHeader);
}
if (cmErr == noErr)
{
cmErr = NCWNewColorWorld(&cw, sysProf, printerProf);
}
/* close any open profiles */
if (sysProf != NULL)
{
(void) CMCloseProfile(sysProf);
}
if (printerProf != NULL)
{
(void) CMCloseProfile(printerProf);
}
.
.
.
/* device-driver functions that use the color world to color match
the image and send it to the printer belong here */
.
.
.
if (cw != NULL)
{
CWDisposeColorWorld(cw);
}
}