80
81
/* ------------------------------------------------------------------- */
83
void usage(char *diag, ...) {
83
#ifdef NT /* You'd think there might be some standards.... */
85
# define stricmp _stricmp
88
# define stricmp strcasecmp
91
/* ------------------------------------------------------------------- */
94
void usage(iccss *cl, char *diag, ...) {
98
inst_capability cap = 0;
87
100
fprintf(stderr,"Read a Display, Version %s\n",ARGYLL_VERSION_STR);
88
101
fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n");
137
151
fprintf(stderr," ** No ports found **\n");
140
153
fprintf(stderr," -p Use projector mode (if available)\n");
141
fprintf(stderr," -y c|l Display type, c = CRT, l = LCD\n");
154
cap = inst_show_disptype_options(stderr, " -y ", icom);
142
155
fprintf(stderr," -k file.cal Load calibration file into display while reading\n");
143
156
fprintf(stderr," -K file.cal Apply calibration file to test values while reading\n");
144
157
fprintf(stderr," -s Save spectral information (default don't save)\n");
155
168
fprintf(stderr," -V Use adaptive measurement mode (if available)\n");
156
169
fprintf(stderr," -w Disable normalisation of white to Y = 100\n");
157
170
fprintf(stderr," -X file.ccmx Apply Colorimeter Correction Matrix\n");
171
fprintf(stderr," -X file.ccss Use Colorimeter Calibration Spectral Samples for calibration\n");
172
if (cap & inst_ccss) {
173
for (i = 0; cl != NULL && cl[i].desc != NULL; i++) {
175
fprintf(stderr," -X N 0: %s\n",cl[i].desc);
177
fprintf(stderr," %d: %s\n",i,cl[i].desc);
181
fprintf(stderr," -Q observ Choose CIE Observer for spectrometer or CCSS colorimeter data:\n");
182
fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2, 1964_10c\n");
158
183
fprintf(stderr," -I b|w Drift compensation, Black: -Ib, White: -Iw, Both: -Ibw\n");
159
184
fprintf(stderr," -C \"command\" Invoke shell \"command\" each time a color is set\n");
160
185
fprintf(stderr," -M \"command\" Invoke shell \"command\" each time a color is measured\n");
161
186
fprintf(stderr," -W n|h|x Override serial port flow control: n = none, h = HW, x = Xon/Xoff\n");
162
187
fprintf(stderr," -D [level] Print debug diagnostics to stderr\n");
163
188
fprintf(stderr," outfile Base name for input[ti1]/output[ti3] file\n");
167
int main(int argc, char *argv[])
194
int main(int argc, char *argv[]) {
170
196
int fa, nfa, mfa; /* current argument we're looking at */
171
197
disppath *disp = NULL; /* Display being used */
179
205
int override = 1; /* Override redirect on X11 */
180
206
int comport = COMPORT; /* COM port used */
181
207
flow_control fc = fc_nc; /* Default flow control */
182
instType itype = instUnknown; /* Default target instrument - none */
183
208
int docalib = 0; /* Do a calibration */
184
209
int highres = 0; /* Use high res mode if available */
185
210
int adaptive = 0; /* Use adaptive mode if available */
186
211
int bdrift = 0; /* Flag, nz for black drift compensation */
187
212
int wdrift = 0; /* Flag, nz for white drift compensation */
188
int dtype = 0; /* Display kind, 0 = default, 1 = CRT, 2 = LCD */
213
int dtype = 0; /* Display type selection charater */
189
214
int proj = 0; /* NZ if projector */
190
215
int noautocal = 0; /* Disable auto calibration */
191
216
int nonorm = 0; /* Disable normalisation */
192
char ccmxname[MAXNAMEL+1] = "\000"; /* Colorimeter Correction Matrix name */
217
char ccxxname[MAXNAMEL+1] = "\000"; /* Colorimeter Correction Matrix name */
218
iccss *cl = NULL; /* List of installed CCSS files */
219
int ncl = 0; /* Number of them */
193
220
ccmx *cmx = NULL; /* Colorimeter Correction Matrix */
221
ccss *ccs = NULL; /* Colorimeter Calibration Spectral Samples */
194
222
int spec = 0; /* Don't save spectral information */
223
icxObserverType obType = icxOT_default;
224
int webdisp = 0; /* NZ for web display, == port number */
195
225
char *ccallout = NULL; /* Change color Shell callout */
196
226
char *mcallout = NULL; /* Measure color Shell callout */
197
227
char inname[MAXNAMEL+1] = "\000"; /* Input cgats file base name */
198
228
char outname[MAXNAMEL+1] = "\000"; /* Output cgats file base name */
199
char calname[MAXNAMEL+1] = "\000"; /* Calibration file name */
229
char calname[MAXNAMEL+1] = "\000"; /* Calibration file name (if any) */
200
230
int softcal = 0; /* nz if cal applied to values rather than hardware */
201
231
double cal[3][MAX_CAL_ENT]; /* Display calibration */
202
232
int ncal = 256; /* number of cal entries used */
259
293
if (argv[fa][1] == '?' || argv[fa][1] == '-') {
260
usage("Usage requested");
294
usage(cl, "Usage requested");
262
296
} else if (argv[fa][1] == 'v') {
265
299
/* Display number */
266
300
} else if (argv[fa][1] == 'd') {
301
if (strncmp(na,"web",3) == 0
302
|| strncmp(na,"WEB",3) == 0) {
305
webdisp = atoi(na+4);
306
if (webdisp == 0 || webdisp > 65535)
307
usage(cl,"Web port number must be in range 1..65535");
267
311
#if defined(UNIX) && !defined(__APPLE__)
270
if (strcmp(&argv[fa][2], "isplay") == 0 || strcmp(&argv[fa][2], "ISPLAY") == 0) {
271
if (++fa >= argc || argv[fa][0] == '-') usage("Parameter expected following -display");
272
setenv("DISPLAY", argv[fa], 1);
274
if (na == NULL) usage("Parameter expected following -d");
314
if (strcmp(&argv[fa][2], "isplay") == 0 || strcmp(&argv[fa][2], "ISPLAY") == 0) {
315
if (++fa >= argc || argv[fa][0] == '-') usage(cl, "Parameter expected following -display");
316
setenv("DISPLAY", argv[fa], 1);
318
if (na == NULL) usage(cl, "Parameter expected following -d");
320
if (strcmp(na,"fake") == 0) {
323
if (sscanf(na, "%d,%d",&ix,&iv) != 2) {
328
free_a_disppath(disp);
329
if ((disp = get_a_display(ix-1)) == NULL)
330
usage(cl, "-d parameter %d out of range",ix);
332
disp->rscreen = iv-1;
337
if (na == NULL) usage(cl, "Parameter expected following -d");
276
339
if (strcmp(na,"fake") == 0) {
279
if (sscanf(na, "%d,%d",&ix,&iv) != 2) {
283
343
if (disp != NULL)
284
344
free_a_disppath(disp);
285
345
if ((disp = get_a_display(ix-1)) == NULL)
286
usage("-d parameter %d out of range",ix);
288
disp->rscreen = iv-1;
346
usage(cl, "-d parameter %d out of range",ix);
293
if (na == NULL) usage("Parameter expected following -d");
295
if (strcmp(na,"fake") == 0) {
300
free_a_disppath(disp);
301
if ((disp = get_a_display(ix-1)) == NULL)
302
usage("-d parameter %d out of range",ix);
305
350
#if defined(UNIX) && !defined(__APPLE__)
306
351
} else if (argv[fa][1] == 'n') {
311
356
} else if (argv[fa][1] == 'c') {
313
if (na == NULL) usage("Paramater expected following -c");
358
if (na == NULL) usage(cl, "Paramater expected following -c");
314
359
comport = atoi(na);
315
if (comport < 1 || comport > 50) usage("-c parameter %d out of range",comport);
360
if (comport < 1 || comport > 50) usage(cl, "-c parameter %d out of range",comport);
318
363
} else if (argv[fa][1] == 'p') {
321
366
/* Display type */
322
367
} else if (argv[fa][1] == 'y' || argv[fa][1] == 'Y') {
324
if (na == NULL) usage("Parameter expected after -y");
325
if (na[0] == 'c' || na[0] == 'C')
327
else if (na[0] == 'l' || na[0] == 'L')
330
usage("-y parameter '%c' not recognised",na[0]);
369
if (na == NULL) usage(cl, "Parameter expected after -y");
332
372
/* Calibration file */
333
373
} else if (argv[fa][1] == 'k' || argv[fa][1] == 'K') {
335
if (na == NULL) usage("Parameter expected after -k");
375
if (na == NULL) usage(cl, "Parameter expected after -k/-K");
336
376
strncpy(calname,na,MAXNAMEL); calname[MAXNAMEL] = '\000';
338
378
if (argv[fa][1] == 'K')
346
386
/* Test patch offset and size */
347
387
} else if (argv[fa][1] == 'P') {
349
if (na == NULL) usage("Parameter expected after -P");
389
if (na == NULL) usage(cl, "Parameter expected after -P");
350
390
if (sscanf(na, " %lf,%lf,%lf ", &ho, &vo, &patscale) != 3)
351
usage("-P parameter '%s' not recognised",na);
391
usage(cl, "-P parameter '%s' not recognised",na);
352
392
if (ho < 0.0 || ho > 1.0
353
393
|| vo < 0.0 || vo > 1.0
354
394
|| patscale <= 0.0 || patscale > 50.0)
355
usage("-P parameters %f %f %f out of range",ho,vo,patscale);
395
usage(cl, "-P parameters %f %f %f out of range",ho,vo,patscale);
356
396
ho = 2.0 * ho - 1.0;
357
397
vo = 2.0 * vo - 1.0;
383
423
/* Colorimeter Correction Matrix */
424
/* or Colorimeter Calibration Spectral Samples */
384
425
} else if (argv[fa][1] == 'X') {
386
if (na == NULL) usage("Parameter expected after -X");
387
strncpy(ccmxname,na,MAXNAMEL-1); ccmxname[MAXNAMEL-1] = '\000';
428
if (na == NULL) usage(cl,"Parameter expected following -X");
429
if (ncl > 0 && sscanf(na, " %d ", &ix) == 1) {
430
if (ix < 0 || ix > ncl)
431
usage(cl, "-X ccss selection is out of range");
432
strncpy(ccxxname,cl[ix].path,MAXNAMEL-1); ccxxname[MAXNAMEL-1] = '\000';
434
strncpy(ccxxname,na,MAXNAMEL-1); ccxxname[MAXNAMEL-1] = '\000';
389
437
} else if (argv[fa][1] == 'I') {
391
if (na == NULL || na[0] == '\000') usage("Parameter expected after -I");
439
if (na == NULL || na[0] == '\000') usage(cl, "Parameter expected after -I");
392
440
for (i=0; ; i++) {
393
441
if (na[i] == '\000')
397
445
else if (na[i] == 'w' || na[i] == 'W')
400
usage("-I parameter '%c' not recognised",na[i]);
448
usage(cl, "-I parameter '%c' not recognised",na[i]);
451
/* Spectral Observer type */
452
} else if (argv[fa][1] == 'Q') {
454
if (na == NULL) usage(cl,"Parameter expecte after -Q");
455
if (strcmp(na, "1931_2") == 0) { /* Classic 2 degree */
456
obType = icxOT_CIE_1931_2;
457
} else if (strcmp(na, "1964_10") == 0) { /* Classic 10 degree */
458
obType = icxOT_CIE_1964_10;
459
} else if (strcmp(na, "1964_10c") == 0) { /* 10 degree corrected */
460
obType = icxOT_CIE_1964_10c;
461
} else if (strcmp(na, "1955_2") == 0) { /* Stiles and Burch 1955 2 degree */
462
obType = icxOT_Stiles_Burch_2;
463
} else if (strcmp(na, "1978_2") == 0) { /* Judd and Voss 1978 2 degree */
464
obType = icxOT_Judd_Voss_2;
465
} else if (strcmp(na, "shaw") == 0) { /* Shaw and Fairchilds 1997 2 degree */
466
obType = icxOT_Shaw_Fairchild_2;
468
usage(cl,"-Q parameter '%s' not recognised",na);
403
471
/* Change color callout */
404
472
} else if (argv[fa][1] == 'C') {
406
if (na == NULL) usage("Parameter expected after -C");
474
if (na == NULL) usage(cl, "Parameter expected after -C");
409
477
/* Measure color callout */
410
478
} else if (argv[fa][1] == 'M') {
412
if (na == NULL) usage("Parameter expected after -M");
480
if (na == NULL) usage(cl, "Parameter expected after -M");
415
483
/* Serial port flow control */
416
484
} else if (argv[fa][1] == 'W') {
418
if (na == NULL) usage("Parameter expected after -W");
486
if (na == NULL) usage(cl, "Parameter expected after -W");
419
487
if (na[0] == 'n' || na[0] == 'N')
421
489
else if (na[0] == 'h' || na[0] == 'H')
461
529
error("Unable to open the default display");
464
/* See if there is an environment variable ccmx */
466
char *na = getenv("ARGYLL_COLMTER_COR_MATRIX");
468
strncpy(ccmxname,na,MAXNAMEL-1); ccmxname[MAXNAMEL-1] = '\000';
532
/* See if there is an environment variable ccxx */
533
if (ccxxname[0] == '\000') {
535
if ((na = getenv("ARGYLL_COLMTER_CAL_SPEC_SET")) != NULL) {
536
strncpy(ccxxname,na,MAXNAMEL-1); ccxxname[MAXNAMEL-1] = '\000';
538
} else if ((na = getenv("ARGYLL_COLMTER_COR_MATRIX")) != NULL) {
539
strncpy(ccxxname,na,MAXNAMEL-1); ccxxname[MAXNAMEL-1] = '\000';
471
/* Colorimeter Correction Matrix */
472
if (ccmxname[0] != '\000') {
473
if ((cmx = new_ccmx()) == NULL)
474
error("new_ccmx failed\n");
475
if (cmx->read_ccmx(cmx,ccmxname))
476
error("Reading Colorimeter Correction Matrix file '%s' failed with error %d:'%s'\n",
477
ccmxname, cmx->errc, cmx->err);
543
/* Load up CCMX or CCSS */
544
if (ccxxname[0] != '\000') {
545
if ((cmx = new_ccmx()) == NULL
546
|| cmx->read_ccmx(cmx, ccxxname)) {
552
/* CCMX failed, try CCSS */
553
if ((ccs = new_ccss()) == NULL
554
|| ccs->read_ccss(ccs, ccxxname)) {
558
error("Reading CCMX/CCSS File '%s' failed\n", ccxxname);
481
if ((rv = disprd_calibration(itype, comport, fc, dtype, proj, adaptive, noautocal, disp,
482
blackbg, override, patsize, ho, vo, verb, debug)) != 0) {
565
if ((rv = disprd_calibration(comport, fc, dtype, proj, adaptive, noautocal, disp,
566
webdisp, blackbg, override, patsize, ho, vo,
567
verb, debug)) != 0) {
483
568
error("docalibration failed with return value %d\n",rv);
487
572
/* Get the file name argument */
488
if (fa >= argc || argv[fa][0] == '-') usage("Filname parameter not found");
573
if (fa >= argc || argv[fa][0] == '-') usage(cl, "Filname parameter not found");
489
574
strncpy(inname,argv[fa++],MAXNAMEL-4); inname[MAXNAMEL-4] = '\000';
490
575
strcpy(outname,inname);
491
576
strcat(inname,".ti1");
623
709
if (strcmp(ccg->t[0].kdata[fi],"DISPLAY") != 0)
624
710
error ("Calibration file '%s' doesn't have DEVICE_CLASS of DISPLAY",calname);
712
if ((fi = ccg->find_kword(ccg, 0, "VIDEO_LUT_CALIBRATION_POSSIBLE")) >= 0) {
713
if (stricmp(ccg->t[0].kdata[fi],"NO") == 0) {
715
if (verb) printf("Switching to soft cal because there is no access to VideoLUTs\n");
626
719
if ((fi = ccg->find_kword(ccg, 0, "COLOR_REP")) < 0)
627
720
error ("Calibration file '%s' doesn't contain keyword COLOR_REP",calname);
628
721
if (strcmp(ccg->t[0].kdata[fi],"RGB") != 0)
654
747
cal[0][0] = -1.0; /* Not used */
657
if ((dr = new_disprd(&errc, itype, fake ? -99 : comport, fc, dtype, proj, adaptive, noautocal,
658
highres, 0, cal, ncal, softcal, disp, blackbg, override, ccallout,
659
mcallout, patsize, ho, vo, cmx != NULL ? cmx->matrix : NULL,
660
spec, icxOT_none, bdrift, wdrift, verb, VERBOUT, debug,
750
if ((dr = new_disprd(&errc, fake ? -99 : comport, fc, dtype, proj, adaptive, noautocal,
751
highres, 0, &noramdac, cal, ncal, softcal, disp, blackbg, override,
752
webdisp, ccallout, mcallout, patsize, ho, vo,
753
cmx != NULL ? cmx->matrix : NULL,
754
ccs != NULL ? ccs->samples : NULL, ccs != NULL ? ccs->no_samp : 0,
755
spec, obType, NULL, bdrift, wdrift, verb, VERBOUT, debug,
661
756
"fake" ICC_FILE_EXT)) == NULL)
662
757
error("new_disprd failed with '%s'\n",disprd_err(errc));
763
free_iccss(cl); cl = NULL; ncl = 0;
667
765
/* Test the CRT with all of the test points */
668
766
if ((rv = dr->read(dr, cols, npat + xpat, 1, npat + xpat, 1, 0)) != 0) {
670
768
error("test_crt returned error code %d\n",rv);
672
770
/* Note what instrument the chart was read with */
673
ocg->add_kword(ocg, 0, "TARGET_INSTRUMENT", inst_name(dr->itype) , NULL);
772
ocg->add_kword(ocg, 0, "TARGET_INSTRUMENT", inst_name(dr->it->get_itype(dr->it)) , NULL);
774
ocg->add_kword(ocg, 0, "TARGET_INSTRUMENT", "Fake" , NULL);
675
776
/* Note if the instrument is natively spectral or not */
676
777
if (dr->it != NULL && dr->it->capabilities(dr->it) & inst_spectral)
775
876
ocg->add_kword(ocg, 0, "NORMALIZED_TO_Y_100","NO", NULL);
777
878
/* Write out the calibration if we have it */
778
if (cal[0][0] >= 0.0) {
879
if (cal != NULL && cal[0][0] >= 0.0) {
779
880
ocg->add_other(ocg, "CAL"); /* our special type is Calibration file */
780
881
ocg->add_table(ocg, tt_other, 1); /* Add another table for RAMDAC values */
781
882
ocg->add_kword(ocg, 1, "DESCRIPTOR", "Argyll Device Calibration State",NULL);
785
886
ocg->add_kword(ocg, 1, "DEVICE_CLASS","DISPLAY", NULL);
786
887
ocg->add_kword(ocg, 1, "COLOR_REP","RGB", NULL);
888
ocg->add_kword(ocg, 0, "VIDEO_LUT_CALIBRATION_POSSIBLE",noramdac ? "NO" : "YES", NULL);
788
890
ocg->add_field(ocg, 1, "RGB_I", r_t);
789
891
ocg->add_field(ocg, 1, "RGB_R", r_t);