Chapter 4. Tag Management

This chapter describes Coloratura functions and data structures for access to the data held in profiles: tag data. For example, you could specify the tone reproduction curve for the red channel of a device, or data for an abstract profile, which transforms data in a profile connection space. Other uses for tag access are to determine if the profile is appropriate for a transform, or to create or modify a profile.

In contrast to headers, which contain fixed-length data that is frequently accessed and provides generic characterization of a profile, tags contain variable-length and fixed-length data that is less frequently accessed and provides the technical details that define a profile. Because tags hold the detailed information, you need access to tag data for complete control of the color management process. Access to headers is discussed in the sections of Chapter 3"Examining Headers of Profiles on Disk: cmsGetProfileSpecHeader()" and "Creating New Profiles, Getting and Setting Headers, and Saving Edits".

The Coloratura CMS does not define tags that are not in the ICC Profile Format Specification. You can find a complete description of all publicly defined tags there. The header file ic.h provides brief descriptions of tags and their data types.

These are the topics covered in this chapter:

To access tag data, you use two data structures that are defined in the ICC Profile Format Specification and declared in ic.h:

Getting Tag Data Sequentially: Tag Iteration

You can iterate through tags to examine a profile more closely and, perhaps, manipulate its contents. You typically use tag iteration as a component of a profile validator, which checks the syntax of a profile or verifies that the contents are meaningful, or a profile examiner, which lists the contents of a profile and helps you determine whether to use it.

Tag Iteration: Pseudocode Example

Tag iteration is similar to profile iteration, which was discussed in the section "Loading Profile Data: cmsOpenProfile()". After you open a profile with cmsOpenProfile(), you create a CMSTagIterator data structure by calling cmsStartTagIteration(), and then repeatedly call cmsNextTagIteration().

In contrast to profile iteration, however, tag iteration functions use the Coloratura version of the profile, that is a CMSProfile data structure. Thus, you do not obtain information from the disk version of the profile, and may get unsaved changes to tag data resulting from previous Coloratura calls.

You can modify tag data during an iteration with the function cmsSetTag(), which is discussed in "Setting Tag Data: cmsSetTag()". Changes are not saved to disk until you save the profile with cmsSaveProfile() or cmsSaveProfileAs(), discussed in "Creating New Profiles, Getting and Setting Headers, and Saving Edits".

When there are no more tags in a profile, cmsNextTagIteration() returns NULL. You then call cmsEndTagIteration(). The Coloratura CMS allocates space to store tag data, so, to free memory, you must call cmsFreeTagValue() when you are done with the data.

Here is pseudocode that illustrates how to step through the tags in a profile. In the interest of clarity, the proper error checking is not performed.

CMSProfile      prof;
CMSTagIterator  theIterator;
 
icTagSignature    name;
icTagTypeSignature  type;
uint32            size;
char             *pdata;
 
cmsStartTagIteration(context, prof, &theIterator);
while (cmsNextTagIteration(context, theIterator, &name,
                          &type, &size, &pdata)!= NULL) {
    /* do whatever with the data from the tag. */
    cmsFreeTagValue(pdata);
}
cmsEndTagIteration(context, theIterator);

Data Structure for Tag Iteration: CMSTagIterator

The pointer CMSTagIterator refers to an opaque data structure that keeps track of position in a list of tags during an iteration. This is the data type declaration:

typedef struct _CMSTagIterator *CMSTagIterator;

Starting Tag Iteration: cmsStartTagIteration()

The function cmsStartTagIteration() creates a CMSTagIterator and starts a tag iteration.

  • This is the prototype for cmsStartTagIteration():

    int32  cmsStartTagIteration(CMSContext ctxt,
                                CMSProfile prof,
                                cmsTagIterator *iterator);

  • These are the arguments of cmsStartTagIteration():

    ctxt 

    The context initialized by cmsOpen().

    prof 

    The profile in which to find tags.

    iterator 

    The newly generated iterator.

  • This is the error code returned by cmsStartTagIteration():

    CMS_OUT_OF_MEMORY 

Stepping Through Tags: cmsNextTagIteration()

The function cmsNextTagIteration() returns the next tag in an iteration sequence. When the iteration is complete, it sets the tag name to NULL and returns CMS_NO_MORE_TAGS.

To change tag data during an iteration, use the function cmsSetTag(), discussed in "Setting Tag Data: cmsSetTag()".

When you are finished with a tag, free its allocated memory by calling cmsFreeTagValue(), which is discussed in "Deleting Tag Data from a Profile: cmsDeleteTag()".

  • This is the prototype for cmsNextTagIteration():

    int32  cmsNextTagIteration(CMSContext ctxt, 
                               CMSTagIterator iterator,
                               icTagSignature *name, 
                               icTagTypeSignature *type,
                               uint32 *size, 
                               void **data);

  • These are the arguments of cmsNextTagIteration():

    ctxt 

    The context initialized by cmsOpen().

    iterator 

    The tag iterator.

    name 

    The returned tag name.

    type 

    The returned data type.

    size 

    The size, in bytes, of the returned data.

    data 

    The data.

  • These are the error codes returned by cmsNextTagIteration():

    CMS_OUT_OF_MEMORY 


    There is not enough memory to hold the next tag.

    CMS_NO_MORE_TAGS 


    There are no more tags in the profile.

Stopping a Tag Iteration: cmsEndTagIteration()

The function cmsEndTagIteration() terminates a tag iteration and deletes the iterator.

  • This is the prototype for cmsEndTagIteration():

    int32 cmsEndTagIteration(CMSContext ctxt, CMSTagIterator iterator);

  • These are the arguments of cmsEndTagIteration():

    ctxt 

    The context initialized by cmsOpen().

    iterator 

    The tag iterator.

Getting Tag Data Directly: cmsGetTag()

When you have an open profile and you know the tag you want to work with, you can read the tag data by calling cmsGetTag() and specifying the tag by name, instead of searching through the list of tags with an iteration.

The function cmsGetTag() returns the tag data type, a pointer to the data, and the size of the data structure. Note that the function might return tag data that has been modified and not yet saved to disk, because the tag data it returns comes from a CMSProfile data structure. For more information on tag data types, see the header file ic.h and the ICC Profile Format Specification.

When you no longer need the storage the Coloratura CMS allocates for returned tag data, free it with a call to cmsFreeTagValue(), discussed in "Deleting Tag Data from a Profile: cmsDeleteTag()".

  • This is the prototype for cmsGetTag():

    int32  cmsGetTag(CMSContext ctxt, 
                     CMSProfile prof,
                     icTagSignature name,                              
                     icTagTypeSignature *type,
                     uint32 *size, void **data);

  • These are the arguments of cmsGetTag():

    ctxt 

    The context initialized by cmsOpen().

    prof 

    The profile that owns the tag.

    name 

    The name of the tag being queried.

    type 

    The returned value for the tag data type.

    size 

    The size, in bytes, of the returned data.

    data 

    A pointer to the data.

  • These are the error codes returned by cmsGetTag():

    CMS_TAG_NOT_FOUND 


    The tag name was not in profile prof.

    CMS_OUT_OF_MEMORY 


    There is not enough memory to store the tag data.

Setting Tag Data: cmsSetTag()

Given a CMSProfile and a tag name, the function cmsSetTag() sets the tag data to values you supply. If the specified tag doesn't exist, cmsSetTag() creates it. The tag data must follow the format given in the ICC Profile Format Specification.

Save modified or newly created tags to a file with cmsSaveProfile() or cmsSaveProfileAs(), which are discussed in "Creating New Profiles, Getting and Setting Headers, and Saving Edits". Any tag changes or deletions you make that you do not explicitly save have no effect on the disk image of the profile.

When you pass data to the Coloratura CMS with cmsSetTag(), it makes a copy of the data. You should, therefore, free storage for your tag data source after you call cmsSetTag(). You free the Coloratura version of the data with cmsFreeTagValue().

  • This is the prototype for cmsSetTag():

    int32  cmsSetTag(CMSContext ctxt, 
                     CMSProfile prof,
                     icTagSignature name,
                     uint32 size,
                     void *data);

  • These are the arguments of cmsSetTag():

    ctxt 

    The context initialized by cmsOpen().

    prof 

    The profile that owns the tag.

    name 

    The name of the tag data.

    size 

    The size, in bytes, of the data.

    data 

    A pointer to the data

  • This is the error code returned by cmsSetTag():

    CMS_OUT_OF_MEMORY 


Deleting Tag Data from a Profile: cmsDeleteTag()

The function cmsDeleteTag() removes tag data from a CMSProfile data structure. Do not attempt to remove data by calling cmsSetTag() with a data size of zero bytes; this will not remove the data and may confuse the Coloratura CMS.

Remember to save a modified CMSProfile structure to a disk file by calling cmsSaveProfile() or cmsSaveProfileAs() (see "Creating New Profiles, Getting and Setting Headers, and Saving Edits"). Any tag changes or deletions you make that you do not explicitly save have no effect on the disk image of the profile.

  • This is the prototype for cmsDeleteTag():

    int32  cmsDeleteTag(CMSContext ctxt, CMSProfile prof,
                                                  icTagSignature tagName);

  • These are the arguments of cmsDeleteTag():

    ctxt 

    The context initialized by cmsOpen().

    prof 

    The profile that owns the tag.

    tagName 

    The name of the tag to delete.

  • These are the error codes returned by cmsDeleteTag():

    CMS_TAG_NOT_FOUND 

Freeing Tag Data Storage: cmsFreeTagValue()

The function cmsFreeTagValue() frees tag data returned by cmsNextTagIteration() or cmsGetTag().

In addition to a data pointer, you must pass cmsFreeTagValue() the tag name to identify the data type to free, because tag data may have internal structure that affects memory allocation.

  • This is the prototype for cmsFreeTagValue():

    int32  cmsFreeTagValue(CMSContext ctxt, 
                                                     icTagSignature name,
                           void *data);

  • These are the arguments of cmsFreeTagValue():

    ctxt 

    The context initialized by cmsOpen().

    name 

    The name of the tag.

    data 

    The data to be freed.