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 6 - Developing ColorSync-Supportive Device Drivers / Developing Your ColorSync Supportive Device Driver


Interacting With the User

Using selection menus, lists, and dialog boxes, you can provide your user with choices that influence the color-matching process. For example, you can offer the user

Searching for Profiles and Displaying Their Names to the User

The ColorSync Manager search functions let you identify types of profiles or profiles having certain characteristics. You can use these functions to search through available version 2.x profiles in the ColorSync\x89 Profiles folder and hone in on profiles that meet criteria you specify. You can set up a search to look for certain classes of device profiles for a specific manufacturer's device, such as printer profiles designed for the printer model your device driver supports. You can even refine the search to look for a specific printer profile for the printer's current state, for example, a profile especially designed for your printer's use of foils and a certain type of ink.

IMPORTANT
The ColorSync Manager 2.x search functions can identify only version 2.x profiles in the ColorSync\x89 Profiles folder. If the folder contains ColorSync 1.0 profiles, they are not investigated during the search.
Searching for profiles entails the following four steps:

  1. Defining the search criteria

    You can define the search criteria broadly based on the profile's device type only or refine the search based on other specific characteristics of a profile carried in its header or elements. "Defining Search Criteria" (page 6-13) describes this step.

  2. Running the search

    After you set up the search criteria, you must call the CMNewProfileSearch function to start the search and find all profiles that match your requirements. "Running the Search" (page 6-13) explains how to do this.

  3. Gaining access to the search results

    Using the search results, you can now obtain references to each of the profiles that match your criteria by calling the CMSearchGetIndProfile function. "Obtaining References to the Qualifying Profiles" (page 6-14) describes how to do this.

  4. Getting the names of qualifying profiles to display to your user

    Once you have references to each of the qualifying profiles, you can obtain the names of the profiles to present to your user. "Getting the Names of Qualifying Profiles" (page 6-14) explains this step.

Defining Search Criteria

Before you begin a profile search, you must describe aspects of the profiles you are looking for. To help you, the ColorSync Manager provides a data structure of type CMSearchRecord that you use to identify the search criteria. Your device driver can declare an instance of the search record and assign values to its fields to characterize the profiles you want to find. The search record data structure of type CMSearchRecord (page 3-51) is described in Advanced Color Imaging Reference.

You define the parameters of a search by first setting the fields of the search record whose values you want matched and then setting the searchMask field to indicate the operative fields. If you don't set the field mask, your search criteria are ignored.

To create a refined search that seeks all profiles belonging to a certain class that also meet other criteria, you must set multiple fields of the search record. For example, suppose you want to find all printer profiles for your manufacturer's printer and you also want to filter out profiles unless they are for a certain device model. To do this, you need to set the search record's deviceManufacturer field to the signature that identifies the manufacturer. This must be the same signature specified in the profile header's deviceManufacturer field when the manufacturer or vendor created the profile. You must also set the deviceModel field to the value that identifies the printer model whose profiles you want to identify. After you set these fields, you must set the searchMask to identify the operative fields. To do this, you can use the constants cmMatchProfileClass, cmMatchManufacturer, and cmMatchModel. After you define a search record that establishes your criteria, you must initiate the search.

For a description of the enumeration that defines constants for profile class signatures, see "Profile Classes" (page 3-13) in Advanced Color Imaging Reference. For a description of the enumeration that defines constants for the search mask, see "Profile Search Record" (page 3-51) in the same book.

Running the Search

Passing to this function the search record whose fields you set in the previous step, you call the CMNewProfileSearch function to run the search on all profiles in the ColorSync\x89 Profiles folder. The CMNewProfileSearch function searches the ColorSync\x89 Profiles folder for version 2.x profiles that meet your criteria. In response, the function returns to your driver a reference to a search results private data structure containing a list of all profiles that match your description.

The function also returns a one-based count telling you how many profiles are in the list. You use this count, along with the search result reference, to navigate the list in order to identify a specific profile and obtain information about it. Your device driver cannot gain direct access to the contents of the search result list.

Obtaining References to the Qualifying Profiles

Using the results of the search, you can now obtain references to each of the qualifying profiles. The one-based count returned by the CMNewProfileSearch function identifies the number of profiles in the list. You can use this count to set the bounds of a loop you can define to obtain a profile reference for each qualifying profile. Identifying the index position of a profile in the search result list, you can call the CMSearchGetIndProfile function repeatedly, incrementing through the list until you obtain references to all of its profiles. The sample code listing in "Searching for Profiles in the ColorSync(TM) Profiles Folder" (page 4-47) shows one approach you can take.

The ColorSync Manager preserves the results of a search you perform until you discard the private data structure containing the search result list by calling CMDisposeProfileSearch. If you know that the user has updated the ColorSync\x89 Profiles folder since you searched it, you can call the CMUpdateProfileSearch function to update the search result without providing the search specification again.

Getting the Names of Qualifying Profiles

After you obtain references to the profiles in the search result list, you must get the names of the profiles so that you can display them in the selection list your user interface provides. You can get the profile names either within your profile reference loop or outside it.

When you are finished with the profiles, you must call the CMCloseProfile function for each one to dispose of the references and release the memory they use.

Setting the Rendering Intent Selected by the User

The ColorSync Manager offers four rendering intents--perceptual, relative colorimetric, saturated, and absolute colorimetric. Every profile supports these. The first three are commonly used to render images matching the colors of a source image to the color gamut of the destination device on which the resulting image is to be rendered in the most optimum way for the type of image.

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 provided and the system profile is used as the source profile, you should allow the user to select the rendering intent to be used.

To allow users to choose the rendering intent most appropriate for color matching their graphical image, you can provide a menu or a dialog box identifying the rendering intent options available. To help your user in choosing the appropriate intent, you can provide meaningful information that identifies the best use of each intent. Users can then select the rendering intent that best maintains important aspects of the image.

Instead of simply listing the available rendering intents by the technical names used to refer to them, you can indicate how they are best used, basing your presentation on this background information:

  • For perceptual matching, all the colors of a given gamut may be scaled to fit within another gamut. This intent is the best choice for realistic images, such as scanned photographs.
  • For saturation matching, the relative saturation of colors is maintained from gamut to gamut. Rendering the image using this intent gives the strongest colors and is the best choice for bar graphs and pie charts, in which the actual color displayed is less important than its vividness.
  • For relative colorimetric matching, the colors that fall within the gamuts of both devices are left unchanged. Some colors in both images will be exactly the same, a useful outcome when colors must match quantitatively. This intent is best suited for logos.

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:

  1. Obtain a profile reference to the system profile.

    "Identifying the Current Default System Profile" (page 4-20) describes how to do this.

  2. Get the profile header of the system profile.

    Passing the profile reference to the function, you can use the CMGetProfileHeader function 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 CM2Header data structure. For a version 1.0 profile, you use the CMHeader data structure. For a description of profile headers see "Apple Profile Header" (page 3-42) in Advanced Color Imaging Reference. In the same book, see the CMGetProfileHeader function (page 3-88).

  3. Assign the new rendering intent to the header field.

    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
    };
  4. Set the modified profile header of the system profile.

    After you assign the rendering intent, you must replace the header by calling the CMSetProfileHeader function. You can use the CMSetProfileHeader function to set a header for a version 1.0 or a version 2.x ColorSync profile. You pass the header you supply in the CMAppleProfileHeader union, which is described in "Apple Profile Header" (page 3-42) in Advanced Color Imaging Reference.

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 for Color Matching and Checking Using the Low-Level Functions" (page 4-25).

The profile header is temporarily modified and the rendering intent change is discarded when you call the CMCloseProfile function. To preserve the change, you must call the CMUpdateProfile function.

Listing 6-1 (page 6-19) shows how to set the rendering intent for a profile.

Setting the Color-Matching Quality Selected by the User

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 "ColorSync Manager Reference for Applications and Device Drivers" in Advanced Color Imaging Reference.

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 selection menu or 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:

  1. Obtain a profile reference to the source profile.

    "Obtaining Profile References" (page 4-16) describes how to do this.

  2. Get the profile header of the source profile.

    Passing the profile reference to the function, you can use the CMGetProfileHeader function to obtain the profile's header. The function returns the profile header using a union of type CMAppleProfileHeader.

  3. Optionally, test the current setting of the source profile header's flags.

    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 the 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. To evaluate and interpret the current setting of the quality flags bits, you can take these steps, in order:

    • Right-shift the 16 bits.
    • Mask off the high 14 bits.
    • Compare the result with values defined by the following enumeration:

      enum {
       cmNormalMode= 0, cmDraftMode= 1,cmBestMode= 2
      };
  1. Set the quality flags bits to the value your user selected.

    To set the quality flag, you can use the constants defined by the enumeration provided by the ColorSync Manager and shown in step 3.

  2. Set the source profile with the modified profile header.

    After you set the flags field based on the user's selection, you must replace the header by calling the CMSetProfileHeader function. You use the CMSetProfileHeader function to set the header. You pass the header you supply in the CMAppleProfileHeader union, which is described in "ColorSync Manager Reference for Applications and Device Drivers" in Advanced Color Imaging Reference.

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 for Color Matching and Checking Using the Low-Level Functions."

The profile header is temporarily modified and the flags field change is discarded when you call the CMCloseProfile function. To preserve the change, you must call the CMUpdateProfile function.

Listing 6-1 shows how to set the system profile's quality flag to best mode for producing the highest-quality color-matched image, and shows how to set 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 6-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 CMGetSystemProfile function to obtain a reference to the system profile and its own MyGetPrinterProfile function 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 CMGetProfileHeader function, 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 in the user's document to be printed, it does not permanently preserve the header field changes. When the code closes its reference to the system profile after having built the color world, the system profile's header modifications are discarded. To write the changes to the profile to preserve them, the code must include a call to the CMUpdateProfile function.

Using the temporarily modified system profile, the code calls the NCWNewColorWorld function to create the color world, 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 6-1 Modifying the system profile header's quality flag and setting the header

#include <Types.h>
#include <CMApplication.h>
#include <stdio.h>
#include <assert.h>
#define kMajorVersionMask0XFF000000
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)
   {
      sysHeader.cm2.flags&= ~(kSpeedAndQualityFlagMask << 16);
      sysHeader.cm2.flags|= (cmBestMode << 16);
      sysHeader.cm2.renderingIntent = cmSaturation;
      cmErr = CMSetProfileHeader(sysProf, &sysHeader);
   }
   if (cmErr == noErr)
   {
      cmErr = NCWNewColorWorld(&cw, sysProf, printerProf);

      (void) MyCMCloseProfile(sysProf);
      sysProf = NULL;
      (void) CMCloseProfile(printerProf);
      printerProf = NULL;
   } 
               .
               .
               .
      /* 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);
   }
      /* close open profiles in case of error */
   if (sysProf != NULL)
   {
    (void) CMCloseProfile(sysProf);
   }
   if (printerProf != NULL)
   {
      (void) CMCloseProfile(printerProf);
   }
}

Previous Book Contents Book Index Next

© Apple Computer, Inc.
13 NOV 1996