![]() |
PATH![]() |
![]() ![]() |
When Color Matching Occurs
describes both general purpose and QuickDraw-specific ColorSync functions for color matching. Using the general purpose functions
CWMatchPixMap
or
CWMatchBitmap
, your application can match the colors of a pixel image or a bitmap image to the display's color gamut without relying on QuickDraw.
Color matching occurs relatively quickly, but for a session involving a large pixel image or bitmap image, the color-matching process may take some time. To keep the user informed, you can provide a progress-reporting function. For example, your function can display an indicator, such as a progress bar, to depict how much of the matching has been done and how much remains. Your function can also allow the user to interrupt the color-matching process.
When your application calls either the CWMatchPixMap function or the CWMatchBitmap function, you can pass the function a pointer to your callback progress-reporting function and a reference constant containing data, such as the progress bar dialog box's window reference. When the CMM used to match the colors calls your progress-reporting function, it passes the reference constant to it. If you provide a progress-reporting function, here is how you should declare the function, assuming you name it MyCMBitmapCallBackProc:
pascal Boolean MyCMBitmapCallBackProc (long progress, void *refCon);
For a complete description of the progress-reporting function declaration, see
MyCMBitmapCallBackProc
.
To use the
CWMatchPixMap
and
CWMatchBitmap
functions, your application must first set up a color world that specifies the profiles involved in the color-matching session as described in
Creating a Color World to Use With the General Purpose Functions
. The color world establishes how matching will take place between the profiles.
Listing 3-7
shows how to match the colors of a bitmap using the general purpose functions that take a color world.
The ColorSync Manager uses the PixMap data type defined by Color QuickDraw. The ColorSync Manager defines and uses the cmBitmap data type, based on the classic QuickDraw Bitmap data type.
Your application can call the function
CWMatchPixMap
to match the colors of a pixel
image to the display's color gamut. To use
CWMatchPixMap
, you first create a color world, as described in
Creating a Color World to Use With the General Purpose Functions
. The color world is based on the source profile for the device used to create the pixel image and the destination profile for the display on which the image is shown.
To match the colors of a pixel image to the display's color gamut, the source profile for the color world must specify a data color space of RGB as its
dataColorSpace
element value to correspond to the pixel map data type, which is implicitly RGB. If the source profile you specify for the color world is the original source profile used to create the pixel image, most likely these values match. However, if you want to verify that the source profile's
dataColorSpace
element specifies RGB, you can use the
CMGetProfileHeader
function to obtain the profile header. The profile header contains the
dataColorSpace
element field. For a pixel image, the display profile's
dataColorSpace
element must also be set to RGB; this is the color space commonly used for displays.
If the source profile is embedded in the document containing the pixel map, your application can extract the profile and open a reference to it before you create the color world. For information on how to extract an embedded profile, see Extracting Profiles Embedded in Pictures . If the source profile is installed in the ColorSync Profiles folder, your application can display a list of profiles to the user to allow the user to select the appropriate one.
Matching the colors of a bitmap image to the current system's display is similar to the process of matching a pixel map's colors, except that the data type of a bitmap image is explicitly stated in the space field of the bitmap. You can specify a bitmap image using any of the following data types: cmGraySpace , cmGrayASpace , cmRGB16Space , cmRGB24Space, cmRGB32Space , cmARGB32Space , cmRGB48Space , cmCMYK32Space , cmCMYK64Space , cmHSV32Space , cmHLS32Space , cmYXY32Space , cmXYZ32Space , cmLUV32Space , cmLAB24Space , cmLab32Space , cmLAB48Space , cmNamedIndexed32Space, cmMCFive8Space, cmMCSix8Space, cmMCSeven8Space, or cmMCEight8Space. The data type of the source bitmap image must correspond to the data color space specified by the color world's source profile.
When you call the
CWMatchBitmap
function, you can pass it a pointer to a bitmap to hold the resulting image. In this case, you must allocate the pixel buffer pointed to by the
image
field of the
CMBitmap
structure. Because the
CWMatchBitmap
function allows you to specify a separate bitmap to hold the resulting color-matched image, you must ensure that the data type you specify in the
space
field of the resulting bitmap matches the destination's color data space. On input, the color space of the source profile must match the color space of the bitmap. If you specify
NULL
for the destination bitmap, on successful output, ColorSync will change the
space
field of the source bitmap to reflect the bitmap space to which the source image was mapped.
Rather than create a bitmap for the color-matched image, you can match the bitmap in place. To do so, you specify NULL instead of passing a pointer to a resulting bitmap.
The
code in
Listing 3-7
shows how to set up a bitmap for the resulting color-matched image before calling the
CWMatchBitmap
function to perform the color matching. The
MyMatchImage
function calls the MyGetImageProfile function (not shown) to obtain an embedded profile from the image. If none is found, it calls the MyGetImageSpace function (also not shown) to determine the color space for the profile, then calls the ColorSync routine
CMGetDefaultProfileBySpace
to obtain the default profile for that space.
The MyMatchImage function then calls GetProfileForMainDisplay, shown in
Listing 3-5
, to get the destination profile. It uses the source and destination profiles to set up a color world by calling
NCWNewColorWorld
, then uses the resulting color world when it calls
CWMatchBitmap
to match the colors to the display.
Listing 3-7 Matching the colors of a bitmap using a color world
void MyMatchImage (FSSpec theImage)
{
CMError theErr;
CMProfileRef sourceProf;
CMProfileRef destProf;
CMWorldRef cw;
CMBitmap bitmap;
OSType theSpace;
/* Init for error handling. If any error during process,
jump to cleanup area and quit trying. */
theErr = noErr;
sourceProf = nil;
destProf = nil;
cw = nil;
bitmap.image = nil;
// Determine source profile.
// 1st - try to find an embedded profile
theErr = MyGetImageProfile(theImage, &sourceProf);
if (theErr == noErr)
{
// 2nd - use default profile for the image space
theErr = MyGetImageSpace(theSpace, &sourceProf);
require(theErr == noErr, cleanup);
theErr = CMGetDefaultProfileBySpace(theSpace, &sourceProf);
require(theErr == noErr, cleanup);
}
require(theErr == noErr, cleanup);
// Determine dest profile.
theErr = GetProfileForMainDisplay(&destProf);
require(theErr == noErr, cleanup);
// Set up a color world.
theErr = NCWNewColorWorld(&cw, sourceProf, destProf);
require(theErr == noErr, cleanup);
// close profiles after setting up color world.
if (sourceProf)
CMCloseProfile(sourceProf);
if (destProf)
CMCloseProfile(destProf);
sourceProf = destProf = nil;
// Read the image into the CMBitmap structure
theErr = MyGetImageBitmap(theImage, &bitmap);
require(theErr == noErr, cleanup);
// Match bitmap in place.
theErr = CWMatchBitmap(cw, &bitmap, nil, nil, nil);
require(theErr == noErr, cleanup);
// Render results here ... (code not shown)
/* Do any necessary cleanup:close profiles and dispose of
color world and bitmap. */
cleanup:
if (sourceProf)
CMCloseProfile(sourceProf);
if (destProf)
CMCloseProfile(destProf);
if (cw)
CWDisposeColorWorld(cw);
if (bitmap.image)
DisposePtr(bitmap.image);
return theErr;
}