272
274
// Hmm. Need to add tele mode as well ~~~
273
275
fprintf(stderr," -a Use ambient measurement mode (absolute results)\n");
274
276
fprintf(stderr," -f Use ambient flash measurement mode (absolute results)\n");
275
fprintf(stderr," -y c|l Display type (if emissive), c = CRT, l = LCD\n");
277
cap = inst_show_disptype_options(stderr, " -y ", icom);
276
278
fprintf(stderr," -i illum Choose illuminant for print/transparency spectral data:\n");
277
279
#ifndef SALONEINSTLIB
278
280
fprintf(stderr," A, C, D50 (def.), D65, F5, F8, F10 or file.sp\n");
280
282
fprintf(stderr," A, C, D50 (def.), D65\n");
282
fprintf(stderr," -o observ Choose CIE Observer for spectral data:\n");
284
fprintf(stderr," -Q observ Choose CIE Observer for spectral data or CCSS instrument:\n");
283
285
#ifndef SALONEINSTLIB
284
286
fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2\n");
296
298
fprintf(stderr," -E extrafilterfile Apply extra filter compensation file\n");
297
299
fprintf(stderr," -x Display Yxy instead of Lab\n");
298
300
fprintf(stderr," -h Display LCh instead of Lab\n");
301
fprintf(stderr," -V Show running average and std. devation from ref.\n");
299
302
#ifndef SALONEINSTLIB
300
303
fprintf(stderr," -T Display correlated color temperatures and CRI\n");
301
304
#endif /* !SALONEINSTLIB */
303
306
fprintf(stderr," -N Disable auto calibration of instrument\n");
304
307
fprintf(stderr," -H Start in high resolution spectrum mode (if available)\n");
305
308
#ifndef SALONEINSTLIB
306
fprintf(stderr," -X file.ccmx Apply Colorimeter Correction Matrix\n");
310
fprintf(stderr," -X file.ccmx Apply Colorimeter Correction Matrix\n");
312
if (cap & inst_ccss) {
313
fprintf(stderr," -X file.ccss Use Colorimeter Calibration Spectral Samples for calibration\n");
314
for (i = 0; cl != NULL && cl[i].desc != NULL; i++) {
316
fprintf(stderr," -X N 0: %s\n",cl[i].desc);
318
fprintf(stderr," %d: %s\n",i,cl[i].desc);
308
322
fprintf(stderr," -W n|h|x Override serial port flow control: n = none, h = HW, x = Xon/Xoff\n");
309
323
fprintf(stderr," -D [level] Print debug diagnostics to stderr\n");
310
324
fprintf(stderr," logfile Optional file to save reading results as text\n");
314
331
int main(int argc, char *argv[])
317
334
int fa, nfa, mfa; /* current argument we're looking at */
337
354
inst_opt_filter fe = inst_opt_filter_unknown;
338
355
/* Filter configuration */
339
356
char outname[MAXNAMEL+1] = "\000"; /* Output logfile name */
340
#ifndef SALONEINSTLIB
341
char ccmxname[MAXNAMEL+1] = "\000"; /* Colorimeter Correction Matrix name */
357
char ccxxname[MAXNAMEL+1] = "\000"; /* Colorimeter Correction/Colorimeter Calibration name */
358
iccss *cl = NULL; /* List of installed CCSS files */
359
int ncl = 0; /* Number of them */
343
360
char filtername[MAXNAMEL+1] = "\000"; /* Filter compensation */
344
361
FILE *fp = NULL; /* Logfile */
345
362
int comport = COMPORT; /* COM port used */
346
instType itype = instUnknown; /* No default target instrument */
347
int dtype = 0; /* Display type, 0 = default, 1 = CRT, 2 = LCD */
363
int dtype = 0; /* Display type selection charater */
348
364
inst_capability cap = inst_unknown; /* Instrument capabilities */
349
365
inst2_capability cap2 = inst2_unknown; /* Instrument capabilities 2 */
350
366
double lx, ly; /* Read location on xy table */
356
372
int spec = 0; /* Need spectral data for observer/illuminant flag */
357
373
icxIllumeType illum = icxIT_D50; /* Spectral defaults */
358
374
xspect cust_illum; /* Custom illumination spectrum */
359
icxObserverType observ = icxOT_CIE_1931_2;
375
icxObserverType obType = icxOT_default;
360
376
xspect sp; /* Last spectrum read */
361
377
xspect rsp; /* Reference spectrum */
362
378
xsp2cie *sp2cie = NULL; /* default conversion */
366
382
double rLab[3] = { -10.0, 0, 0}; /* Reference Lab */
367
383
double Yxy[3] = { 0.0, 0, 0}; /* Yxy value */
368
384
double LCh[3] = { 0.0, 0, 0}; /* LCh value */
385
double refstats = 0; /* Print running avg & stddev against ref */
386
double rstat_n; /* Stats N */
387
double rstat_Lab[3]; /* Stats sum of Lab's */
388
double rstat_Labsq[3]; /* Stats sum of Lab's squared */
369
389
int savdrd = 0; /* At least one saved reading is available */
370
390
int ix; /* Reading index number */
371
391
int loghead = 0; /* NZ if log file heading has been printed */
416
439
} else if (argv[fa][1] == 'c' || argv[fa][1] == 'C') {
418
if (na == NULL) usage(debug);
441
if (na == NULL) usage(debug, cl);
419
442
comport = atoi(na);
420
if (comport < 1 || comport > 40) usage(debug);
443
if (comport < 1 || comport > 40) usage(debug, cl);
422
445
/* Display type */
423
446
} else if (argv[fa][1] == 'y' || argv[fa][1] == 'Y') {
425
if (na == NULL) usage(debug);
426
if (na[0] == 'c' || na[0] == 'C')
428
else if (na[0] == 'l' || na[0] == 'L')
448
if (na == NULL) usage(debug, cl);
433
451
/* Spectral Illuminant type */
434
452
} else if (argv[fa][1] == 'i' || argv[fa][1] == 'I') {
436
if (na == NULL) usage(debug);
454
if (na == NULL) usage(debug, cl);
437
455
if (strcmp(na, "A") == 0) {
461
479
illum = icxIT_custom;
462
480
if (read_xspect(&cust_illum, na) != 0)
465
483
#else /* SALONEINSTLIB */
468
486
#endif /* SALONEINSTLIB */
470
488
/* Spectral Observer type */
471
} else if (argv[fa][1] == 'o' || argv[fa][1] == 'O') {
489
} else if (argv[fa][1] == 'Q') {
473
if (na == NULL) usage(debug);
491
if (na == NULL) usage(debug, cl);
474
492
if (strcmp(na, "1931_2") == 0) { /* Classic 2 degree */
476
observ = icxOT_CIE_1931_2;
493
obType = icxOT_CIE_1931_2;
477
494
} else if (strcmp(na, "1964_10") == 0) { /* Classic 10 degree */
479
observ = icxOT_CIE_1964_10;
495
obType = icxOT_CIE_1964_10;
480
496
#ifndef SALONEINSTLIB
481
497
} else if (strcmp(na, "1955_2") == 0) { /* Stiles and Burch 1955 2 degree */
483
observ = icxOT_Stiles_Burch_2;
498
obType = icxOT_Stiles_Burch_2;
484
499
} else if (strcmp(na, "1978_2") == 0) { /* Judd and Voss 1978 2 degree */
486
observ = icxOT_Judd_Voss_2;
500
obType = icxOT_Judd_Voss_2;
487
501
} else if (strcmp(na, "shaw") == 0) { /* Shaw and Fairchilds 1997 2 degree */
489
observ = icxOT_Shaw_Fairchild_2;
502
obType = icxOT_Shaw_Fairchild_2;
490
503
#endif /* !SALONEINSTLIB */
494
507
/* Request transmission measurement */
495
508
} else if (argv[fa][1] == 't') {
573
586
else if (na[0] == 'u' || na[0] == 'U')
574
587
fe = inst_opt_filter_UVCut;
578
591
/* Extra filter compensation file */
579
592
} else if (argv[fa][1] == 'E') {
581
if (na == NULL) usage(debug);
594
if (na == NULL) usage(debug, cl);
582
595
strncpy(filtername,na,MAXNAMEL-1); filtername[MAXNAMEL-1] = '\000';
617
634
#ifndef SALONEINSTLIB
618
/* Colorimeter Correction Matrix */
635
/* Colorimeter Correction Matrix or */
637
/* or Colorimeter Calibration Spectral Samples */
619
638
} else if (argv[fa][1] == 'X') {
621
if (na == NULL) usage(debug);
622
strncpy(ccmxname,na,MAXNAMEL-1); ccmxname[MAXNAMEL-1] = '\000';
641
if (na == NULL) usage(debug, cl);
642
if (ncl > 0 && sscanf(na, " %d ", &ix) == 1) {
643
if (ix < 0 || ix >= ncl)
645
strncpy(ccxxname,cl[ix].path,MAXNAMEL-1); ccxxname[MAXNAMEL-1] = '\000';
647
strncpy(ccxxname,na,MAXNAMEL-1); ccxxname[MAXNAMEL-1] = '\000';
625
649
/* Serial port flow control */
626
650
} else if (argv[fa][1] == 'W') {
628
if (na == NULL) usage(debug);
652
if (na == NULL) usage(debug, cl);
629
653
if (na[0] == 'n' || na[0] == 'N')
631
655
else if (na[0] == 'h' || na[0] == 'H')
683
/* See if there is an environment variable ccxx */
684
if (ccxxname[0] == '\000') {
686
if ((na = getenv("ARGYLL_COLMTER_CAL_SPEC_SET")) != NULL) {
687
strncpy(ccxxname,na,MAXNAMEL-1); ccxxname[MAXNAMEL-1] = '\000';
659
689
#ifndef SALONEINSTLIB
660
/* See if there is an environment variable ccmx */
662
char *na = getenv("ARGYLL_COLMTER_COR_MATRIX");
664
strncpy(ccmxname,na,MAXNAMEL-1); ccmxname[MAXNAMEL-1] = '\000';
690
} else if ((na = getenv("ARGYLL_COLMTER_COR_MATRIX")) != NULL) {
691
strncpy(ccxxname,na,MAXNAMEL-1); ccxxname[MAXNAMEL-1] = '\000';
669
696
/* - - - - - - - - - - - - - - - - - - - */
670
697
/* Setup the instrument ready to do reads */
671
if ((it = new_inst(comport, itype, debug, verb)) == NULL) {
698
if ((it = new_inst(comport, 0, debug, verb)) == NULL) {
672
699
warning("Unknown, inappropriate or no instrument detected");
807
/* Set CRT or LCD mode */
808
if (dtype == 1 || dtype == 2) {
813
om = inst_opt_proj_crt;
815
om = inst_opt_proj_lcd;
818
om = inst_opt_disp_crt;
820
om = inst_opt_disp_lcd;
823
if ((rv = it->set_opt_mode(it,om)) != inst_ok) {
824
printf("Setting %s mode %s not supported by instrument\n",
825
proj ? "projector" : "display", dtype == 1 ? "CRT" : "LCD");
829
} else if (proj && it->capabilities(it) & (inst_emis_proj_crt | inst_emis_proj_lcd)) {
830
printf("Either CRT or LCD must be selected\n");
834
} else if (it->capabilities(it) & (inst_emis_disp_crt | inst_emis_disp_lcd)) {
835
printf("Either CRT or LCD must be selected\n");
833
/* Set display type */
836
if (cap & inst_emis_disptype) {
838
if ((ix = inst_get_disptype_index(it, dtype)) == 0) {
843
if ((rv = it->set_opt_mode(it, inst_opt_disp_type, ix)) != inst_ok) {
844
printf("Setting display type ix %d not supported by instrument\n",ix);
849
printf("Display type ignored - instrument doesn't support display type\n");
851
} else if (cap & (inst_emis_disptypem)) {
852
printf("A display type must be selected\n");
866
/* If we have non-standard observer we need spectral or CCSS */
867
if (obType != icxOT_default && (cap & inst_spectral) == 0 && (cap & inst_ccss) == 0) {
868
printf("Non standard observer needs spectral information or CCSS capability\n");
869
printf("and instrument doesn't support either.\n");
874
/* If we don't have CCSS then we need spectral for non-standard observer */
875
if (obType != icxOT_default && (cap & inst_ccss) == 0) {
849
879
if ((spec || pspec) && (cap & inst_spectral) == 0) {
850
880
printf("Need spectral information for custom illuminant or observer\n");
851
881
printf("and instrument doesn't support it\n");
923
#ifndef SALONEINSTLIB
924
955
/* Colorimeter Correction Matrix */
925
if (ccmxname[0] != '\000') {
956
if (ccxxname[0] != '\000') {
958
#ifndef SALONEINSTLIB
928
if ((cap & inst_ccmx) == 0) {
929
printf("\nInstrument doesn't have Colorimeter Correction Matix capability\n");
933
if ((cmx = new_ccmx()) == NULL) {
961
if ((cx = new_ccmx()) == NULL) {
934
962
printf("\nnew_ccmx failed\n");
938
if (cmx->read_ccmx(cmx,ccmxname)) {
939
printf("\nReading Colorimeter Correction Matrix file '%s' failed with error %d:'%s'\n",
940
ccmxname, cmx->errc, cmx->err);
966
if (cx->read_ccmx(cx,ccxxname) == 0) {
967
if ((cap & inst_ccmx) == 0) {
968
printf("\nInstrument doesn't have Colorimeter Correction Matrix capability\n");
972
if ((rv = it->col_cor_mat(it, cx->matrix)) != inst_ok) {
973
printf("\nSetting Colorimeter Correction Matrix failed with error :'%s' (%s)\n",
974
it->inst_interp_error(it, rv), it->interp_error(it, rv));
983
#ifndef SALONEINSTLIB
988
/* CCMX failed, try CCSS */
989
if ((cs = new_ccss()) == NULL) {
990
printf("\nnew_ccss failed\n");
994
if (cs->read_ccss(cs,ccxxname)) {
995
printf("\nReading CCMX/CCSS File '%s' failed with error %d:'%s'\n",
996
ccxxname, cs->errc, cs->err);
1001
if ((cap & inst_ccss) == 0) {
1002
printf("\nInstrument doesn't have Colorimeter Calibration Spectral Sample capability\n");
1007
if ((rv = it->col_cal_spec_set(it, obType, NULL, cs->samples, cs->no_samp)) != inst_ok) {
1008
printf("\nSetting Colorimeter Calibration Spectral Samples failed with error :'%s' (%s)\n",
1009
it->inst_interp_error(it, rv), it->interp_error(it, rv));
945
if ((rv = it->col_cor_mat(it, cmx->matrix)) != inst_ok) {
946
printf("\nSetting Colorimeter Correction Matrix failed with error :'%s' (%s)\n",
1019
/* If non-standard observer wasn't set by a CCSS file above */
1020
if (obType != icxOT_default && (cap & inst_ccss) && ccssset == 0) {
1021
if ((rv = it->col_cal_spec_set(it, obType, NULL, NULL, 0)) != inst_ok) {
1022
printf("\nSetting Colorimeter Calibration Spectral Samples failed with error :'%s' (%s)\n",
947
1023
it->inst_interp_error(it, rv), it->interp_error(it, rv));
956
1029
/* If it batter powered, show the status of the battery */
957
1030
if ((cap2 & inst2_has_battery)) {
1029
1104
illum = icxIT_none;
1031
1106
/* Create a spectral conversion object */
1032
if ((sp2cie = new_xsp2cie(illum, &cust_illum, observ, NULL
1033
#ifndef SALONEINSTLIB
1035
#endif /* !SALONEINSTLIB */
1107
if ((sp2cie = new_xsp2cie(illum, &cust_illum, obType, NULL, icSigXYZData)) == NULL)
1037
1108
error("Creation of spectral conversion object failed");
1530
1613
error("Instrument didn't return spectral data");
1533
if (inst_illuminant(&insp, itype) != 0)
1616
if (inst_illuminant(&insp, it->get_itype(it)) != 0)
1534
1617
error ("Instrument doesn't have an FWA illuminent");
1536
1619
/* Creat the base conversion object */
1537
1620
if (sp2cief[fidx] == NULL) {
1538
if ((sp2cief[fidx] = new_xsp2cie(illum, &cust_illum, observ,
1621
if ((sp2cief[fidx] = new_xsp2cie(illum, &cust_illum, obType,
1539
1622
NULL, icSigXYZData)) == NULL)
1540
1623
error("Creation of spectral conversion object failed");
1681
1764
nxyz[1] = XYZ[1] / XYZ[1];
1683
1766
/* Compute CCT */
1684
if ((cct = icx_XYZ2ill_ct(axyz, icxIT_Ptemp, observ, NULL, XYZ, NULL, 0)) < 0)
1767
if ((cct = icx_XYZ2ill_ct(axyz, icxIT_Ptemp, obType, NULL, XYZ, NULL, 0)) < 0)
1685
1768
error ("Got bad cct\n");
1686
1769
axyz[0] /= axyz[1];
1687
1770
axyz[2] /= axyz[1];
1692
1775
cct_de = icmLabDE(lab, alab);
1694
1777
/* Compute VCT */
1695
if ((vct = icx_XYZ2ill_ct(axyz, icxIT_Ptemp, observ, NULL, XYZ, NULL, 1)) < 0)
1778
if ((vct = icx_XYZ2ill_ct(axyz, icxIT_Ptemp, obType, NULL, XYZ, NULL, 1)) < 0)
1696
1779
error ("Got bad vct\n");
1697
1780
axyz[0] /= axyz[1];
1698
1781
axyz[2] /= axyz[1];
1703
1786
vct_de = icmLabDE(lab, alab);
1705
1788
/* Compute VDT */
1706
if ((vdt = icx_XYZ2ill_ct(axyz, icxIT_Dtemp, observ, NULL, XYZ, NULL, 1)) < 0)
1789
if ((vdt = icx_XYZ2ill_ct(axyz, icxIT_Dtemp, obType, NULL, XYZ, NULL, 1)) < 0)
1707
1790
error ("Got bad vct\n");
1708
1791
axyz[0] /= axyz[1];
1709
1792
axyz[2] /= axyz[1];
1809
1892
if (rLab[0] >= -1.0) {
1894
double avg[3], sdev[3];
1896
for (j = 0; j < 3; j++) {
1897
rstat_Lab[j] += Lab[j];
1898
rstat_Labsq[j] += Lab[j] * Lab[j];
1900
avg[j] = rstat_Lab[j]/rstat_n;
1901
sdev[j] = sqrt(rstat_n * rstat_Labsq[j] - rstat_Lab[j] * rstat_Lab[j])/rstat_n;
1903
printf(" Lab stats %.0f: Avg %f %f %f, S.Dev %f %f %f\n",
1904
rstat_n, avg[0], avg[1], avg[2], sdev[0], sdev[1], sdev[2]);
1810
1906
#ifndef SALONEINSTLIB
1811
1907
printf(" Delta E to reference is %f %f %f (%f, CIE94 %f)\n",
1812
1908
Lab[0] - rLab[0], Lab[1] - rLab[1], Lab[2] - rLab[2],