12 |
|
|
13 |
|
#include <stdio.h> |
14 |
|
#include <string.h> |
15 |
+ |
#include <math.h> |
16 |
|
#include "color.h" |
17 |
|
|
18 |
|
#define CEPS 1e-4 /* color epsilon */ |
271 |
|
COLOR ciecolor; |
272 |
|
|
273 |
|
spec_cie(ciecolor, s, e); |
274 |
< |
cie_rgb(col, ciecolor); |
274 |
> |
colortrans(col, xyz2rgbmat, ciecolor); |
275 |
|
} |
276 |
|
|
277 |
|
|
278 |
|
static double |
279 |
|
spec_dot( /* spectrum dot-product with cumulative observer */ |
280 |
< |
SCOLOR scol, |
280 |
> |
const SCOLOR scol, |
281 |
|
int ncs, |
282 |
|
const float wlpt[4], |
283 |
|
const unsigned short cumul[], |
312 |
|
void |
313 |
|
scolor2cie( /* accurate conversion from spectrum to XYZ */ |
314 |
|
COLOR col, |
315 |
< |
SCOLOR scol, |
315 |
> |
const SCOLOR scol, |
316 |
|
int ncs, |
317 |
|
const float wlpt[4] |
318 |
|
) |
330 |
|
void |
331 |
|
scolor2rgb( /* accurate conversion from spectrum to RGB */ |
332 |
|
COLOR col, |
333 |
< |
SCOLOR scol, |
333 |
> |
const SCOLOR scol, |
334 |
|
int ncs, |
335 |
|
const float wlpt[4] |
336 |
|
) |
346 |
|
} |
347 |
|
|
348 |
|
|
349 |
+ |
void |
350 |
+ |
scolor_out( /* prepare (spectral) color for output */ |
351 |
+ |
COLORV *cout, |
352 |
+ |
RGBPRIMS pr, |
353 |
+ |
const SCOLOR cres |
354 |
+ |
) |
355 |
+ |
{ |
356 |
+ |
static COLORMAT xyz2myp; |
357 |
+ |
static RGBPRIMP lastp = NULL; |
358 |
+ |
|
359 |
+ |
if (!pr) { /* output is spectral */ |
360 |
+ |
copyscolor(cout, cres); |
361 |
+ |
} else if (pr == stdprims) { /* output is standard RGB */ |
362 |
+ |
scolor_rgb(cout, cres); |
363 |
+ |
} else if (pr == xyzprims) { /* output is XYZ */ |
364 |
+ |
scolor_cie(cout, cres); |
365 |
+ |
scalecolor(cout, WHTEFFICACY); |
366 |
+ |
} else if (NCSAMP > 3) { /* spectral -> custom RGB */ |
367 |
+ |
COLOR xyz; |
368 |
+ |
if (lastp != pr) |
369 |
+ |
compxyz2rgbWBmat(xyz2myp, lastp=pr); |
370 |
+ |
scolor_cie(xyz, cres); |
371 |
+ |
colortrans(cout, xyz2myp, xyz); |
372 |
+ |
clipgamut(cout, xyz[CIEY], CGAMUT_LOWER, cblack, cwhite); |
373 |
+ |
} else { /* else copy unknown RGB */ |
374 |
+ |
copycolor(cout, cres); |
375 |
+ |
} |
376 |
+ |
} |
377 |
+ |
|
378 |
+ |
|
379 |
|
double |
380 |
< |
scolor_photopic( /* compute scotopic integral for spectral color */ |
381 |
< |
SCOLOR scol |
380 |
> |
scolor2photopic( /* compute scotopic integral for spectral color */ |
381 |
> |
const SCOLOR scol, |
382 |
> |
int ncs, |
383 |
> |
const float wlpt[4] |
384 |
|
) |
385 |
|
{ |
386 |
< |
if (NCSAMP == 3) |
386 |
> |
if (ncs == 3) |
387 |
|
return bright(scol); |
388 |
|
|
389 |
< |
return(spec_dot(scol, NCSAMP, WLPART, cie_y_cumul, CIE_Y_WLMIN, CIE_Y_WLMAX)); |
389 |
> |
return(spec_dot(scol, ncs, wlpt, cie_y_cumul, CIE_Y_WLMIN, CIE_Y_WLMAX)); |
390 |
|
} |
391 |
|
|
392 |
|
|
393 |
|
double |
394 |
+ |
scolor2scotopic( /* compute Y channel for spectral color */ |
395 |
+ |
const SCOLOR scol, |
396 |
+ |
int ncs, |
397 |
+ |
const float wlpt[4] |
398 |
+ |
) |
399 |
+ |
{ |
400 |
+ |
return(spec_dot(scol, ncs, wlpt, scotopic_cumul, SCOTOPIC_WLMIN, SCOTOPIC_WLMAX)); |
401 |
+ |
} |
402 |
+ |
|
403 |
+ |
|
404 |
+ |
double |
405 |
+ |
scolor2melanopic( /* compute melanopic integral for spectral color */ |
406 |
+ |
const SCOLOR scol, |
407 |
+ |
int ncs, |
408 |
+ |
const float wlpt[4] |
409 |
+ |
) |
410 |
+ |
{ |
411 |
+ |
return(spec_dot(scol, ncs, wlpt, melanopic_cumul, MELANOPIC_WLMIN, MELANOPIC_WLMAX)); |
412 |
+ |
} |
413 |
+ |
|
414 |
+ |
|
415 |
+ |
double |
416 |
+ |
scolor_photopic( /* compute scotopic integral for spectral color */ |
417 |
+ |
const SCOLOR scol |
418 |
+ |
) |
419 |
+ |
{ |
420 |
+ |
return(scolor2photopic(scol, NCSAMP, WLPART)); |
421 |
+ |
} |
422 |
+ |
|
423 |
+ |
|
424 |
+ |
double |
425 |
|
scolor_scotopic( /* compute Y channel for spectral color */ |
426 |
< |
SCOLOR scol |
426 |
> |
const SCOLOR scol |
427 |
|
) |
428 |
|
{ |
429 |
< |
return(spec_dot(scol, NCSAMP, WLPART, scotopic_cumul, SCOTOPIC_WLMIN, SCOTOPIC_WLMAX)); |
429 |
> |
return(scolor2scotopic(scol, NCSAMP, WLPART)); |
430 |
|
} |
431 |
|
|
432 |
|
|
433 |
|
double |
434 |
|
scolor_melanopic( /* compute melanopic integral for spectral color */ |
435 |
< |
SCOLOR scol |
435 |
> |
const SCOLOR scol |
436 |
|
) |
437 |
|
{ |
438 |
< |
return(spec_dot(scol, NCSAMP, WLPART, melanopic_cumul, MELANOPIC_WLMIN, MELANOPIC_WLMAX)); |
438 |
> |
return(scolor2melanopic(scol, NCSAMP, WLPART)); |
439 |
|
} |
440 |
|
|
441 |
|
|
442 |
|
void |
443 |
+ |
convertscolorcol( /* any uniform spectrum to working */ |
444 |
+ |
SCOLOR rcol, |
445 |
+ |
const COLORV src[], |
446 |
+ |
int snc, |
447 |
+ |
double swl0, |
448 |
+ |
double swl1 |
449 |
+ |
) |
450 |
+ |
{ |
451 |
+ |
if (NCSAMP > 3) { /* spectrum -> spectrum */ |
452 |
+ |
convertscolor(rcol, NCSAMP, WLPART[0], WLPART[3], |
453 |
+ |
src, snc, swl0, swl1); |
454 |
+ |
} else if ((snc <= MAXCSAMP) & (swl0 > swl1)) { |
455 |
+ |
float wlpt[4]; /* no intermediate conversion needed */ |
456 |
+ |
wlpt[0] = swl0; wlpt[3] = swl1; |
457 |
+ |
wlpt[1] = WLPART[1]; wlpt[2] = WLPART[2]; |
458 |
+ |
scolor2rgb(rcol, (COLORV *)src, snc, wlpt); |
459 |
+ |
} else { |
460 |
+ |
SCOLOR dcol; /* else convert spectrum first */ |
461 |
+ |
int dnc = snc*(WLPART[0] - WLPART[3])/fabs(swl0 - swl1) + .99; |
462 |
+ |
if (dnc > MAXCSAMP) dnc = MAXCSAMP; |
463 |
+ |
convertscolor(dcol, dnc, WLPART[0], WLPART[3], src, snc, swl0, swl1); |
464 |
+ |
scolor2rgb(rcol, dcol, dnc, WLPART); |
465 |
+ |
} |
466 |
+ |
} |
467 |
+ |
|
468 |
+ |
|
469 |
+ |
void |
470 |
|
cie_rgb( /* convert CIE color to standard RGB */ |
471 |
|
COLOR rgb, |
472 |
< |
COLOR xyz |
472 |
> |
const COLOR xyz |
473 |
|
) |
474 |
|
{ |
475 |
|
colortrans(rgb, xyz2rgbmat, xyz); |
482 |
|
COLOR col, |
483 |
|
double brt, |
484 |
|
int gamut, |
485 |
< |
COLOR lower, |
486 |
< |
COLOR upper |
485 |
> |
const COLOR lower, |
486 |
> |
const COLOR upper |
487 |
|
) |
488 |
|
{ |
489 |
|
int rflags = 0; |
528 |
|
void |
529 |
|
colortrans( /* convert c1 by mat and put into c2 */ |
530 |
|
COLOR c2, |
531 |
< |
COLORMAT mat, |
532 |
< |
COLOR c1 |
531 |
> |
const COLORMAT mat, |
532 |
> |
const COLOR c1 |
533 |
|
) |
534 |
|
{ |
535 |
|
COLOR cout; |
545 |
|
void |
546 |
|
multcolormat( /* multiply m1 by m2 and put into m3 */ |
547 |
|
COLORMAT m3, /* m3 can be either m1 or m2 w/o harm */ |
548 |
< |
COLORMAT m2, |
549 |
< |
COLORMAT m1 |
548 |
> |
const COLORMAT m2, |
549 |
> |
const COLORMAT m1 |
550 |
|
) |
551 |
|
{ |
552 |
|
COLORMAT mt; |
738 |
|
int |
739 |
|
compxyzWBmat( /* CIE von Kries transform from wht1 to wht2 */ |
740 |
|
COLORMAT mat, |
741 |
< |
float wht1[2], |
742 |
< |
float wht2[2] |
741 |
> |
const float wht1[2], |
742 |
> |
const float wht2[2] |
743 |
|
) |
744 |
|
{ |
745 |
|
COLOR cw1, cw2; |