KCMS CMM Developer's Guide

Chapter 5 KcsProfile Derivative

In This Chapter

This chapter discusses the following topics to help you create a KcsProfile class derivative that is dynamically loadable at runtime:

Figure 5-1 shows the relationship of the KcsProfile class to the parent classes in the KCMS class hierarchy. See Figure 1-2 for an illustration of all the relevant KCMS classes.

Figure 5-1 KcsProfile Derivative

Graphic

External Entry Points

The KCMS framework uses external entry points to load your derivative as an executable. The mandatory and optional entry points are described.

Mandatory

When you derive from a KcsProfile class and create a KcsProfile instance you must provide these mandatory external entry points:

extern

long KcsDLOpen ProfCount; KcsProfile * KcsCreateProf(KcsStatus *sStat, KcsIO

*aIO); KcsProfile * KcsCreateProBlnk(KcsStatus *aStat, KcsId aCmmID, 

	KcsVersion aCmmVersion, KcsId aProfId,  	KcsVersion

aProfVersion);

The KcsCreateProf()() entry point creates an instance of a KcsProfile derivative that is determined by the profile's CMM Id within aIO.

The KcsCreateProfBlnk()() entry point creates an instance of a KcsProfile derivative that is determined by aCmmID and aCmmVersion. This is how an empty profile is created from scratch. The aProfId argument specifies which KcsProfileFormat derivative to use.

Optional

When you derive from a KcsProfile class, the optional entry points are:

KcsStatusId

KcsInitProf(); KcsStatusId

KcsCleanupProf();

Example

Example 5-1 shows you how to use the entry points when creating a KcsProfile instance.


Example 5-1 KcsProfile Class Entry Points Example

/* Required entry points

*/ extern long KcsDLOpenProfCount = 0;  /* Construct a profile object using

KcsIO */ KcsProfile * KcsCreateProf(KcsStatus *aStat, KcsIO *aIO) { 	//Create

the new derivative 	return (new KcsProfileKCMS(aStat, aIO)); } /* Construct an

in-memory profile object using the ids */ KcsProfile *

KcsCreateProfBlnk(KcsStatus *aStat, KcsId aCmmId,  	KcsVersion aCmmVersion,

KcsId aProfId,  	KcsVersion aProfVersion) { 	//Create the new derivative

	return(new KcsProfileKCMS (aStat, aCmmId, aCmmVersion,  		aProfId,

aProfVersion)); } /* Optional entry points */ KcsStatus KcsInitProf(long

libMajor, long libMinor, long *myMajor,  		long *myMinor) { 	// Set up the

return values 	*myMajor = KCS_MAJOR_VERSION; 	*myMinor = KCS_MINOR_VERSION; 

	//Check the major version 	if (libMajor != KCS_MAJOR_VERSION) 		return

(KCS_CMM_MAJOR_VERSION_MISMATCH);  	//Currently, if minor version of library

is less than the KCMS  	// minor version, return an error. 	if (libMinor !=

KCS_MINOR_VERSION) 		return (KCS_CMM_MINOR_VERSION_MISMATCH);  	//Library

guarantees if your minor version number is greater than 	//KCMS minor version

number, it will handle it. No more init. 	return(KCS_SUCCESS); }  KcsStatus

KcsCleanupProf() { 	/* Clean up is performed in the destructor */ 	return;

}

Member Function Override Rules

The following table tells you which KcsProfile member functions you must override and can override when deriving from this class. The member functions indicated with an "X" in the Must column are required to successfully derive from this base class. All of these member functions are defined in the kcsprofi.h header file and the KCMS CMM Reference Manual.

Table 5-1 KcsProfile Member Function Override Rules

Member Function 

Override Rules 

Must 

Can 

Do Not 

connect()()

 

 

createEmptyProfile()()

 

 

evaluate()()

 

 

getAttribute()()

 

 

initDataMember()()

 

 

isColorSenseCMM()()

 

 

KcsProfile()()

 

 

~KcsProfile()()

 

 

load()()

 

 

optimize()()

 

 

propagateAttributes2Xforms()()

 

 

save()()

 

 

save()()

 

 

setAttribute()()

 

 

setOpAndCont()()

 

 

setTimeAttribute()()

 

 

setXform()()

 

 

unload()()

 

 

updateMonitorXforms()()

 

 

updatePrinterXforms()()

 

 

updateScannerXforms()()

 

 

updateXforms()()

 

 

XformIsNOP()()

 

Attribute Sets

Attributes can include the following information:

The attribute set is represented by the KcsAttrAttributesSet object. The KcsProfile class getAttribute()() and setAttribute()() methods map directly to the KcsAttrAttributesSet object's getAttribute()() and setAttribute()() methods.

Before performing any operation, the KcsProfile base class loads what is necessary for that operation. For example, the getAttribute()() method always loads the attribute set before it accesses the KcsAttributeSet instance. It also tries to unload data based on the unload hints you supplied.

The base class overrides the following list of attribute set values with the getAttribute()() and setAttribute()() methods:

If getAttribute()() or setAttribute()() intercepts one of these attributes, it does not use the KcsAttributeSet class. Instead it uses a KcsProfile class derivative; otherwise, it is passed to the KcsAttrAttributesSet object.

KcsProfileFormat Instance

In addition to overriding attribute set values, the KcsProfile base class uses a KcsProfileFormat instance. (See the protected KcsProfile pointer iFormat in the kcsprofi.h header file.) KcsProfile uses the KcsProfileFormat object to:

The KcsProfileFormat object supports a consistent interface to attributes and transformations as objects. For example, if the profile format is the ICC format, the derivative of the KcsProfile class can use the KcsProfileFormat derivation supplied with the KCMS framework.

Transformations

Transformations are represented by an array of pointers to instances of the KcsXform class hierarchy. This array is indexed by the enum type KcsXformType.

The logical transformation types are listed in Table 5-2 .


Note -

In Table 5-2 , RCS refers to reference color space. This Kodak term is equivalent to profile connection space (PCS).


Table 5-2 Logical Transformation Types

KcsXformType Values

Logical Transformation Type 

Description 

KcsSftIntoRCS = 0

into-RCS

Input color space to the output color space which can be one of the standard references. 

KcsXftOutofRCS = 1

outof-RCS

Output color space (possibly one of the standards) to the input color space. 

KcsSftFwdEffect = 2

forward-RCS-effect

An effect that goes from a color space to that same color space.  

KcsXftRvsEffect = 3

reverse-RCS-effect

Inverse of forward-RCS-effect. 

KcsXftFwdSimulate = 4

simulation-RCS

Special processing done to device's output, if simulation is desired on another device. If there is not a simulation-RCS transformation, the KCMS framework defaults to connecting the outof-RCS to the into-RCS transformations, which generates an RCS-to-RCS transformation that approximates the simulation. This results in a clip close to the simulation normally seen on devices. Currently, profiles do not supply simulation-RCS transformations by default. This connection technique fails on profiles that perform gamut-mapping. 

KcsXftFwdGamut = 5

gamut-test-RCS

Provides all gamut testing for the device. The gamut-test-RCS transformation output is a set of 8-bit values representing how much this particular data is out of gamut for all n components.

KcsXftFwdComplete = 6

complete-forward transform

Profile's transformation from a source device to a destination device. It includes any intermediate effects connected to the chain. 

KcsXftRvsComplete = 7

complete-reverse transform

Goes from the destination device backwards through any of the inverse effects and then into the color space of the input device. 

KcsXftRcsSimulate = 8

complete-simulate transform

Maps the pixels from the source device through the destination device, its simulationtransformation, and ultimately to the destination device (the device on which you are viewing the data). 

KcsXftRCSGamut = 9

complete-gamut transform

Gamut test for whole chain. 

The set of types in Table 5-2 refer to RCS. However, the KCMS framework supports a non-RCS model where there is no RCS. The only mandate is that CMMs support the standard references (CIEXYZ and CIELAB) and that the color spaces match between connections. (Even this mandate is not strictly applied since the KcsProfile base class connect()() method automatically inserts profiles if that creates a match).

Instead of referring to the into-RCS transformation as going from a non-RCS into a RCS, the ICC specification describes a transformation from an input color space to an output color space. The output may be one of the standard references if it is a device profile.

Transformation Type Methods

The methods supplied to the evaluate()() method of the derived class choose which KcsXform instance to use. The KcsForward()(), KcsReverse()(), KcsSimuate()(), and KcsGamutTest()() methods map directly to the corresponding complete transformation types.

Constructors and Destructors

KcsProfile includes two types of constructors: an I/O-based constructor and an identifier-based constructor.

The I/O-based constructor takes something that is out in static store and instantiates the profile based on the data contained within it. That I/O object can represent file, memory, network, or any other I/O derivative. This relates back to the save methods where the state is saved through an I/O object. This constructor generates a KcsProfile derivative from a saved state.

The identifier-based constructor indicates the CMM Id, CMM version, ProfileId, and the profile version. This constructor allows creation of an empty profile and determines which CMM to use, which profile format to use, and which CMM version to use. They are defaulted to create the latest ICC CMM, with the latest KCMS profile format version.

Both constructors allocate or create a profile format object. Then they take the ChunkSet of that profile format object and use that to set their own ChunkSet. This is how KcsProfile and KcsProfileFormat objects link their KcsChunkSet objects during construction. This happens in the base class, so derivatives do not need to do this unless they have special requirements such as requiring a special derivation of the ChunkSet object.

Creation Methods

Each profile constructor corresponds to two createProfile()() methods. Both methods use the runtime mechanism in the KcsLoadable class to dynamically load themselves at runtime. During creation of an identifier-based profile, a createProfile()() method automatically loads the runtime module, which allocates the correct derivative. It then calls createEmptyProfile()() for initialization.

Save Methods

KcsProfile includes two types of save()() methods: a blind save and an I/O-basedsave.

The blind save()() method saves the profile to the current location. No arguments are required and the timelastsaved attribute is set. The iFormat save()() is called. (iFormat is a pointer to the KcsProfileFormat instance in the KcsProfile base class. See "KcsProfileFormat Instance" for details.) The KcsProfileFormat class saves the profile (with iFormat) because only that class knows the content of the data.

The I/O-based save()() method constructs a new chunk set by

  1. Replacing the one currently there

  2. Doing a blind save to the new chunk set

  3. Resetting everything back

This save method also creates an empty profile by calling the createEmptyProfile()() method.

Since the I/O-based save means save the data to something different, or something new, save()() must reset all the default data to a loadable empty profile with no attributes and no transformations.

All load()() and save()() methods are based on chunk sets. All chunk sets are based on I/O objects. Therefore, indirectly, save()() uses the I/O object to get its data from static store. See Chapter 4, KcsIO Derivative ," for details.

The I/O-based save()() is not virtual because it just wraps around the virtual blind save()() method.

Using connect()()

The connect()() method is one of the most demanding methods of the KcsProfile class. It uses all of the profiles that are in the list sequence, as well as the opAndHints operation, to determine which transformations to generate and how to generate them. It also checks a number of internal rules to ensure those connections are possible. For example, it checks to see that color spaces are compatible. The KCMS profile model does not include a specific reference. Some color management solutions do, but the KCMS framework checks the consistency of the connections. As illustrated in Figure 5-2 , the connected sequence shares the Xforms (through the class) of those in the list.

Figure 5-2 Sequences Sharing Xforms

Graphic

The KCMS framework also does automatic insertion of profiles if those color spaces do not match properly. For example, if you want to connect a KCMS profile that uses KCMS RGB as its connection space with an XYZ profile that uses CIE Lab as its connection space, connect()() looks for a KCMS RGB-to-CIE Lab profile and automatically inserts it into the list. The rest of the connection proceeds as if that profile was in the list when called.

The connect()() method searches through all KCMS profiles so more can be installed to add to the flexibility of this mechanism. opAndHints allows you to trim result to contain only the operations wanted for future use. For example, if you only want to perform a forward operation, then supply only KcsForward--even if there is enough information to connect and create a reverse operation. The default behavior in the base class is to not create the KcsReverseOp transformation. The method only creates what you tell it to create. The only exception is attributes. All profiles need attributes; otherwise, result is useless. It is recommended that derivatives keep consistent with this policy.

When the base KcsProfile connects profiles and creates a new one, it does not create a connection of profiles. One profile is generated with the KcsProfile elements: attributes, transformations, and a format object. The connect()() method uses sequences of transformations to fill in the results transformation array. The sequences are generated based on the content of the profile in the list sequence.

As shown in Figure 5-2 , if you give a list consisting of an input device with an output device as the only profiles listed, the connect()() method takes the into-RCS transformation of the input device, connects it with the outof-RCS transformation of the output device, and creates a sequence. The method then assigns that sequence to the complete-Forward index of a result. If KcsForwardOp is the only operation specified in opAndHints, that is the only sequence generated. Figure 5-2 also illustrates KcsReverseOp.

The connect()() method also goes through a composition of all the attributes in all the profiles in the sequence list. A set of attribute rules, a composition method in the KcsAttributeSet class, and the base class connect()() method feed the list of attributes from profile objects in the list to the KcsAttributeSet composition method.

By default, when connecting the simulation transformations for the resulting profile, the connect()() method looks for the simulation-RCS transformation to accomplish the simulation part of the chain. If connect()() doesn't find one and the outof-RCS and into-RCS transformations of the simulated device are available, it makes a simulation sequence that contains these transformations in place of the simulation-RCS transformation. This results in a clipping close to the simulation normally seen on devices.

Examples

Use Figure 5-3 with the two examples described below to better understand the connect()() method and RCS simulation.

Figure 5-3 Into- and Out-of-RCS Transformations

Graphic

With Printer RCS Transformation

Three profiles exist in the sequence list: a scanner, a printer, and a monitor. A value of (KcsForwardOp|KcsSimulateOp) for opAndHints indicates to the KcsProfile::connect()() method that data in the scanner color space is ready to go into the printer color space and then transform so it can be previewed on the monitor supplied. The complete simulation transformation is a sequence of the into-RCS transformation of the scanner profile, the simulate-RCS transformation of the printer profile, and the outof-RCS transformation of the monitor profile.

Without Printer RCS Transformation

If RCS simulation is not available in the printer profile, the connect()() method connects the transformations by first connecting the into-RCS transformation of the scanner profile to the outof-RCS transformation of the printer profile, then to the into-RCS transformation of the printer profile, and then to the outof-RCS transformation in the monitor profile. Note that for the printer simulation transformation, the simulate-RCS is replaced with the combination outof-RCS and into-RCS transformations. This clips color to the simulated device.

If the simulated profile has neither the simulate-RCS nor the into-RCS and outof-RCS combination, connect()() returns a KCS_NOT_ENOUGH_DATA_4_OP error.

Characterization and Calibration

Characterization and calibration are handled through the update methods of the KcsProfile class, namely

These methods either characterize or calibrate, depending on the content of those tables.

The base class implementation of updateMonitorXforms()(), updatePrinterXforms()(), and() updateScannerXforms()() returns errors indicating that this particular profile does not support calibration or characterization, depending upon which data are supplied. The KcsProfile base class implements updateXforms()() to provide some general-purpose device typing, yet executes the device-specific update mechanism in the derivations. This allows you to put your characterization and calibration techniques in your KcsProfile derivative while using the base class to determine which type of device is actually being updated.