The ICC Profile format is defined by the International Color Consortium (ICC). For background on the origination and purpose of this format, refer to https://www.color.org/index.xalter.
Creating an ICC Profile
To create an ICC profile, start by calling LICCProfile::Initialize to initialize an ICC profile structure (ICCPROFILEEXT). This must be called before creating a new profile or loading an existing profile. Within the ICCPROFILEEXT structure is an ICCHEADER structure that contains header information for the profile. Once the ICCPROFILEEXT structure has been initialized, the header must be initialized by calling LICCProfile::InitHeader. This sets the members of the ICCHEADER structure to their default values. The following functions can be used to change the ICCHEADER values from default values to custom values:
The user can set the Profile ID in the header of the ICC Profile structure by calling the LICCProfile::SetProfileId. This function sets the value of ICCPROFILEEXT.ICCHEADER.uProfileID member automatically with an auto-generated ID. To set the Profile file ID, the ICC profile must be complete.
Tags
The ICC Profile can also include tags. Tags can be inserted in an ICC profile, created but not inserted, or deleted. To insert a tag in an ICC profile, do the following:
To create a tag without inserting it into an ICC profile, call LICCProfile::CreateTagData. When that tag is no longer needed, free it by calling LICCProfile::FreeTagType.
At anytime the user can get a tag from an ICC profile by calling the LICCProfile::GetTagData function. The user can delete a tag by calling the LICCProfile::DeleteTag function.
Tags are of various types. These types have a signature associated with them to identify them. Tags also have signatures associated with them. One or both of these signatures may be used when creating, inserting or deleting tags. To get the signature of a specific tag type, call the LICCProfile::GetTagTypeSig function. For more information on tags, types and signatures, please refer to the documentation available through https://www.color.org/index.xalter.
When working with ICC profiles, it may be necessary to convert values from one form to another. Variables of the type:
L_IccS15Fixed16Number, or L_IccU16Fixed16Number requires data in a 2 bytes fixed, 2 bytes fraction form. The LICCProfile::DoubleToU8Fixed8Number function converts a double value into a 2 bytes fixed, 2 bytes fraction form, allowing the user to set these variables. The LICCProfile::Convert2bFixed2bNumberToDouble function converts a 2 bytes fixed, 2 bytes fraction value into a double value, allowing the user to get data from these variables.
L_IccU8Fixed8Number requires data in a 1 byte fixed, 1 byte fraction form. The LICCProfile::DoubleToU8Fixed8Number function converts a double value into 1 byte fixed, 1 byte fraction form, allowing the user to set these variables. The LICCProfile::U8Fixed8NumberToDouble function converts 1 byte fixed, 1 byte fraction value into a double value, allowing the user to get data from these variables.
The pData pointer of the ICCPROFILEEXT structure points to a block of memory that contains the ICC profile as a whole. This pointer does not generate automatically after each new tag added or deleted. Therefore, to regenerate a pointer to the updated profile, call the LICCProfile::GeneratePointer function. Please note however, that before calling any of the LICCProfile::GenerateFile or LICCProfile::Save functions, make sure that the uDataSize and pData pointer of the ICCPROFILEEXT has the right data either by loading an ICC profile into them, or by calling the LICCProfile::GeneratePointer to generate them.
The user can export the information of some tags into a buffer of sequential bytes using the following functions:
LICCProfile::ConvertCurveTypeToBuffer , converts the information of an ICCTAG_CURVE_TYPE structure (CurveType tag) into one buffer of sequential bytes.
LICCProfile::ConvertCLUTToBuffer, converts the information of an ICC_CLUT8 or ICC_CLUT16 structure (the color of the lookup table data used into LutAToBType and LutBToAType tags) into one buffer of sequential bytes.
LICCProfile::ConvertParametricCurveTypeToBuffer, converts the information of an ICCTAG_PARAMETRIC_CURVE_TYPE structure (ParametricCurveType tag) into one buffer of sequential bytes. To retrieve the number of parameters of a parametric curve type function, call the LICCProfile::GetParametricCurveNumberOfParameters functions. This number of parameters will be used in calculating the size of the buffer will filled by the converted data.
Loading an ICC Profile
ICC profiles can be saved to ICC files or embedded in image files and loaded at a later date. Before loading an existing ICC profile from a saved file, the LICCProfile::Initialize function must be called to initialize the ICC profile structure.
To load an ICC profile from an image file, call LICCProfile::Load. This function loads the pData member of the ICCPROFILEEXT structure with a pointer to one block of memory that contains the entire ICC profile. It also loads the uDataSize member with the size of the profile.
Once this information has been loaded, call LICCProfile::Fill to extract the ICC profile information from the memory block and fill the appropriate members of the ICCPROFILEEXT structure.
A profile structure can also be loaded directly from an ICC profile file, using the LICCProfile::Fill function.
Saving an ICC Profile
An ICC profile can be saved, or embedded, in a TIFF, GIF or JPEG image file by calling LICCProfile::Save. To save an ICC profile to an ICC profile file, call LICCProfile::GenerateFile.
Freeing an ICC Profile
When an ICC profile structure is no longer needed, free the structure by calling LICCProfile::Free.