summaryrefslogtreecommitdiff
path: root/spectro/dispcal.c
diff options
context:
space:
mode:
Diffstat (limited to 'spectro/dispcal.c')
-rwxr-xr-x[-rw-r--r--]spectro/dispcal.c217
1 files changed, 130 insertions, 87 deletions
diff --git a/spectro/dispcal.c b/spectro/dispcal.c
index 65e2f10..a4798af 100644..100755
--- a/spectro/dispcal.c
+++ b/spectro/dispcal.c
@@ -151,6 +151,8 @@
#undef CHECK_MODEL /* Do readings to check the accuracy of our model */
#undef SHOW_WINDOW_ONFAKE /* Display a test window up for a fake device */
+#undef DEBUG_MEAS_RES /* Debug just VideoLUT resolution code */
+
/* Invoke with -dfake for testing with a fake device. */
/* Will use a fake.icm/.icc profile if present, or a built in fake */
/* device behaviour if not. */
@@ -178,18 +180,19 @@
#define RDAC_SMOOTH 0.3 /* RAMDAC curve fitting smoothness */
#define MEAS_RES /* Measure the RAMNDAC entry size */
-#ifdef DEBUG_PLOT
+#if defined(DEBUG_PLOT) || defined(DEBUG) || defined(DEBUG_MEAS_RES)
#include "plot.h"
#endif
#if defined(DEBUG)
-
-#define DBG(xxx) fprintf xxx ;
-#define dbgo stderr
+# define DBG(xxx) fprintf xxx ;
+# define DEBUG_MEAS_RES
#else
-#define DBG(xxx)
+# define DBG(xxx)
#endif /* DEBUG */
+#define dbgo stderr
+
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Sample points used in initial device model optimisation */
@@ -1242,6 +1245,7 @@ static double comp_ct(
int plank, /* NZ if Plankian locus, 0 if Daylight locus */
int dovct, /* NZ if visual match, 0 if traditional correlation */
icxObserverType obType, /* If not default, set a custom observer */
+ xspect custObserver[3], /* If obType = icxOT_custom */
double xyz[3] /* Color to match */
) {
double ct_xyz[3]; /* XYZ on locus */
@@ -1254,7 +1258,7 @@ static double comp_ct(
obType = icxOT_CIE_1931_2;
if ((ct = icx_XYZ2ill_ct(ct_xyz, plank != 0 ? icxIT_Ptemp : icxIT_Dtemp,
- obType, NULL, xyz, NULL, dovct)) < 0)
+ obType, custObserver, xyz, NULL, dovct)) < 0)
error("Got bad color temperature conversion\n");
if (de != NULL) {
@@ -1317,7 +1321,7 @@ static int comp_ramdac_prec(
val[i] = (double)i;
meas[i] = ttt[i].XYZ[1];
}
-#ifdef DEBUG
+#ifdef DEBUG_MEAS_RES
fprintf(dbgo,"raw measurements:\n");
do_plot(val, meas, NULL, NULL, 17);
#endif
@@ -1337,67 +1341,85 @@ static int comp_ramdac_prec(
/* Create score for each hypothesis */
scale = 1.0;
- for (j = 0; j < 5; j++) {
+ for (j = 0; j < 5; j++) { /* Res 8, 9, 10, 11, 12 bits */
int k;
- int step = 1 << (4 - j);
+ int step = 1 << (4 - j); /* Step 16, 8, 4, 2, 1 */
double v = 0.0;
double merr;
+ int off;
+ double oscore; /* Offset score */
bits[j] = 8.0 + j;
+ score[j] = 1e38;
- /* Create the target response */
- for (i = 0; i < 17;) {
- for (k = 0; k < step && (i+k) < 17; k++) {
- targ[i + k] = v;
+ /* Try possible offsets */
+ for (off = 0; off < step; off++) {
+ int ik = off; /* Initial k */
+
+ /* Create the target response */
+ for (i = 0; i < 17;) {
+ int ii; /* Actual count of loop */
+ for (ii = 0, k = ik; k < step && (i+k) < 17; k++, ii++) {
+ targ[i + ii] = v;
//printf("j %d: targ[%d] = %f\n",j,i+k,v);
+ }
+ v += step/16.0;
+ i += ii;
+ ik = 0;
}
- v += step/16.0;
- i += k;
- }
- /* Tweak it for typical display non-linearity */
- min = 1e9, max = -1e9;
- for (i = 0; i < 17; i++) {
- targ[i] = pow((NVAL + targ[i]/16.0)/255.0, 2.2);
- if (targ[i] < min)
- min = targ[i];
- if (targ[i] > max)
- max = targ[i];
- }
- for (i = 0; i < 17; i++)
- targ[i] = (targ[i] - min)/(max - min);
+ /* Tweak it for typical display non-linearity */
+ min = 1e9, max = -1e9;
+ for (i = 0; i < 17; i++) {
+ targ[i] = pow((NVAL + targ[i]/16.0)/255.0, 2.2);
+ if (targ[i] < min)
+ min = targ[i];
+ if (targ[i] > max)
+ max = targ[i];
+ }
+ for (i = 0; i < 17; i++)
+ targ[i] = (targ[i] - min)/(max - min);
+
+ /* Try and make fit a little better */
+ /* with a crude optimisation */
+ for (k = 0; k < 50; k++) {
+
+ merr = 0.0;
+ for (i = 0; i < 17; i++)
+ merr += targ[i] - meas[i];
+ merr /= 17.0;
- /* Try and make fit a little better */
- /* with a crude optimisation */
- for (k = 0; k < 50; k++) {
+ for (i = 0; i < 17; i++) {
+ targ[i] *= (1.0 + 0.5 * merr);
+ targ[i] -= 0.5 * merr;
+// targ[i] -= merr;
+ }
+ }
- merr = 0.0;
- for (i = 0; i < 17; i++)
- merr += targ[i] - meas[i];
- merr /= 17.0;
-
+ oscore = 0.0;
for (i = 0; i < 17; i++) {
- targ[i] *= (1.0 + 0.5 * merr);
- targ[i] -= 0.5 * merr;
-// targ[i] -= merr;
+ double tt = targ[i] - meas[i];
+ tt *= tt;
+ oscore += tt;
}
- }
- score[j] = 0.0;
- for (i = 0; i < 17; i++) {
- double tt = targ[i] - meas[i];
- score[j] += tt * tt;
+#ifdef DEBUG_MEAS_RES
+ printf("%d bits %d offset score %f\n",8+j,off,oscore);
+ do_plot(val, meas, targ, NULL, 17);
+#endif
+ /* keep best score from offsets */
+ if (oscore < score[j])
+ score[j] = oscore;
}
+
score[j] *= scale;
- scale *= 1.1;
+ scale *= 1.7; /* De-weight higher bit depth slightly */
+ /* Correct if overall graph is symetrical */
+ /* around minimum value ? */
-#ifdef DEBUG
- printf("%d bits score %f\n",8+j,score[j]);
- do_plot(val, meas, targ, NULL, 17);
-#endif
}
- /* Pick the best score */
+ /* Locate the best and second best scores */
bcor = bcor2 = 1e8;
bbits = 0;
@@ -1415,9 +1437,15 @@ static int comp_ramdac_prec(
/* Don't pick anything if it's not reasonably certain */
if (bcor2/bcor < 1.3
|| (bcor2/bcor < 2.1 && bcor > 0.15)
- ) rbits = 0;
+ ) {
+#ifdef DEBUG_MEAS_RES
+ printf("bcor2/bcor < 1.3 %d\n",bcor2/bcor < 1.3);
+ printf("bcor2/bcor < 2.1 %d && bcor > 0.15 %d -> %d\n", bcor2/bcor < 2.1, bcor > 0.15, bcor2/bcor < 2.1 && bcor > 0.15);
+#endif
+ rbits = 0;
+ }
-#ifdef DEBUG
+#ifdef DEBUG_MEAS_RES
printf("Win score %f by cor %f, ratio %f\n",bcor, bcor2 - bcor, bcor2/bcor);
printf("Best %d, returning %d bits\n",bbits,rbits);
do_plot10(bits, score, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 5, 1);
@@ -1489,7 +1517,7 @@ double g_def_gamma = 2.4;
*/
/* Flag = 0x0000 = default */
-/* Flag & 0x0001 = list ChromCast's */
+/* Flag & 0x0001 = list ChromeCast's */
void usage(int flag, char *diag, ...) {
int i;
disppath **dp;
@@ -1532,10 +1560,10 @@ void usage(int flag, char *diag, ...) {
if (flag & 0x001) {
ccast_id **ids;
if ((ids = get_ccids()) == NULL) {
- fprintf(stderr," ** Error discovering ChromCasts **\n");
+ fprintf(stderr," ** Error discovering ChromeCasts **\n");
} else {
if (ids[0] == NULL)
- fprintf(stderr," ** No ChromCasts found **\n");
+ fprintf(stderr," ** No ChromeCasts found **\n");
else {
int i;
for (i = 0; ids[i] != NULL; i++)
@@ -1548,7 +1576,7 @@ void usage(int flag, char *diag, ...) {
fprintf(stderr," -dmadvr Display via MadVR Video Renderer\n");
#endif
// fprintf(stderr," -d fake Use a fake display device for testing, fake%s if present\n",ICC_FILE_EXT);
- fprintf(stderr," -c listno Set communication port from the following list (default %d)\n",COMPORT);
+ fprintf(stderr," -c listno Choose instrument from the following list (default %d)\n",COMPORT);
if ((icmps = new_icompaths(g_log)) != NULL) {
icompath **paths;
if ((paths = icmps->paths) != NULL) {
@@ -1556,8 +1584,8 @@ void usage(int flag, char *diag, ...) {
for (i = 0; ; i++) {
if (paths[i] == NULL)
break;
- if ((paths[i]->itype == instSpyder1 && setup_spyd2(0) == 0)
- || (paths[i]->itype == instSpyder2 && setup_spyd2(1) == 0))
+ if ((paths[i]->dtype == instSpyder1 && setup_spyd2(0) == 0)
+ || (paths[i]->dtype == instSpyder2 && setup_spyd2(1) == 0))
fprintf(stderr," %d = '%s' !! Disabled - no firmware !!\n",i+1,paths[i]->name);
else
fprintf(stderr," %d = '%s'\n",i+1,paths[i]->name);
@@ -1614,7 +1642,7 @@ void usage(int flag, char *diag, ...) {
if (cap2 & inst2_ccss) {
fprintf(stderr," -X file.ccss Use Colorimeter Calibration Spectral Samples for calibration\n");
fprintf(stderr," -Q observ Choose CIE Observer for spectrometer or CCSS colorimeter data:\n");
- fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2, 1964_10c\n");
+ fprintf(stderr," 1931_2 (def), 1964_10, 2012_2, 2012_10, S&B 1955_2, shaw, J&V 1978_2, 1964_10c or file.cmf\n");
}
fprintf(stderr," -I b|w Drift compensation, Black: -Ib, White: -Iw, Both: -Ibw\n");
fprintf(stderr," -Y R:rate Override measured refresh rate with rate Hz\n");
@@ -1702,6 +1730,8 @@ int main(int argc, char *argv[]) {
ccss *ccs = NULL; /* Colorimeter Calibration Spectral Samples */
int spec = 0; /* Want spectral data from instrument */
icxObserverType obType = icxOT_default;
+ xspect custObserver[3]; /* If obType = icxOT_custom */
+
disprd *dr = NULL; /* Display patch read object */
csamp asgrey; /* Main calibration loop test points */
double dispLum = 0.0; /* Display luminence reading */
@@ -1733,12 +1763,18 @@ int main(int argc, char *argv[]) {
/* causes warning messages in 10.10. */
/* OS X 10.6+ uses a nominal gamma of 2.2 */
- if (Gestalt(gestaltSystemVersionMajor, &MacMajVers) == noErr
+ if (
+#ifdef NEVER
+ Gestalt(gestaltSystemVersionMajor, &MacMajVers) == noErr
&& Gestalt(gestaltSystemVersionMinor, &MacMinVers) == noErr
- && Gestalt(gestaltSystemVersionBugFix, &MacBFVers) == noErr) {
- if (MacMajVers >= 10 && MacMinVers >= 6) {
+ && Gestalt(gestaltSystemVersionBugFix, &MacBFVers) == noErr
+ && MacMajVers >= 10 && MacMinVers >= 6
+#else
+ floor(kCFCoreFoundationVersionNumber) >= kCFCoreFoundationVersionNumber10_6
+#endif
+
+ ) {
g_def_gamma = 2.4;
- }
}
#endif /* >= 1040 */
}
@@ -1818,7 +1854,7 @@ int main(int argc, char *argv[]) {
ccdisp = atoi(na+3);
if (ccdisp <= 0)
- usage(0,"ChromCast number must be in range 1..N");
+ usage(0,"ChromeCast number must be in range 1..N");
}
fa = nfa;
#ifdef NT
@@ -1916,6 +1952,10 @@ int main(int argc, char *argv[]) {
obType = icxOT_CIE_1931_2;
} else if (strcmp(na, "1964_10") == 0) { /* Classic 10 degree */
obType = icxOT_CIE_1964_10;
+ } else if (strcmp(na, "2012_2") == 0) { /* Latest 2 degree */
+ obType = icxOT_CIE_2012_2;
+ } else if (strcmp(na, "2012_10") == 0) { /* Latest 10 degree */
+ obType = icxOT_CIE_2012_10;
} else if (strcmp(na, "1964_10c") == 0) { /* 10 degree corrected */
obType = icxOT_CIE_1964_10c;
} else if (strcmp(na, "1955_2") == 0) { /* Stiles and Burch 1955 2 degree */
@@ -1924,8 +1964,11 @@ int main(int argc, char *argv[]) {
obType = icxOT_Judd_Voss_2;
} else if (strcmp(na, "shaw") == 0) { /* Shaw and Fairchilds 1997 2 degree */
obType = icxOT_Shaw_Fairchild_2;
- } else
- usage(0,"-Q parameter '%s' not recognised",na);
+ } else { /* Assume it's a filename */
+ obType = icxOT_custom;
+ if (read_cmf(custObserver, na) != 0)
+ usage(0,"Failed to read custom observer CMF from -Q file '%s'",na);
+ }
/* Change color callout */
} else if (argv[fa][1] == 'C') {
@@ -2288,13 +2331,13 @@ int main(int argc, char *argv[]) {
/* If we've requested ChromeCast, look it up */
if (ccdisp) {
if ((ccids = get_ccids()) == NULL)
- error("discovering ChromCasts failed");
+ error("discovering ChromeCasts failed");
if (ccids[0] == NULL)
- error("There are no ChromCasts to use\n");
+ error("There are no ChromeCasts to use\n");
for (i = 0; ccids[i] != NULL; i++)
;
if (ccdisp < 1 || ccdisp > i)
- error("Chosen ChromCasts (%d) is outside list (1..%d)\n",ccdisp,i);
+ error("Chosen ChromeCasts (%d) is outside list (1..%d)\n",ccdisp,i);
ccid = ccids[ccdisp-1];
}
@@ -2353,7 +2396,7 @@ int main(int argc, char *argv[]) {
cmx != NULL ? cmx->cc_cbid : 0,
cmx != NULL ? cmx->matrix : NULL,
ccs != NULL ? ccs->samples : NULL, ccs != NULL ? ccs->no_samp : 0,
- spec, obType, NULL, bdrift, wdrift,
+ spec, obType, custObserver, bdrift, wdrift,
"fake" ICC_FILE_EXT, g_log)) == NULL)
error("new_disprd() failed with '%s'\n",disprd_err(errc));
@@ -2409,10 +2452,10 @@ int main(int argc, char *argv[]) {
wp[0] = w[0]/(w[0] + w[1] + w[2]);
wp[1] = w[1]/(w[0] + w[1] + w[2]);
- cct = comp_ct(&cct_de, NULL, 1, 0, obType, w); /* Compute CCT */
- cdt = comp_ct(&cdt_de, NULL, 0, 0, obType, w); /* Compute CDT */
- vct = comp_ct(&vct_de, NULL, 1, 1, obType, w); /* Compute VCT */
- vdt = comp_ct(&vdt_de, NULL, 0, 1, obType, w); /* Compute VDT */
+ cct = comp_ct(&cct_de, NULL, 1, 0, obType, custObserver, w); /* Compute CCT */
+ cdt = comp_ct(&cdt_de, NULL, 0, 0, obType, custObserver, w); /* Compute CDT */
+ vct = comp_ct(&vct_de, NULL, 1, 1, obType, custObserver, w); /* Compute VCT */
+ vdt = comp_ct(&vdt_de, NULL, 0, 1, obType, custObserver, w); /* Compute VDT */
/* Compute advertised current gamma - use the gross curve shape for robustness */
cgamma = pop_gamma(tcols[0].XYZ[1], tcols[1].XYZ[1], tcols[2].XYZ[1]);
@@ -3193,9 +3236,9 @@ int main(int argc, char *argv[]) {
} else if (temp > 0.0) { /* Daylight color temperature */
double XYZ[3];
if (planckian)
- rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL);
+ rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL, 0);
else
- rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL);
+ rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL, 0);
if (rv != 0)
error("Failed to compute XYZ of target color temperature %f\n",temp);
icmXYZ2Yxy(tYxy, XYZ);
@@ -3222,7 +3265,7 @@ int main(int argc, char *argv[]) {
} else { /* Target is native white */
printf("\nAdjust R,G & B gain to desired white point. Press space when done.\n");
/* Compute the CT and delta E to white locus of target */
- ct = comp_ct(&ct_de, NULL, planckian, dovct, obType, tcols[0].XYZ);
+ ct = comp_ct(&ct_de, NULL, planckian, dovct, obType, custObserver, tcols[0].XYZ);
printf(" Initial Br %.2f, x %.4f , y %.4f , %c%cT %4.0fK DE 2K %4.1f\n",
tarw, tYxy[1],tYxy[2],
dovct ? 'V' : 'C', planckian ? 'C' : 'D', ct,ct_de);
@@ -3264,7 +3307,7 @@ int main(int argc, char *argv[]) {
} else { /* Target is native white */
double lxyz[3]; /* Locus XYZ */
- ct = comp_ct(&ct_de, lxyz, planckian, dovct, obType, tcols[0].XYZ);
+ ct = comp_ct(&ct_de, lxyz, planckian, dovct, obType, custObserver, tcols[0].XYZ);
icmXYZ2Yxy(tYxy, lxyz);
/* lxyz is already normalised */
@@ -3476,9 +3519,9 @@ int main(int argc, char *argv[]) {
} else if (temp > 0.0) { /* Daylight color temperature */
double XYZ[3];
if (planckian)
- rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL);
+ rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL, 0);
else
- rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL);
+ rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL, 0);
if (rv != 0)
error("Failed to compute XYZ of target color temperature %f\n",temp);
icmXYZ2Yxy(tYxy, XYZ);
@@ -3652,9 +3695,9 @@ int main(int argc, char *argv[]) {
} else if (temp > 0.0) { /* Daylight color temperature */
double XYZ[3];
if (planckian)
- rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL);
+ rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL, 0);
else
- rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL);
+ rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL, 0);
if (rv != 0)
error("Failed to compute XYZ of target color temperature %f\n",temp);
icmXYZ2Yxy(tYxy, XYZ);
@@ -3695,7 +3738,7 @@ int main(int argc, char *argv[]) {
icmXYZ2Lab(&tXYZ, bLab, bLab);
/* And color temperature */
- ct = comp_ct(&ct_de, NULL, planckian, dovct, obType, tcols[2].XYZ);
+ ct = comp_ct(&ct_de, NULL, planckian, dovct, obType, custObserver, tcols[2].XYZ);
printf("\n");
@@ -4187,9 +4230,9 @@ int main(int argc, char *argv[]) {
} else if (temp > 0.0) { /* Daylight color temperature */
if (planckian)
- rv = icx_ill_sp2XYZ(x.twh, icxOT_default, NULL, icxIT_Ptemp, temp, NULL);
+ rv = icx_ill_sp2XYZ(x.twh, icxOT_default, NULL, icxIT_Ptemp, temp, NULL, 0);
else
- rv = icx_ill_sp2XYZ(x.twh, icxOT_default, NULL, icxIT_Dtemp, temp, NULL);
+ rv = icx_ill_sp2XYZ(x.twh, icxOT_default, NULL, icxIT_Dtemp, temp, NULL, 0);
if (rv != 0)
error("Failed to compute XYZ of target color temperature %f\n",temp);
//printf("~1 Raw target from temp %f XYZ = %f %f %f\n",temp,x.twh[0],x.twh[1],x.twh[2]);
@@ -4360,7 +4403,7 @@ int main(int argc, char *argv[]) {
0.2, /* Background relative to reference white */
80.0, /* Display is 80 cd/m^2 */
0.0, 0.01, x.nwh, /* 0% flare and 1% glare same white point */
- 0, 1.0);
+ 0, 1.0, 0.0, NULL);
break;
case gt_Rec709:
@@ -4371,7 +4414,7 @@ int main(int argc, char *argv[]) {
0.2, /* Background relative to reference white */
1000.0/3.1415, /* Luminance of white in the Image field (cd/m^2) */
0.0, 0.01, x.nwh, /* 0% flare and 1% glare same white point */
- 0, 1.0);
+ 0, 1.0, 0.0, NULL);
break;
default:
@@ -4384,7 +4427,7 @@ int main(int argc, char *argv[]) {
0.2, /* Background relative to reference white */
x.twh[1], /* Target white level (cd/m^2) */
0.0, 0.01, x.nwh, /* 0% flare and 1% glare same white point */
- 0, 1.0);
+ 0, 1.0, 0.0, NULL);
/* Compute the normalisation values */
x.svc->XYZ_to_cam(x.svc, Jab, x.nwh); /* Relative white point */