summaryrefslogtreecommitdiff
path: root/spectro/spec2cie.c
diff options
context:
space:
mode:
Diffstat (limited to 'spectro/spec2cie.c')
-rwxr-xr-xspectro/spec2cie.c129
1 files changed, 85 insertions, 44 deletions
diff --git a/spectro/spec2cie.c b/spectro/spec2cie.c
index 6c56e67..fd40c51 100755
--- a/spectro/spec2cie.c
+++ b/spectro/spec2cie.c
@@ -53,7 +53,7 @@
This is intended for conversion of reflective measurements to XYZ -
there is no illuminant for emissive values.
- L*a*b* is always D50.
+ L*a*b* is always D50, since it is intended for ICC profile construction.
*/
@@ -133,10 +133,10 @@ main(int argc, char *argv[])
int ci, mi, yi, ki; /* Indexes of device values */
int fwacomp = 0; /* FWA compensation */
int doplot = 0; /* Plot each patches spectrum */
- char* illum_str = "D50";
icxIllumeType tillum = icxIT_none; /* Target/simulated instrument illuminant, if set. */
xspect cust_tillum, *tillump = NULL; /* Custom target/simulated illumination spectrum */
/* if tillum == icxIT_custom */
+ char* illum_str = "D50";
icxIllumeType illum = icxIT_none; /* CIE calc. illuminant spectrum, and FWA inst. */
/* illuminant if tillum not set. */
xspect cust_illum; /* Custom CIE illumination spectrum if illum == icxIT_custom */
@@ -149,6 +149,8 @@ main(int argc, char *argv[])
icxObserverType obType = icxOT_none;
xspect custObserver[3]; /* Custom observer CMF's */
+ icmXYZNumber ill_wp_XYZ; /* if ill_wp != NULL, same as ill_wp */
+
int npat; /* Number of patches */
int ti; /* Field index */
char *kw;
@@ -654,10 +656,11 @@ main(int argc, char *argv[])
int Xi, Yi, Zi, Li, ai, bi; /* CGATS indexes for each field */
int spi[XSPECT_MAX_BANDS]; /* CGATS indexes for each wavelength */
int oXi, oYi, oZi, oLi, oai, obi; /* CGATS indexes for each ouput field */
+ int oL2i, oa2i, ob2i; /* For illuminant wp L*a*b* output */
xsp2cie *sp2cie; /* Spectral conversion object */
xspect sp;
double XYZ[3];
- double Lab[3];
+ double Lab[3], Lab2[3];
char buf[100];
/* These are only set if fwa is needed */
xspect rmwsp; /* Raw medium white spectrum */
@@ -710,6 +713,17 @@ main(int argc, char *argv[])
}
+ /* If CIE calculation illuminant is not standard, compute it's white point */
+ if (illum != icxIT_D50 && illum != icxIT_none) {
+ ill_wp = _ill_wp;
+
+ /* Compute normalised XYZ of illuminant */
+ if (icx_ill_sp2XYZ(ill_wp, obType, custObserver, illum, 0.0, &cust_illum, 0) != 0)
+ error("icx_ill_sp2XYZ returned error");
+
+ icmAry2XYZ(ill_wp_XYZ, ill_wp);
+ }
+
/* copy fields to output file (except spectral if nospec) */
for (i = 0; i < icg->t[0].nfields; i++) {
@@ -758,27 +772,51 @@ main(int argc, char *argv[])
oai = ai;
obi = bi;
- /* allocate elements */
+ /* If non-standard illuminant is being used, add extra LAB fields */
+ /* to show illuminant relative values (Not used for profiling!) */
+ if (ill_wp != NULL) {
+ char buf[50] = { '\000' }, *cp;
- if ((elems = (cgats_set_elem *)
- calloc(ocg->t[0].nfields, sizeof(cgats_set_elem))) == NULL)
- {
- error("Out of memory");
- }
+ strncpy(buf, illum_str, 40);
- /* If CIE calculation illuminant is not standard, compute it's white point */
- if (illum != icxIT_D50 && illum != icxIT_none) {
- ill_wp = _ill_wp;
+ /* Replace spaces */
+ for (cp = buf; *cp != '\000'; cp++) {
+ if (*cp == ' ')
+ *cp = '_';
+ }
+ /* Remove extension */
+ for (; cp >= buf; cp--) {
+ if (*cp == '.') {
+ *cp = '\000';
+ break;
+ }
+ }
+ strcat(buf, "LAB");
+ cp = buf + strlen(buf);
+ cp[0] = '_';
- /* Compute normalised XYZ of illuminant */
- if (icx_ill_sp2XYZ(ill_wp, obType, custObserver, illum, 0.0, &cust_illum, 0) != 0)
- error("icx_ill_sp2XYZ returned error");
+ cp[1] = 'L';
+ if ((oL2i = ocg->add_field(ocg, 0, buf, r_t)) < 0)
+ error ("Cannot add field to table");
+
+ cp[1] = 'A';
+ if ((oa2i = ocg->add_field(ocg, 0, buf, r_t)) < 0)
+ error ("Cannot add field to table");
+
+ cp[1] = 'B';
+ if ((ob2i = ocg->add_field(ocg, 0, buf, r_t)) < 0)
+ error ("Cannot add field to table");
+ }
+
+ /* allocate elements */
+ if ((elems = (cgats_set_elem *)
+ calloc(ocg->t[0].nfields, sizeof(cgats_set_elem))) == NULL) {
+ error("Out of memory");
}
/* Create a spectral conversion object */
- if ((sp2cie = new_xsp2cie(illum, &cust_illum, obType, custObserver,
- icSigXYZData, icxClamp)) == NULL)
- {
+ if ((sp2cie = new_xsp2cie(illum, 0.0, &cust_illum, obType, custObserver,
+ icSigXYZData, icxClamp)) == NULL) {
error ("Creation of spectral conversion object failed");
}
@@ -921,14 +959,15 @@ main(int argc, char *argv[])
ocg->add_kword(ocg, 0, "ILLUMINANT_WHITE_POINT_XYZ",buf, NULL);
}
- /* Transform patches from spectral to CIE */
+ /* Transform patches from spectral to CIE, */
+ /* after correcting the spectrum for possible XRGA and FWA. */
for (i = 0; i < npat; i++) {
- xspect corr_sp;
/* copy all input colums to output (except spectral if nospec) */
for (jj = j = 0; j < icg->t[0].nfields; j++) {
if (nospec) {
+
/* See if this is a spectral field */
for (k = 0; nospec && k < sp.spec_n; k++) {
if (spi[k] == j)
@@ -963,39 +1002,27 @@ main(int argc, char *argv[])
}
/* Read the spectral values for this patch */
- for (j = 0; j < sp.spec_n; j++) {
+ for (j = 0; j < sp.spec_n; j++)
sp.spec[j] = *((double *)icg->t[0].fdata[i][spi[j]]);
- }
+
if (calstdo != xcalstd_none)
xspec_convert_xrga(&sp, &sp, calpol, calstdo, calstdi);
+ /* Convert it to CIE space */
if (fwacomp) {
- corr_sp = sp; /* Copy spectrum */
-
- /* Convert it to CIE space */
- sp2cie->sconvert (sp2cie, &corr_sp, XYZ, &sp);
-
- /* Write the corrected spectral values for this patch */
- if (nospec == 0) {
- for (j = 0; j < sp.spec_n; j++) {
- elems[spi[j]].d = sp.spec[j] = corr_sp.spec[j];
- }
- }
+ sp2cie->sconvert(sp2cie, &sp, XYZ, &sp);
+ } else {
+ sp2cie->convert(sp2cie, XYZ, &sp);
}
- /* No FWA comp */
- else {
- /* Convert it to CIE space */
- sp2cie->convert (sp2cie, XYZ, &sp);
+ /* Standard pseudo-absolute D50 ICC Lab */
+ icmXYZ2Lab(&icmD50, Lab, XYZ);
+ /* Illuminant relative Lab */
+ if (ill_wp != NULL) {
+ icmXYZ2Lab(&ill_wp_XYZ, Lab2, XYZ);
}
- /* Could use sp2cie->get_cie_il() to get CIE white point */
- /* if we wanted to return L*a*b* relative to that. */
- /* We would have to mark that in the .ti3 though. */
- /* This won't work for emmisive though, since get_cie_il() will return 'E' */
- icmXYZ2Lab(&icmD50, Lab, XYZ);
-
#ifdef ALLOW_PLOT
if (doplot) {
int ii;
@@ -1018,14 +1045,28 @@ main(int argc, char *argv[])
do_plot(xx,y1,NULL,NULL,ii);
}
#endif
+ /* Write the corrected spectral values for this patch */
+ if (nospec == 0
+ && (calstdo != xcalstd_none || fwacomp)) {
+ for (j = 0; j < sp.spec_n; j++) {
+ elems[spi[j]].d = sp.spec[j];
+ }
+ }
+
elems[oXi].d = XYZ[0] * 100.0;
elems[oYi].d = XYZ[1] * 100.0;
elems[oZi].d = XYZ[2] * 100.0;
-
+
elems[oLi].d = Lab[0];
elems[oai].d = Lab[1];
elems[obi].d = Lab[2];
+ if (ill_wp != NULL) {
+ elems[oL2i].d = Lab2[0];
+ elems[oa2i].d = Lab2[1];
+ elems[ob2i].d = Lab2[2];
+ }
+
ocg->add_setarr(ocg, 0, elems);
}