KCMS CMM Developer's Guide
  Suchtext Nur in diesem Buch
Dieses Buch im PDF-Format herunterladen

KcsProfile Derivative

5

This chapter discusses the following topics to help you create a KcsProfile class derivative that is dynamically loadable at runtime:
  • External entry points with an example
  • Member function override rules
  • Helpful information on attributes and the KcsProfileFormat instance

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 withinaIO.
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

The following example shows you how to use the entry points when creating a KcsProfile instance.
Code Example 5-1 KcsProfile Class Entry Points Example

  /* Sample entry points for a new profile derivative */  
  extern "C" {  
       extern long      KcsDLOpenProfCount;  
       KcsProfile *     KcsCreateProf(KcsStatus *aStat, KcsIO *aIO);  
       KcsProfile *     KcsCreateProfBlnk(KcsStatus *aStat,  
                             KcsId aCmmId, KcsVersion aCmmVersion,  
                             KcsId aProfId, KcsVersion aProfVersion);  
       KcsStatus        KcsCleanupProf();  
  };  
  /* 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)  
  {  

Code Example 5-1 KcsProfile Class Entry Points Example (Continued)

       //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, can override, and should not override when deriving from this class. The member functions indicated with an "X" in the Must column are
requiredto 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..........MustOverride Rules

Can

Do Not
connect()
X
createEmptyProfile()
X
createProfile()
X
evaluate()
X
getAttribute()
X
getFormat()

X
getOpAndCont()

X
getXform()

X
initDataMember()
X
isColorSenseCMM()
X
KcsProfile()X

~KcsProfile()
X
load()
X
optimize()
X
propagateAttributes2Xforms()
X
save()
X
save()
X
setAttribute()
X
setOpAndCont()
X
setTimeAttribute()
X
setXform()
X
unload()
X
updateMonitorXforms()
X
updatePrinterXforms()
X
Table 5-1 KcsProfile(Continued)
Member Function..........MustOverride Rules

Can

Do Not
updateScannerXforms()X
updateXforms()X
XformIsNOP()X

Attribute Sets

Attributes can include the following information:
  • Profile's manufacturer name
  • Input and output color spaces
  • Calibration data
  • Device's colorimetric information (for example, monitor's white point)
The attribute set is represented by the KcsAttrAttributesSet object. There are getAttribute() and setAttribute() methods in the KcsProfile class that map directly to 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 following list of attribute set values are overridden by the base class with the getAttribute() and setAttribute() methods:
  • Attribute number
  • Attribute set
  • Profile length
  • Pixel layout supported
  • Supported operations
  • CMM version
  • ICC profile version
If getAttribute() or setAttribute() intercepts one of these attributes, it does not use the KcsAttributeSet class. It uses a KcsProfile class derivative; otherwise, it is passed to the KcsAttrAttributesSet object.

KcsProfileFormat Instance

In addition to attributes and transforms, the KcsProfile base class uses a KcsProfileFormat instance for:
  • Making the version number of profile data in static store transparent
  • Special formats that a CMM might need
  • Compatibility with new and old supported profile formats
The KcsProfileFormat object supports a consistent interface to attributes and transforms 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.

Transforms

Transforms are represented by an array of pointers to instances of the KcsXform class hierarchy. This array is indexed by KcsXformTypes. The logical transform types are listed in Table 5-2.
The ICC specification defines the profile color space (PCS) which is equivalent to RCS.
Table 5-2
XformType ValuesLogical Transform TypeDescription
KcsSftIntoRCS = 0into-RCSInput color space to the output color space which can be one of the standard references.
KcsXftOutofRCS = 1outof-RCSOutput color space (possibly one of the standards) to the input color space.
KcsSftFwdEffect = 2forward-RCS-effectAn effect that goes from a color space to that same color space.
KcsXftRvsEffect = 3reverse-RCS-effectInverse of forward-RCS-effect.
Table 5-2 (Continued)
XformType ValuesLogical Transform TypeDescription
KcsXftFwdSimulate = 4simulation-RCSSpecial processing done to device's output, if simulation is desired on another device. If there is not a simulation-RCS transform, the KCMS framework defaults to connecting the outof-RCS to the into-RCS transformations, which generates an RCS-to-RCS transform that approximates the simulation. This results in a clip close to the simulation normally seen on devices. Currently, profiles do not supply simulation-RCS transforms by default. This connection technique fails on profiles that perform gamut-mapping; therefore, profiles that do gamut-map, should include one of these transforms.
KcsXftFwdGamut = 5gamut-test-RCSProvides all gamut testing for the device. The gamut-test-RCS transform output is a set of 8-bit values representing how much this particular data is out of gamut for all n components.
KcsXftFwdComplete = 6complete-forward transformProfile's transformation from a source device to a destination device. It includes any intermediate effects connected to the chain.
KcsXftRvsComplete = 7complete-reverse transformGoes from the destination device backwards through any of the inverse effects and then into the color space of the input device.
KcsXftRcsSimulate = 8complete-simulate transformMaps the pixels from the source device through the destination device, its simulate transform, and ultimately to the destination device (the device on which you are viewing the data).
KcsXftRCSGamut = 9complete-gamut transformGamut test for whole chain.
The set of types in Table 5-2 refer to RCS. The ICC profile format describes two sets of types: RCS or PCS. However, the KCMS framework supports a non-RCS model where there is no RCS. The only mandate is that CMMs support a number of standard references and that the color spaces match between connections. (Even this mandate is not strictly applied since the base class connect() method automatically inserts profiles if that creates a match).
Instead of referring to the into-RCS transform as going from a non-RCS into a RCS, the ICC 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.

Transform 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

There are two types of constructors: the I/O-based constructor and the 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.

Creators

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

Save Methods

There are two types of save methods: the blind save and the I/O-based save. 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. 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 transforms.
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 transforms 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-1, the connected sequence shares the Xforms (through the class) of those in the list.

Grafik

Figure 5-1

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 method uses sequences of transforms to fill in the results transform array. The sequences are generated based on the content of the profile in the list sequence. As shown in Figure 5-1, if you gave a list consisting of an input device with an output device as the only profiles listed, the method takes the into-RCS transform of the input device, connects it with the outof-RCS transform 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-1 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 transform to accomplish the simulation part of the chain. If connect() doesn't find one and the outof-RCS and into-RCS transforms of the simulated device are available, it makes a simulation sequence that contains these transforms in place of the simulation-RCS transform.

Examples

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

Grafik

Figure 5-2

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 transform 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 transform, 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. These methods either characterize or calibrate depending on the content of those tables.
The base class implementation of updateScannerXforms(), updateMonitorXforms(), and updatePrinterXforms() returns errors indicating that this particular profile does not support calibration or characterization, depending upon which data is 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.