summaryrefslogtreecommitdiff
path: root/profile/verify.c
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2014-09-01 15:43:52 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2014-09-01 15:43:52 +0200
commitc07d0c2d2f6f7b0eb6e92cc6204bf05037957e82 (patch)
tree41791cbe367cf023b98043fee56f9346b2592b49 /profile/verify.c
parentd7f89e6fe63b8697fab5a901cfce457b375638b3 (diff)
Imported Upstream version 1.6.3upstream/1.6.3
Diffstat (limited to 'profile/verify.c')
-rw-r--r--profile/verify.c783
1 files changed, 0 insertions, 783 deletions
diff --git a/profile/verify.c b/profile/verify.c
deleted file mode 100644
index 849d7fc..0000000
--- a/profile/verify.c
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Argyll Color Correction System
- * Verify two sets of PCS values.
- *
- * Author: Graeme W. Gill
- * Date: 7/6/2005
- *
- * Copyright 2005 Graeme W. Gill
- * All rights reserved.
- *
- * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
- * see the License.txt file for licencing details.
- */
-
-/*
- * This program takes in two CGATS files (probably but not necesserily .ti3 files) of PCS
- * values (either XYZ, L*a*b* or spectral), matches the values, and computes
- * overall errors. This is useful for verifying proofing systems.
- */
-
-/*
- * TTBD:
- */
-
-#undef DEBUG
-
-#define verbo stdout
-
-#include <stdio.h>
-#include <string.h>
-#if defined(__IBMC__)
-#include <float.h>
-#endif
-#include "copyright.h"
-#include "aconfig.h"
-#include "numlib.h"
-#include "vrml.h"
-#include "cgats.h"
-#include "xicc.h"
-#include "ccmx.h"
-#include "insttypes.h"
-#include "sort.h"
-
-void
-usage(void) {
- fprintf(stderr,"Verify CIE values, Version %s\n",ARGYLL_VERSION_STR);
- fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n");
- fprintf(stderr,"usage: verify [-options] target.ti3 measured.ti3\n");
- fprintf(stderr," -v Verbose - print each patch value\n");
- fprintf(stderr," -n Normalise each files reading to white Y\n");
- fprintf(stderr," -N Normalise each files reading to white XYZ\n");
- fprintf(stderr," -D Use D50 100.0 as L*a*b* white reference\n");
- fprintf(stderr," -c Show CIE94 delta E values\n");
- fprintf(stderr," -k Show CIEDE2000 delta E values\n");
- fprintf(stderr," -s Sort patch values by error\n");
- fprintf(stderr," -w create VRML vector visualisation (measured.wrl)\n");
- fprintf(stderr," -W create VRML marker visualisation (measured.wrl)\n");
- fprintf(stderr," -x Use VRML axes\n");
- fprintf(stderr," -f [illum] Use Fluorescent Whitening Agent compensation [opt. simulated inst. illum.:\n");
- fprintf(stderr," M0, M1, M2, A, C, D50 (def.), D50M2, D65, F5, F8, F10 or file.sp]\n");
- fprintf(stderr," -i illum Choose illuminant for computation of CIE XYZ from spectral data & FWA:\n");
- fprintf(stderr," A, C, D50 (def.), D50M2, D65, F5, F8, F10 or file.sp\n");
- fprintf(stderr," -o observ Choose CIE Observer for spectral data:\n");
- fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2\n");
- fprintf(stderr," -X file.ccmx Apply Colorimeter Correction Matrix to second file\n");
- fprintf(stderr," target.ti3 Target (reference) PCS or spectral values.\n");
- fprintf(stderr," measured.ti3 Measured (actual) PCS or spectral values\n");
- exit(1);
- }
-
-/* Patch value type */
-typedef struct {
- char sid[50]; /* sample id */
- double v[3]; /* Lab value */
- double de; /* Delta E */
-} pval;
-
-int main(int argc, char *argv[])
-{
- int fa,nfa; /* current argument we're looking at */
- int verb = 0;
- int norm = 0; /* 1 = norm to Y, 2 = norm to XYZ */
- int usestdd50 = 0; /* Use standard D50 instead of scaled D50 as Lab reference */
- int cie94 = 0;
- int cie2k = 0;
- int dovrml = 0;
- int doaxes = 0;
- int dosort = 0;
- char ccmxname[MAXNAMEL+1] = "\000"; /* Colorimeter Correction Matrix name */
- ccmx *cmx = NULL; /* Colorimeter Correction Matrix */
-
- struct {
- char name[MAXNAMEL+1]; /* Patch filename */
- int isdisp; /* nz if display */
- int isdnormed; /* Has display data been normalised to 100 ? */
- int npat; /* Number of patches */
- pval *pat; /* patch values */
- } cg[2]; /* Target and current patch file information */
-
- int *match; /* Array mapping first list indexes to corresponding second */
- int *sort; /* Array of first list indexes in sorted order */
- int fwacomp = 0; /* FWA compensation */
- int spec = 0; /* Use spectral data flag */
- icxIllumeType tillum = icxIT_none; /* Target/simulated instrument illuminant */
- xspect cust_tillum, *tillump = NULL; /* Custom target/simulated illumination spectrum */
- icxIllumeType illum = icxIT_D50; /* Spectral defaults */
- xspect cust_illum; /* Custom illumination spectrum */
- icxObserverType observ = icxOT_CIE_1931_2;
-
- icmXYZNumber labw = icmD50; /* The Lab white reference */
-
- char out_name[MAXNAMEL+4+1]; /* VRML name */
- vrml *wrl = NULL;
-
- int i, j, n;
-
-#if defined(__IBMC__)
- _control87(EM_UNDERFLOW, EM_UNDERFLOW);
- _control87(EM_OVERFLOW, EM_OVERFLOW);
-#endif
-
- if (argc <= 1)
- usage();
-
- /* Process the arguments */
- for(fa = 1;fa < argc;fa++) {
-
- nfa = fa; /* skip to nfa if next argument is used */
- if (argv[fa][0] == '-') { /* Look for any flags */
- char *na = NULL; /* next argument after flag, null if none */
-
- if (argv[fa][2] != '\000')
- na = &argv[fa][2]; /* next is directly after flag */
- else {
- if ((fa+1) < argc) {
- if (argv[fa+1][0] != '-') {
- nfa = fa + 1;
- na = argv[nfa]; /* next is seperate non-flag argument */
- }
- }
- }
-
- if (argv[fa][1] == '?')
- usage();
-
- else if (argv[fa][1] == 'v' || argv[fa][1] == 'V')
- verb = 1;
-
- /* normalize */
- else if (argv[fa][1] == 'n' || argv[fa][1] == 'N') {
- norm = 1;
- if (argv[fa][1] == 'N')
- norm = 2;
- }
-
- else if (argv[fa][1] == 'D')
- usestdd50 = 1;
-
- /* VRML */
- else if (argv[fa][1] == 'w')
- dovrml = 1;
- else if (argv[fa][1] == 'W')
- dovrml = 2;
-
- /* Axes */
- else if (argv[fa][1] == 'x')
- doaxes = 1;
-
- /* CIE94 delta E */
- else if (argv[fa][1] == 'c' || argv[fa][1] == 'C') {
- cie94 = 1;
- cie2k = 0;
- }
-
- else if (argv[fa][1] == 'k' || argv[fa][1] == 'K') {
- cie94 = 0;
- cie2k = 1;
- }
-
- /* Sort */
- else if (argv[fa][1] == 's' || argv[fa][1] == 'S')
- dosort = 1;
-
- /* FWA compensation */
- else if (argv[fa][1] == 'f') {
- fwacomp = 1;
-
- if (na != NULL) { /* Argument is present - target/simulated instr. illum. */
- fa = nfa;
- if (strcmp(na, "A") == 0
- || strcmp(na, "M0") == 0) {
- spec = 1;
- tillum = icxIT_A;
- } else if (strcmp(na, "C") == 0) {
- spec = 1;
- tillum = icxIT_C;
- } else if (strcmp(na, "D50") == 0
- || strcmp(na, "M1") == 0) {
- spec = 1;
- tillum = icxIT_D50;
- } else if (strcmp(na, "D50M2") == 0
- || strcmp(na, "M2") == 0) {
- spec = 1;
- tillum = icxIT_D50M2;
- } else if (strcmp(na, "D65") == 0) {
- spec = 1;
- tillum = icxIT_D65;
- } else if (strcmp(na, "F5") == 0) {
- spec = 1;
- tillum = icxIT_F5;
- } else if (strcmp(na, "F8") == 0) {
- spec = 1;
- tillum = icxIT_F8;
- } else if (strcmp(na, "F10") == 0) {
- spec = 1;
- tillum = icxIT_F10;
- } else { /* Assume it's a filename */
- spec = 1;
- tillum = icxIT_custom;
- if (read_xspect(&cust_tillum, na) != 0)
- usage();
- }
- }
- }
-
- /* Spectral to CIE Illuminant type */
- else if (argv[fa][1] == 'i' || argv[fa][1] == 'I') {
- fa = nfa;
- if (na == NULL) usage();
- if (strcmp(na, "A") == 0) {
- spec = 1;
- illum = icxIT_A;
- } else if (strcmp(na, "C") == 0) {
- spec = 1;
- illum = icxIT_C;
- } else if (strcmp(na, "D50") == 0) {
- spec = 1;
- illum = icxIT_D50;
- } else if (strcmp(na, "D50M2") == 0) {
- spec = 1;
- illum = icxIT_D50M2;
- } else if (strcmp(na, "D65") == 0) {
- spec = 1;
- illum = icxIT_D65;
- } else if (strcmp(na, "F5") == 0) {
- spec = 1;
- illum = icxIT_F5;
- } else if (strcmp(na, "F8") == 0) {
- spec = 1;
- illum = icxIT_F8;
- } else if (strcmp(na, "F10") == 0) {
- spec = 1;
- illum = icxIT_F10;
- } else { /* Assume it's a filename */
- spec = 1;
- illum = icxIT_custom;
- if (read_xspect(&cust_illum, na) != 0)
- usage();
- }
- }
-
- /* Spectral Observer type */
- else if (argv[fa][1] == 'o' || argv[fa][1] == 'O') {
- fa = nfa;
- if (na == NULL) usage();
- if (strcmp(na, "1931_2") == 0) { /* Classic 2 degree */
- spec = 1;
- observ = icxOT_CIE_1931_2;
- } else if (strcmp(na, "1964_10") == 0) { /* Classic 10 degree */
- spec = 1;
- observ = icxOT_CIE_1964_10;
- } else if (strcmp(na, "1955_2") == 0) { /* Stiles and Burch 1955 2 degree */
- spec = 1;
- observ = icxOT_Stiles_Burch_2;
- } else if (strcmp(na, "1978_2") == 0) { /* Judd and Voss 1978 2 degree */
- spec = 1;
- observ = icxOT_Judd_Voss_2;
- } else if (strcmp(na, "shaw") == 0) { /* Shaw and Fairchilds 1997 2 degree */
- spec = 1;
- observ = icxOT_Shaw_Fairchild_2;
- } else
- usage();
- }
-
- /* Colorimeter Correction Matrix for second file */
- else if (argv[fa][1] == 'X') {
- fa = nfa;
- if (na == NULL) usage();
- strncpy(ccmxname,na,MAXNAMEL-1); ccmxname[MAXNAMEL-1] = '\000';
-
- } else
- usage();
- } else
- break;
- }
-
- /* Get the file name arguments */
- if (fa >= argc || argv[fa][0] == '-') usage();
- strncpy(cg[0].name,argv[fa++],MAXNAMEL); cg[0].name[MAXNAMEL] = '\000';
-
- if (fa >= argc || argv[fa][0] == '-') usage();
- strncpy(cg[1].name,argv[fa],MAXNAMEL); cg[1].name[MAXNAMEL] = '\000';
-
- /* Create VRML name */
- {
- char *xl;
- strcpy(out_name, cg[1].name);
- if ((xl = strrchr(out_name, '.')) == NULL) /* Figure where extention is */
- xl = out_name + strlen(out_name);
- strcpy(xl,".wrl");
- }
-
- if (fwacomp && spec == 0)
- error ("FWA compensation only works when viewer and/or illuminant selected");
-
- /* Colorimeter Correction Matrix */
- if (ccmxname[0] != '\000') {
- if ((cmx = new_ccmx()) == NULL)
- error("new_ccmx failed\n");
- if (cmx->read_ccmx(cmx,ccmxname))
- error("Reading Colorimeter Correction Matrix file '%s' failed with error %d:'%s'\n",
- ccmxname, cmx->errc, cmx->err);
- }
-
- /* Open up each file in turn, target then measured, */
- /* and read in the CIE values. */
- for (n = 0; n < 2; n++) {
- cgats *cgf = NULL; /* cgats file data */
- int isLab = 0; /* 0 if file CIE is XYZ, 1 if is Lab */
- int sidx; /* Sample ID index */
- int xix, yix, zix;
-
- /* Open CIE target values */
- cgf = new_cgats(); /* Create a CGATS structure */
- cgf->add_other(cgf, ""); /* Allow any signature file */
-
- if (cgf->read_name(cgf, cg[n].name))
- error("CGATS file '%s' read error : %s",cg[n].name,cgf->err);
-
- if (cgf->ntables < 1)
- error ("Input file '%s' doesn't contain at least one table",cg[n].name);
-
- /* Check if the file is suitable */
- if (!spec
- && cgf->find_field(cgf, 0, "LAB_L") < 0
- && cgf->find_field(cgf, 0, "XYZ_X") < 0) {
-
- if (cgf->find_kword(cgf, 0, "SPECTRAL_BANDS") < 0)
- error ("Neither CIE nor spectral data found in file '%s'",cg[n].name);
-
- /* Switch to using spectral information */
- if (verb)
- printf("No CIE data found, switching to spectral with standard observer & D50 for file '%s'\n",cg[n].name);
- spec = 1;
- illum = icxIT_D50;
- observ = icxOT_CIE_1931_2;
- }
- if (spec && cgf->find_kword(cgf, 0, "SPECTRAL_BANDS") < 0)
- error ("No spectral data data found in file '%s' when spectral expected",cg[n].name);
-
- if (!spec && cgf->find_field(cgf, 0, "LAB_L") >= 0)
- isLab = 1;
-
- cg[n].npat = cgf->t[0].nsets; /* Number of patches */
-
- /* Figure out what sort of device it is */
- {
- int ti;
-
- cg[n].isdisp = 0;
-
- if ((ti = cgf->find_kword(cgf, 0, "DEVICE_CLASS")) < 0)
- error ("Input file '%s' doesn't contain keyword DEVICE_CLASS",cg[n].name);
-
- if (strcmp(cgf->t[0].kdata[ti],"DISPLAY") == 0) {
- cg[n].isdisp = 1;
- illum = icxIT_none; /* Displays are assumed to be self luminous */
- /* ?? What if two files are different ?? */
- }
-
- /* See if the CIE data has been normalised to Y = 100 */
- if ((ti = cgf->find_kword(cgf, 0, "NORMALIZED_TO_Y_100")) < 0
- || strcmp(cgf->t[0].kdata[ti],"NO") == 0) {
- cg[n].isdnormed = 0;
- } else {
- cg[n].isdnormed = 1;
- }
- }
-
- /* Read all the target patches */
- if (cg[n].npat <= 0)
- error("No sets of data in file '%s'",cg[n].name);
-
- if (verb && n == 0) {
- fprintf(verbo,"No of test patches = %d\n",cg[n].npat);
- }
-
- /* Allocate arrays to hold test patch input and output values */
- if ((cg[n].pat = (pval *)malloc(sizeof(pval) * cg[n].npat)) == NULL)
- error("Malloc failed - pat[]");
-
- /* Read in the CGATs fields */
- if ((sidx = cgf->find_field(cgf, 0, "SAMPLE_ID")) < 0
- && (sidx = cgf->find_field(cgf, 0, "SampleName")) < 0
- && (sidx = cgf->find_field(cgf, 0, "Sample_Name")) < 0
- && (sidx = cgf->find_field(cgf, 0, "SAMPLE_NAME")) < 0
- && (sidx = cgf->find_field(cgf, 0, "SAMPLE_LOC")) < 0)
- error("Input file '%s' doesn't contain field SAMPLE_ID, SampleName, Sample_Name, SAMPLE_NAME or SAMPLE_LOC",cg[n].name);
- if (cgf->t[0].ftype[sidx] != nqcs_t
- && cgf->t[0].ftype[sidx] != cs_t)
- error("Sample ID/Name field isn't a quoted or non quoted character string");
-
- if (spec == 0) { /* Using instrument tristimulous value */
-
- if (isLab) { /* Expect Lab */
- if ((xix = cgf->find_field(cgf, 0, "LAB_L")) < 0)
- error("Input file '%s' doesn't contain field LAB_L",cg[n].name);
- if (cgf->t[0].ftype[xix] != r_t)
- error("Field LAB_L is wrong type");
- if ((yix = cgf->find_field(cgf, 0, "LAB_A")) < 0)
- error("Input file '%s' doesn't contain field LAB_A",cg[n].name);
- if (cgf->t[0].ftype[yix] != r_t)
- error("Field LAB_A is wrong type");
- if ((zix = cgf->find_field(cgf, 0, "LAB_B")) < 0)
- error("Input file '%s' doesn't contain field LAB_B",cg[n].name);
- if (cgf->t[0].ftype[zix] != r_t)
- error("Field LAB_B is wrong type");
-
- } else { /* Expect XYZ */
- if ((xix = cgf->find_field(cgf, 0, "XYZ_X")) < 0)
- error("Input file '%s' doesn't contain field XYZ_X",cg[n].name);
- if (cgf->t[0].ftype[xix] != r_t)
- error("Field XYZ_X is wrong type");
- if ((yix = cgf->find_field(cgf, 0, "XYZ_Y")) < 0)
- error("Input file '%s' doesn't contain field XYZ_Y",cg[n].name);
- if (cgf->t[0].ftype[yix] != r_t)
- error("Field XYZ_Y is wrong type");
- if ((zix = cgf->find_field(cgf, 0, "XYZ_Z")) < 0)
- error("Input file '%s' doesn't contain field XYZ_Z",cg[n].name);
- if (cgf->t[0].ftype[zix] != r_t)
- error("Field XYZ_Z is wrong type");
- }
-
- for (i = 0; i < cg[n].npat; i++) {
- strcpy(cg[n].pat[i].sid, (char *)cgf->t[0].fdata[i][sidx]);
- cg[n].pat[i].v[0] = *((double *)cgf->t[0].fdata[i][xix]);
- cg[n].pat[i].v[1] = *((double *)cgf->t[0].fdata[i][yix]);
- cg[n].pat[i].v[2] = *((double *)cgf->t[0].fdata[i][zix]);
-
- if (!isLab) { /* If XYZ */
-
- /* If normalised to 100, scale back to 1.0 */
- if (!cg[n].isdisp || !cg[n].isdnormed) {
- cg[n].pat[i].v[0] /= 100.0; /* scale back to 1.0 */
- cg[n].pat[i].v[1] /= 100.0;
- cg[n].pat[i].v[2] /= 100.0;
- }
- } else { /* If Lab */
- icmLab2XYZ(&icmD50, cg[n].pat[i].v, cg[n].pat[i].v);
- }
- /* Apply ccmx */
- if (n == 1 && cmx != NULL) {
- cmx->xform(cmx, cg[n].pat[i].v, cg[n].pat[i].v);
- }
- }
-
- } else { /* Using spectral data */
- int ii;
- xspect sp;
- char buf[100];
- int spi[XSPECT_MAX_BANDS]; /* CGATS indexes for each wavelength */
- xsp2cie *sp2cie; /* Spectral conversion object */
-
- if ((ii = cgf->find_kword(cgf, 0, "SPECTRAL_BANDS")) < 0)
- error ("Input file doesn't contain keyword SPECTRAL_BANDS");
- sp.spec_n = atoi(cgf->t[0].kdata[ii]);
- if ((ii = cgf->find_kword(cgf, 0, "SPECTRAL_START_NM")) < 0)
- error ("Input file doesn't contain keyword SPECTRAL_START_NM");
- sp.spec_wl_short = atof(cgf->t[0].kdata[ii]);
- if ((ii = cgf->find_kword(cgf, 0, "SPECTRAL_END_NM")) < 0)
- error ("Input file doesn't contain keyword SPECTRAL_END_NM");
- sp.spec_wl_long = atof(cgf->t[0].kdata[ii]);
- if (!cg[n].isdisp || cg[n].isdnormed != 0)
- sp.norm = 100.0;
- else
- sp.norm = 1.0;
-
- /* Find the fields for spectral values */
- for (j = 0; j < sp.spec_n; j++) {
- int nm;
-
- /* Compute nearest integer wavelength */
- nm = (int)(sp.spec_wl_short + ((double)j/(sp.spec_n-1.0))
- * (sp.spec_wl_long - sp.spec_wl_short) + 0.5);
-
- sprintf(buf,"SPEC_%03d",nm);
-
- if ((spi[j] = cgf->find_field(cgf, 0, buf)) < 0)
- error("Input file doesn't contain field %s",buf);
- }
-
- /* Create a spectral conversion object */
- if ((sp2cie = new_xsp2cie(illum, illum == icxIT_none ? NULL : &cust_illum,
- observ, NULL, icSigXYZData, icxClamp)) == NULL)
- error("Creation of spectral conversion object failed");
-
- if (fwacomp) {
- int ti;
- xspect mwsp; /* Medium spectrum */
- instType itype; /* Spectral instrument type */
- xspect insp; /* Instrument illuminant */
-
- mwsp = sp; /* Struct copy */
-
- if ((ti = cgf->find_kword(cgf, 0, "TARGET_INSTRUMENT")) < 0)
- error ("Can't find target instrument in '%s' needed for FWA compensation",cg[n].name);
-
- if ((itype = inst_enum(cgf->t[0].kdata[ti])) == instUnknown)
- error ("Unrecognised target instrument '%s'", cgf->t[0].kdata[ti]);
-
- if (inst_illuminant(&insp, itype) != 0)
- error ("Instrument doesn't have an FWA illuminent");
-
- /* Determine a media white spectral reflectance */
- for (j = 0; j < mwsp.spec_n; j++)
- mwsp.spec[j] = 0.0;
-
- /* Since we don't want to assume that there are any associated device */
- /* values present in each file, we can't use this as means of */
- /* determining the media color. Use an alternative approach here, */
- /* which may give slightly different results to profile. */
-
- /* Track the maximum reflectance for any band to determine white. */
- /* This might silently fail, if there isn't white in the sample set. */
- for (i = 0; i < cg[0].npat; i++) {
- for (j = 0; j < mwsp.spec_n; j++) {
- double rv = *((double *)cgf->t[0].fdata[i][spi[j]]);
- if (rv > mwsp.spec[j])
- mwsp.spec[j] = rv;
- }
- }
-
- /* If we are setting a specific simulated instrument illuminant */
- if (tillum != icxIT_none) {
- tillump = &cust_tillum;
- if (tillum != icxIT_custom) {
- if (standardIlluminant(tillump, tillum, 0.0)) {
- error("simulated inst. illum. not recognised");
- }
- }
- }
-
- if (sp2cie->set_fwa(sp2cie, &insp, tillump, &mwsp))
- error ("Set FWA on sp2cie failed");
-
- if (verb) {
- double FWAc;
- sp2cie->get_fwa_info(sp2cie, &FWAc);
- fprintf(verbo,"FWA content = %f\n",FWAc);
- }
- }
-
- for (i = 0; i < cg[0].npat; i++) {
-
- strcpy(cg[n].pat[i].sid, (char *)cgf->t[0].fdata[i][sidx]);
-
- /* Read the spectral values for this patch */
- for (j = 0; j < sp.spec_n; j++) {
- sp.spec[j] = *((double *)cgf->t[0].fdata[i][spi[j]]);
- }
-
- /* Convert it to XYZ space */
- sp2cie->convert(sp2cie, cg[n].pat[i].v, &sp);
-
- /* Applu ccmx */
- if (n == 1 && cmx != NULL) {
- cmx->xform(cmx, cg[n].pat[i].v, cg[n].pat[i].v);
- }
- }
-
- sp2cie->del(sp2cie); /* Done with this */
-
- } /* End of reading in CGATs file */
-
-
- /* Normalise this file to white = 1.0 or D50 */
- if (norm) {
- double bxyz[3] = { 0.0, -100.0, 0.0 };
-
- /* Locate patch with biggest Y */
- for (i = 0; i < cg[n].npat; i++) {
- double xyz[3];
- icmLab2XYZ(&icmD50, xyz, cg[n].pat[i].v);
- if (cg[n].pat[i].v[1] > bxyz[1]) {
- icmCpy3(bxyz, cg[n].pat[i].v);
- }
- }
-
- /* Then normalize all the values */
- for (i = 0; i < cg[n].npat; i++) {
- if (norm == 1) {
- cg[n].pat[i].v[0] /= bxyz[1];
- cg[n].pat[i].v[1] /= bxyz[1];
- cg[n].pat[i].v[2] /= bxyz[1];
- } else {
- cg[n].pat[i].v[0] *= icmD50.X/bxyz[0];
- cg[n].pat[i].v[1] *= icmD50.Y/bxyz[1];
- cg[n].pat[i].v[2] *= icmD50.Z/bxyz[2];
- }
- }
- }
- cgf->del(cgf); /* Clean up */
- }
- if (cmx != NULL)
- cmx->del(cmx);
- cmx = NULL;
-
- /* Check that the number of test patches matches */
- if (cg[0].npat != cg[1].npat)
- error("Number of patches between '%s' and '%s' doesn't match",cg[0].name,cg[1].name);
-
- /* Create a list to map the second list of patches to the first */
- if ((match = (int *)malloc(sizeof(int) * cg[0].npat)) == NULL)
- error("Malloc failed - match[]");
- for (i = 0; i < cg[0].npat; i++) {
- for (j = 0; j < cg[1].npat; j++) {
- if (strcmp(cg[0].pat[i].sid, cg[1].pat[j].sid) == 0)
- break; /* Found it */
- }
- if (j < cg[1].npat) {
- match[i] = j;
- } else {
- error("Failed to find matching patch to '%s'",cg[0].pat[i].sid);
- }
- }
-
- /* Adjust the reference white Y to be larger than the largest Y of the two files */
- if (!usestdd50) {
- double maxy = -1e6;
-
- for (n = 0; n < 2; n++) {
- for (i = 0; i < cg[n].npat; i++) {
- if (cg[n].pat[i].v[1] > maxy)
- maxy = cg[n].pat[i].v[1];
- }
- }
- labw.X *= maxy/icmD50.Y; /* Scale white uniformly */
- labw.Y *= maxy/icmD50.Y; /* Scale white uniformly */
- labw.Z *= maxy/icmD50.Y;
-
- if (verb)
- printf("L*a*b* white reference = XYZ %f %f %f\n",labw.X,labw.Y,labw.Z);
- }
-
- /* Convert XYZ to Lab */
- for (n = 0; n < 2; n++) {
- for (i = 0; i < cg[n].npat; i++) {
- icmXYZ2Lab(&labw, cg[n].pat[i].v, cg[n].pat[i].v);
- }
- }
-
- /* Compute the delta E's */
- for (i = 0; i < cg[0].npat; i++) {
- if (cie2k)
- cg[0].pat[i].de = icmCIE2K(cg[0].pat[i].v, cg[1].pat[match[i]].v);
- else if (cie94)
- cg[0].pat[i].de = icmCIE94(cg[0].pat[i].v, cg[1].pat[match[i]].v);
- else
- cg[0].pat[i].de = icmLabDE(cg[0].pat[i].v, cg[1].pat[match[i]].v);
- }
-
- /* Create sorted list, from worst to best. */
- if ((sort = (int *)malloc(sizeof(int) * cg[0].npat)) == NULL)
- error("Malloc failed - sort[]");
- for (i = 0; i < cg[0].npat; i++)
- sort[i] = i;
-
-#define HEAP_COMPARE(A,B) (cg[0].pat[A].de > cg[0].pat[B].de)
- HEAPSORT(int, sort, cg[0].npat);
-#undef HEAP_COMPARE
-
- /* - - - - - - - - - - */
- /* Figure out the report */
- {
- double merr = 0.0, aerr = 0.0;
- int n90;
- double merr90 = 0.0, aerr90 = 0.0;
- int n10;
- double merr10 = 0.0, aerr10 = 0.0;
- double rad;
-
- if (dovrml) {
- wrl = new_vrml(out_name, doaxes, 0);
- wrl->start_line_set(wrl, 0);
-
- /* Fudge sphere diameter */
- rad = 10.0/pow(cg[0].npat, 1.0/3.0);
- }
-
- /* Do overall results */
- for (i = 0; i < cg[0].npat; i++) {
- double de;
- if (dosort)
- j = sort[i];
- else
- j = i;
-
- de = cg[0].pat[j].de;
- aerr += de;
-
- if (verb) {
- printf("%s: %f %f %f <=> %f %f %f de %f\n",
- cg[0].pat[j].sid,
- cg[0].pat[j].v[0], cg[0].pat[j].v[1], cg[0].pat[j].v[2],
- cg[1].pat[match[j]].v[0], cg[1].pat[match[j]].v[1], cg[1].pat[match[j]].v[2],
- de);
- }
-
- if (de > merr)
- merr = de;
-
- if (dovrml) {
- if (de > 1e-6) {
- wrl->add_vertex(wrl, 0, cg[0].pat[j].v);
- wrl->add_vertex(wrl, 0, cg[1].pat[j].v);
- }
- if (dovrml == 2) {
- wrl->add_marker(wrl, cg[0].pat[j].v, NULL, rad);
- wrl->add_marker(wrl, cg[1].pat[j].v, NULL, rad);
- }
- }
-
- }
- if (cg[0].npat > 0)
- aerr /= (double)cg[0].npat;
-
- if (dovrml) {
- wrl->make_lines(wrl, 0, 2);
- wrl->del(wrl);
- wrl = NULL;
- }
-
- /* Do best 90% */
- n90 = (int)(cg[0].npat * 9.0/10.0 + 0.5);
- for (i = (cg[0].npat-n90); i < cg[0].npat; i++) {
- double de = cg[0].pat[sort[i]].de;
- aerr90 += de;
- if (de > merr90)
- merr90 = de;
- }
- if (n90 > 0)
- aerr90 /= (double)n90;
-
- /* Do worst 10% */
- n10 = (int)(cg[0].npat * 1.0/10.0 + 0.5);
- for (i = 0; i < n10; i++) {
- double de = cg[0].pat[sort[i]].de;
- aerr10 += de;
- if (de > merr10)
- merr10 = de;
- }
- if (n10 > 0)
- aerr10 /= (double)n10;
-
- if (verb) {
- fprintf(verbo,"No of test patches in worst 10%% are = %d\n",n10);
- fprintf(verbo,"No of test patches in best 90%% are = %d\n",n90);
- }
- printf("Verify results:\n");
- printf(" Total errors%s: peak = %f, avg = %f\n", cie2k ? " (CIEDE2000)" : cie94 ? " (CIE94)" : "", merr, aerr);
- printf(" Worst 10%% errors%s: peak = %f, avg = %f\n", cie2k ? " (CIEDE2000)" : cie94 ? " (CIE94)" : "", merr10, aerr10);
- printf(" Best 90%% errors%s: peak = %f, avg = %f\n", cie2k ? " (CIEDE2000)" : cie94 ? " (CIE94)" : "", merr90, aerr90);
-
- free(sort);
- free(match);
- free(cg[0].pat);
- free(cg[1].pat);
- }
-
- return 0;
-}
-
-