KCMS CMM Developer's Guide

Characterization and Calibration

Characterization and calibration are accessed using the following KCMS "C" API calls:

See the SDK manual KCMS Application Developer's Guide for more information on these calls.

The KcsProfile base class contains virtual methods to characterize and calibrate two types of devices: scanners and monitors. You must decide whether to override the base functionality to take characterization and calibration data and turn it into the appropriate KcsXform data.


Note -

Currently, the default CMM supports monitor and scanner characterization and calibration only. It does not support printer characterization and calibration. However enabling hooks exist in the source so you can write a CMM that supports printers.


Attributes are set using the normal mechanisms. The KCMS "C" API code excerpt in Example 3-9 shows characterization and calibration.


Example 3-9 Characterization and Calibration

KcsCalibrationData                  *calData;
     KcsCharacterizationData        *charData;
     float                          Luminance_float_out[3][256];    
     double                         test_double[3];   

/* this is a test which does not use real data - just a gamma curve for the 
*  calibration structure and the same curve *.75 for the characterization curve. */

      /*create luminance tables with a gamma = 2.22 */
      for (j=0; j<levels; j++) {
             input_val = j * (1.0/255.0);
             Luminance_float_out[0][j] = pow(input_val, 2.22);
             Luminance_float_out[1][j] = pow(input_val, 2.22);
             Luminance_float_out[2][j] = pow(input_val, 2.22);
      }
      /* Fill out the measurement structures - The illuminant must be D50 */
      test_double[0] = 0.9642;
      test_double[1] = 1.0;
      test_double[2] = 0.8249;
      sizemeas = (int) (sizeof(KcsMeasurementBase) + sizeof(long) +
           sizeof(KcsMeasurementSample) * levels);
      charData =

(KcsCharacterizationData *) malloc(sizemeas);     
      charData->base.countSupplied = levels;
      charData->base.numInComp = 3;
      charData->base.numOutComp = 3;
      charData->base.inputSpace = KcsCIEXYZ;
      charData->base.outputSpace = KcsRGB;
      for (i=0; i< levels; i++) {
             charData->val.patch[i].weight = 1.0;
             charData->val.patch[i].standardDeviation = 0.0;
             charData->val.patch[i].sampleType = KcsChromatic; 

             charData->val.patch[i].input[KcsRGB_R] = (float)i/255;
             charData->val.patch[i].input[KcsRGB_G] = (float)i/255;
             charData->val.patch[i].input[KcsRGB_B] = (float)i/255;
             charData->val.patch[i].input[3] = 0.0; 

             charData->val.patch[i].output[KcsRGB_R] = (Luminance_float_out[0][i])/0.75;
             charData->val.patch[i].output[KcsRGB_G] = (Luminance_float_out[1][i])/0.75;
             charData->val.patch[i].output[KcsRGB_B] = (Luminance_float_out[2][i])/0.75;
             charData->val.patch[i].output[3] = 0.0;
     }
     charData->val.patch[0].sampleType = KcsBlack;
     charData->val.patch[255].sampleType = KcsWhite;

     sizemeas = (int) (sizeof(KcsMeasurementBase) + sizeof(long) +
             sizeof(KcsMeasurementSample) * levels);
     calData = (KcsCalibrationData *) malloc(sizemeas);

     calData->base.countSupplied = levels;    
     calData->base.numInComp = 3;
     calData->base.numOutComp = 3;    
     calData->base.inputSpace = KcsRGB;
     calData->base.outputSpace = KcsRGB;
     for (i=0; i< levels; i++) {
             calData->val.patch[i].weight = 1.0;
             calData->val.patch[i].standardDeviation = 0.0;
             calData->val.patch[i].sampleType = KcsChromatic; 

             calData->val.patch[i].input[KcsRGB_R] = (float)i/255;
             calData->val.patch[i].input[KcsRGB_G] = (float)i/255;
             calData->val.patch[i].input[KcsRGB_B] = (float)i/255;
             calData->val.patch[i].input[3] = 0.0; 

             calData->val.patch[i].output[KcsRGB_R] = Luminance_float_out[0][i];
             calData->val.patch[i].output[KcsRGB_G] = Luminance_float_out[1][i];
             calData->val.patch[i].output[KcsRGB_B] = Luminance_float_out[2][i];
             calData->val.patch[i].output[3] = 0.0;
      }     
             calData->val.patch[0].sampleType = KcsBlack;
             calData->val.patch[255].sampleType = KcsWhite;
      printf("Update a profile with characterization and calibration data.\n");
      rc = KcsUpdateProfile(profileid, charData, calData, NULL);
      if(rc != KCS_SUCCESS) {
         KcsGetLastError(&errDesc);
         fprintf(stderr, 
               "unable to update profile: %s\n", errDesc.desc);   
         KcsFreeProfile(profileid);
         return(-1);
     }