KCMS Application Developer's Guide

KcsUpdateProfile()

KcsStatusId
 KcsUpdateProfile(KcsProfileId profile,
         KcsCharacterizationData *charact,
         KcsCalibrationData *calib, void *CMMSpecificData)

Purpose

Use KcsUpdateProfile() to change the profile data in the loaded profile according to the supplied measurement data.

The data supplied to this call depends on the type of device the profile represents. The default CMM currently supports scanners and monitors. Printer profiles are not currently supported. The "C" API also will be used for printers, when implemented by the default or alternative CMMs. The data required for this call depends on whether the profile is calibrated or characterized.

Characterization refers to defining the generic color response of all devices of the same make and model (normally by making measurements on a number of sample devices to find an average response). Characterization requires colorimetric measurements. Example 4-13 shows how these measurements are used to update a profile.

Calibration refers to fine-tuning a specific device's color response. It changes the profile data so that it can be color managed to produce the same color response as other devices of the same make and model.

The charact argument to this function refers to a set of color sample measurements where sample is a color patch on a test target.

For a scanner, the test target is a target that is scanned. In this case, each color sample in the measurement set consists of an input that is the CIEXYZ value of the color patch, as measured. The sample output is the RGB value that the scanner produced when scanning the color patch. In addition, each sample contains fields for the sample weight, standard deviation, and sample type. The weight is a hint indicating the importance of the sample color. The default should equal 1.0. The standard deviation is used to indicate the statistics of a set of measurements of the sample color that have been reduced to a single sample. The sample type is used to indicate that a color sample represents either black, white, other, neutral, or chromatic color. For best results, the sample type field should be correctly set for each color sample. For example, the KcsFluorescent sample type can be used to tag special color samples with this property. The sample type is a hint passed by the KCMS framework to the CMM.

Note that CIEXYZ values are to be scaled in the range 0.0 to 100.0 and that RGB values are to be scaled in range 0.0 to 1.0. For additional details, see "KcsCharacterizationData".

For a monitor, the charact argument is not used. Pointer *charact should be set to NULL when KcsUpdateProfile() is called for a monitor profile. Characterization data consists of the following profile attributes:

These attributes must be set and valid prior to calling KcsUpdateProfile(). Your application must use KcsSetAttribute() to set these attributes.

Arguments

Table 4-27 KcsUpdateProfile() Arguments

Argument 

Description 

profile

The identifier of the profile to be updated. 

*charact

A set of color sample measurements where sample is a color patch on a test target. 

*calib

The linearization tables needed to calibrate the profile. These tables are required to calibrate all device types. They are also required when calling KcsUpdateProfile() to characterize a scanner or monitor. Both the input and output spaces are KcsRGB for a scanner and monitor. The RGB samples are scaled in the range of 0.0 to 1.0.

*CMMSpecificData 

A pointer to any additional data needed by a specific CMM to update the profile. Refer to the CMM documentation for any specific data required. For use with the default CMM, your application should set this argument to NULL.

Returns

Table 4-28 KcsUpdateProfile() Return Strings

KCS_SUCCESS

KCS_MEM_ALLOC_ERROR

KCS_CC_UPDATE_NEEDS_MORE_DATA

KCS_CC_UPDATE_INVALID_DATA

Example

To call KcsUpdateProfile() successfully, the profile must contain a small number of attributes that identify the type of device the profile represents. It is assumed that the profile already contains these attributes.

An example is given of how to allocate and fill out the arguments required to call KcsUpdateProfile().


Example 4-13 KcsUpdateProfile()

#pragma ident "@(#) kcms_update.c"
 /* kcs_update.c */
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <math.h>
 #include <kcms/kcs.h>
 #include <kcms/kcstypes.h>
 #include <kcms/kcsattrb.h>

 float            Luminance_float_out[3][256];

 /* test code to check profile calibration * /
 main(int argc, char **argv)
 {
 KcsCalibrationData            *calData;
 KcsProfileDesc                x_desc, desc;
 KcsProfileId                  profileid;
 KcsStatusId                   status;
 KcsAttributeValue             attrValue;
 KcsErrDesc                    errDesc;
 int                           levels = 256, channels = 3;
 int                           sizemeas, nvalues, i, j;
 FILE                          *simfile;
 float                         input_val;
 size_t                        rc;
 
 /* Read in the measured calibration data from a file */
 /* file lum_out should be located in demo directory with this program */

 if ((simfile = fopen("lum_out", "r")) == NULL) {
     fprintf(stderr,"cannot open output luminance file\n");
     exit(1);
     }

 for (i=0; i<channels; i++)
     for (j=0; j<levels; j++)
             Luminance_float_out[i][j] = 0.0;
 nvalues = levels * channels;
 rc = fread(Luminance_float_out, sizeof(float), nvalues, simfile);
 fclose(simfile);

 /* Fill out the measurement structures */
 sizemeas = (int) (sizeof(KcsMeasurementBase) + sizeof(long) + 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;

 if (!argv[1]) {
     fprintf(stderr, "Usage kcms_update profile_in [profile_out]\n");
     exit(1);
     }
  /* Let the library open the file */
 x_desc.type = KcsSolarisProfile;
 x_desc.desc.solarisFile.fileName = argv[optind];
 x_desc.desc.solarisFile.hostName = NULL;
 x_desc.desc.solarisFile.oflag = O_RDWR;
 x_desc.desc.solarisFile.mode = 0;

 status = KcsLoadProfile(&profileid, &x_desc, KcsLoadAllNow);
 if(status != KCS_SUCCESS) {
     status = KcsGetLastError(&errDesc);
     printf("LoadProfile error: %s\n", errDesc.desc);
     }

 status = KcsUpdateProfile(profileid, NULL, calData, NULL);
 if(status != KCS_SUCCESS) {
     status = KcsGetLastError(&errDesc);
     printf("UpdateProfile error: %s\n", errDesc.desc);
     KcsFreeProfile(profileid);
     exit(1);
     }

 if (argv[2]) {
     /* Save to an output file */
     desc.type = KcsSolarisProfile;
     desc.desc.solarisFile.fileName = argv[2];
     desc.desc.solarisFile.hostName = NULL;
     desc.desc.solarisFile.oflag = O_RDWR|O_CREAT|O_TRUNC;