1
2 /* Illuminant measurement utility */
3
4 /*
5 * Argyll Color Correction System
6 * Author: Graeme W. Gill
7 * Date: 3/10/2001
8 *
9 * Derived from printread.c/chartread.c
10 * Was called printspot.
11 *
12 * Copyright 2001 - 2013 Graeme W. Gill
13 * All rights reserved.
14 *
15 * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
16 * see the License.txt file for licencing details.
17 */
18
19 /* This program uses an instrument capable of spectral illuminant/emissive */
20 /* and reflective (non-UV filtered) measurement, to measure an illuminant */
21 /* spectrum that includes a UV estimate. */
22
23 /* Based on spotread.c */
24
25 /*
26 TTBD:
27
28 Should add support for converting Spyder correction readings to ccmx.
29 (see SpyderDeviceCorrections.txt)
30
31 */
32
33 /*
34 Test mode files restored/saved:
35
36 outname_i.sp Illuminant spectrum
37 outname_r.sp Illuminant off paper spectrum
38 outname_p.sp Instrument measured paper reflectance spectrum
39
40 Just saved:
41
42 outname_mpir.sp Measured paper under illuminant spectrum
43 outname_cpir.sp Computed paper under illuminant spectrum
44 */
45
46 #undef DEBUG /* Debug messages */
47 #undef PLOT_FITTING /* Plot the fitting itterations */
48 #undef SHOWDXX /* Plot the best matched daylight as well */
49
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <math.h>
53 #include <sys/types.h>
54 #include <time.h>
55 #include <string.h>
56 #include "copyright.h"
57 #include "aconfig.h"
58 #include "numlib.h"
59 #include "cgats.h"
60 #include "xicc.h"
61 #include "conv.h"
62 #include "inst.h"
63 #include "icoms.h"
64 #include "instappsup.h"
65 #include "plot.h"
66 #include "ui.h"
67 #ifdef ENABLE_USB
68 # include "spyd2.h"
69 #endif
70
71 #include <stdarg.h>
72
73 #if defined (NT)
74 #include <conio.h>
75 #endif
76
77 /* Deal with an instrument error. */
78 /* Return 0 to retry, 1 to abort */
ierror(inst * it,inst_code ic)79 static int ierror(inst *it, inst_code ic) {
80 int ch;
81 empty_con_chars();
82 printf("Got '%s' (%s) error.\nHit Esc or Q to give up, any other key to retry:",
83 it->inst_interp_error(it, ic), it->interp_error(it, ic));
84 fflush(stdout);
85 ch = next_con_char();
86 printf("\n");
87 if (ch == 0x03 || ch == 0x1b || ch == 'q' || ch == 'Q') /* Escape, ^C or Q */
88 return 1;
89 return 0;
90 }
91
92 #if defined(__APPLE__) && defined(__POWERPC__)
93
94 /* Workaround for a ppc gcc 3.3 optimiser bug... */
gcc_bug_fix(int i)95 static int gcc_bug_fix(int i) {
96 static int nn;
97 nn += i;
98 return nn;
99 }
100
101 #define GCC_BUGFIX(XX) gcc_bug_fix(XX);
102 #else /* !APPLE */
103 #define GCC_BUGFIX(XX)
104 #endif /* !APPLE */
105
106
107 /* ============================================================== */
108 /* optimizer callback */
109
110 /* Structure to hold optimisation information */
111 typedef struct {
112 xspect *i_sp; /* Illuminiant measurement */
113 xspect *r_sp; /* Illuminant off paper measurement */
114 xspect *p_sp; /* Paper reflectance measurement */
115
116 xsp2cie *pap; /* Estimated illuminant + UV on paper lookup inc FWA */
117 xsp2cie *ref; /* Measured illuminant on paper lookup */
118
119 xspect ill; /* Illuminant with UV added - set by bfindfunc() */
120 xspect cpsp; /* FWA corrected calculated paper reflectance */
121 xspect srop; /* Scaled measured paper reflectance */
122
123 double lab0[3], lab1[3]; /* Conversion of calculated vs. measured */
124 } bfinds;
125
126 /* Optimize the UV content that minimizes the (weighted) Delta E */
bfindfunc(void * adata,double pv[])127 static double bfindfunc(void *adata, double pv[]) {
128 bfinds *b = (bfinds *)adata;
129 int i;
130 double rv = 0.0;
131
132 /* Add UV level to illuminant */
133 b->ill = *b->i_sp; /* Structure copy */
134 xsp_setUV(&b->ill, b->i_sp, pv[0]); /* Extends ill range into UV */
135
136 #ifdef NEVER /* Plot the two reflectance spectra */
137 printf("Black = Measured illum, Red = illum + %f UV\n",pv[0]);
138 xspect_plot(b->i_sp, &b->ill, NULL);
139 #endif
140
141 /* Update the conversion to use observer illuminant with UV */
142 if (b->pap->update_fwa_custillum(b->pap, NULL, &b->ill) != 0)
143 error ("Updating FWA compensation failed");
144
145 /* Apply FWA compensation to the paper reflectance */
146 b->pap->sconvert(b->pap, &b->cpsp, b->lab0, b->p_sp);
147
148 /* Adjust gain factor of measured illuminant off paper */
149 /* and divide by illuminant measurement to give reflectance */
150 b->srop = *b->r_sp;
151 for (i = 0; i < b->r_sp->spec_n; i++) {
152 double ww = XSPECT_XWL(b->r_sp, i);
153 double ival = value_xspect(b->i_sp, ww);
154 if (ival < 0.05) /* Stop noise sending it wild */
155 ival = 0.05;
156 b->srop.spec[i] *= pv[1]/ival;
157 if (b->srop.spec[i] < 0.0)
158 b->srop.spec[i] = 0.0;
159 }
160
161 /* Compute Lab of the computed reflectance under flat spectrum */
162 b->ref->convert(b->ref, b->lab0, &b->cpsp);
163
164 /* Compute Lab value of illuminant measured reflectance */
165 b->ref->convert(b->ref, b->lab1, &b->srop);
166
167 /* Weighted Delta E (low weight on a* error) */
168 rv = sqrt( (b->lab0[0] - b->lab1[0]) * (b->lab0[0] - b->lab1[0])
169 + 0.1 * (b->lab0[1] - b->lab1[1]) * (b->lab0[1] - b->lab1[1])
170 + (b->lab0[2] - b->lab1[2]) * (b->lab0[2] - b->lab1[2]));
171
172 /* Add a slight weight of the UV level, to minimize it */
173 /* if the case is unconstrained. */
174 rv += 0.1 * fabs(pv[0]);
175
176 #ifdef PLOT_FITTING /* Plot the two reflectance spectra */
177 printf("rev = %f (%f %f %f - %f %f %f) from UV %f GA %f\n",rv, b->lab0[0], b->lab0[1], b->lab0[2], b->lab1[0], b->lab1[1], b->lab1[2], pv[0], pv[1]);
178
179 printf("Black = Measured, Red = trial\n");
180 xspect_plot(&b->srop, &b->cpsp, NULL);
181 #endif
182
183 return rv;
184 }
185
186 /* ============================================================== */
187 #ifdef SHOWDXX /* Plot the best matched daylight as well */
188
189 /* optimizer callback for computing daylight match */
190
191 /* Structure to hold optimisation information */
192 typedef struct {
193 xspect ill; /* Illuminant with UV added - target */
194 xspect dxx; /* Daylight spectrum */
195
196 xsp2cie *ref; /* reference Lab conversion */
197
198 double lab0[3], lab1[3]; /* Conversion of target vs. Daylight */
199 } cfinds;
200
201 /* Optimize the daylight color temperature and level to minimizes the Delta E */
cfindfunc(void * adata,double pv[])202 static double cfindfunc(void *adata, double pv[]) {
203 cfinds *b = (cfinds *)adata;
204 int i;
205 double rv = 0.0;
206
207 /* Compute daylight with the given color temperature */
208 standardIlluminant( &b->dxx, icxIT_Dtemp, pv[0]);
209 b->dxx.norm = 1.0;
210
211 /* Adjust the level of daylight spectra */
212 for (i = 0; i < b->dxx.spec_n; i++) {
213 b->dxx.spec[i] *= pv[1];
214 }
215
216 /* Compute Lab of target */
217 b->ref->convert(b->ref, b->lab0, &b->ill);
218
219 /* Compute Lab of Dxx */
220 b->ref->convert(b->ref, b->lab1, &b->dxx);
221
222 /* Weighted Delta E (low weight on a* error) */
223 rv = icmLabDEsq(b->lab0, b->lab1);
224
225 //printf("~1 rev = %f (%f %f %f - %f %f %f) from %f %f\n",rv, b->lab0[0], b->lab0[1], b->lab0[2], b->lab1[0], b->lab1[1], b->lab1[2], pv[0], pv[1]);
226 return rv;
227 }
228
229 #endif /* SHOWDXX */
230
231 /* ============================================================== */
232 void
usage(char * diag,...)233 usage(char *diag, ...) {
234 icompaths *icmps;
235 fprintf(stderr,"Measure an illuminant, Version %s\n",ARGYLL_VERSION_STR);
236 fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n");
237 if (diag != NULL) {
238 va_list args;
239 fprintf(stderr,"Diagnostic: ");
240 va_start(args, diag);
241 vfprintf(stderr, diag, args);
242 va_end(args);
243 fprintf(stderr,"\n");
244 }
245 fprintf(stderr,"usage: illumread [-options] output.sp\n");
246 fprintf(stderr," -v Verbose mode\n");
247 fprintf(stderr," -S Plot spectrum for each reading\n");
248 fprintf(stderr," -c listno Choose instrument from the following list (default 1)\n");
249 if ((icmps = new_icompaths(g_log)) != NULL) {
250 icompath **paths;
251 if ((paths = icmps->paths) != NULL) {
252 int i;
253 for (i = 0; ; i++) {
254 if (paths[i] == NULL)
255 break;
256 if ((paths[i]->itype == instSpyder1 && setup_spyd2(0) == 0)
257 || (paths[i]->itype == instSpyder2 && setup_spyd2(1) == 0))
258 fprintf(stderr," %d = '%s' !! Disabled - no firmware !!\n",i+1,paths[i]->name);
259 else
260 fprintf(stderr," %d = '%s'\n",i+1,paths[i]->name);
261 }
262 } else
263 fprintf(stderr," ** No ports found **\n");
264 }
265 fprintf(stderr," -N Disable initial calibration of instrument if possible\n");
266 fprintf(stderr," -H Use high resolution spectrum mode (if available)\n");
267 fprintf(stderr," -Y r Set refresh measurement mode\n");
268 fprintf(stderr," -Y R:rate Override measured refresh rate with rate Hz\n");
269 fprintf(stderr," -W n|h|x Override serial port flow control: n = none, h = HW, x = Xon/Xoff\n");
270 fprintf(stderr," -T Test mode - restore & save measurements to\n");
271 fprintf(stderr," *_i.sp, *_r.sp, *_p.sp, *_mpir.sp, *_cpir.sp files\n");
272 fprintf(stderr," -D [level] Print debug diagnostics to stderr\n");
273 fprintf(stderr," illuminant.sp File to save measurement to\n");
274
275 if (icmps != NULL)
276 icmps->del(icmps);
277 exit(1);
278 }
279
main(int argc,char * argv[])280 int main(int argc, char *argv[])
281 {
282 int i,j;
283 int fa, nfa, mfa; /* current argument we're looking at */
284 int verb = 0;
285 int debug = 0;
286 int nocal = 0; /* Disable initial calibration */
287 int pspec = 0; /* 2 = Plot out the spectrum for each reading */
288 int highres = 0; /* Use high res mode if available */
289 int refrmode = -1; /* -1 = default, = non-refresh mode, 1 = non-refresh mode */
290 double refrate = 0.0; /* 0.0 = default, > 0.0 = override refresh rate */
291 char outname[MAXNAMEL+1] = "\000"; /* Spectral output file name */
292
293 int tmode = 0; /* Test mode */
294 char tname[MAXNAMEL+11] = "\000", *tnp; /* Test mode file names */
295 int rd_i = 0, rd_r = 0, rd_p = 0; /* Test mode flags */
296
297 icompaths *icmps = NULL; /* Ports to choose from */
298 int comno = 1; /* Specific port suggested by user */
299 inst *it = NULL; /* Instrument object, NULL if none */
300 inst_mode mode = 0; /* Instrument reading mode */
301 inst_opt_type trigmode = inst_opt_unknown; /* Chosen trigger mode */
302 instType itype = instUnknown; /* No default target instrument */
303 inst_mode cap = inst_mode_none; /* Instrument mode capabilities */
304 inst2_capability cap2 = inst2_none; /* Instrument capabilities 2 */
305 inst3_capability cap3 = inst3_none; /* Instrument capabilities 3 */
306 baud_rate br = baud_38400; /* Target baud rate */
307 flow_control fc = fc_nc; /* Default flow control */
308
309 inst_code rv;
310 int uswitch = 0; /* Instrument switch is enabled */
311 xspect i_sp; /* Illuminant emsission spectrum */
312 xspect r_sp; /* Illuminant reflected from paper emission spectrum */
313 xspect p_sp; /* Paper reflectance spectrum */
314 xspect insp; /* Instrument illuminant (for FWA) */
315 xspect ill; /* Estimated illuminant */
316 xspect aill; /* Accumulated result */
317 int nacc = 0; /* Number accumulated */
318 ipatch val; /* Value read */
319
320 set_exe_path(argv[0]); /* Set global exe_path and error_program */
321 check_if_not_interactive();
322
323 i_sp.spec_n = 0;
324 r_sp.spec_n = 0;
325 p_sp.spec_n = 0;
326 insp.spec_n = 0;
327 ill.spec_n = 0;
328 aill.spec_n = 0;
329
330 /* Process the arguments */
331 mfa = 0; /* Minimum final arguments */
332 for(fa = 1;fa < argc;fa++) {
333 nfa = fa; /* skip to nfa if next argument is used */
334 if (argv[fa][0] == '-') { /* Look for any flags */
335 char *na = NULL; /* next argument after flag, null if none */
336
337 if (argv[fa][2] != '\000')
338 na = &argv[fa][2]; /* next is directly after flag */
339 else {
340 if ((fa+1+mfa) < argc) {
341 if (argv[fa+1][0] != '-') {
342 nfa = fa + 1;
343 na = argv[nfa]; /* next is seperate non-flag argument */
344 }
345 }
346 }
347
348 if (argv[fa][1] == '?') {
349 usage(NULL);
350
351 } else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
352 verb = 1;
353 g_log->verb = verb;
354
355 } else if (argv[fa][1] == 'S') {
356 pspec = 2;
357
358 /* COM port */
359 } else if (argv[fa][1] == 'c') {
360 fa = nfa;
361 if (na == NULL) usage(NULL);
362 comno = atoi(na);
363 if (comno < 1 || comno > 99) usage(NULL);
364
365 /* No initial calibration */
366 } else if (argv[fa][1] == 'N') {
367 nocal = 1;
368
369 /* High res mode */
370 } else if (argv[fa][1] == 'H') {
371 highres = 1;
372
373 /* Extra flags */
374 } else if (argv[fa][1] == 'Y') {
375 if (na == NULL)
376 usage(NULL);
377
378 if (na[0] == 'R') {
379 if (na[1] != ':')
380 usage("-Y R:rate syntax incorrect");
381 refrate = atof(na+2);
382 if (refrate < 5.0 || refrate > 150.0)
383 usage("-Y R:rate %f Hz not in valid range",refrate);
384 } else if (na[0] == 'r')
385 refrmode = 1;
386 else
387 usage(NULL);
388 fa = nfa;
389
390 /* Serial port flow control */
391 } else if (argv[fa][1] == 'W') {
392 fa = nfa;
393 if (na == NULL) usage(NULL);
394
395 if (na[0] == 'n' || na[0] == 'N')
396 fc = fc_None;
397 else if (na[0] == 'h' || na[0] == 'H')
398 fc = fc_Hardware;
399 else if (na[0] == 'x' || na[0] == 'X')
400 fc = fc_XonXOff;
401 else
402 usage(NULL);
403
404 } else if (argv[fa][1] == 'T') {
405 tmode = 1;
406
407 } else if (argv[fa][1] == 'D') {
408 debug = 1;
409 if (na != NULL && na[0] >= '0' && na[0] <= '9') {
410 debug = atoi(na);
411 fa = nfa;
412 }
413 g_log->debug = debug;
414 } else
415 usage(NULL);
416 }
417 else
418 break;
419 }
420
421 /* Get the output spectrum file name argument */
422 if (fa >= argc)
423 usage(NULL);
424
425 strncpy(outname,argv[fa++],MAXNAMEL-1); outname[MAXNAMEL-1] = '\000';
426
427 if (tmode) {
428 strcpy(tname, outname);
429 if ((tnp = strrchr(tname, '.')) == NULL)
430 tnp = tname + strlen(tname);
431
432 /* Special debug */
433 strcpy(tnp, "_i.sp");
434 if (read_xspect(&i_sp, NULL, tname) == 0) {
435 rd_i = 1;
436 printf("(Found '%s' file and loaded it)\n",tname);
437 }
438 strcpy(tnp, "_r.sp");
439 if (read_xspect(&r_sp, NULL, tname) == 0) {
440 rd_r = 1;
441 printf("(Found '%s' file and loaded it)\n",tname);
442 }
443 strcpy(tnp, "_p.sp");
444 if (read_xspect(&p_sp, NULL, tname) == 0) {
445 rd_p = 1;
446 /* Should read instrument type from debug_p.sp !! */
447 if (inst_illuminant(&insp, instI1Pro) != 0) /* Hack !! */
448 error ("Instrument doesn't have an FWA illuminent");
449 printf("(Found '%s' file and loaded it)\n",tname);
450 }
451 }
452
453 /* Until the measurements are done, or we give up */
454 for (;;) {
455 int c;
456
457 /* Print the menue of adjustments */
458 printf("\nPress 1 .. 7\n");
459 printf("1) Measure direct illuminant%s\n",i_sp.spec_n != 0 ? " (measured)":"");
460 printf("2) Measure illuminant reflected from paper%s\n", r_sp.spec_n != 0 ? " (measured)":"");
461 printf("3) Measure paper%s\n", p_sp.spec_n != 0 ? " (measured)":"");
462 if (it == NULL) {
463 printf("4) Select another instrument, Currently %d (", comno);
464 if (icmps == NULL)
465 icmps = new_icompaths(g_log);
466 else
467 icmps->refresh(icmps);
468 if (icmps != NULL) {
469 icompath **paths;
470 if ((paths = icmps->paths) != NULL) {
471 int i;
472 for (i = 0; ; i++) {
473 if (paths[i] == NULL)
474 break;
475 if ((i+1) == comno) {
476 printf(" '%s'",paths[i]->name);
477 break;
478 }
479 }
480 }
481 }
482 printf(")\n");
483 } else
484 printf("4) Select another instrument, Currently %s\n", inst_name(itype));
485 printf("5) Compute illuminant spectrum, average result with %d previous readings & save it\n",nacc);
486 printf("6) Compute illuminant spectrum from this reading & save result\n");
487 printf("7) Exit\n");
488
489 empty_con_chars();
490 c = next_con_char();
491 printf("'%c'\n",c);
492
493 /* Deal with doing a measurement */
494 if (c == '1' || c == '2' || c == '3') {
495 int ch;
496
497 if (it == NULL) {
498 icompath *ipath;
499 if (icmps == NULL)
500 icmps = new_icompaths(g_log);
501
502 /* Open the instrument */
503 ipath = icmps->get_path(icmps, comno);
504 if ((it = new_inst(ipath, 0, g_log, DUIH_FUNC_AND_CONTEXT)) == NULL) {
505 printf("!!! Unknown, inappropriate or no instrument detected !!!\n");
506 continue;
507 }
508
509 if (verb)
510 printf("Connecting to the instrument ..\n");
511
512 #ifdef DEBUG
513 printf("About to init the comms\n");
514 #endif
515
516 /* Establish communications */
517 if ((rv = it->init_coms(it, br, fc, 15.0)) != inst_ok) {
518 printf("!!! Failed to initialise communications with instrument\n"
519 " or wrong instrument or bad configuration !!!\n"
520 " ('%s' + '%s')\n", it->inst_interp_error(it, rv), it->interp_error(it, rv));
521 it->del(it);
522 it = NULL;
523 itype = instUnknown;
524 continue;
525 }
526
527 #ifdef DEBUG
528 printf("Established comms & initing the instrument\n");
529 #endif
530
531 /* Initialise the instrument */
532 if ((rv = it->init_inst(it)) != inst_ok) {
533 printf("!!! Instrument initialisation failed with '%s' (%s) !!!\n",
534 it->inst_interp_error(it, rv), it->interp_error(it, rv));
535 it->del(it);
536 it = NULL;
537 itype = instUnknown;
538 continue;
539 }
540
541 itype = it->get_itype(it); /* get actual type of instrument */
542
543 /* Check the instrument has the necessary capabilities */
544 it->capabilities(it, &cap, &cap2, &cap3);
545
546 /* Need spectral */
547 if (!IMODETST(cap, inst_mode_spectral)) {
548 printf("Instrument lacks spectral measurement capability");
549 }
550
551 if (refrmode >= 0 && it->check_mode(it, inst_mode_emis_refresh_ovd) != inst_ok
552 && it->check_mode(it, inst_mode_emis_norefresh_ovd) != inst_ok) {
553 if (verb) {
554 printf("Requested refresh mode override and instrument doesn't support it (ignored)\n");
555 refrmode = -1;
556 }
557 }
558
559 /* Disable iniial calibration of machine if selected */
560 if (nocal != 0) {
561 if ((rv = it->get_set_opt(it,inst_opt_noinitcalib, 0)) != inst_ok) {
562 printf("Setting no-initial calibrate failed failed with '%s' (%s) !!!\n",
563 it->inst_interp_error(it, rv), it->interp_error(it, rv));
564 printf("Disable initial-calibrate not supported\n");
565 }
566 }
567 }
568
569 /* Check the instrument has the necessary capabilities for this measurement */
570 it->capabilities(it, &cap, &cap2, &cap3);
571
572 if (c == '1') {
573 if (it->check_mode(it, inst_mode_emis_ambient) == inst_ok) {
574 mode = inst_mode_emis_ambient;
575 } else if (it->check_mode(it, inst_mode_emis_spot) == inst_ok) {
576 mode = inst_mode_emis_spot;
577 } else {
578 printf("!!! Instrument doesn't have ambient or emissive capability !!!\n");
579 continue;
580 }
581 }
582 if (c == '2') {
583 if (it->check_mode(it, inst_mode_emis_tele) == inst_ok) {
584 mode = inst_mode_emis_tele;
585 } else if (it->check_mode(it, inst_mode_emis_spot) == inst_ok) {
586 mode = inst_mode_emis_spot;
587 } else {
588 printf("!!! Instrument doesn't have telephoto or emissive capability !!!\n");
589 continue;
590 }
591 }
592 if (c == '3') {
593 inst_opt_filter filt;
594
595 if (it->check_mode(it, inst_mode_ref_spot) == inst_ok) {
596 mode = inst_mode_ref_spot;
597 } else {
598 printf("!!! Instrument lacks reflective spot measurement capability !!!\n");
599 continue;
600 }
601
602 if ((rv = it->get_set_opt(it, inst_stat_get_filter, &filt)) == inst_ok) {
603 if (filt & inst_opt_filter_UVCut) {
604 printf("!!! Instrument has UV filter - can't measure FWA !!!\n");
605 continue;
606 }
607 }
608 }
609 mode |= inst_mode_spectral;
610
611 if (refrmode == 0)
612 mode |= inst_mode_emis_norefresh_ovd;
613 else if (refrmode == 1)
614 mode |= inst_mode_emis_refresh_ovd;
615
616 if (highres) {
617 if (IMODETST(cap, inst_mode_highres)) {
618 mode |= inst_mode_highres;
619 } else if (verb) {
620 printf("!!! High resolution ignored - instrument doesn't support it !!!\n");
621 }
622 }
623
624 if ((rv = it->set_mode(it, mode)) != inst_ok) {
625 printf("!!! Setting instrument mode failed with error :'%s' (%s) !!!\n",
626 it->inst_interp_error(it, rv), it->interp_error(it, rv));
627 continue;
628 }
629 it->capabilities(it, &cap, &cap2, &cap3);
630
631 if (refrate > 0.0) {
632 if (!(cap2 & inst2_set_refresh_rate)) {
633 if (verb)
634 printf("Attempted to set refresh rate and instrument doesn't support setting it (ignored)\n");
635 refrate = 0.0;
636 } else {
637 if ((rv = it->set_refr_rate(it, refrate)) != inst_ok) {
638 error("Setting instrument refresh rate to %f Hz failed with error :'%s' (%s)",
639 refrate, it->inst_interp_error(it, rv), it->interp_error(it, rv));
640 }
641 }
642 }
643
644 /* If it batter powered, show the status of the battery */
645 if ((cap2 & inst2_has_battery)) {
646 double batstat = 0.0;
647 if ((rv = it->get_set_opt(it, inst_stat_battery, &batstat)) == inst_ok)
648 printf("The battery charged level is %.0f%%\n",batstat * 100.0);
649 }
650
651 /* If it's an instrument that need positioning do trigger using user via uicallback */
652 /* in illumread, else enable switch or keyboard trigger if possible. */
653 if ((cap2 & inst2_xy_locate) && (cap2 & inst2_xy_position)) {
654 trigmode = inst_opt_trig_prog;
655
656 } else if (cap2 & inst2_user_switch_trig) {
657 trigmode = inst_opt_trig_user_switch;
658 uswitch = 1;
659
660 /* Or go for user via uicallback trigger */
661 } else if (cap2 & inst2_user_trig) {
662 trigmode = inst_opt_trig_user;
663
664 /* Or something is wrong with instrument capabilities */
665 } else {
666 printf("!!! No reasonable trigger mode avilable for this instrument !!!\n");
667 continue;
668 }
669 if ((rv = it->get_set_opt(it, trigmode)) != inst_ok) {
670 printf("!!! Setting trigger mode failed with error :'%s' (%s) !!!\n",
671 it->inst_interp_error(it, rv), it->interp_error(it, rv));
672 continue;
673 }
674
675 /* Setup the keyboard trigger to return our commands */
676 inst_set_uih(0x0, 0xff, DUIH_TRIG);
677 inst_set_uih('q', 'q', DUIH_ABORT);
678 inst_set_uih('Q', 'Q', DUIH_ABORT);
679 inst_set_uih(0x03, 0x03, DUIH_ABORT); /* ^c */
680 inst_set_uih(0x1b, 0x1b, DUIH_ABORT); /* Esc */
681
682 /* Hold table */
683 if (cap2 & inst2_xy_holdrel) {
684 for (;;) { /* retry loop */
685 if ((rv = it->xy_sheet_hold(it)) == inst_ok)
686 break;
687
688 if (ierror(it, rv)) {
689 printf("!!! Setting paper hold failed with error :'%s' (%s) !!!\n",
690 it->inst_interp_error(it, rv), it->interp_error(it, rv));
691 it->xy_clear(it);
692 continue;
693 }
694 }
695 }
696
697 /* Do any needed calibration before the user places the instrument on a desired spot */
698 if (it->needs_calibration(it) != inst_calt_none) {
699 double lx, ly;
700 inst_code ev;
701
702 printf("\nInstrument needs a calibration before continuing\n");
703
704 /* save current location */
705 if ((cap2 & inst2_xy_locate) && (cap2 & inst2_xy_position)) {
706 for (;;) { /* retry loop */
707 if ((ev = it->xy_get_location(it, &lx, &ly)) == inst_ok)
708 break;
709 if (ierror(it, ev) == 0) /* Ignore */
710 continue;
711 break; /* Abort */
712 }
713 if (ev != inst_ok) {
714 printf("!!! Setting calibration location failed with error :'%s' (%s) !!!\n",
715 it->inst_interp_error(it, rv), it->interp_error(it, rv));
716 continue;
717 }
718 }
719
720 ev = inst_handle_calibrate(it, inst_calt_needed, inst_calc_none, NULL, NULL, 0);
721 if (ev != inst_ok) { /* Abort or fatal error */
722 printf("!!! Calibration failed with error :'%s' (%s) !!!\n",
723 it->inst_interp_error(it, rv), it->interp_error(it, rv));
724 continue;
725 }
726
727 /* restore location */
728 if ((cap2 & inst2_xy_locate) && (cap2 & inst2_xy_position)) {
729 for (;;) { /* retry loop */
730 if ((ev = it->xy_position(it, 0, lx, ly)) == inst_ok)
731 break;
732 if (ierror(it, ev) == 0) /* Ignore */
733 continue;
734 break; /* Abort */
735 }
736 if (ev != inst_ok) {
737 printf("!!! Restoring location failed with error :'%s' (%s) !!!\n",
738 it->inst_interp_error(it, rv), it->interp_error(it, rv));
739 continue;
740 }
741 }
742 }
743
744 /* Now do the measurement: */
745
746 /* If this is an xy instrument: */
747 if ((cap2 & inst2_xy_locate) && (cap2 & inst2_xy_position)) {
748
749 /* Allow the user to position the instrument */
750 for (;;) { /* retry loop */
751 if ((rv = it->xy_locate_start(it)) == inst_ok)
752 break;
753 if (ierror(it, rv) == 0) /* Ignore */
754 continue;
755 break; /* Abort */
756 }
757 if (rv != inst_ok)
758 break; /* Abort */
759
760 if (c != 3) {
761 printf("!!! Unexpected: XY instrument used for emissive measurements !!!\n");
762 continue;
763 }
764
765 printf("Using the XY table controls, position the instrument sight\n");
766 printf("so as to read the paper,\n");
767
768 /* Purely manual instrument */
769 } else {
770
771 if (c == '1') {
772 if (it->check_mode(it, inst_mode_emis_ambient) == inst_ok) {
773 printf("\n(If applicable) set instrument to ambient measurenent mode, or place\n");
774 printf("ambient adapter on it, and position it so as to measure the illuminant directly.\n");
775 } else {
776 printf("\n(If applicable) set instrument to emissive measurenent mode,\n");
777 printf("and position it so as to measure the illuminant directly.\n");
778 }
779 } else if (c == '2') {
780 if (it->check_mode(it, inst_mode_emis_tele) == inst_ok) {
781 printf("\n(If applicable) set instrument to telephoto measurenent mode,\n");
782 printf("position it so as to measure the illuminant reflected from the paper.\n");
783 } else {
784 printf("\n(If applicable) set instrument to emsissive measurenent mode,\n");
785 printf("position it so as to measure the illuminant reflected from the paper.\n");
786 }
787 } else if (c == '3') {
788 printf("\n(If applicable) set instrument to reflective measurenent mode,\n");
789 printf("position it so as to measure the paper.");
790 } else
791 error("Unexpected choice");
792 }
793 if (uswitch)
794 printf("Hit ESC or Q to abort, or instrument switch or any other key to take a reading: ");
795 else
796 printf("Hit ESC or Q to abort, any any other key to take a reading: ");
797 fflush(stdout);
798
799 if ((cap2 & inst2_xy_locate) && (cap2 & inst2_xy_position)) {
800
801 /* Wait for the user to hit a key */
802 for (;;) {
803 if ((rv = inst_get_uicallback()(inst_get_uicontext(), inst_armed)) != inst_ok)
804 break;
805 }
806
807 if (rv == inst_user_abort) {
808 break; /* Abort */
809
810 } else if (rv == inst_user_trig) {
811 double lx, ly;
812 inst_code ev;
813
814 /* Take the location set on the sight, and move the instrument */
815 /* to take the measurement there. */
816 if ((cap2 & inst2_xy_locate) && (cap2 & inst2_xy_position)) {
817 for (;;) { /* retry loop */
818 if ((rv = it->xy_get_location(it, &lx, &ly)) == inst_ok)
819 break;
820 if (ierror(it, rv) == 0) /* Ignore */
821 continue;
822 break; /* Abort */
823 }
824 if (rv != inst_ok)
825 break; /* Abort */
826
827 for (;;) { /* retry loop */
828 if ((rv = it->xy_locate_end(it)) == inst_ok)
829 break;
830 if (ierror(it, rv) == 0) /* Ignore */
831 continue;
832 break; /* Abort */
833 }
834 if (rv != inst_ok)
835 break; /* Abort */
836
837 for (;;) { /* retry loop */
838 if ((rv = it->xy_position(it, 1, lx, ly)) == inst_ok)
839 break;
840 if (ierror(it, rv) == 0) /* Ignore */
841 continue;
842 break; /* Abort */
843 }
844 if (rv != inst_ok)
845 break; /* Abort */
846 }
847 rv = it->read_sample(it, "SPOT", &val, 1);
848
849 /* Restore the location the instrument to have the location */
850 /* sight over the selected patch. */
851 for (;;) { /* retry loop */
852 if ((ev = it->xy_position(it, 0, lx, ly)) == inst_ok)
853 break;
854 if (ierror(it, ev) == 0) /* Ignore */
855 continue;
856 break; /* Abort */
857 }
858 if (ev != inst_ok)
859 break; /* Abort */
860 }
861 /* else what ? */
862
863 /* Not an XY instrument */
864 } else {
865 rv = it->read_sample(it, "SPOT", &val, 1);
866 }
867
868 /* Release paper */
869 if (cap2 & inst2_xy_holdrel) {
870 it->xy_clear(it);
871 }
872
873 #ifdef DEBUG
874 printf("read_sample returned '%s' (%s)\n",
875 it->inst_interp_error(it, rv), it->interp_error(it, rv));
876 #endif /* DEBUG */
877
878 /* Deal with a trigger or command */
879 if ((rv & inst_mask) == inst_user_trig) {
880 ch = inst_get_uih_char() & 0xff;
881
882 /* Deal with a command or abort */
883 } else if ((rv & inst_mask) == inst_user_abort) {
884 ch = inst_get_uih_char();
885
886 if (ch & DUIH_CMND) {
887 ch &= 0xff;
888 } else if (ch & DUIH_ABORT) {
889 printf("\nIlluminant measure aborted at user request!\n");
890 continue;
891 }
892
893 /* Deal with a needs calibration */
894 } else if ((rv & inst_mask) == inst_needs_cal) {
895 inst_code ev;
896 printf("\nIlluminant measure failed because instruments needs calibration.\n");
897 ev = inst_handle_calibrate(it, inst_calt_needed, inst_calc_none, NULL, NULL, 0);
898 continue;
899
900 /* Deal with a bad sensor position */
901 } else if ((rv & inst_mask) == inst_wrong_config) {
902 printf("\nIlluminant measure failed due to the sensor being in the wrong position\n(%s)\n",it->interp_error(it, rv));
903 continue;
904
905 /* Deal with a misread */
906 } else if ((rv & inst_mask) == inst_misread) {
907 printf("\nIlluminant measure failed due to misread (%s)\n",it->interp_error(it, rv));
908 continue;
909
910 /* Deal with a communications error */
911 } else if ((rv & inst_mask) == inst_coms_fail) {
912 empty_con_chars();
913 printf("\nIlluminant measure failed due to communication problem.\n");
914 printf("Hit Esc or Q to give up, any other key to retry:"); fflush(stdout);
915 continue;
916
917 /* Some other fatal error */
918 } else if (rv != inst_ok) {
919 printf("\nGot fatal error '%s' (%s)\n",
920 it->inst_interp_error(it, rv), it->interp_error(it, rv));
921 continue;
922 }
923
924 if (c == '1') { /* Illuminant */
925 i_sp = val.sp;
926 if (tmode && rd_i == 0) {
927 strcpy(tnp, "_i.sp");
928 write_xspect(tname, inst_mrt_emission, &i_sp);
929 }
930 } else if (c == '2') { /* Illuminant reflected on paper */
931 r_sp = val.sp;
932 if (tmode && rd_r == 0) {
933 strcpy(tnp, "_r.sp");
934 write_xspect(tname, inst_mrt_emission, &r_sp);
935 }
936 } else if (c == '3') { /* Paper reflectance */
937 p_sp = val.sp;
938
939 /* Get the illuminant spectrum too */
940 if (inst_illuminant(&insp, itype) != 0)
941 error ("Instrument doesn't have an FWA illuminent");
942
943 if (tmode && rd_p == 0) {
944 /* Should save instrument type/instrument illuminant spectrum !!! */
945 strcpy(tnp, "_p.sp");
946 write_xspect(tname, inst_mrt_reflective, &p_sp);
947 }
948 }
949
950 if (pspec) {
951 double xx[XSPECT_MAX_BANDS];
952 double y1[XSPECT_MAX_BANDS];
953 double xmin, xmax, ymin, ymax;
954 int nn;
955
956 if (val.sp.spec_n <= 0)
957 error("Instrument didn't return spectral data");
958
959 printf("Spectrum from %f to %f nm in %d steps\n",
960 val.sp.spec_wl_short, val.sp.spec_wl_long, val.sp.spec_n);
961
962 if (val.sp.spec_n > XSPECT_MAX_BANDS)
963 error("Got > %d spectral values (%d)",XSPECT_MAX_BANDS,val.sp.spec_n);
964
965 for (j = 0; j < val.sp.spec_n; j++) {
966 GCC_BUGFIX(j)
967 xx[j] = val.sp.spec_wl_short
968 + j * (val.sp.spec_wl_long - val.sp.spec_wl_short)/(val.sp.spec_n-1);
969
970 y1[j] = value_xspect(&val.sp, xx[j]);
971 }
972
973 xmax = val.sp.spec_wl_long;
974 xmin = val.sp.spec_wl_short;
975 ymin = ymax = 0.0; /* let it scale */
976 do_plot_x(xx, y1, NULL, NULL, val.sp.spec_n, 1,
977 xmin, xmax, ymin, ymax, 2.0);
978 }
979
980 continue;
981 } /* End of take a measurement */
982
983 /* Deal with selecting the instrument */
984 if (c == '4') {
985
986 if (it != NULL)
987 it->del(it);
988 it = NULL;
989 itype = instUnknown;
990
991 if (icmps == NULL)
992 icmps = new_icompaths(g_log);
993 else
994 icmps->refresh(icmps);
995 if (icmps != NULL) {
996 icompath **paths;
997 if ((paths = icmps->paths) != NULL) {
998 int i;
999 for (i = 0; ; i++) {
1000 if (paths[i] == NULL)
1001 break;
1002 if ((paths[i]->itype == instSpyder1 && setup_spyd2(0) == 0)
1003 || (paths[i]->itype == instSpyder2 && setup_spyd2(1) == 0))
1004 fprintf(stderr," %d = '%s' !! Disabled - no firmware !!\n",i+1,paths[i]->name);
1005 else
1006 fprintf(stderr," %d = '%s'\n",i+1,paths[i]->name);
1007 }
1008 printf("Select device 1 - %d: \n",i);
1009 empty_con_chars();
1010 c = next_con_char();
1011
1012 if (c < '1' || c > ('0' + i)) {
1013 printf("'%c' is out of range - ignored !\n",c);
1014 } else {
1015 comno = c - '0';
1016 }
1017
1018 } else {
1019 fprintf(stderr,"No ports to select from!\n");
1020 }
1021 }
1022 continue;
1023 }
1024 if (c == '5' || c == '6') { /* Compute result */
1025 xspect cpisp; /* FWA corrected calculated initial paper reflectance */
1026 double gain;
1027 bfinds bf; /* Optimization context */
1028 double xyz0[3], xyz1[3];
1029 double tt[2], sr[2];
1030 double rv;
1031
1032 if (i_sp.spec_n == 0) {
1033 printf("Need to measure the direct illuminant\n");
1034 continue;
1035 }
1036 if (r_sp.spec_n == 0) {
1037 printf("Need to measure the illuminant reflected off paper\n");
1038 continue;
1039 }
1040 if (p_sp.spec_n == 0) {
1041 printf("Need to measure the paper\n");
1042 continue;
1043 }
1044
1045 /* Normalize direct illumination */
1046 for (gain = 0.0, i = 0; i < i_sp.spec_n; i++)
1047 gain += i_sp.spec[i];
1048 gain /= i_sp.spec_n;
1049 for (i = 0; i < i_sp.spec_n; i++)
1050 i_sp.spec[i] /= gain;
1051
1052 /* Normalize indirect illumination */
1053 for (gain = 0.0, i = 0; i < r_sp.spec_n; i++)
1054 gain += r_sp.spec[i];
1055 gain /= r_sp.spec_n;
1056 for (i = 0; i < r_sp.spec_n; i++)
1057 r_sp.spec[i] /= gain;
1058
1059 /* Normalize paper reflectance to 1.0 */
1060 xspect_denorm(&p_sp);
1061
1062 bf.i_sp = &i_sp;
1063 bf.r_sp = &r_sp;
1064 bf.p_sp = &p_sp;
1065
1066 if ((bf.pap = new_xsp2cie(icxIT_custom, &i_sp, icxOT_CIE_1931_2, NULL, icSigLabData, icxClamp)) == NULL)
1067 error("new_xsp2cie pap failed");
1068
1069 if (bf.pap->set_fwa(bf.pap, &insp, NULL, &p_sp) != 0)
1070 error ("Setting FWA compensation failed");
1071
1072 /* Setup the equal energy to Lab conversion */
1073 if ((bf.ref = new_xsp2cie(icxIT_E, NULL, icxOT_CIE_1931_2, NULL, icSigLabData, icxClamp)) == NULL)
1074 error("new_xsp2cie ref failed");
1075
1076 /* Estimate an initial gain match */
1077 tt[0] = 0.0;
1078 tt[1] = 1.0;
1079 bfindfunc((void *)&bf, tt);
1080 icmLab2XYZ(&icmD50, xyz0, bf.lab0);
1081 icmLab2XYZ(&icmD50, xyz1, bf.lab1);
1082
1083 gain = xyz0[1] / xyz1[1];
1084 //printf("~1 Target XYZ %f %f %f, is %f %f %f, gain needed = %f\n",xyz0[0],xyz0[1],xyz0[2],xyz1[0],xyz1[1],xyz1[2],gain);
1085
1086 for (i = 0; i < r_sp.spec_n; i++)
1087 r_sp.spec[i] *= gain;
1088
1089 /* Check initial gain match is OK */
1090 bfindfunc((void *)&bf, tt);
1091 cpisp = bf.cpsp; /* Copy initial match */
1092 icmLab2XYZ(&icmD50, xyz0, bf.lab0);
1093 icmLab2XYZ(&icmD50, xyz1, bf.lab1);
1094 #ifdef NEVER
1095 printf("~1 Target XYZ %f %f %f, now %f %f %f\n",xyz0[0],xyz0[1],xyz0[2],xyz1[0],xyz1[1],xyz1[2]);
1096 #endif
1097
1098 tt[0] = 0.1, tt[1] = 1.0; /* Search parameter starting values */
1099 sr[0] = sr[1] = 0.1; /* Search parameter search radiuses */
1100
1101 if (powell(&rv, 2, tt, sr, 0.0001, 1000,
1102 bfindfunc, (void *)&bf, NULL, NULL) != 0) {
1103 printf("Optimization search failed\n");
1104 continue;
1105 }
1106 printf("(Best match DE %f, UV content = %f (gain match %f))\n", rv, tt[0], tt[1]);
1107
1108 /* Compute the result */
1109 bfindfunc((void *)&bf, tt);
1110 ill = bf.ill;
1111
1112 if (c == '5' && nacc > 0) {
1113 for (i = 0; i < ill.spec_n; i++)
1114 aill.spec[i] += ill.spec[i];
1115 nacc++;
1116 } else {
1117 aill = ill;
1118 nacc = 1;
1119 }
1120
1121 /* Save the result */
1122 if (aill.spec_n == 0) {
1123 printf("Nothing to save!\n");
1124 } else {
1125 for (i = 0; i < ill.spec_n; i++)
1126 ill.spec[i] = aill.spec[i]/nacc;
1127
1128 if(write_xspect(outname, inst_mrt_ambient, &ill))
1129 printf("\nWriting file '%s' failed\n",outname);
1130 else
1131 printf("\nWriting file '%s' succeeded\n",outname);
1132
1133 if (tmode) {
1134 strcpy(tnp, "_mpir.sp"); // Measured paper under illuminant spectrum
1135 write_xspect(tname, inst_mrt_reflective, &bf.srop);
1136 strcpy(tnp, "_cpir.sp"); // Computed paper under illuminant spectrum
1137 write_xspect(tname, inst_mrt_reflective, &bf.cpsp);
1138 }
1139 }
1140
1141 /* Plot the result */
1142 if (pspec) {
1143 double xx[XSPECT_MAX_BANDS];
1144 double y1[XSPECT_MAX_BANDS];
1145 double y2[XSPECT_MAX_BANDS];
1146 double y3[XSPECT_MAX_BANDS];
1147 double xmin, xmax, ymin, ymax;
1148 int nn;
1149
1150 #ifdef SHOWDXX
1151 cfinds cf; /* Optimization context */
1152 double tt[2], sr[2];
1153 double rv;
1154 xspect cpdsp; /* FWA corrected calculated daylight paper reflectance */
1155
1156 /* Setup the referencec comversion */
1157 if ((cf.ref = new_xsp2cie(icxIT_E, NULL, icxOT_CIE_1931_2, NULL, icSigLabData, icxClamp)) == NULL)
1158 error("new_xsp2cie ref failed");
1159
1160 cf.ill = bf.ill;
1161
1162 /* Set starting values */
1163 tt[0] = 5000.0; /* degrees */
1164 tt[1] = 1.0;
1165 cfindfunc((void *)&cf, tt);
1166 icmLab2XYZ(&icmD50, xyz0, cf.lab0);
1167 icmLab2XYZ(&icmD50, xyz1, cf.lab1);
1168
1169 tt[1] = xyz0[1] / xyz1[1];
1170
1171 sr[0] = 10.0;
1172 sr[1] = 0.1; /* Search parameter search radiuses */
1173
1174 if (powell(&rv, 2, tt, sr, 0.0001, 1000,
1175 cfindfunc, (void *)&cf, NULL, NULL) != 0) {
1176 error("Optimization search failed\n");
1177 }
1178 printf("(Best daylight match DE %f, temp = %f (gain match %f))\n", rv, tt[0], tt[1]);
1179
1180 /* Compute the result */
1181 cfindfunc((void *)&cf, tt);
1182
1183 printf("Illuminant: Black - Measured, Red - with estimated UV, Green - daylight\n");
1184
1185 if (bf.ill.spec_n > XSPECT_MAX_BANDS)
1186 error("Got > %d spectral values (%d)",XSPECT_MAX_BANDS,bf.ill.spec_n);
1187
1188 for (j = 0; j < bf.ill.spec_n; j++) {
1189 GCC_BUGFIX(j)
1190 xx[j] = XSPECT_XWL(&bf.ill, j);
1191 y1[j] = value_xspect(bf.i_sp, xx[j]); /* Measured (black) */
1192 y2[j] = value_xspect(&bf.ill, xx[j]); /* Computed (red)*/
1193 y3[j] = value_xspect(&cf.dxx, xx[j]); /* Daylight match (green)*/
1194 }
1195
1196 xmax = bf.ill.spec_wl_long;
1197 xmin = bf.ill.spec_wl_short;
1198 ymin = ymax = 0.0; /* let it scale */
1199 do_plot_x(xx, y1, y2, y3, bf.ill.spec_n, 1,
1200 xmin, xmax, ymin, ymax, 2.0);
1201
1202 /* Update the conversion to the matched Dayligh */
1203 if (bf.pap->update_fwa_custillum(bf.pap, NULL, &cf.dxx) != 0)
1204 error ("Updating FWA compensation to daylight failed");
1205
1206 /* Apply FWA compensation to the paper reflectance */
1207 bf.pap->sconvert(bf.pap, &cpdsp, NULL, bf.p_sp);
1208
1209 printf("Paper Reflectance: Black - Measured, Red - Initial FWA model, Green - FWA Final FWA model\n");
1210 // printf("Paper Reflectance: Black - Measured, Red - FWA Modelled, Green - Daylight modelled\n");
1211
1212 for (j = 0; j < bf.cpsp.spec_n; j++) {
1213 GCC_BUGFIX(j)
1214 xx[j] = XSPECT_XWL(&bf.cpsp, j);
1215 y1[j] = value_xspect(&bf.srop, xx[j]); /* Measured reflectance (black) */
1216 y2[j] = value_xspect(&cpisp, xx[j]); /* Computed initial reflectance (red) */
1217 y3[j] = value_xspect(&bf.cpsp, xx[j]); /* Computed final reflectance (green) */
1218 // y3[j] = value_xspect(&cpdsp, xx[j]); /* Computed daylight reflectance (green) */
1219 }
1220
1221 xmax = bf.cpsp.spec_wl_long;
1222 xmin = bf.cpsp.spec_wl_short;
1223 ymin = ymax = 0.0; /* let it scale */
1224 do_plot_x(xx, y1, y2, y3, bf.cpsp.spec_n, 1,
1225 xmin, xmax, ymin, ymax, 2.0);
1226
1227 #else // !SHOWDXX
1228 printf("Illuminant: Black - Measured, Red - with estimated UV\n");
1229
1230 if (bf.ill.spec_n > XSPECT_MAX_BANDS)
1231 error("Got > %d spectral values (%d)",XSPECT_MAX_BANDS,bf.ill.spec_n);
1232
1233 for (j = 0; j < bf.ill.spec_n; j++) {
1234 GCC_BUGFIX(j)
1235 xx[j] = XSPECT_XWL(&bf.ill, j);
1236 y1[j] = value_xspect(bf.i_sp, xx[j]); /* Measured (black) */
1237 y2[j] = value_xspect(&bf.ill, xx[j]); /* Computed (red)*/
1238 }
1239
1240 xmax = bf.ill.spec_wl_long;
1241 xmin = bf.ill.spec_wl_short;
1242 ymin = ymax = 0.0; /* let it scale */
1243 do_plot_x(xx, y1, y2, NULL, bf.ill.spec_n, 1,
1244 xmin, xmax, ymin, ymax, 2.0);
1245
1246 printf("Paper Reflectance: Black - Measured, Red - Initial FWA model, Green - FWA Final FWA model\n");
1247
1248 for (j = 0; j < bf.cpsp.spec_n; j++) {
1249 GCC_BUGFIX(j)
1250 xx[j] = XSPECT_XWL(&bf.cpsp, j);
1251 y1[j] = value_xspect(&bf.srop, xx[j]); /* Measured reflectance (black) */
1252 y2[j] = value_xspect(&cpisp, xx[j]); /* Computed initial reflectance (red) */
1253 y3[j] = value_xspect(&bf.cpsp, xx[j]); /* Computed final reflectance (green) */
1254 }
1255
1256 xmax = bf.cpsp.spec_wl_long;
1257 xmin = bf.cpsp.spec_wl_short;
1258 ymin = ymax = 0.0; /* let it scale */
1259 do_plot_x(xx, y1, y2, y3, bf.cpsp.spec_n, 1,
1260 xmin, xmax, ymin, ymax, 2.0);
1261
1262 #endif // !SHOWDXX
1263 printf("%s illuminant with UV:\n",c == '5' ? "Averaged" : "Computed");
1264
1265 for (j = 0; j < ill.spec_n; j++) {
1266 GCC_BUGFIX(j)
1267 xx[j] = XSPECT_XWL(&ill, j);
1268 y1[j] = value_xspect(&ill, xx[j]);
1269 }
1270
1271 xmax = ill.spec_wl_long;
1272 xmin = ill.spec_wl_short;
1273 ymin = ymax = 0.0; /* let it scale */
1274 do_plot_x(xx, y1, NULL, NULL, ill.spec_n, 1,
1275 xmin, xmax, ymin, ymax, 2.0);
1276 }
1277
1278 /* Make sure that the illuminant is re-measured for another reading */
1279 i_sp.spec_n = 0;
1280 r_sp.spec_n = 0;
1281
1282 continue;
1283 }
1284
1285 if (c == '7' || c == 0x3) { /* Exit */
1286 break;
1287 }
1288
1289 } /* Next command */
1290
1291 #ifdef DEBUG
1292 printf("About to exit\n");
1293 #endif
1294
1295 /* Free instrument */
1296 if (it != NULL)
1297 it->del(it);
1298
1299 return 0;
1300 }
1301
1302
1303
1304
1305