This chapter describes how to manipulate ICC profiles with the Coloratura CMS. Profiles contain the data required to perform color manipulations.
This chapter does not describe the profile format, which is covered in the ICC Profile Format Specification. The format of the profile on disk is irrelevant in any case, because when the Coloratura CMS loads a profile from disk, it stores the data in an opaque data structure, which is then used in all subsequent interactions with the profile data. Details about interacting with profile data are covered in Chapter 4, "Tag Management."
This chapter discusses profile data structures and accessor functions in the following sections:
The first task you face in a Coloratura application is to identify the profiles you need. There are three ways to specify profiles:
predefined information
default profiles
profile iteration
You can use predefined information when you know which device profile you need. For example, if you are writing an Impressario™ model file for a printer, the profile will have a name matching the device name, and the profile can be embedded directly in the model file. Another useful place to put profile names is in an X resource file.
The constants CMS_DEFAULT_MONITOR and CMS_DEFAULT_CMYK specify default profile names. You can specify preferred values for these parameters, if you do not want to use those set in cms.h. Alternatively, you can use the default filenames, but use versions in directories controlled by the environment variable CMS_DEFAULT_PATH. For more information on CMS_DEFAULT_PATH, see "Loading Profile Data: cmsOpenProfile()".
If you do not know the profile you need and do not want to use a default, you can examine the profiles available on your system and select one. The technique for doing this is profile iteration. Typically, you select a profile based on its header information, and then open it, that is, load the data into a Coloratura data structure for further interaction. You can also use profile iteration to make a list for a profile selection menu. For example, you could create a list of all the profiles for a device type or make a list of all profiles that use a given profile connection space.
To perform a profile iteration, you first create a CMSProfileIterator by calling cmsStartProfileIteration(), and then repeatedly call cmsNextProfileIteration(). If there is another profile in the iteration sequence, cmsNextProfileIteration() sets a pointer to its filename. When there are no more profiles on disk, cmsNextProfileIteration() returns NULL.
To efficiently select a profile or display a set of profiles in a menu, you typically need only the minimal information kept in profile headers, which are only 128 bytes. Use cmsGetHeaderProfileSpec() to query a profile on disk for header information.
When there are no more profiles available, you dispose of the iterator by calling cmsEndProfileIteration().
The following code fragment illustrates a profile iteration. In the interest of clarity, the proper error checking is not shown.
char *pspec; CMSProfileIterator theIterator; icHeader header; cmsStartProfileIteration(context, &theIterator); while (cmsNextProfileIteration(context, theIterator, &pspec) != NULL) { cmsGetProfileSpecHeader(context, spec, &header); if (/* tests on fields in header pass */) { /* code to add profile to the application */ } free(pspec); } cmsEndProfileIteration(context, theIterator); |
The next sections detail the data structures and function calls in this example, and introduce related functions.
The data structure icHeader is not discussed because it is not a Coloratura structure; it is the profile header data structure defined by the ICCColor Profile Format Specification. icHeader is defined in ic.h. Since icHeader is of fixed size, you are responsible for allocating and freeing storage for it, as discussed in "Managing Memory".
The pointer CMSProfileIterator refers to an opaque data structure that keeps track of position in a list of profiles during an iteration. This is the data type declaration:
typedef struct _CMSProfileIterator *CMSProfileIterator; |
The function cmsStartProfileIteration() starts a profile iteration and creates a CMSProfileIterator.
This is the prototype for cmsStartProfileIteration():
int32 cmsStartProfileIteration(CMSContext ctxt, CMSProfileIterator *iterator); |
These are the arguments ofcmsStartProfileIteration():
ctxt | The context initialized by cmsOpen(). | |
iterator | The newly generated iterator. |
This is the error code returned by cmsStartProfileIteration():
CMS_PROFILE_NOT_FOUND |
|
The function cmsNextProfileIteration() finds the next filename in a profile iteration. When the iteration is complete, the function returns NULL.
This is the prototype for cmsNextProfileIteration():
int32 cmsNextProfileIteration(CMSContext ctxt, CMSProfileIterator profIterator, char **spec); |
These are the arguments of cmsNextProfileIteration():
ctxt | The context initialized by cmsOpen(). | |
profIterator | The profile iterator. | |
spec | The filename of the next profile. |
These are the error codes returned by cmsNextProfileIteration():
CMS_OUT_OF_MEMORY |
| |
CMS_NO_MORE_PROFILES |
|
The function cmsGetProfileHeader() reads the ICC profile header from a profile on disk.
You can also read a profile header from an open profile, one that has been read into a Coloratura data structure; see "Getting Open-Profile Header Information: cmsGetProfileHeader()".
This is the prototype for cmsGetProfileSpecHeader():
int32 cmsGetProfileSpecHeader(CMSContext ctxt, char *spec, icHeader *pHeader); |
These are the arguments of cmsGetProfileSpecHeader():
ctxt | The context initialized by cmsOpen(). | |
spec | The filename of the profile. | |
pHeader | A pointer to the data structure in which the profile header is to be stored. |
The error code cmsGetProfileSpecHeader() returns is
CMS_PROFILE_NOT_FOUND |
|
The function cmsEndProfileIteration() ends a profile iteration and disposes of the iterator.
This is the prototype for cmsEndProfileIteration():
int32 cmsEndProfileIteration(CMSContext ctxt, CMSProfileIterator profIterator); |
These are the arguments of cmsEndProfileIteration():
ctxt | The context initialized by cmsOpen(). | |
profIterator | The iterator to be disposed of. |
This is the error code returned by cmsEndProfileIteration():
CMS_FAILURE |
|
After you identify the profiles you need, you must open them to place the data in appropriate data structures and make the information available to Coloratura functions. Interactions with profile data then occur via the pointer CMSProfile, which refers to an opaque Coloratura data structure that holds the profile data; you cannot make any assumptions about the data structure.
To make profile data available to the Coloratura CMS, call cmsOpenProfile(), which places the data in a CMSProfile data structure. When you are done working with the profile, call cmsCloseProfile() to allow the framework to recover some memory. To completely remove a profile from the file system, call cmsDeleteProfile().
The following sections provide more detail about CMSProfile and the open, close, and delete functions.
The pointer CMSProfile refers to an opaque data structure that stores profile data. All of your program's interactions with profile data are mediated by a CMSProfile.
This is the prototype for CMSProfile:
typedef struct _CMSProfile *CMSProfile; |
You call the function cmsOpenProfile() to provide Coloratura functions with access to profile data that are on disk. Only after the profile is open can your application read from it, write to it, or include it in a transform. The function cmsOpenProfile() needs a filename to get the data from disk, but all subsequent references to the profile data are through the CMSProfile pointer set by cmsOpenProfile().
This is the prototype for cmsOpenProfile():
int32 cmsOpenProfile(CMSContext ctxt, char *spec, CMSProfile *prof); |
These are the arguments of cmsOpenProfile():
These are the error codes returned by cmsOpenProfile():
CMS_OUT_OF_MEMORY |
| |
CMS_PROFILE_NOT_FOUND |
|
The function cmsCloseProfile() closes the copy of a profile in memory, that is, a CMSProfile data structure, and frees the memory allocated. If you want to remove the profile data from disk, use cmsDeleteProfile(), discussed below.
The function cmsCloseProfile() does not automatically save the CMSProfile data to disk. To save changes to a profile before you call cmsCloseProfile(), call cmsSaveProfile(), which is discussed in "Saving Profile Changes to Disk: cmsSaveProfile()", or cmsSaveProfileAs(), which is discussed in "Saving to a New File on Disk: cmsSaveProfileAs()".
This is the prototype for cmsCloseProfile():
int32 cmsCloseProfile(CMSContext ctxt, CMSProfile prof); |
These are the arguments of cmsCloseProfile():
ctxt | The context initialized by cmsOpen(). | |
prof | The profile to be closed. |
The function cmsDeleteProfile() deletes a profile from the file system. The usual IRIX permission system applies; you might not have permission to delete a given profile.
This is the prototype for cmsDeleteProfile():
int32 cmsDeleteProfile (CMSContext ctxt, char *name); |
These are the arguments ofcmsDeleteProfile():
ctxt | The context initialized by cmsOpen(). | |
name | The profile name. |
If cmsDeleteProfile() cannot find the profile, it will return the error
CMS_PROFILE_NOT_FOUND |
|
To calibrate devices such as scanners, monitors, or printers, or to fine tune an existing profile, you often need to create and modify profiles. You create new profiles by calling cmsCreateProfile().
The function cmsSetProfileHeader() sets new header values for an open profile: a profile you just created, or a profile you have edited whose header information you want to change. To inspect the header of an open profile, you can call cmsGetProfileHeader(). This returns the same information as cmsGetProfileSpecHeader() (see "Examining Headers of Profiles on Disk: cmsGetProfileSpecHeader()"), but it uses the CMSProfile, rather than the filename, to identify the profile data.
If you want to change other data in the profile, see Chapter 4, "Tag Management," which describes the calls you use to create or modify a profile's tag data.
To save a modified version of a profile to disk and retain the original, call cmsSaveProfileAs(). Typically, you call this function when you want to do one of the following:
save an edited profile under a new name
save changes to a newly created profile
To overwrite the original version of a profile on disk that you have opened and edited, use cmsSaveProfile().
The cmsCreateProfile() function creates a new CMSProfile data structure that contains no tag data. The new profile is not available to the file system until you save it with a call to cmsSaveProfileAs(), which is discussed in "Saving to a New File on Disk: cmsSaveProfileAs()".
This is the prototype for cmsCreateProfile():
int32 cmsCreateProfile(CMSContext ctxt, CMSProfile *prof); |
These are the arguments of cmsCreateProfile():
ctxt | The context initialized by cmsOpen(). | |
prof | A pointer to the new CMSProfile. |
This is the error code returned by cmsCreateProfile():
CMS_OUT_OF_MEMORY |
|
The function cmsGetProfileHeader() returns the same information as cmsGetProfileSpecHeader() (see "Examining Headers of Profiles on Disk: cmsGetProfileSpecHeader()"), but differs in that it takes a CMSProfile, rather than a filename.
cmsGetProfileHeader() gets the header information from an open profile and returns a pointer to an icHeader data structure, which is declared in ic.h (see the ICC Device Profile Format Specification for a definition of what is stored in an icHeader structure). Since icHeader is of fixed size, you must allocate and free storage for it, as discussed in "Managing Memory".
This is the prototype for cmsGetProfileHeader():
int32 cmsGetProfileHeader(CMSContext ctxt, CMSProfile prof, icHeader *pHeader); |
These are the arguments of cmsGetProfileHeader():
ctxt | The context initialized by cmsOpen(). | |
prof | The CMSProfile where the header data come from. | |
pHeader | A pointer to the data structure in which to store the information. |
This is the error code returned by cmsGetProfileHeader():
CMS_FAILURE |
The function cmsSetProfileHeader() stores a header in an open profile. Typically, you use cmsSetProfileHeader() to put a header in a new profile.
The Coloratura CMS does not provide a function to update selected fields of a header, which it reads or writes as a whole. To update a specific field, you should first read the header into an icHeader structure, using cmsGetProfileHeader(). Then update the field with your own code and write the header to the profile with cmsSetProfileHeader().
The header file ic.h defines icHeader. Since icHeader is of fixed size, you must allocate and free storage for it. See the ICC Profile Format Specification for a definition of what is stored in a header.
This is the prototype for cmsSetProfileHeader():
int32 cmsSetProfileHeader(CMSContext ctxt, CMSProfile prof, icHeader *pHeader); |
These are the arguments of cmsSetProfileHeader():
ctxt | The context initialized by cmsOpen(). | |
prof | The profile whose header you want to set. | |
pHeader | A pointer to the data structure from which to read the information. |
This is the error code returned by cmsSetProfileHeader():
CMS_OUT_OF_MEMORY |
|
The cmsSaveProfile() function saves an open profile to permanent storage, making it available to the file system. It does not remove the CMSProfile data structure from memory; the data remains available for further editing. Use cmsCloseProfile() to delete the CMSProfile data structure.
This is the prototype for cmsSaveProfile():
int32 cmsSaveProfile(CMSContext ctxt, CMSProfile prof); |
These are the arguments of cmsSaveProfile():
ctxt | The context initialized by cmsOpen(). | |
prof | The profile. |
The function cmsSaveProfile() returns an error if you try to save a profile that does not have a filename. Use cmsSaveProfileAs() to save a profile and attach a name to it. These are the error codes returned by cmsSaveProfile():
CMS_FAILURE |
| |
CMS_OUT_OF_MEMORY |
|
The function cmsSaveProfileAs() is similar to cmsSaveProfile(), in that it writes a profile to permanent storage, but it creates a new file with a filename you specify.
This is the prototype for cmsSaveProfileAs():
int32 cmsSaveProfileAs(CMSContext ctxt, CMSProfile prof, char*spec); |
These are the arguments ofcmsSaveProfileAs():
ctxt | The context initialized by cmsOpen(). | |
prof | The profile to be saved. | |
spec | The filename of the saved profile. |
These are the error codes returned by cmsSaveProfileAs():
CMS_FAILURE |
| |
CMS_OUT_OF_MEMORY |
| |
CMS_EXACT_PROFILE_EXISTS |
|
The ICCColor Profile Format Specification prescribes a way to embed ICC profiles in image data. This allows you to move color data to different computers and operating systems without concern for whether the necessary profiles are present at the destination.
The functions cmsExportProfile() and cmsImportProfile() exchange data between a CMSProfile data structure and data in the ICC format. This simplifies interactions with image data that include embedded profiles. You free storage for the exported data with cmsFreeProfileExport().
The function cmsExportProfile() converts the data in a CMSProfile data structure to the ICC file format. Storage for the exported data is allocated by the Coloratura CMS, so it must be freed by calling cmsFreeProfileExport().
This is the prototype for cmsExportProfile():
int32 cmsExportProfile(CMSContext ctxt, CMSProfile prof, uint32 *length, void **outputData); |
These are the arguments of cmsExportProfile():
ctxt | The context initialized by cmsOpen(). | |
prof | The CMSProfile data structure to be converted. | |
length | The size of exported data, in bytes. | |
outputData | A buffer of data in the ICC format. |
This is the error code returned by cmsExportProfile():
CMS_OUT_OF_MEMORY |
|
The function cmsFreeProfileExport() frees the output data storage created by cmsExportProfile().
This is the prototype for cmsFreeProfileExport():
int32 cmsFreeProfileExport(CMSContext ctxt, void *outputData); |
These are the arguments of cmsFreeProfileExport():
ctxt | The context initialized by cmsOpen(). | |
outputData | The buffer of data to be freed. |
To create a CMSProfile data structure from a data buffer that is in the ICC format, typically obtained from an embedded profile, call cmsImportProfile(). You provide a CMSProfile, which cmsImportProfile() initializes to locate the newly constructed profile data structure.
This is the prototype for cmsImportProfile():
int32 cmsImportProfile(CMSContext ctxt, uint32 length, void *inputData, CMSProfile *profile); |
These are the arguments of cmsImportProfile():
ctxt | The context initialized by cmsOpen(). | |
length | The size, in bytes, of the input data. | |
inputData | A buffer of data in the ICC format. | |
profile | The profile to be initialized. |
This is the error code returned by cmsImportProfile():
CMS_OUT_OF_MEMORY |
| |
CMS_WRONG_DATA |
|