From c07d0c2d2f6f7b0eb6e92cc6204bf05037957e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 1 Sep 2014 15:43:52 +0200 Subject: Imported Upstream version 1.6.3 --- xicc/xspect.c | 2452 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 2218 insertions(+), 234 deletions(-) (limited to 'xicc/xspect.c') diff --git a/xicc/xspect.c b/xicc/xspect.c index a372d60..cc0ce85 100644 --- a/xicc/xspect.c +++ b/xicc/xspect.c @@ -23,16 +23,7 @@ /* * TTBD: * - * If needed by ISO 13655-1009: - * fwa_convert() function takes two illuminants: - * first one is the measurement illumination to correct to, - * the second is the assumed illumination spectrum for XYZ conversion. - * so we compute the spectral reflectance as if the instrument had - * one sort of practical illuminant (and taking into account FWA), - * and then convert to D50 equivalent. - * Need to bypass FWA if inst illum == simulated inst. illum. - * Need to modify tools to allow optional param to -f which is - * the simulated instrument illum, then make -i have -M0, -M1, -M2 options. + * Should add some more modern standard CMFs - see * * [Does this make any sense though ? That is what's happening * for a standard A illuminant instrument emitting D50 XYZ values, @@ -52,6 +43,7 @@ #else # include "numsup.h" #endif +#include "conv.h" #include "xspect.h" #define CLAMP_XYZ /* [def] Clamp XYZ to be >= 0.0 */ @@ -279,8 +271,9 @@ static int daylight_il(xspect *sp, double ct) { double xd, yd; double m1, m2; - if (ct < 1000.0 || ct > 35000.0) /* Actually, accuracy is guaranteed from only 4000 - 25000 */ + if (ct < 4000.0 || ct > 25000.0) { /* Only accurate down to 4000 */ return 1; + } /* Compute chromaticity coordinates */ if (ct < 7000.0) { @@ -306,6 +299,8 @@ static int daylight_il(xspect *sp, double ct) { return 0; } +#endif /* !SALONEINSTLIB */ + /* General temperature Planckian (black body) spectra */ /* Fill in the given xspect with the specified Planckian illuminant */ /* Return nz if temperature is out of range */ @@ -317,7 +312,6 @@ static int planckian_il(xspect *sp, double ct) { return 1; /* Set out targets */ -// sp->spec_n = 107; /* 5nm */ sp->spec_n = 531; /* 1nm */ sp->spec_wl_short = 300.0; sp->spec_wl_long = 830; @@ -337,6 +331,8 @@ static int planckian_il(xspect *sp, double ct) { return 0; } +#ifndef SALONEINSTLIB + /* CIE F5 */ /* Fluorescent, Standard, 6350K, CRI 72 */ static xspect il_F5 = { @@ -364,7 +360,7 @@ static xspect il_F5 = { /* Fluorescent, Wide band 5000K, CRI 95 */ static xspect il_F8 = { 107, 300.0, 830.0, /* 109 bands from 300 to 830 nm in 5nm steps */ - 20.0, /* Arbitrary scale factor */ + 30.0, /* Arbitrary scale factor */ { /* 300 */ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, /* 340 */ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, @@ -388,7 +384,7 @@ static xspect il_F8 = { /* Fluorescent, Narrow band 5000K, CRI 81 */ static xspect il_F10 = { 107, 300.0, 830.0, /* 109 bands from 300 to 830 nm in 5nm steps */ - 20.0, /* Arbitrary scale factor */ + 30.0, /* Arbitrary scale factor */ { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, @@ -503,28 +499,16 @@ double temp /* Optional temperature in degrees kelvin, for Dtemp and Ptemp * return 0; case icxIT_Dtemp: return daylight_il(sp, temp); +#endif case icxIT_Ptemp: return planckian_il(sp, temp); -#endif } return 1; } -/* ------------- */ - -/* Spectral locus poligon cache */ -typedef struct { - int n; /* Number of spectral vertexes, 0 if uninit */ - double xmin, xmax, ymin, ymax; /* Boundint box */ - double tx[3], ty[3]; /* Fast inner triangle test, RGB */ - double be[3][3]; /* baricentric equations of triangle */ -// double eed[3]; /* Distance of triangle points to 0.3, 0.3 */ - double x[XSPECT_MAX_BANDS]; /* x value of vertex */ - double y[XSPECT_MAX_BANDS]; /* y value of vertex */ -} xslpoly; /* ------------- */ -/* Observer Data and locus poligon cache */ +/* Observer Data */ /* Standard CIE 1931 2 degree */ static xspect ob_CIE_1931_2[3] = { @@ -833,8 +817,6 @@ static xspect ob_CIE_1931_2[3] = { } }; -static xslpoly poly_CIE_1931_2 = { 0 }; - /* Standard CIE 1964 10 degree */ static xspect ob_CIE_1964_10[3] = { { @@ -1142,8 +1124,6 @@ static xspect ob_CIE_1964_10[3] = { } }; -static xslpoly poly_CIE_1964_10 = { 0 }; - #ifndef SALONEINSTLIB /* Standard CIE 1964 10 degree observer, */ /* adjusted for compatibility with 2 degree observer. */ @@ -1454,8 +1434,6 @@ static xspect ob_CIE_1964_10c[3] = { } }; -static xslpoly poly_CIE_1964_10c = { 0 }; - /* Judd & Voss 1978 2 degree */ static xspect ob_Judd_Voss_2[3] = { { @@ -1532,8 +1510,6 @@ static xspect ob_Judd_Voss_2[3] = { } }; -static xslpoly poly_Judd_Voss_2 = { 0 }; - /* Stiles & Burch 1955 2 degree, */ /* rotated to align with 1931 XYZ space, */ @@ -1601,8 +1577,6 @@ static xspect ob_Stiles_Burch_2[3] = { } }; -static xslpoly poly_Stiles_Burch_2 = { 0 }; - /* Shaw & Fairchild 1997 2 degree observer. */ /* From Mark Shaw's Masters thesis: */ /* "Evaluating the 1931 CIE Color Matching Functions" */ @@ -1666,8 +1640,898 @@ static xspect ob_Shaw_Fairchild_2[3] = { } }; -static xslpoly poly_Shaw_Fairchild_2 = { 0 }; +#ifdef NEVER +CIE TC 1-36 proposed +2-deg XYZ CMFs transformed from the CIE (2006) 2-deg LMS cone fundamentals + +390 3.769647E-03 4.146161E-04 1.847260E-02 +391 4.532416E-03 5.028333E-04 2.221101E-02 +392 5.446553E-03 6.084991E-04 2.669819E-02 +393 6.538868E-03 7.344436E-04 3.206937E-02 +394 7.839699E-03 8.837389E-04 3.847832E-02 +395 9.382967E-03 1.059646E-03 4.609784E-02 +396 1.120608E-02 1.265532E-03 5.511953E-02 +397 1.334965E-02 1.504753E-03 6.575257E-02 +398 1.585690E-02 1.780493E-03 7.822113E-02 +399 1.877286E-02 2.095572E-03 9.276013E-02 +400 2.214302E-02 2.452194E-03 1.096090E-01 +401 2.601285E-02 2.852216E-03 1.290077E-01 +402 3.043036E-02 3.299115E-03 1.512047E-01 +403 3.544325E-02 3.797466E-03 1.764441E-01 +404 4.109640E-02 4.352768E-03 2.049517E-01 +405 4.742986E-02 4.971717E-03 2.369246E-01 +406 5.447394E-02 5.661014E-03 2.725123E-01 +407 6.223612E-02 6.421615E-03 3.117820E-01 +408 7.070048E-02 7.250312E-03 3.547064E-01 +409 7.982513E-02 8.140173E-03 4.011473E-01 +410 8.953803E-02 9.079860E-03 4.508369E-01 +411 9.974848E-02 1.005608E-02 5.034164E-01 +412 1.104019E-01 1.106456E-02 5.586361E-01 +413 1.214566E-01 1.210522E-02 6.162734E-01 +414 1.328741E-01 1.318014E-02 6.760982E-01 +415 1.446214E-01 1.429377E-02 7.378822E-01 +416 1.566468E-01 1.545004E-02 8.013019E-01 +417 1.687901E-01 1.664093E-02 8.655573E-01 +418 1.808328E-01 1.785302E-02 9.295791E-01 +419 1.925216E-01 1.907018E-02 9.921293E-01 +420 2.035729E-01 2.027369E-02 1.051821E+00 +421 2.137531E-01 2.144805E-02 1.107509E+00 +422 2.231348E-01 2.260041E-02 1.159527E+00 +423 2.319245E-01 2.374789E-02 1.208869E+00 +424 2.403892E-01 2.491247E-02 1.256834E+00 +425 2.488523E-01 2.612106E-02 1.305008E+00 +426 2.575896E-01 2.739923E-02 1.354758E+00 +427 2.664991E-01 2.874993E-02 1.405594E+00 +428 2.753532E-01 3.016909E-02 1.456414E+00 +429 2.838921E-01 3.165145E-02 1.505960E+00 +430 2.918246E-01 3.319038E-02 1.552826E+00 +431 2.989200E-01 3.477912E-02 1.595902E+00 +432 3.052993E-01 3.641495E-02 1.635768E+00 +433 3.112031E-01 3.809569E-02 1.673573E+00 +434 3.169047E-01 3.981843E-02 1.710604E+00 +435 3.227087E-01 4.157940E-02 1.748280E+00 +436 3.288194E-01 4.337098E-02 1.787504E+00 +437 3.349242E-01 4.517180E-02 1.826609E+00 +438 3.405452E-01 4.695420E-02 1.863108E+00 +439 3.451688E-01 4.868718E-02 1.894332E+00 +440 3.482554E-01 5.033657E-02 1.917479E+00 +441 3.494153E-01 5.187611E-02 1.930529E+00 +442 3.489075E-01 5.332218E-02 1.934819E+00 +443 3.471746E-01 5.470603E-02 1.932650E+00 +444 3.446705E-01 5.606335E-02 1.926395E+00 +445 3.418483E-01 5.743393E-02 1.918437E+00 +446 3.390240E-01 5.885107E-02 1.910430E+00 +447 3.359926E-01 6.030809E-02 1.901224E+00 +448 3.324276E-01 6.178644E-02 1.889000E+00 +449 3.280157E-01 6.326570E-02 1.871996E+00 +450 3.224637E-01 6.472352E-02 1.848545E+00 +451 3.156225E-01 6.614749E-02 1.817792E+00 +452 3.078201E-01 6.757256E-02 1.781627E+00 +453 2.994771E-01 6.904928E-02 1.742514E+00 +454 2.909776E-01 7.063280E-02 1.702749E+00 +455 2.826646E-01 7.238339E-02 1.664439E+00 +456 2.747962E-01 7.435960E-02 1.629207E+00 +457 2.674312E-01 7.659383E-02 1.597360E+00 +458 2.605847E-01 7.911436E-02 1.568896E+00 +459 2.542749E-01 8.195345E-02 1.543823E+00 +460 2.485254E-01 8.514816E-02 1.522157E+00 +461 2.433039E-01 8.872657E-02 1.503611E+00 +462 2.383414E-01 9.266008E-02 1.486673E+00 +463 2.333253E-01 9.689723E-02 1.469595E+00 +464 2.279619E-01 1.013746E-01 1.450709E+00 +465 2.219781E-01 1.060145E-01 1.428440E+00 +466 2.151735E-01 1.107377E-01 1.401587E+00 +467 2.075619E-01 1.155111E-01 1.370094E+00 +468 1.992183E-01 1.203122E-01 1.334220E+00 +469 1.902290E-01 1.251161E-01 1.294275E+00 +470 1.806905E-01 1.298957E-01 1.250610E+00 +471 1.707154E-01 1.346299E-01 1.203696E+00 +472 1.604471E-01 1.393309E-01 1.154316E+00 +473 1.500244E-01 1.440235E-01 1.103284E+00 +474 1.395705E-01 1.487372E-01 1.051347E+00 +475 1.291920E-01 1.535066E-01 9.991789E-01 +476 1.189859E-01 1.583644E-01 9.473958E-01 +477 1.090615E-01 1.633199E-01 8.966222E-01 +478 9.951424E-02 1.683761E-01 8.473981E-01 +479 9.041850E-02 1.735365E-01 8.001576E-01 +480 8.182895E-02 1.788048E-01 7.552379E-01 +481 7.376817E-02 1.841819E-01 7.127879E-01 +482 6.619477E-02 1.896559E-01 6.725198E-01 +483 5.906380E-02 1.952101E-01 6.340976E-01 +484 5.234242E-02 2.008259E-01 5.972433E-01 +485 4.600865E-02 2.064828E-01 5.617313E-01 +486 4.006154E-02 2.121826E-01 5.274921E-01 +487 3.454373E-02 2.180279E-01 4.948809E-01 +488 2.949091E-02 2.241586E-01 4.642586E-01 +489 2.492140E-02 2.307302E-01 4.358841E-01 +490 2.083981E-02 2.379160E-01 4.099313E-01 +491 1.723591E-02 2.458706E-01 3.864261E-01 +492 1.407924E-02 2.546023E-01 3.650566E-01 +493 1.134516E-02 2.640760E-01 3.454812E-01 +494 9.019658E-03 2.742490E-01 3.274095E-01 +495 7.097731E-03 2.850680E-01 3.105939E-01 +496 5.571145E-03 2.964837E-01 2.948102E-01 +497 4.394566E-03 3.085010E-01 2.798194E-01 +498 3.516303E-03 3.211393E-01 2.654100E-01 +499 2.887638E-03 3.344175E-01 2.514084E-01 +500 2.461588E-03 3.483536E-01 2.376753E-01 +501 2.206348E-03 3.629601E-01 2.241211E-01 +502 2.149559E-03 3.782275E-01 2.107484E-01 +503 2.337091E-03 3.941359E-01 1.975839E-01 +504 2.818931E-03 4.106582E-01 1.846574E-01 +505 3.649178E-03 4.277595E-01 1.720018E-01 +506 4.891359E-03 4.453993E-01 1.596918E-01 +507 6.629364E-03 4.635396E-01 1.479415E-01 +508 8.942902E-03 4.821376E-01 1.369428E-01 +509 1.190224E-02 5.011430E-01 1.268279E-01 +510 1.556989E-02 5.204972E-01 1.176796E-01 +511 1.997668E-02 5.401387E-01 1.094970E-01 +512 2.504698E-02 5.600208E-01 1.020943E-01 +513 3.067530E-02 5.800972E-01 9.527993E-02 +514 3.674999E-02 6.003172E-01 8.890075E-02 +515 4.315171E-02 6.206256E-01 8.283548E-02 +516 4.978584E-02 6.409398E-01 7.700982E-02 +517 5.668554E-02 6.610772E-01 7.144001E-02 +518 6.391651E-02 6.808134E-01 6.615436E-02 +519 7.154352E-02 6.999044E-01 6.117199E-02 +520 7.962917E-02 7.180890E-01 5.650407E-02 +521 8.821473E-02 7.351593E-01 5.215121E-02 +522 9.726978E-02 7.511821E-01 4.809566E-02 +523 1.067504E-01 7.663143E-01 4.431720E-02 +524 1.166192E-01 7.807352E-01 4.079734E-02 +525 1.268468E-01 7.946448E-01 3.751912E-02 +526 1.374060E-01 8.082074E-01 3.446846E-02 +527 1.482471E-01 8.213817E-01 3.163764E-02 +528 1.593076E-01 8.340701E-01 2.901901E-02 +529 1.705181E-01 8.461711E-01 2.660364E-02 +530 1.818026E-01 8.575799E-01 2.438164E-02 +531 1.931090E-01 8.682408E-01 2.234097E-02 +532 2.045085E-01 8.783061E-01 2.046415E-02 +533 2.161166E-01 8.879907E-01 1.873456E-02 +534 2.280650E-01 8.975211E-01 1.713788E-02 +535 2.405015E-01 9.071347E-01 1.566174E-02 +536 2.535441E-01 9.169947E-01 1.429644E-02 +537 2.671300E-01 9.269295E-01 1.303702E-02 +538 2.811351E-01 9.366731E-01 1.187897E-02 +539 2.954164E-01 9.459482E-01 1.081725E-02 +540 3.098117E-01 9.544675E-01 9.846470E-03 +541 3.241678E-01 9.619834E-01 8.960687E-03 +542 3.384319E-01 9.684390E-01 8.152811E-03 +543 3.525786E-01 9.738289E-01 7.416025E-03 +544 3.665839E-01 9.781519E-01 6.744115E-03 +545 3.804244E-01 9.814106E-01 6.131421E-03 +546 3.940988E-01 9.836669E-01 5.572778E-03 +547 4.076972E-01 9.852081E-01 5.063463E-03 +548 4.213484E-01 9.863813E-01 4.599169E-03 +549 4.352003E-01 9.875357E-01 4.175971E-03 +550 4.494206E-01 9.890228E-01 3.790291E-03 +551 4.641616E-01 9.910811E-01 3.438952E-03 +552 4.794395E-01 9.934913E-01 3.119341E-03 +553 4.952180E-01 9.959172E-01 2.829038E-03 +554 5.114395E-01 9.980205E-01 2.565722E-03 +555 5.280233E-01 9.994608E-01 2.327186E-03 +556 5.448696E-01 9.999930E-01 2.111280E-03 +557 5.618898E-01 9.997557E-01 1.915766E-03 +558 5.790137E-01 9.989839E-01 1.738589E-03 +559 5.961882E-01 9.979123E-01 1.577920E-03 +560 6.133784E-01 9.967737E-01 1.432128E-03 +561 6.305897E-01 9.957356E-01 1.299781E-03 +562 6.479223E-01 9.947115E-01 1.179667E-03 +563 6.654866E-01 9.935534E-01 1.070694E-03 +564 6.833782E-01 9.921156E-01 9.718623E-04 +565 7.016774E-01 9.902549E-01 8.822531E-04 +566 7.204110E-01 9.878596E-01 8.010231E-04 +567 7.394495E-01 9.849324E-01 7.273884E-04 +568 7.586285E-01 9.815036E-01 6.606347E-04 +569 7.777885E-01 9.776035E-01 6.001146E-04 +570 7.967750E-01 9.732611E-01 5.452416E-04 +571 8.154530E-01 9.684764E-01 4.954847E-04 +572 8.337389E-01 9.631369E-01 4.503642E-04 +573 8.515493E-01 9.571062E-01 4.094455E-04 +574 8.687862E-01 9.502540E-01 3.723345E-04 +575 8.853376E-01 9.424569E-01 3.386739E-04 +576 9.011588E-01 9.336897E-01 3.081396E-04 +577 9.165278E-01 9.242893E-01 2.804370E-04 +578 9.318245E-01 9.146707E-01 2.552996E-04 +579 9.474524E-01 9.052333E-01 2.324859E-04 +580 9.638388E-01 8.963613E-01 2.117772E-04 +581 9.812596E-01 8.883069E-01 1.929758E-04 +582 9.992953E-01 8.808462E-01 1.759024E-04 +583 1.017343E+00 8.736445E-01 1.603947E-04 +584 1.034790E+00 8.663755E-01 1.463059E-04 +585 1.051011E+00 8.587203E-01 1.335031E-04 +586 1.065522E+00 8.504295E-01 1.218660E-04 +587 1.078421E+00 8.415047E-01 1.112857E-04 +588 1.089944E+00 8.320109E-01 1.016634E-04 +589 1.100320E+00 8.220154E-01 9.291003E-05 +590 1.109767E+00 8.115868E-01 8.494468E-05 +591 1.118438E+00 8.007874E-01 7.769425E-05 +592 1.126266E+00 7.896515E-01 7.109247E-05 +593 1.133138E+00 7.782053E-01 6.507936E-05 +594 1.138952E+00 7.664733E-01 5.960061E-05 +595 1.143620E+00 7.544785E-01 5.460706E-05 +596 1.147095E+00 7.422473E-01 5.005417E-05 +597 1.149464E+00 7.298229E-01 4.590157E-05 +598 1.150838E+00 7.172525E-01 4.211268E-05 +599 1.151326E+00 7.045818E-01 3.865437E-05 +600 1.151033E+00 6.918553E-01 3.549661E-05 +601 1.150002E+00 6.791009E-01 3.261220E-05 +602 1.148061E+00 6.662846E-01 2.997643E-05 +603 1.144998E+00 6.533595E-01 2.756693E-05 +604 1.140622E+00 6.402807E-01 2.536339E-05 +605 1.134757E+00 6.270066E-01 2.334738E-05 +606 1.127298E+00 6.135148E-01 2.150221E-05 +607 1.118342E+00 5.998494E-01 1.981268E-05 +608 1.108033E+00 5.860682E-01 1.826500E-05 +609 1.096515E+00 5.722261E-01 1.684667E-05 +610 1.083928E+00 5.583746E-01 1.554631E-05 +611 1.070387E+00 5.445535E-01 1.435360E-05 +612 1.055934E+00 5.307673E-01 1.325915E-05 +613 1.040592E+00 5.170130E-01 1.225443E-05 +614 1.024385E+00 5.032889E-01 1.133169E-05 +615 1.007344E+00 4.895950E-01 1.048387E-05 +616 9.895268E-01 4.759442E-01 0.000000E+00 +617 9.711213E-01 4.623958E-01 0.000000E+00 +618 9.523257E-01 4.490154E-01 0.000000E+00 +619 9.333248E-01 4.358622E-01 0.000000E+00 +620 9.142877E-01 4.229897E-01 0.000000E+00 +621 8.952798E-01 4.104152E-01 0.000000E+00 +622 8.760157E-01 3.980356E-01 0.000000E+00 +623 8.561607E-01 3.857300E-01 0.000000E+00 +624 8.354235E-01 3.733907E-01 0.000000E+00 +625 8.135565E-01 3.609245E-01 0.000000E+00 +626 7.904565E-01 3.482860E-01 0.000000E+00 +627 7.664364E-01 3.355702E-01 0.000000E+00 +628 7.418777E-01 3.228963E-01 0.000000E+00 +629 7.171219E-01 3.103704E-01 0.000000E+00 +630 6.924717E-01 2.980865E-01 0.000000E+00 +631 6.681600E-01 2.861160E-01 0.000000E+00 +632 6.442697E-01 2.744822E-01 0.000000E+00 +633 6.208450E-01 2.631953E-01 0.000000E+00 +634 5.979243E-01 2.522628E-01 0.000000E+00 +635 5.755410E-01 2.416902E-01 0.000000E+00 +636 5.537296E-01 2.314809E-01 0.000000E+00 +637 5.325412E-01 2.216378E-01 0.000000E+00 +638 5.120218E-01 2.121622E-01 0.000000E+00 +639 4.922070E-01 2.030542E-01 0.000000E+00 +640 4.731224E-01 1.943124E-01 0.000000E+00 +641 4.547417E-01 1.859227E-01 0.000000E+00 +642 4.368719E-01 1.778274E-01 0.000000E+00 +643 4.193121E-01 1.699654E-01 0.000000E+00 +644 4.018980E-01 1.622841E-01 0.000000E+00 +645 3.844986E-01 1.547397E-01 0.000000E+00 +646 3.670592E-01 1.473081E-01 0.000000E+00 +647 3.497167E-01 1.400169E-01 0.000000E+00 +648 3.326305E-01 1.329013E-01 0.000000E+00 +649 3.159341E-01 1.259913E-01 0.000000E+00 +650 2.997374E-01 1.193120E-01 0.000000E+00 +651 2.841189E-01 1.128820E-01 0.000000E+00 +652 2.691053E-01 1.067113E-01 0.000000E+00 +653 2.547077E-01 1.008052E-01 0.000000E+00 +654 2.409319E-01 9.516653E-02 0.000000E+00 +655 2.277792E-01 8.979594E-02 0.000000E+00 +656 2.152431E-01 8.469044E-02 0.000000E+00 +657 2.033010E-01 7.984009E-02 0.000000E+00 +658 1.919276E-01 7.523372E-02 0.000000E+00 +659 1.810987E-01 7.086061E-02 0.000000E+00 +660 1.707914E-01 6.671045E-02 0.000000E+00 +661 1.609842E-01 6.277360E-02 0.000000E+00 +662 1.516577E-01 5.904179E-02 0.000000E+00 +663 1.427936E-01 5.550703E-02 0.000000E+00 +664 1.343737E-01 5.216139E-02 0.000000E+00 +665 1.263808E-01 4.899699E-02 0.000000E+00 +666 1.187979E-01 4.600578E-02 0.000000E+00 +667 1.116088E-01 4.317885E-02 0.000000E+00 +668 1.047975E-01 4.050755E-02 0.000000E+00 +669 9.834835E-02 3.798376E-02 0.000000E+00 +670 9.224597E-02 3.559982E-02 0.000000E+00 +671 8.647506E-02 3.334856E-02 0.000000E+00 +672 8.101986E-02 3.122332E-02 0.000000E+00 +673 7.586514E-02 2.921780E-02 0.000000E+00 +674 7.099633E-02 2.732601E-02 0.000000E+00 +675 6.639960E-02 2.554223E-02 0.000000E+00 +676 6.206225E-02 2.386121E-02 0.000000E+00 +677 5.797409E-02 2.227859E-02 0.000000E+00 +678 5.412533E-02 2.079020E-02 0.000000E+00 +679 5.050600E-02 1.939185E-02 0.000000E+00 +680 4.710606E-02 1.807939E-02 0.000000E+00 +681 4.391411E-02 1.684817E-02 0.000000E+00 +682 4.091411E-02 1.569188E-02 0.000000E+00 +683 3.809067E-02 1.460446E-02 0.000000E+00 +684 3.543034E-02 1.358062E-02 0.000000E+00 +685 3.292138E-02 1.261573E-02 0.000000E+00 +686 3.055672E-02 1.170696E-02 0.000000E+00 +687 2.834146E-02 1.085608E-02 0.000000E+00 +688 2.628033E-02 1.006476E-02 0.000000E+00 +689 2.437465E-02 9.333376E-03 0.000000E+00 +690 2.262306E-02 8.661284E-03 0.000000E+00 +691 2.101935E-02 8.046048E-03 0.000000E+00 +692 1.954647E-02 7.481130E-03 0.000000E+00 +693 1.818727E-02 6.959987E-03 0.000000E+00 +694 1.692727E-02 6.477070E-03 0.000000E+00 +695 1.575417E-02 6.027677E-03 0.000000E+00 +696 1.465854E-02 5.608169E-03 0.000000E+00 +697 1.363571E-02 5.216691E-03 0.000000E+00 +698 1.268205E-02 4.851785E-03 0.000000E+00 +699 1.179394E-02 4.512008E-03 0.000000E+00 +700 1.096778E-02 4.195941E-03 0.000000E+00 +701 1.019964E-02 3.902057E-03 0.000000E+00 +702 9.484317E-03 3.628371E-03 0.000000E+00 +703 8.816851E-03 3.373005E-03 0.000000E+00 +704 8.192921E-03 3.134315E-03 0.000000E+00 +705 7.608750E-03 2.910864E-03 0.000000E+00 +706 7.061391E-03 2.701528E-03 0.000000E+00 +707 6.549509E-03 2.505796E-03 0.000000E+00 +708 6.071970E-03 2.323231E-03 0.000000E+00 +709 5.627476E-03 2.153333E-03 0.000000E+00 +710 5.214608E-03 1.995557E-03 0.000000E+00 +711 4.831848E-03 1.849316E-03 0.000000E+00 +712 4.477579E-03 1.713976E-03 0.000000E+00 +713 4.150166E-03 1.588899E-03 0.000000E+00 +714 3.847988E-03 1.473453E-03 0.000000E+00 +715 3.569452E-03 1.367022E-03 0.000000E+00 +716 3.312857E-03 1.268954E-03 0.000000E+00 +717 3.076022E-03 1.178421E-03 0.000000E+00 +718 2.856894E-03 1.094644E-03 0.000000E+00 +719 2.653681E-03 1.016943E-03 0.000000E+00 +720 2.464821E-03 9.447269E-04 0.000000E+00 +721 2.289060E-03 8.775171E-04 0.000000E+00 +722 2.125694E-03 8.150438E-04 0.000000E+00 +723 1.974121E-03 7.570755E-04 0.000000E+00 +724 1.833723E-03 7.033755E-04 0.000000E+00 +725 1.703876E-03 6.537050E-04 0.000000E+00 +726 1.583904E-03 6.078048E-04 0.000000E+00 +727 1.472939E-03 5.653435E-04 0.000000E+00 +728 1.370151E-03 5.260046E-04 0.000000E+00 +729 1.274803E-03 4.895061E-04 0.000000E+00 +730 1.186238E-03 4.555970E-04 0.000000E+00 +731 1.103871E-03 4.240548E-04 0.000000E+00 +732 1.027194E-03 3.946860E-04 0.000000E+00 +733 9.557493E-04 3.673178E-04 0.000000E+00 +734 8.891262E-04 3.417941E-04 0.000000E+00 +735 8.269535E-04 3.179738E-04 0.000000E+00 +736 7.689351E-04 2.957441E-04 0.000000E+00 +737 7.149425E-04 2.750558E-04 0.000000E+00 +738 6.648590E-04 2.558640E-04 0.000000E+00 +739 6.185421E-04 2.381142E-04 0.000000E+00 +740 5.758303E-04 2.217445E-04 0.000000E+00 +741 5.365046E-04 2.066711E-04 0.000000E+00 +742 5.001842E-04 1.927474E-04 0.000000E+00 +743 4.665005E-04 1.798315E-04 0.000000E+00 +744 4.351386E-04 1.678023E-04 0.000000E+00 +745 4.058303E-04 1.565566E-04 0.000000E+00 +746 3.783733E-04 1.460168E-04 0.000000E+00 +747 3.526892E-04 1.361535E-04 0.000000E+00 +748 3.287199E-04 1.269451E-04 0.000000E+00 +749 3.063998E-04 1.183671E-04 0.000000E+00 +750 2.856577E-04 1.103928E-04 0.000000E+00 +751 2.664108E-04 1.029908E-04 0.000000E+00 +752 2.485462E-04 9.611836E-05 0.000000E+00 +753 2.319529E-04 8.973323E-05 0.000000E+00 +754 2.165300E-04 8.379694E-05 0.000000E+00 +755 2.021853E-04 7.827442E-05 0.000000E+00 +756 1.888338E-04 7.313312E-05 0.000000E+00 +757 1.763935E-04 6.834142E-05 0.000000E+00 +758 1.647895E-04 6.387035E-05 0.000000E+00 +759 1.539542E-04 5.969389E-05 0.000000E+00 +760 1.438270E-04 5.578862E-05 0.000000E+00 +761 1.343572E-04 5.213509E-05 0.000000E+00 +762 1.255141E-04 4.872179E-05 0.000000E+00 +763 1.172706E-04 4.553845E-05 0.000000E+00 +764 1.095983E-04 4.257443E-05 0.000000E+00 +765 1.024685E-04 3.981884E-05 0.000000E+00 +766 9.584715E-05 3.725877E-05 0.000000E+00 +767 8.968316E-05 3.487467E-05 0.000000E+00 +768 8.392734E-05 3.264765E-05 0.000000E+00 +769 7.853708E-05 3.056140E-05 0.000000E+00 +770 7.347551E-05 2.860175E-05 0.000000E+00 +771 6.871576E-05 2.675841E-05 0.000000E+00 +772 6.425257E-05 2.502943E-05 0.000000E+00 +773 6.008292E-05 2.341373E-05 0.000000E+00 +774 5.620098E-05 2.190914E-05 0.000000E+00 +775 5.259870E-05 2.051259E-05 0.000000E+00 +776 4.926279E-05 1.921902E-05 0.000000E+00 +777 4.616623E-05 1.801796E-05 0.000000E+00 +778 4.328212E-05 1.689899E-05 0.000000E+00 +779 4.058715E-05 1.585309E-05 0.000000E+00 +780 3.806114E-05 1.487243E-05 0.000000E+00 +781 3.568818E-05 1.395085E-05 0.000000E+00 +782 3.346023E-05 1.308528E-05 0.000000E+00 +783 3.137090E-05 1.227327E-05 0.000000E+00 +784 2.941371E-05 1.151233E-05 0.000000E+00 +785 2.758222E-05 1.080001E-05 0.000000E+00 +786 2.586951E-05 1.013364E-05 0.000000E+00 +787 2.426701E-05 9.509919E-06 0.000000E+00 +788 2.276639E-05 8.925630E-06 0.000000E+00 +789 2.136009E-05 8.377852E-06 0.000000E+00 +790 2.004122E-05 7.863920E-06 0.000000E+00 +791 1.880380E-05 7.381539E-06 0.000000E+00 +792 1.764358E-05 6.929096E-06 0.000000E+00 +793 1.655671E-05 6.505136E-06 0.000000E+00 +794 1.553939E-05 6.108221E-06 0.000000E+00 +795 1.458792E-05 5.736935E-06 0.000000E+00 +796 1.369853E-05 5.389831E-06 0.000000E+00 +797 1.286705E-05 5.065269E-06 0.000000E+00 +798 1.208947E-05 4.761667E-06 0.000000E+00 +799 1.136207E-05 4.477561E-06 0.000000E+00 +800 1.068141E-05 4.211597E-06 0.000000E+00 +801 1.004411E-05 3.962457E-06 0.000000E+00 +802 9.446399E-06 3.728674E-06 0.000000E+00 +803 8.884754E-06 3.508881E-06 0.000000E+00 +804 8.356050E-06 3.301868E-06 0.000000E+00 +805 7.857521E-06 3.106561E-06 0.000000E+00 +806 7.386996E-06 2.922119E-06 0.000000E+00 +807 6.943576E-06 2.748208E-06 0.000000E+00 +808 6.526548E-06 2.584560E-06 0.000000E+00 +809 6.135087E-06 2.430867E-06 0.000000E+00 +810 5.768284E-06 2.286786E-06 0.000000E+00 +811 5.425069E-06 2.151905E-06 0.000000E+00 +812 5.103974E-06 2.025656E-06 0.000000E+00 +813 4.803525E-06 1.907464E-06 0.000000E+00 +814 4.522350E-06 1.796794E-06 0.000000E+00 +815 4.259166E-06 1.693147E-06 0.000000E+00 +816 4.012715E-06 1.596032E-06 0.000000E+00 +817 3.781597E-06 1.504903E-06 0.000000E+00 +818 3.564496E-06 1.419245E-06 0.000000E+00 +819 3.360236E-06 1.338600E-06 0.000000E+00 +820 3.167765E-06 1.262556E-06 0.000000E+00 +821 2.986206E-06 1.190771E-06 0.000000E+00 +822 2.814999E-06 1.123031E-06 0.000000E+00 +823 2.653663E-06 1.059151E-06 0.000000E+00 +824 2.501725E-06 9.989507E-07 0.000000E+00 +825 2.358723E-06 9.422514E-07 0.000000E+00 +826 2.224206E-06 8.888804E-07 0.000000E+00 +827 2.097737E-06 8.386690E-07 0.000000E+00 +828 1.978894E-06 7.914539E-07 0.000000E+00 +829 1.867268E-06 7.470770E-07 0.000000E+00 +830 1.762465E-06 7.053860E-07 0.000000E+00 + +CIE TC 1-36 proposed +10-deg XYZ CMFs transformed from the CIE (2006) 2-deg LMS cone fundamentals + +390 2.952420E-03 4.076779E-04 1.318752E-02 +391 3.577275E-03 4.977769E-04 1.597879E-02 +392 4.332146E-03 6.064754E-04 1.935758E-02 +393 5.241609E-03 7.370040E-04 2.343758E-02 +394 6.333902E-03 8.929388E-04 2.835021E-02 +395 7.641137E-03 1.078166E-03 3.424588E-02 +396 9.199401E-03 1.296816E-03 4.129467E-02 +397 1.104869E-02 1.553159E-03 4.968641E-02 +398 1.323262E-02 1.851463E-03 5.962964E-02 +399 1.579791E-02 2.195795E-03 7.134926E-02 +400 1.879338E-02 2.589775E-03 8.508254E-02 +401 2.226949E-02 3.036799E-03 1.010753E-01 +402 2.627978E-02 3.541926E-03 1.195838E-01 +403 3.087862E-02 4.111422E-03 1.408647E-01 +404 3.611890E-02 4.752618E-03 1.651644E-01 +405 4.204986E-02 5.474207E-03 1.927065E-01 +406 4.871256E-02 6.285034E-03 2.236782E-01 +407 5.612868E-02 7.188068E-03 2.582109E-01 +408 6.429866E-02 8.181786E-03 2.963632E-01 +409 7.319818E-02 9.260417E-03 3.381018E-01 +410 8.277331E-02 1.041303E-02 3.832822E-01 +411 9.295327E-02 1.162642E-02 4.316884E-01 +412 1.037137E-01 1.289884E-02 4.832440E-01 +413 1.150520E-01 1.423442E-02 5.379345E-01 +414 1.269771E-01 1.564080E-02 5.957740E-01 +415 1.395127E-01 1.712968E-02 6.568187E-01 +416 1.526661E-01 1.871265E-02 7.210459E-01 +417 1.663054E-01 2.038394E-02 7.878635E-01 +418 1.802197E-01 2.212935E-02 8.563391E-01 +419 1.941448E-01 2.392985E-02 9.253017E-01 +420 2.077647E-01 2.576133E-02 9.933444E-01 +421 2.207911E-01 2.760156E-02 1.059178E+00 +422 2.332355E-01 2.945513E-02 1.122832E+00 +423 2.452462E-01 3.133884E-02 1.184947E+00 +424 2.570397E-01 3.327575E-02 1.246476E+00 +425 2.688989E-01 3.529554E-02 1.308674E+00 +426 2.810677E-01 3.742705E-02 1.372628E+00 +427 2.933967E-01 3.967137E-02 1.437661E+00 +428 3.055933E-01 4.201998E-02 1.502449E+00 +429 3.173165E-01 4.446166E-02 1.565456E+00 +430 3.281798E-01 4.698226E-02 1.624940E+00 +431 3.378678E-01 4.956742E-02 1.679488E+00 +432 3.465097E-01 5.221219E-02 1.729668E+00 +433 3.543953E-01 5.491387E-02 1.776755E+00 +434 3.618655E-01 5.766919E-02 1.822228E+00 +435 3.693084E-01 6.047429E-02 1.867751E+00 +436 3.770107E-01 6.332195E-02 1.914504E+00 +437 3.846850E-01 6.619271E-02 1.961055E+00 +438 3.918591E-01 6.906185E-02 2.005136E+00 +439 3.980192E-01 7.190190E-02 2.044296E+00 +440 4.026189E-01 7.468288E-02 2.075946E+00 +441 4.052637E-01 7.738452E-02 2.098231E+00 +442 4.062482E-01 8.003601E-02 2.112591E+00 +443 4.060660E-01 8.268524E-02 2.121427E+00 +444 4.052283E-01 8.538745E-02 2.127239E+00 +445 4.042529E-01 8.820537E-02 2.132574E+00 +446 4.034808E-01 9.118925E-02 2.139093E+00 +447 4.025362E-01 9.431041E-02 2.144815E+00 +448 4.008675E-01 9.751346E-02 2.146832E+00 +449 3.979327E-01 1.007349E-01 2.142250E+00 +450 3.932139E-01 1.039030E-01 2.128264E+00 +451 3.864108E-01 1.069639E-01 2.103205E+00 +452 3.779513E-01 1.099676E-01 2.069388E+00 +453 3.684176E-01 1.129992E-01 2.030030E+00 +454 3.583473E-01 1.161541E-01 1.988178E+00 +455 3.482214E-01 1.195389E-01 1.946651E+00 +456 3.383830E-01 1.232503E-01 1.907521E+00 +457 3.288309E-01 1.273047E-01 1.870689E+00 +458 3.194977E-01 1.316964E-01 1.835578E+00 +459 3.103345E-01 1.364178E-01 1.801657E+00 +460 3.013112E-01 1.414586E-01 1.768440E+00 +461 2.923754E-01 1.468003E-01 1.735338E+00 +462 2.833273E-01 1.524002E-01 1.701254E+00 +463 2.739463E-01 1.582021E-01 1.665053E+00 +464 2.640352E-01 1.641400E-01 1.625712E+00 +465 2.534221E-01 1.701373E-01 1.582342E+00 +466 2.420135E-01 1.761233E-01 1.534439E+00 +467 2.299346E-01 1.820896E-01 1.482544E+00 +468 2.173617E-01 1.880463E-01 1.427438E+00 +469 2.044672E-01 1.940065E-01 1.369876E+00 +470 1.914176E-01 1.999859E-01 1.310576E+00 +471 1.783672E-01 2.060054E-01 1.250226E+00 +472 1.654407E-01 2.120981E-01 1.189511E+00 +473 1.527391E-01 2.183041E-01 1.129050E+00 +474 1.403439E-01 2.246686E-01 1.069379E+00 +475 1.283167E-01 2.312426E-01 1.010952E+00 +476 1.167124E-01 2.380741E-01 9.541809E-01 +477 1.056121E-01 2.451798E-01 8.995253E-01 +478 9.508569E-02 2.525682E-01 8.473720E-01 +479 8.518206E-02 2.602479E-01 7.980093E-01 +480 7.593120E-02 2.682271E-01 7.516389E-01 +481 6.733159E-02 2.765005E-01 7.082645E-01 +482 5.932018E-02 2.850035E-01 6.673867E-01 +483 5.184106E-02 2.936475E-01 6.284798E-01 +484 4.486119E-02 3.023319E-01 5.911174E-01 +485 3.836770E-02 3.109438E-01 5.549619E-01 +486 3.237296E-02 3.194105E-01 5.198843E-01 +487 2.692095E-02 3.278683E-01 4.862772E-01 +488 2.204070E-02 3.365263E-01 4.545497E-01 +489 1.773951E-02 3.456176E-01 4.249955E-01 +490 1.400745E-02 3.554018E-01 3.978114E-01 +491 1.082291E-02 3.660893E-01 3.730218E-01 +492 8.168996E-03 3.775857E-01 3.502618E-01 +493 6.044623E-03 3.896960E-01 3.291407E-01 +494 4.462638E-03 4.021947E-01 3.093356E-01 +495 3.446810E-03 4.148227E-01 2.905816E-01 +496 3.009513E-03 4.273539E-01 2.726773E-01 +497 3.090744E-03 4.398206E-01 2.555143E-01 +498 3.611221E-03 4.523360E-01 2.390188E-01 +499 4.491435E-03 4.650298E-01 2.231335E-01 +500 5.652072E-03 4.780482E-01 2.078158E-01 +501 7.035322E-03 4.915173E-01 1.930407E-01 +502 8.669631E-03 5.054224E-01 1.788089E-01 +503 1.060755E-02 5.197057E-01 1.651287E-01 +504 1.290468E-02 5.343012E-01 1.520103E-01 +505 1.561956E-02 5.491344E-01 1.394643E-01 +506 1.881640E-02 5.641302E-01 1.275353E-01 +507 2.256923E-02 5.792416E-01 1.163771E-01 +508 2.694456E-02 5.944264E-01 1.061161E-01 +509 3.199910E-02 6.096388E-01 9.682266E-02 +510 3.778185E-02 6.248296E-01 8.852389E-02 +511 4.430635E-02 6.399656E-01 8.118263E-02 +512 5.146516E-02 6.550943E-01 7.463132E-02 +513 5.912224E-02 6.702903E-01 6.870644E-02 +514 6.714220E-02 6.856375E-01 6.327834E-02 +515 7.538941E-02 7.012292E-01 5.824484E-02 +516 8.376697E-02 7.171103E-01 5.353812E-02 +517 9.233581E-02 7.330917E-01 4.914863E-02 +518 1.011940E-01 7.489041E-01 4.507511E-02 +519 1.104362E-01 7.642530E-01 4.131175E-02 +520 1.201511E-01 7.788199E-01 3.784916E-02 +521 1.303960E-01 7.923410E-01 3.467234E-02 +522 1.411310E-01 8.048510E-01 3.175471E-02 +523 1.522944E-01 8.164747E-01 2.907029E-02 +524 1.638288E-01 8.273520E-01 2.659651E-02 +525 1.756832E-01 8.376358E-01 2.431375E-02 +526 1.878114E-01 8.474653E-01 2.220677E-02 +527 2.001621E-01 8.568868E-01 2.026852E-02 +528 2.126822E-01 8.659242E-01 1.849246E-02 +529 2.253199E-01 8.746041E-01 1.687084E-02 +530 2.380254E-01 8.829552E-01 1.539505E-02 +531 2.507787E-01 8.910274E-01 1.405450E-02 +532 2.636778E-01 8.989495E-01 1.283354E-02 +533 2.768607E-01 9.068753E-01 1.171754E-02 +534 2.904792E-01 9.149652E-01 1.069415E-02 +535 3.046991E-01 9.233858E-01 9.753000E-03 +536 3.196485E-01 9.322325E-01 8.886096E-03 +537 3.352447E-01 9.412862E-01 8.089323E-03 +538 3.513290E-01 9.502378E-01 7.359131E-03 +539 3.677148E-01 9.587647E-01 6.691736E-03 +540 3.841856E-01 9.665325E-01 6.083223E-03 +541 4.005312E-01 9.732504E-01 5.529423E-03 +542 4.166669E-01 9.788415E-01 5.025504E-03 +543 4.325420E-01 9.832867E-01 4.566879E-03 +544 4.481063E-01 9.865720E-01 4.149405E-03 +545 4.633109E-01 9.886887E-01 3.769336E-03 +546 4.781440E-01 9.897056E-01 3.423302E-03 +547 4.927483E-01 9.899849E-01 3.108313E-03 +548 5.073315E-01 9.899624E-01 2.821650E-03 +549 5.221315E-01 9.900731E-01 2.560830E-03 +550 5.374170E-01 9.907500E-01 2.323578E-03 +551 5.534217E-01 9.922826E-01 2.107847E-03 +552 5.701242E-01 9.943837E-01 1.911867E-03 +553 5.874093E-01 9.966221E-01 1.734006E-03 +554 6.051269E-01 9.985649E-01 1.572736E-03 +555 6.230892E-01 9.997775E-01 1.426627E-03 +556 6.410999E-01 9.999440E-01 1.294325E-03 +557 6.590659E-01 9.992200E-01 1.174475E-03 +558 6.769436E-01 9.978793E-01 1.065842E-03 +559 6.947143E-01 9.961934E-01 9.673215E-04 +560 7.123849E-01 9.944304E-01 8.779264E-04 +561 7.299978E-01 9.927831E-01 7.967847E-04 +562 7.476478E-01 9.911578E-01 7.231502E-04 +563 7.654250E-01 9.893925E-01 6.563501E-04 +564 7.834009E-01 9.873288E-01 5.957678E-04 +565 8.016277E-01 9.848127E-01 5.408385E-04 +566 8.201041E-01 9.817253E-01 4.910441E-04 +567 8.386843E-01 9.780714E-01 4.459046E-04 +568 8.571936E-01 9.738860E-01 4.049826E-04 +569 8.754652E-01 9.692028E-01 3.678818E-04 +570 8.933408E-01 9.640545E-01 3.342429E-04 +571 9.106772E-01 9.584409E-01 3.037407E-04 +572 9.273554E-01 9.522379E-01 2.760809E-04 +573 9.432502E-01 9.452968E-01 2.509970E-04 +574 9.582244E-01 9.374773E-01 2.282474E-04 +575 9.721304E-01 9.286495E-01 2.076129E-04 +576 9.849237E-01 9.187953E-01 1.888948E-04 +577 9.970067E-01 9.083014E-01 1.719127E-04 +578 1.008907E+00 8.976352E-01 1.565030E-04 +579 1.021163E+00 8.872401E-01 1.425177E-04 +580 1.034327E+00 8.775360E-01 1.298230E-04 +581 1.048753E+00 8.687920E-01 1.182974E-04 +582 1.063937E+00 8.607474E-01 1.078310E-04 +583 1.079166E+00 8.530233E-01 9.832455E-05 +584 1.093723E+00 8.452535E-01 8.968787E-05 +585 1.106886E+00 8.370838E-01 8.183954E-05 +586 1.118106E+00 8.282409E-01 7.470582E-05 +587 1.127493E+00 8.187320E-01 6.821991E-05 +588 1.135317E+00 8.086352E-01 6.232132E-05 +589 1.141838E+00 7.980296E-01 5.695534E-05 +590 1.147304E+00 7.869950E-01 5.207245E-05 +591 1.151897E+00 7.756040E-01 4.762781E-05 +592 1.155582E+00 7.638996E-01 4.358082E-05 +593 1.158284E+00 7.519157E-01 3.989468E-05 +594 1.159934E+00 7.396832E-01 3.653612E-05 +595 1.160477E+00 7.272309E-01 3.347499E-05 +596 1.159890E+00 7.145878E-01 3.068400E-05 +597 1.158259E+00 7.017926E-01 2.813839E-05 +598 1.155692E+00 6.888866E-01 2.581574E-05 +599 1.152293E+00 6.759103E-01 2.369574E-05 +600 1.148163E+00 6.629035E-01 2.175998E-05 +601 1.143345E+00 6.498911E-01 1.999179E-05 +602 1.137685E+00 6.368410E-01 1.837603E-05 +603 1.130993E+00 6.237092E-01 1.689896E-05 +604 1.123097E+00 6.104541E-01 1.554815E-05 +605 1.113846E+00 5.970375E-01 1.431231E-05 +606 1.103152E+00 5.834395E-01 1.318119E-05 +607 1.091121E+00 5.697044E-01 1.214548E-05 +608 1.077902E+00 5.558892E-01 1.119673E-05 +609 1.063644E+00 5.420475E-01 1.032727E-05 +610 1.048485E+00 5.282296E-01 9.530130E-06 +611 1.032546E+00 5.144746E-01 8.798979E-06 +612 1.015870E+00 5.007881E-01 8.128065E-06 +613 9.984859E-01 4.871687E-01 7.512160E-06 +614 9.804227E-01 4.736160E-01 6.946506E-06 +615 9.617111E-01 4.601308E-01 6.426776E-06 +616 9.424119E-01 4.467260E-01 0.000000E+00 +617 9.227049E-01 4.334589E-01 0.000000E+00 +618 9.027804E-01 4.203919E-01 0.000000E+00 +619 8.828123E-01 4.075810E-01 0.000000E+00 +620 8.629581E-01 3.950755E-01 0.000000E+00 +621 8.432731E-01 3.828894E-01 0.000000E+00 +622 8.234742E-01 3.709190E-01 0.000000E+00 +623 8.032342E-01 3.590447E-01 0.000000E+00 +624 7.822715E-01 3.471615E-01 0.000000E+00 +625 7.603498E-01 3.351794E-01 0.000000E+00 +626 7.373739E-01 3.230562E-01 0.000000E+00 +627 7.136470E-01 3.108859E-01 0.000000E+00 +628 6.895336E-01 2.987840E-01 0.000000E+00 +629 6.653567E-01 2.868527E-01 0.000000E+00 +630 6.413984E-01 2.751807E-01 0.000000E+00 +631 6.178723E-01 2.638343E-01 0.000000E+00 +632 5.948484E-01 2.528330E-01 0.000000E+00 +633 5.723600E-01 2.421835E-01 0.000000E+00 +634 5.504353E-01 2.318904E-01 0.000000E+00 +635 5.290979E-01 2.219564E-01 0.000000E+00 +636 5.083728E-01 2.123826E-01 0.000000E+00 +637 4.883006E-01 2.031698E-01 0.000000E+00 +638 4.689171E-01 1.943179E-01 0.000000E+00 +639 4.502486E-01 1.858250E-01 0.000000E+00 +640 4.323126E-01 1.776882E-01 0.000000E+00 +641 4.150790E-01 1.698926E-01 0.000000E+00 +642 3.983657E-01 1.623822E-01 0.000000E+00 +643 3.819846E-01 1.550986E-01 0.000000E+00 +644 3.657821E-01 1.479918E-01 0.000000E+00 +645 3.496358E-01 1.410203E-01 0.000000E+00 +646 3.334937E-01 1.341614E-01 0.000000E+00 +647 3.174776E-01 1.274401E-01 0.000000E+00 +648 3.017298E-01 1.208887E-01 0.000000E+00 +649 2.863684E-01 1.145345E-01 0.000000E+00 +650 2.714900E-01 1.083996E-01 0.000000E+00 +651 2.571632E-01 1.025007E-01 0.000000E+00 +652 2.434102E-01 9.684588E-02 0.000000E+00 +653 2.302389E-01 9.143944E-02 0.000000E+00 +654 2.176527E-01 8.628318E-02 0.000000E+00 +655 2.056507E-01 8.137687E-02 0.000000E+00 +656 1.942251E-01 7.671708E-02 0.000000E+00 +657 1.833530E-01 7.229404E-02 0.000000E+00 +658 1.730097E-01 6.809696E-02 0.000000E+00 +659 1.631716E-01 6.411549E-02 0.000000E+00 +660 1.538163E-01 6.033976E-02 0.000000E+00 +661 1.449230E-01 5.676054E-02 0.000000E+00 +662 1.364729E-01 5.336992E-02 0.000000E+00 +663 1.284483E-01 5.016027E-02 0.000000E+00 +664 1.208320E-01 4.712405E-02 0.000000E+00 +665 1.136072E-01 4.425383E-02 0.000000E+00 +666 1.067579E-01 4.154205E-02 0.000000E+00 +667 1.002685E-01 3.898042E-02 0.000000E+00 +668 9.412394E-02 3.656091E-02 0.000000E+00 +669 8.830929E-02 3.427597E-02 0.000000E+00 +670 8.281010E-02 3.211852E-02 0.000000E+00 +671 7.761208E-02 3.008192E-02 0.000000E+00 +672 7.270064E-02 2.816001E-02 0.000000E+00 +673 6.806167E-02 2.634698E-02 0.000000E+00 +674 6.368176E-02 2.463731E-02 0.000000E+00 +675 5.954815E-02 2.302574E-02 0.000000E+00 +676 5.564917E-02 2.150743E-02 0.000000E+00 +677 5.197543E-02 2.007838E-02 0.000000E+00 +678 4.851788E-02 1.873474E-02 0.000000E+00 +679 4.526737E-02 1.747269E-02 0.000000E+00 +680 4.221473E-02 1.628841E-02 0.000000E+00 +681 3.934954E-02 1.517767E-02 0.000000E+00 +682 3.665730E-02 1.413473E-02 0.000000E+00 +683 3.412407E-02 1.315408E-02 0.000000E+00 +684 3.173768E-02 1.223092E-02 0.000000E+00 +685 2.948752E-02 1.136106E-02 0.000000E+00 +686 2.736717E-02 1.054190E-02 0.000000E+00 +687 2.538113E-02 9.775050E-03 0.000000E+00 +688 2.353356E-02 9.061962E-03 0.000000E+00 +689 2.182558E-02 8.402962E-03 0.000000E+00 +690 2.025590E-02 7.797457E-03 0.000000E+00 +691 1.881892E-02 7.243230E-03 0.000000E+00 +692 1.749930E-02 6.734381E-03 0.000000E+00 +693 1.628167E-02 6.265001E-03 0.000000E+00 +694 1.515301E-02 5.830085E-03 0.000000E+00 +695 1.410230E-02 5.425391E-03 0.000000E+00 +696 1.312106E-02 5.047634E-03 0.000000E+00 +697 1.220509E-02 4.695140E-03 0.000000E+00 +698 1.135114E-02 4.366592E-03 0.000000E+00 +699 1.055593E-02 4.060685E-03 0.000000E+00 +700 9.816228E-03 3.776140E-03 0.000000E+00 +701 9.128517E-03 3.511578E-03 0.000000E+00 +702 8.488116E-03 3.265211E-03 0.000000E+00 +703 7.890589E-03 3.035344E-03 0.000000E+00 +704 7.332061E-03 2.820496E-03 0.000000E+00 +705 6.809147E-03 2.619372E-03 0.000000E+00 +706 6.319204E-03 2.430960E-03 0.000000E+00 +707 5.861036E-03 2.254796E-03 0.000000E+00 +708 5.433624E-03 2.090489E-03 0.000000E+00 +709 5.035802E-03 1.937586E-03 0.000000E+00 +710 4.666298E-03 1.795595E-03 0.000000E+00 +711 4.323750E-03 1.663989E-03 0.000000E+00 +712 4.006709E-03 1.542195E-03 0.000000E+00 +713 3.713708E-03 1.429639E-03 0.000000E+00 +714 3.443294E-03 1.325752E-03 0.000000E+00 +715 3.194041E-03 1.229980E-03 0.000000E+00 +716 2.964424E-03 1.141734E-03 0.000000E+00 +717 2.752492E-03 1.060269E-03 0.000000E+00 +718 2.556406E-03 9.848854E-04 0.000000E+00 +719 2.374564E-03 9.149703E-04 0.000000E+00 +720 2.205568E-03 8.499903E-04 0.000000E+00 +721 2.048294E-03 7.895158E-04 0.000000E+00 +722 1.902113E-03 7.333038E-04 0.000000E+00 +723 1.766485E-03 6.811458E-04 0.000000E+00 +724 1.640857E-03 6.328287E-04 0.000000E+00 +725 1.524672E-03 5.881375E-04 0.000000E+00 +726 1.417322E-03 5.468389E-04 0.000000E+00 +727 1.318031E-03 5.086349E-04 0.000000E+00 +728 1.226059E-03 4.732403E-04 0.000000E+00 +729 1.140743E-03 4.404016E-04 0.000000E+00 +730 1.061495E-03 4.098928E-04 0.000000E+00 +731 9.877949E-04 3.815137E-04 0.000000E+00 +732 9.191847E-04 3.550902E-04 0.000000E+00 +733 8.552568E-04 3.304668E-04 0.000000E+00 +734 7.956433E-04 3.075030E-04 0.000000E+00 +735 7.400120E-04 2.860718E-04 0.000000E+00 +736 6.880980E-04 2.660718E-04 0.000000E+00 +737 6.397864E-04 2.474586E-04 0.000000E+00 +738 5.949726E-04 2.301919E-04 0.000000E+00 +739 5.535291E-04 2.142225E-04 0.000000E+00 +740 5.153113E-04 1.994949E-04 0.000000E+00 +741 4.801234E-04 1.859336E-04 0.000000E+00 +742 4.476245E-04 1.734067E-04 0.000000E+00 +743 4.174846E-04 1.617865E-04 0.000000E+00 +744 3.894221E-04 1.509641E-04 0.000000E+00 +745 3.631969E-04 1.408466E-04 0.000000E+00 +746 3.386279E-04 1.313642E-04 0.000000E+00 +747 3.156452E-04 1.224905E-04 0.000000E+00 +748 2.941966E-04 1.142060E-04 0.000000E+00 +749 2.742235E-04 1.064886E-04 0.000000E+00 +750 2.556624E-04 9.931439E-05 0.000000E+00 +751 2.384390E-04 9.265512E-05 0.000000E+00 +752 2.224525E-04 8.647225E-05 0.000000E+00 +753 2.076036E-04 8.072780E-05 0.000000E+00 +754 1.938018E-04 7.538716E-05 0.000000E+00 +755 1.809649E-04 7.041878E-05 0.000000E+00 +756 1.690167E-04 6.579338E-05 0.000000E+00 +757 1.578839E-04 6.148250E-05 0.000000E+00 +758 1.474993E-04 5.746008E-05 0.000000E+00 +759 1.378026E-04 5.370272E-05 0.000000E+00 +760 1.287394E-04 5.018934E-05 0.000000E+00 +761 1.202644E-04 4.690245E-05 0.000000E+00 +762 1.123502E-04 4.383167E-05 0.000000E+00 +763 1.049725E-04 4.096780E-05 0.000000E+00 +764 9.810596E-05 3.830123E-05 0.000000E+00 +765 9.172477E-05 3.582218E-05 0.000000E+00 +766 8.579861E-05 3.351903E-05 0.000000E+00 +767 8.028174E-05 3.137419E-05 0.000000E+00 +768 7.513013E-05 2.937068E-05 0.000000E+00 +769 7.030565E-05 2.749380E-05 0.000000E+00 +770 6.577532E-05 2.573083E-05 0.000000E+00 +771 6.151508E-05 2.407249E-05 0.000000E+00 +772 5.752025E-05 2.251704E-05 0.000000E+00 +773 5.378813E-05 2.106350E-05 0.000000E+00 +774 5.031350E-05 1.970991E-05 0.000000E+00 +775 4.708916E-05 1.845353E-05 0.000000E+00 +776 4.410322E-05 1.728979E-05 0.000000E+00 +777 4.133150E-05 1.620928E-05 0.000000E+00 +778 3.874992E-05 1.520262E-05 0.000000E+00 +779 3.633762E-05 1.426169E-05 0.000000E+00 +780 3.407653E-05 1.337946E-05 0.000000E+00 +781 3.195242E-05 1.255038E-05 0.000000E+00 +782 2.995808E-05 1.177169E-05 0.000000E+00 +783 2.808781E-05 1.104118E-05 0.000000E+00 +784 2.633581E-05 1.035662E-05 0.000000E+00 +785 2.469630E-05 9.715798E-06 0.000000E+00 +786 2.316311E-05 9.116316E-06 0.000000E+00 +787 2.172855E-05 8.555201E-06 0.000000E+00 +788 2.038519E-05 8.029561E-06 0.000000E+00 +789 1.912625E-05 7.536768E-06 0.000000E+00 +790 1.794555E-05 7.074424E-06 0.000000E+00 +791 1.683776E-05 6.640464E-06 0.000000E+00 +792 1.579907E-05 6.233437E-06 0.000000E+00 +793 1.482604E-05 5.852035E-06 0.000000E+00 +794 1.391527E-05 5.494963E-06 0.000000E+00 +795 1.306345E-05 5.160948E-06 0.000000E+00 +796 1.226720E-05 4.848687E-06 0.000000E+00 +797 1.152279E-05 4.556705E-06 0.000000E+00 +798 1.082663E-05 4.283580E-06 0.000000E+00 +799 1.017540E-05 4.027993E-06 0.000000E+00 +800 9.565993E-06 3.788729E-06 0.000000E+00 +801 8.995405E-06 3.564599E-06 0.000000E+00 +802 8.460253E-06 3.354285E-06 0.000000E+00 +803 7.957382E-06 3.156557E-06 0.000000E+00 +804 7.483997E-06 2.970326E-06 0.000000E+00 +805 7.037621E-06 2.794625E-06 0.000000E+00 +806 6.616311E-06 2.628701E-06 0.000000E+00 +807 6.219265E-06 2.472248E-06 0.000000E+00 +808 5.845844E-06 2.325030E-06 0.000000E+00 +809 5.495311E-06 2.186768E-06 0.000000E+00 +810 5.166853E-06 2.057152E-06 0.000000E+00 +811 4.859511E-06 1.935813E-06 0.000000E+00 +812 4.571973E-06 1.822239E-06 0.000000E+00 +813 4.302920E-06 1.715914E-06 0.000000E+00 +814 4.051121E-06 1.616355E-06 0.000000E+00 +815 3.815429E-06 1.523114E-06 0.000000E+00 +816 3.594719E-06 1.435750E-06 0.000000E+00 +817 3.387736E-06 1.353771E-06 0.000000E+00 +818 3.193301E-06 1.276714E-06 0.000000E+00 +819 3.010363E-06 1.204166E-06 0.000000E+00 +820 2.837980E-06 1.135758E-06 0.000000E+00 +821 2.675365E-06 1.071181E-06 0.000000E+00 +822 2.522020E-06 1.010243E-06 0.000000E+00 +823 2.377511E-06 9.527779E-07 0.000000E+00 +824 2.241417E-06 8.986224E-07 0.000000E+00 +825 2.113325E-06 8.476168E-07 0.000000E+00 +826 1.992830E-06 7.996052E-07 0.000000E+00 +827 1.879542E-06 7.544361E-07 0.000000E+00 +828 1.773083E-06 7.119624E-07 0.000000E+00 +829 1.673086E-06 6.720421E-07 0.000000E+00 +830 1.579199E-06 6.345380E-07 0.000000E+00 +#endif /* NEVER */ #endif /* !SALONEINSTLIB */ /* Return pointers to three xpsects with a standard observer weighting curves */ @@ -1745,36 +2609,6 @@ char *standardObserverDescription(icxObserverType obType) { return "Unknown observer"; } -/* Return a pointer to the spectral locus poligon */ -/* return NULL on failure. */ -static xslpoly *spectral_locus_poligon( -icxObserverType obType /* Type of observer */ -) { - switch (obType) { - case icxOT_custom: - return NULL; - case icxOT_none: - return NULL; - case icxOT_default: - case icxOT_CIE_1931_2: - return &poly_CIE_1931_2; - case icxOT_CIE_1964_10: - return &poly_CIE_1964_10; -#ifndef SALONEINSTLIB - case icxOT_Stiles_Burch_2: - return &poly_Stiles_Burch_2; - case icxOT_Judd_Voss_2: - return &poly_Judd_Voss_2; - case icxOT_CIE_1964_10c: - return &poly_CIE_1964_10c; - case icxOT_Shaw_Fairchild_2: - return &poly_Shaw_Fairchild_2; -#endif /* !SALONEINSTLIB */ - default: - return NULL; - } -} - #ifndef SALONEINSTLIB /* ----------------------------------- */ @@ -2135,6 +2969,8 @@ int write_nxspect(char *fname, xspect *sp, int nspec, int type) { sprintf(buf,"%f", sp->norm); ocg->add_kword(ocg, 0, "SPECTRAL_NORM",buf, NULL); + /* Should we adda A COORD field for "CMF" and an INDEX field for "SPECT" ? */ + /* Generate fields for spectral values */ for (i = 0; i < sp->spec_n; i++) { int nm; @@ -2172,6 +3008,7 @@ int write_nxspect(char *fname, xspect *sp, int nspec, int type) { /* Up to nspec will be restored starting at offset off.. */ /* The number restored from the file will be written to *nret */ /* type: 0 = any, mask: 1 = SPECT, 2 = CMF, 4 = ccss */ +/* (Note that not all ccss information is read. Use ccss->read_ccss() for this. */ /* Return NZ on error */ /* (Would be nice to return an error message!) */ int read_nxspect(xspect *sp, char *fname, int *nret, int off, int nspec, int type) { @@ -2454,6 +3291,44 @@ static int getval_raw_xspec_lin(xspect *sp, double *rv, double wl) { return rc; } +/* Get a raw linearly interpolated spectrum value x 3. */ +/* Return NZ if value is valid, Z and last valid value */ +/* if outside the range */ +/* NOTE: Returned value isn't normalised by sp->norm */ +static int getval_raw_xspec3_lin(xspect *sp, double *rv, double wl) { + int i, rc = 1; + double f, w; + + if (wl < sp[0].spec_wl_short) { + wl = sp[0].spec_wl_short; + rc = 0; + } + + if (wl > sp[0].spec_wl_long) { + wl = sp[0].spec_wl_long; + rc = 0; + } + + /* Compute fraction 0.0 - 1.0 out of known spectrum */ + f = (wl - sp[0].spec_wl_short) / (sp[0].spec_wl_long - sp[0].spec_wl_short); + f *= (sp[0].spec_n - 1.0); + i = (int)floor(f); /* Base grid coordinate */ + + if (i < 0) /* Limit to valid cube base index range */ + i = 0; + else if (i > (sp[0].spec_n - 2)) + i = (sp[0].spec_n - 2); + + w = f - (double)i; /* Interpolation weighting factor */ + + /* Compute interpolated value */ + rv[0] = (1.0 - w) * sp[0].spec[i] + w * sp[0].spec[i+1]; + rv[1] = (1.0 - w) * sp[1].spec[i] + w * sp[1].spec[i+1]; + rv[2] = (1.0 - w) * sp[2].spec[i] + w * sp[2].spec[i+1]; + + return rc; +} + #ifdef NEVER /* Nearest neighbor resampler, for testing */ /* Get a raw nearest-neighbor interpolated spectrum value. */ /* Return NZ if value is valid, Z and last valid value */ @@ -2587,6 +3462,7 @@ void xspect2xspect(xspect *dst, xspect *targ, xspect *src) { /* Given an emission spectrum, set the UV output to the given level. */ /* The shape of the UV is taken from FWA1_stim, and the level is */ /* with respect to the Y of the input spectrum. */ +/* The output range is extended to accomodate the UV wavelengths */ void xsp_setUV(xspect *out, xspect *in, double uvlevel) { int i, xs, xe; double ww, avg; @@ -2594,7 +3470,7 @@ void xsp_setUV(xspect *out, xspect *in, double uvlevel) { cin = *in; - /* Compute the average of the input spetrum */ + /* Compute the average of the input spectrum */ for (avg = 0.0, i = 0; i < cin.spec_n; i++) avg += cin.spec[i]; avg /= cin.spec_n; @@ -2618,6 +3494,9 @@ void xsp_setUV(xspect *out, xspect *in, double uvlevel) { getval_raw_xspec_lin(&cin, &inv, ww); getval_raw_xspec_lin(&FWA1_stim, &uvv, ww); + /* Input illuminant with no Uv */ + out->spec[i] = inv; + /* Taper measured illum out */ bl = (ww - FWA1_stim.spec_wl_short)/(FWA1_stim.spec_wl_long - FWA1_stim.spec_wl_short); bl = bl < 0.0 ? 0.0 : (bl > 1.0 ? 1.0 : bl); @@ -3735,8 +4614,9 @@ xspect *in /* Spectrum to be converted */ /* are used, also consistent with CIE and ANSI CGATS recommendations. */ out[j] = 0.0; for (ww = p->observer[j].spec_wl_short; ww <= p->observer[j].spec_wl_long; ww += 1.0) { - double I, O, S; - getval_xspec(&p->illuminant, &I, ww); + double I = 1.0, O, S; + if (!p->isemis) + getval_xspec(&p->illuminant, &I, ww); getval_xspec(&p->observer[j], &O, ww); getval_xspec(in, &S, ww); if (j == 1) @@ -3788,7 +4668,7 @@ icxIllumeType ilType, /* Illuminant */ xspect *custIllum, /* Optional custom illuminant */ icxObserverType obType, /* Observer */ xspect custObserver[3], /* Optional custom observer */ -icColorSpaceSignature rcs, /* Return color space, icSigXYZData or icSigLabData */ +icColorSpaceSignature rcs, /* Return color space, icSigXYZData or D50 icSigLabData */ /* ** Must be icSigXYZData if SALONEINSTLIB ** */ icxClamping clamp /* NZ to clamp XYZ/Lab to be +ve */ ) { @@ -3924,9 +4804,10 @@ icxClamping clamp /* NZ to clamp XYZ/Lab to be +ve */ #ifndef SALONEINSTLIB + /* -------------------------------------------------------- */ -/* Return the spectrum locus rangefor the given observer */ +/* Return the spectrum locus range for the given observer */ /* return 0 on sucecss, nz if observer not known */ int icx_spectrum_locus_range(double *min_wl, double *max_wl, icxObserverType obType) { xspect *sp[3]; @@ -3947,7 +4828,7 @@ int icx_spectrum_locus_range(double *min_wl, double *max_wl, icxObserverType obT int icx_spectrum_locus(double xyz[3], double wl, icxObserverType obType) { xspect *sp[3]; - DBGF((DBGA,"icx_spectrum_locus got obs %d wl %f\n",obType, wl)); + DBGF((DBGA,"icx_chrom_locus got obs %d wl %f\n",obType, wl)); if (standardObserver(sp, obType)) return 1; @@ -3966,113 +4847,1033 @@ int icx_spectrum_locus(double xyz[3], double wl, icxObserverType obType) { return 0; } +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* Pre-calculated spectral locuses of Daylight and Plankian at 5 Mired intervals */ +/* These aren't actually spectrum, they are XYZ values */ +/* indexed by temperature in Mired */ + +static xspect illoc_Daylight_CIE_1931_2[3] = { + { + 69, 60.000000, 400.000000, + 1.0, + { + 0.970635, 0.968292, 0.966045, 0.963906, 0.961884, + 0.959990, 0.958232, 0.956618, 0.955155, 0.953850, + 0.952710, 0.951740, 0.950945, 0.950330, 0.949899, + 0.949656, 0.949604, 0.949747, 0.950085, 0.950619, + 0.951352, 0.952283, 0.953413, 0.954741, 0.956265, + 0.957984, 0.959896, 0.961999, 0.964289, 0.966764, + 0.969419, 0.972251, 0.975254, 0.978425, 0.981759, + 0.985248, 0.988889, 0.992674, 0.996597, 1.000651, + 1.004828, 1.009121, 1.013522, 1.018021, 1.022611, + 1.027281, 1.032021, 1.036822, 1.041673, 1.046562, + 1.051478, 1.056409, 1.061342, 1.066265, 1.071163, + 1.076024, 1.080834, 1.085577, 1.090239, 1.094805, + 1.099259, 1.103586, 1.107771, 1.111796, 1.115647, + 1.119306, 1.122759, 1.125989, 1.128981 + } + }, + { + 69, 60.000000, 400.000000, + 1.0, + { + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000 + } + }, + { + 69, 60.000000, 400.000000, + 1.0, + { + 1.787622, 1.747661, 1.707659, 1.667701, 1.627864, + 1.588223, 1.548842, 1.509780, 1.471093, 1.432827, + 1.395026, 1.357727, 1.320965, 1.284767, 1.249158, + 1.214160, 1.179790, 1.146125, 1.113225, 1.081024, + 1.049542, 1.018793, 0.988790, 0.959541, 0.931050, + 0.903320, 0.876351, 0.850140, 0.824684, 0.799977, + 0.776012, 0.752780, 0.730272, 0.708479, 0.687390, + 0.666992, 0.647275, 0.628227, 0.609834, 0.592085, + 0.574967, 0.558466, 0.542572, 0.527270, 0.512549, + 0.498396, 0.484799, 0.471746, 0.459226, 0.447227, + 0.435739, 0.424749, 0.414250, 0.404229, 0.394677, + 0.385586, 0.376946, 0.368749, 0.360986, 0.353651, + 0.346735, 0.340234, 0.334139, 0.328447, 0.323151, + 0.318248, 0.313734, 0.309607, 0.305862 + } + } +}; + +static xspect illoc_Plankian_CIE_1931_2[3] = { + { + 189, 60.000000, 1000.000000, + 1.0, + { + 0.990017, 0.987458, 0.985018, 0.982708, 0.980540, + 0.978522, 0.976663, 0.974970, 0.973449, 0.972105, + 0.970942, 0.969965, 0.969174, 0.968572, 0.968159, + 0.967936, 0.967902, 0.968056, 0.968396, 0.968922, + 0.969629, 0.970517, 0.971581, 0.972819, 0.974227, + 0.975803, 0.977542, 0.979441, 0.981495, 0.983702, + 0.986058, 0.988559, 0.991200, 0.993979, 0.996891, + 0.999934, 1.003102, 1.006394, 1.009804, 1.013331, + 1.016970, 1.020718, 1.024572, 1.028529, 1.032586, + 1.036739, 1.040986, 1.045325, 1.049751, 1.054263, + 1.058857, 1.063532, 1.068285, 1.073113, 1.078013, + 1.082985, 1.088024, 1.093130, 1.098299, 1.103530, + 1.108822, 1.114170, 1.119575, 1.125034, 1.130544, + 1.136105, 1.141715, 1.147371, 1.153072, 1.158817, + 1.164604, 1.170431, 1.176297, 1.182201, 1.188140, + 1.194115, 1.200122, 1.206161, 1.212231, 1.218329, + 1.224456, 1.230610, 1.236790, 1.242994, 1.249221, + 1.255470, 1.261741, 1.268032, 1.274342, 1.280670, + 1.287015, 1.293376, 1.299753, 1.306144, 1.312548, + 1.318965, 1.325393, 1.331833, 1.338282, 1.344741, + 1.351208, 1.357683, 1.364165, 1.370653, 1.377146, + 1.383645, 1.390147, 1.396654, 1.403162, 1.409674, + 1.416186, 1.422700, 1.429214, 1.435728, 1.442241, + 1.448753, 1.455263, 1.461771, 1.468275, 1.474777, + 1.481274, 1.487767, 1.494255, 1.500738, 1.507215, + 1.513686, 1.520150, 1.526607, 1.533057, 1.539498, + 1.545932, 1.552356, 1.558772, 1.565178, 1.571574, + 1.577960, 1.584336, 1.590701, 1.597054, 1.603397, + 1.609727, 1.616045, 1.622351, 1.628644, 1.634924, + 1.641190, 1.647444, 1.653683, 1.659908, 1.666119, + 1.672315, 1.678497, 1.684663, 1.690814, 1.696949, + 1.703069, 1.709173, 1.715260, 1.721331, 1.727386, + 1.733423, 1.739444, 1.745447, 1.751433, 1.757402, + 1.763353, 1.769286, 1.775201, 1.781098, 1.786976, + 1.792836, 1.798677, 1.804500, 1.810304, 1.816088, + 1.821853, 1.827600, 1.833326, 1.839033, 1.844721, + 1.850388, 1.856036, 1.861664, 1.867272, 1.872859, + 1.878426, 1.883973, 1.889500, 1.895006 + } + }, + { + 189, 60.000000, 1000.000000, + 1.0, + { + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000 + } + }, + { + 189, 60.000000, 1000.000000, + 1.0, + { + 1.807443, 1.767939, 1.728424, 1.688977, 1.649677, + 1.610595, 1.571797, 1.533345, 1.495294, 1.457694, + 1.420591, 1.384023, 1.348026, 1.312628, 1.277856, + 1.243731, 1.210269, 1.177483, 1.145385, 1.113980, + 1.083273, 1.053267, 1.023960, 0.995350, 0.967433, + 0.940204, 0.913655, 0.887779, 0.862566, 0.838007, + 0.814090, 0.790805, 0.768140, 0.746084, 0.724623, + 0.703745, 0.683438, 0.663689, 0.644486, 0.625814, + 0.607663, 0.590019, 0.572870, 0.556203, 0.540006, + 0.524267, 0.508975, 0.494117, 0.479683, 0.465661, + 0.452040, 0.438809, 0.425958, 0.413476, 0.401354, + 0.389581, 0.378149, 0.367047, 0.356266, 0.345798, + 0.335634, 0.325764, 0.316182, 0.306879, 0.297847, + 0.289078, 0.280566, 0.272302, 0.264279, 0.256492, + 0.248932, 0.241594, 0.234472, 0.227558, 0.220848, + 0.214334, 0.208013, 0.201877, 0.195922, 0.190142, + 0.184533, 0.179089, 0.173806, 0.168679, 0.163703, + 0.158875, 0.154189, 0.149641, 0.145229, 0.140947, + 0.136792, 0.132760, 0.128847, 0.125050, 0.121366, + 0.117792, 0.114323, 0.110958, 0.107692, 0.104523, + 0.101449, 0.098466, 0.095571, 0.092763, 0.090038, + 0.087394, 0.084829, 0.082340, 0.079926, 0.077583, + 0.075310, 0.073104, 0.070964, 0.068888, 0.066874, + 0.064919, 0.063023, 0.061184, 0.059399, 0.057667, + 0.055987, 0.054357, 0.052775, 0.051240, 0.049752, + 0.048307, 0.046906, 0.045546, 0.044226, 0.042946, + 0.041704, 0.040499, 0.039330, 0.038195, 0.037095, + 0.036027, 0.034990, 0.033985, 0.033009, 0.032062, + 0.031144, 0.030252, 0.029387, 0.028548, 0.027734, + 0.026943, 0.026177, 0.025432, 0.024710, 0.024009, + 0.023329, 0.022669, 0.022029, 0.021407, 0.020804, + 0.020219, 0.019651, 0.019099, 0.018564, 0.018044, + 0.017540, 0.017051, 0.016576, 0.016115, 0.015668, + 0.015233, 0.014811, 0.014402, 0.014005, 0.013619, + 0.013245, 0.012881, 0.012528, 0.012186, 0.011853, + 0.011530, 0.011217, 0.010912, 0.010617, 0.010329, + 0.010051, 0.009780, 0.009517, 0.009262, 0.009014, + 0.008773, 0.008540, 0.008313, 0.008092 + } + } +}; + +static xspect illoc_Daylight_CIE_1964_10[3] = { + { + 69, 60.000000, 400.000000, + 1.0, + { + 0.949535, 0.948408, 0.947363, 0.946408, 0.945551, + 0.944800, 0.944161, 0.943639, 0.943243, 0.942976, + 0.942844, 0.942853, 0.943006, 0.943308, 0.943763, + 0.944374, 0.945146, 0.946079, 0.947174, 0.948434, + 0.949861, 0.951455, 0.953217, 0.955146, 0.957242, + 0.959504, 0.961930, 0.964519, 0.967268, 0.970175, + 0.973237, 0.976450, 0.979812, 0.983317, 0.986963, + 0.990743, 0.994653, 0.998688, 1.002842, 1.007108, + 1.011480, 1.015951, 1.020514, 1.025161, 1.029883, + 1.034672, 1.039519, 1.044415, 1.049348, 1.054309, + 1.059288, 1.064271, 1.069249, 1.074207, 1.079135, + 1.084018, 1.088844, 1.093597, 1.098265, 1.102832, + 1.107284, 1.111605, 1.115781, 1.119796, 1.123634, + 1.127280, 1.130718, 1.133933, 1.136910 + } + }, + { + 69, 60.000000, 400.000000, + 1.0, + { + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000 + } + }, + { + 69, 60.000000, 400.000000, + 1.0, + { + 1.736104, 1.699156, 1.662051, 1.624867, 1.587679, + 1.550555, 1.513559, 1.476750, 1.440182, 1.403904, + 1.367961, 1.332394, 1.297239, 1.262528, 1.228292, + 1.194555, 1.161341, 1.128728, 1.096782, 1.065445, + 1.034742, 1.004693, 0.975315, 0.946623, 0.918626, + 0.891332, 0.864747, 0.838873, 0.813712, 0.789262, + 0.765521, 0.742485, 0.720149, 0.698506, 0.677549, + 0.657271, 0.637662, 0.618713, 0.600415, 0.582756, + 0.565728, 0.549318, 0.533516, 0.518310, 0.503690, + 0.489644, 0.476161, 0.463230, 0.450839, 0.438977, + 0.427633, 0.416797, 0.406457, 0.396605, 0.387228, + 0.378318, 0.369864, 0.361858, 0.354290, 0.347151, + 0.340434, 0.334131, 0.328233, 0.322735, 0.317629, + 0.312911, 0.308575, 0.304616, 0.301031 + } + } +}; + +static xspect illoc_Plankian_CIE_1964_10[3] = { + { + 189, 60.000000, 1000.000000, + 1.0, + { + 0.974241, 0.972539, 0.970952, 0.969490, 0.968163, + 0.966977, 0.965941, 0.965060, 0.964340, 0.963785, + 0.963398, 0.963183, 0.963140, 0.963272, 0.963578, + 0.964058, 0.964713, 0.965540, 0.966539, 0.967707, + 0.969041, 0.970540, 0.972201, 0.974020, 0.975994, + 0.978121, 0.980396, 0.982816, 0.985378, 0.988077, + 0.990911, 0.993876, 0.996967, 1.000182, 1.003517, + 1.006968, 1.010533, 1.014206, 1.017986, 1.021868, + 1.025851, 1.029929, 1.034101, 1.038362, 1.042711, + 1.047144, 1.051659, 1.056252, 1.060921, 1.065663, + 1.070476, 1.075357, 1.080304, 1.085314, 1.090384, + 1.095514, 1.100699, 1.105939, 1.111231, 1.116573, + 1.121962, 1.127398, 1.132878, 1.138400, 1.143962, + 1.149564, 1.155202, 1.160875, 1.166582, 1.172320, + 1.178090, 1.183888, 1.189713, 1.195565, 1.201441, + 1.207340, 1.213262, 1.219204, 1.225165, 1.231144, + 1.237140, 1.243152, 1.249179, 1.255219, 1.261272, + 1.267336, 1.273410, 1.279494, 1.285586, 1.291686, + 1.297792, 1.303903, 1.310020, 1.316140, 1.322264, + 1.328390, 1.334517, 1.340646, 1.346774, 1.352902, + 1.359028, 1.365152, 1.371274, 1.377392, 1.383506, + 1.389615, 1.395720, 1.401819, 1.407911, 1.413996, + 1.420075, 1.426145, 1.432207, 1.438260, 1.444304, + 1.450337, 1.456361, 1.462374, 1.468376, 1.474367, + 1.480346, 1.486312, 1.492266, 1.498207, 1.504134, + 1.510048, 1.515948, 1.521834, 1.527705, 1.533561, + 1.539402, 1.545228, 1.551037, 1.556831, 1.562609, + 1.568370, 1.574114, 1.579842, 1.585552, 1.591245, + 1.596920, 1.602578, 1.608217, 1.613839, 1.619442, + 1.625026, 1.630592, 1.636139, 1.641668, 1.647177, + 1.652666, 1.658137, 1.663587, 1.669019, 1.674430, + 1.679822, 1.685193, 1.690544, 1.695876, 1.701187, + 1.706477, 1.711747, 1.716997, 1.722226, 1.727434, + 1.732621, 1.737788, 1.742934, 1.748058, 1.753162, + 1.758245, 1.763306, 1.768347, 1.773366, 1.778364, + 1.783341, 1.788296, 1.793230, 1.798143, 1.803034, + 1.807904, 1.812753, 1.817580, 1.822386, 1.827170, + 1.831933, 1.836674, 1.841394, 1.846092 + } + }, + { + 189, 60.000000, 1000.000000, + 1.0, + { + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000 + } + }, + { + 189, 60.000000, 1000.000000, + 1.0, + { + 1.775958, 1.738417, 1.700795, 1.663169, 1.625615, + 1.588201, 1.550992, 1.514049, 1.477427, 1.441177, + 1.405344, 1.369969, 1.335088, 1.300732, 1.266930, + 1.233704, 1.201074, 1.169056, 1.137662, 1.106903, + 1.076786, 1.047315, 1.018493, 0.990321, 0.962796, + 0.935916, 0.909677, 0.884073, 0.859098, 0.834744, + 0.811003, 0.787866, 0.765323, 0.743365, 0.721980, + 0.701159, 0.680891, 0.661164, 0.641968, 0.623290, + 0.605120, 0.587446, 0.570257, 0.553542, 0.537290, + 0.521489, 0.506129, 0.491199, 0.476688, 0.462586, + 0.448883, 0.435567, 0.422630, 0.410062, 0.397852, + 0.385993, 0.374473, 0.363285, 0.352420, 0.341868, + 0.331622, 0.321672, 0.312013, 0.302634, 0.293529, + 0.284689, 0.276109, 0.267780, 0.259696, 0.251849, + 0.244234, 0.236843, 0.229670, 0.222710, 0.215956, + 0.209402, 0.203043, 0.196873, 0.190887, 0.185079, + 0.179445, 0.173979, 0.168676, 0.163533, 0.158544, + 0.153704, 0.149010, 0.144457, 0.140042, 0.135759, + 0.131606, 0.127578, 0.123672, 0.119884, 0.116210, + 0.112648, 0.109194, 0.105845, 0.102598, 0.099449, + 0.096397, 0.093437, 0.090567, 0.087785, 0.085088, + 0.082473, 0.079938, 0.077480, 0.075098, 0.072788, + 0.070550, 0.068380, 0.066276, 0.064237, 0.062260, + 0.060345, 0.058488, 0.056688, 0.054943, 0.053252, + 0.051613, 0.050025, 0.048485, 0.046993, 0.045547, + 0.044145, 0.042787, 0.041470, 0.040194, 0.038958, + 0.037760, 0.036598, 0.035473, 0.034382, 0.033325, + 0.032300, 0.031308, 0.030346, 0.029413, 0.028510, + 0.027634, 0.026786, 0.025963, 0.025166, 0.024394, + 0.023646, 0.022921, 0.022218, 0.021537, 0.020877, + 0.020237, 0.019618, 0.019017, 0.018435, 0.017871, + 0.017324, 0.016795, 0.016281, 0.015784, 0.015302, + 0.014835, 0.014382, 0.013943, 0.013518, 0.013106, + 0.012706, 0.012319, 0.011944, 0.011581, 0.011228, + 0.010887, 0.010556, 0.010235, 0.009925, 0.009623, + 0.009331, 0.009048, 0.008774, 0.008508, 0.008251, + 0.008001, 0.007759, 0.007524, 0.007297, 0.007077, + 0.006863, 0.006656, 0.006455, 0.006261 + } + } +}; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* Fast but slightly less accurate CCT support */ + +/* Context for optimiser callback */ +typedef struct { + xspect *iloc; /* Locus to match to */ + double xyz[3]; /* Target XYZ */ + icmXYZNumber XYZ; /* Target as XYZ number for DE wp */ + xsp2cie *conv; /* Means of converting spectrum to XYZ */ + int viscct; /* nz to use visual best match color temperature */ +} cct2ctx; + +static double cct2_func(void *fdata, double tp[]) { + cct2ctx *x = (cct2ctx *)fdata; + double xyz[3]; /* Current value */ + double lab1[3], lab2[3]; + xspect sp; + double rv = 0.0; + icmXYZNumber *wp = &x->XYZ; + + /* Get XYZ for given temp in Mired. */ + /* Will clip to limits of locus */ + getval_raw_xspec3_lin(x->iloc, xyz, tp[0]); + + xyz[0] /= xyz[1]; + xyz[2] /= xyz[1]; + xyz[1] /= xyz[1]; + + /* Compute the color difference to the target */ + if (x->viscct) { + /* Use modern CIEDE2000 color difference - gives a better visual match */ + icmXYZ2Lab(wp, lab1, x->xyz); + icmXYZ2Lab(wp, lab2, xyz); + rv = icmCIE2Ksq(lab1, lab2); + } else { + /* Use original CIE 1960 UCS space color difference */ + icmXYZ21960UCS(lab1, x->xyz); + icmXYZ21960UCS(lab2, xyz); + rv = icmLabDEsq(lab1, lab2); + } + +//a1logd(g_log, 1, " cct2_func returning %f for temp = %f\n",rv,1e6/tp[0]); +//DBGF((DBGA,"returning %f for temp = %f\n",rv,tp[0])); + return rv; + +} + +/* Given a choice of temperature dependent illuminant (icxIT_Dtemp or icxIT_Ptemp), */ +/* return the closest correlated color temperature to the XYZ. */ +/* An observer type can be chosen for interpretting the spectrum of the input and */ +/* the illuminant. */ +/* Return -1.0 on erorr */ +double icx_XYZ2ill_ct2( +double txyz[3], /* If not NULL, return the XYZ of the locus temperature */ +icxIllumeType ilType, /* Type of illuminant, icxIT_Dtemp or icxIT_Ptemp */ +icxObserverType obType, /* Observer, CIE_1931_2 or CIE_1964_10 */ +double xyz[3], /* Input XYZ value */ +int viscct /* nz to use visual CIEDE2000, 0 to use CCT CIE 1960 UCS. */ +) { + cct2ctx x; /* Context for callback */ + double cp[1], s[1]; + double rv; + int i; + double tc, ber, bct = 0.0; + + x.viscct = viscct; + + if (ilType != icxIT_Dtemp && ilType != icxIT_Ptemp) + return -1.0; + if (obType != icxOT_CIE_1931_2 && obType != icxOT_CIE_1964_10) + return -1.0; + + /* Locus to use */ + if (obType == icxOT_CIE_1931_2) { + if (ilType == icxIT_Dtemp) { + x.iloc = illoc_Daylight_CIE_1931_2; + } else { + x.iloc = illoc_Plankian_CIE_1931_2; + } + } else { + if (ilType == icxIT_Dtemp) { + x.iloc = illoc_Daylight_CIE_1964_10; + } else { + x.iloc = illoc_Plankian_CIE_1964_10; + } + } + + icmAry2Ary(x.xyz, xyz); + + /* Normalise target */ + x.xyz[0] /= x.xyz[1]; + x.xyz[2] /= x.xyz[1]; + x.xyz[1] /= x.xyz[1]; + + /* Convert to XYZ number for DE wp */ + icmAry2XYZ(x.XYZ, x.xyz); + + /* Do some start samples, to avoid getting trapped in local minima */ + for (ber = 1e9, i = 0; i < 6; i++) { + double er; + tc = x.iloc[0].spec_wl_short + + i/(6-1.0) * (x.iloc[0].spec_wl_long - x.iloc[0].spec_wl_short); + if ((er = cct2_func((void *)&x, &tc)) < ber) { + ber = er; + bct = tc; + } +//a1logd(g_log, 1, " starting tc = %f, err = %f\n",1e6/tc,er); +//DBGF((DBGA,"tc = %f, er = %f\n",1e6/tc,er)); + } + cp[0] = bct; + s[0] = 20.0; + + /* Locate the CCT in Mired */ + if (powell(&rv, 1, cp, s, 0.01, 1000, cct2_func, (void *)&x, NULL, NULL) != 0) { + x.conv->del(x.conv); + return -1.0; + } + + if(txyz != NULL) { + /* Return the closest value on the locus */ + getval_raw_xspec3_lin(x.iloc, txyz, cp[0]); + txyz[0] /= txyz[1]; + txyz[2] /= txyz[1]; + txyz[1] /= txyz[1]; + } + +//a1logd(g_log, 1, " returning %f with error %f delta E94 %f\n",1e6/cp[0],sqrt(rv)); +//DBGF((DBGA,"returning %f with error %f delta E94 %f\n",cp[0],sqrt(rv))); + return 1e6/cp[0]; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* Spectral and illuminant chromaticity locus support */ + +/* All the nomenclature is for spectral locus, */ +/* but we use the same mechanism for a Daylight or */ +/* Plankian illuminant locus, substituting temp/Mired for wavelength/nm */ + +/* Chromaticity locus poligon vertex */ +typedef struct { + double xy[2]; /* xy, u'v' value */ + double xy_n[2]; /* xy, u'v' inwards normal direction */ + double dist; /* Accumulated distance */ + double rgb[3]; /* Representative color at this point */ +} xslvtx; + +/* Vertex bounding box */ +typedef struct { + int ix; /* Starting index of vertex */ + int n; /* Number of vertexes in box */ + double xmin; + double ymin; + double xmax; + double ymax; +} xslbbx; + +#define SLOC_BBXN 19 /* 19 vertexes per bounding box */ + +/* Chromaticity locus poligon cache */ +struct _xslpoly { + int sp; /* 0 = Spectral Locus, 1 = Daylight, 2 = Plankian */ + icxObserverType obType; /* Type of observer */ + int uv; /* 0 = xy, 1 = u'v' space */ + int n; /* Number of vertexes, 0 if uninit */ + double wl_short; /* First reading wavelength in nm (shortest)/ smallest Mired */ + double wl_long; /* Last reading wavelength in nm (longest)/ largest Mired */ + double xmin, xmax, ymin, ymax; /* xy Boundint box */ + double tx[3], ty[3]; /* xy Fast inner triangle test, RGB (spectral locus) */ + double be[3][3]; /* xy baricentric equations of triangle (spectral locus) */ +// double eed[3]; /* xy Distance of triangle points to 0.3, 0.3 (spectral locus) */ + xslvtx v[XSPECT_MAX_BANDS]; /* vertex values */ + int nbb; /* Number of bounding boxes */ + xslbbx bb[XSPECT_MAX_BANDS/SLOC_BBXN + 1]; /* Bounding boxes */ + double d_max; /* Maximum distance */ + double rv[XSPECT_MAX_BANDS]; /* distance to wl reverse lookup */ +}; + /* Init a xslpoly */ /* Return nz on error */ -static int icx_init_locus_poly(icxObserverType obType) { - xslpoly *poly; +static int icx_init_locus_poly( + xslpoly *p +) { +// static CRITICAL_SECTION lock = { NULL, -1 }; + static amutex_static(lock); - if ((poly = spectral_locus_poligon(obType)) == NULL) - return 1; +// InitializeCriticalSection(&(lock)); + + /* Prevent threads trying to multiply initialise the xslpoly */ +// EnterCriticalSection(&(lock)); + amutex_lock(lock); - /* Initialise (should have a mutex!) */ - if (poly->n == 0) { - int i, j, c; + if (p->n == 0) { + int i0, in; + double wl_short, wl_long; + int ii, i, j, c; double Yxy[3]; double xyz[3]; xspect *sp[3]; -double tt[3][3]; - - if (standardObserver(sp, obType)) - return 3; - - poly->n = sp[0]->spec_n; - poly->xmin = poly->ymin = 1e6; - poly->xmax = poly->ymax = -1e6; - - for (i = 0; i < poly->n; i++) { - xyz[0] = sp[0]->spec[i]; - xyz[1] = sp[1]->spec[i]; - xyz[2] = sp[2]->spec[i]; - - icmXYZ2Yxy(Yxy, xyz); - - poly->x[i] = Yxy[1]; - poly->y[i] = Yxy[2]; - if (poly->x[i] < poly->xmin) - poly->xmin = poly->x[i]; - if (poly->x[i] > poly->xmax) - poly->xmax = poly->x[i]; - if (poly->y[i] < poly->ymin) - poly->ymin = poly->y[i]; - if (poly->y[i] > poly->ymax) - poly->ymax = poly->y[i]; + double tt[3][3]; + double dist = 0.0; + + if (standardObserver(sp, p->obType)) { + amutex_unlock(lock); + return 1; + } + + if (p->sp == 0) { /* If spectral locus */ + i0 = 0; + in = sp[0]->spec_n; + wl_short = sp[0]->spec_wl_short; + wl_long = sp[0]->spec_wl_long; + + /* Limit the range to 400 - 700, as the locus is not well behaved outside that */ + if (wl_short < 400.0) { + i0 = (int)ceil(XSPECT_DIX(sp[0]->spec_wl_short, sp[0]->spec_wl_long, sp[0]->spec_n, 400.0)); + wl_short = XSPECT_WL(sp[0]->spec_wl_short, sp[0]->spec_wl_long, sp[0]->spec_n, i0); + } + if (wl_long > 700.0) { + in = (int)ceil(XSPECT_DIX(sp[0]->spec_wl_short, sp[0]->spec_wl_long, sp[0]->spec_n, 700.0)); + wl_long = XSPECT_WL(sp[0]->spec_wl_short, sp[0]->spec_wl_long, sp[0]->spec_n, in); + in++; + } + + p->n = in - i0; + p->wl_short = wl_short; + p->wl_long = wl_long; + p->xmin = p->ymin = 1e6; + p->xmax = p->ymax = -1e6; + + /* Compute xy, and accumulated distance along locus */ + for (ii = 0, i = i0; i < in; i++, ii++) { + double wl = XSPECT_WL(p->wl_short, p->wl_long, p->n, ii); + + xyz[0] = sp[0]->spec[i]; + xyz[1] = sp[1]->spec[i]; + xyz[2] = sp[2]->spec[i]; + + if (p->uv == 0) + icmXYZ2Yxy(Yxy, xyz); + else + icmXYZ21976UCS(Yxy, xyz); + p->v[ii].xy[0] = Yxy[1]; + p->v[ii].xy[1] = Yxy[2]; + + if (ii == 0) { + p->v[ii].dist = 0.0; + } else { + double d0, d1; + d0 = p->v[ii].xy[0] - p->v[ii-1].xy[0]; + d1 = p->v[ii].xy[1] - p->v[ii-1].xy[1]; + dist += sqrt(d0 * d0 + d1 * d1); + p->v[ii].dist = dist; + } + + /* Compute a display color */ + icx_wl2RGB_ds(p->v[ii].rgb, wl, 0.1); + +//a1logd(g_log, 1, " [%d] = %f %f, dist %f\n",i,p->v[ii].xy[0],p->v[ii].xy[1],p->v[ii].dist); + if (Yxy[1] < p->xmin) + p->xmin = Yxy[1]; + if (Yxy[1] > p->xmax) + p->xmax = Yxy[1]; + if (Yxy[2] < p->ymin) + p->ymin = Yxy[2]; + if (Yxy[2] > p->ymax) + p->ymax = Yxy[2]; + } + + } else { /* Daylight or Plankian locus */ + xspect *iloc; + icxIllumeType ilType = p->sp == 1 ? icxIT_Dtemp : icxIT_Ptemp; + + if (p->obType == icxOT_CIE_1931_2) { + if (ilType == icxIT_Dtemp) { + iloc = illoc_Daylight_CIE_1931_2; + } else { + iloc = illoc_Plankian_CIE_1931_2; + } + } else { + if (ilType == icxIT_Dtemp) { + iloc = illoc_Daylight_CIE_1964_10; + } else { + iloc = illoc_Plankian_CIE_1964_10; + } + } + + i0 = 0; + in = iloc[0].spec_n; + wl_short = iloc[0].spec_wl_short; + wl_long = iloc[0].spec_wl_long; + + p->n = in - i0; + p->wl_short = wl_short; + p->wl_long = wl_long; + p->xmin = p->ymin = 1e6; + p->xmax = p->ymax = -1e6; + + /* Compute xy/u'v', and accumulated distance along locus */ + for (ii = 0, i = i0; i < in; i++, ii++) { + double xyz[3]; + double temp; + + xyz[0] = iloc[0].spec[i]; + xyz[1] = iloc[1].spec[i]; + xyz[2] = iloc[2].spec[i]; + + if (p->uv == 0) + icmXYZ2Yxy(Yxy, xyz); + else + icmXYZ21976UCS(Yxy, xyz); + p->v[ii].xy[0] = Yxy[1]; + p->v[ii].xy[1] = Yxy[2]; + + if (ii == 0) { + p->v[ii].dist = 0.0; + } else { + double d0, d1; + d0 = p->v[ii].xy[0] - p->v[ii-1].xy[0]; + d1 = p->v[ii].xy[1] - p->v[ii-1].xy[1]; + dist += sqrt(d0 * d0 + d1 * d1); + p->v[ii].dist = dist; + } + + /* Compute a display color */ + icx_XYZ2RGB_ds(p->v[ii].rgb, xyz, 0.1); + +//a1logd(g_log, 1, " [%d] Mired %f = %f %f, dist %f\n",i,XSPECT_WL(wl_short, wl_long, in, i),p->v[ii].xy[0],p->v[ii].xy[1],p->v[ii].dist); + if (Yxy[1] < p->xmin) + p->xmin = Yxy[1]; + if (Yxy[1] > p->xmax) + p->xmax = Yxy[1]; + if (Yxy[2] < p->ymin) + p->ymin = Yxy[2]; + if (Yxy[2] > p->ymax) + p->ymax = Yxy[2]; + } } - /* Select 3 points for inner triangle in RGB order */ - poly->tx[0] = poly->x[poly->n - 1]; - poly->ty[0] = poly->y[poly->n - 1]; - - xyz[0] = value_xspect(sp[0], 517.0); - xyz[1] = value_xspect(sp[1], 517.0); - xyz[2] = value_xspect(sp[2], 517.0); - icmXYZ2Yxy(Yxy, xyz); - poly->tx[1] = Yxy[1]; - poly->ty[1] = Yxy[2]; - - poly->tx[2] = poly->x[0]; - poly->ty[2] = poly->y[0]; - - /* Compute distance from triangles to 0.3, 0.3 */ -// for (i = 0; i < 3; i++) { -// poly->eed[i] = sqrt((poly->tx[i] - 0.3) * (poly->tx[i] - 0.3) -// + (poly->ty[i] - 0.3) * (poly->ty[i] - 0.3)); -// } - - /* Compute baricentric equations */ - for (i = 0; i < 3; i++) { - tt[0][i] = poly->tx[i]; - tt[1][i] = poly->ty[i]; - tt[2][i] = 1.0; + /* Compute bounding boxes */ + for (i = ii = 0; i < p->n;) { + int m; + p->bb[ii].ix = i; + p->bb[ii].xmin = p->bb[ii].ymin = 1e6; + p->bb[ii].xmax = p->bb[ii].ymax = -1e6; + for (m = 0; m < SLOC_BBXN && i < p->n; i++, m++) { + if (p->v[i].xy[0] < p->bb[ii].xmin) + p->bb[ii].xmin = p->v[i].xy[0]; + if (p->v[i].xy[1] < p->bb[ii].ymin) + p->bb[ii].ymin = p->v[i].xy[1]; + if (p->v[i].xy[0] > p->bb[ii].xmax) + p->bb[ii].xmax = p->v[i].xy[0]; + if (p->v[i].xy[1] > p->bb[ii].ymax) + p->bb[ii].ymax = p->v[i].xy[1]; + } + p->bb[ii++].n = m; } - if (icmInverse3x3(poly->be, tt)) - error("icx_init_locus_poly: Matrix inversion failed"); + p->nbb = ii; - /* Compute baricentric of 0.3 0.3 */ - /* (Not currently used. How to move center to 0.3 0.3 ?? */ -// for (i = 0; i < 3; i++) -// poly->eed[i] = poly->be[i][0] * 0.3 + poly->be[i][1] * 0.3 + poly->be[i][2]; +//for (i = 0; i < p->nbb; i++) +//a1logd(g_log, 1,"bb %d: n = %d, bb %f %f %f %f",i,p->bb[i].n, p->bb[i].xmin,p->bb[i].xmax,p->bb[i].ymin,p->bb[i].ymax); + + /* Compute reverse lookup of distance to wavelength/temp */ + { + p->d_max = p->v[p->n-1].dist; + +//a1logd(g_log, 1,"d_max = %f\n",p->d_max); + + p->rv[0] = 0.0; + for (i = 1; i < XSPECT_MAX_BANDS; i++) + p->rv[i] = -1.0; + + /* Create search start points */ + for (i = 0; i < p->n; i++) { + int ix; + ix = (int)floor(XSPECT_DIX(0.0, p->d_max, XSPECT_MAX_BANDS, p->v[i].dist)); + if (p->rv[ix] < 0.0 || (double)i < p->rv[ix]) { + p->rv[ix] = (double)i; +//a1logd(g_log, 1,"ix %d dist %f start ix %d\n",ix,p->v[i].dist,i); + } + } + + /* Go through start points and create interpolated points */ + for (i = XSPECT_MAX_BANDS-2; i > 0; i--) { + double d, wl0, d0, wl1, d1, bl, wl; + int j, ix; + + d = XSPECT_WL(0.0, p->d_max, XSPECT_MAX_BANDS, i); /* Distance of this cell */ + + /* Find a search start point - skip any empty slots */ + for (j = i; j >= 0; j--) { + ix = (int)p->rv[j]; + if (ix >= 0) + break; + } + if (j < 0) + ix = 0; + + for (; ix >= 0; ix--) { + d0 = p->v[ix].dist; + if (d0 <= d) + break; + } + if (ix < 0) + ix = 0; + wl0 = XSPECT_WL(wl_short, wl_long, p->n, ix); + + /* Locate the fwd point after this entries distance */ + for (j = ix+1; j < p->n; j++) { + d1 = p->v[j].dist; + if (d1 >= d) + break; + } + if (j >= p->n) { + d1 = p->d_max; + j--; + if (ix == j) { + ix--; + wl0 = XSPECT_WL(wl_short, wl_long, p->n, ix); + d0 = p->v[ix].dist; + } + } + wl1 = XSPECT_WL(wl_short, wl_long, p->n, j); + + /* Linearly interpolate for this entries distance */ + bl = (d - d0)/(d1 - d0); +//a1logd(g_log, 1,"rv ix %d, d %f, bl %f, ixs %d - %d, ds %f - %f, wls %f - %f\n",i,d,bl, ix,j,d0,d1,wl0,wl1); + wl = (1.0 - bl) * wl0 + bl * wl1; + p->rv[i] = wl; + } + p->rv[0] = wl_short; + p->rv[XSPECT_MAX_BANDS-1] = wl_long; + +//for (i = 0; i < XSPECT_MAX_BANDS; i++) +// a1logd(g_log, 1,"rv %d = %f\n",i,p->rv[i]); + } + + /* Compute outward normals, and delta wl/delta dist */ + for (i = 0; i < p->n; i++) { + int span = 1; + double pn[2], mm; + + if (i < 50) /* Hack to straighten up 400nm */ + span = 20; + + i0 = i - span; + in = i + span; + if (i0 < 0) { + i0 = 0; + in = i0 + 2 * span; + } + if (in > (p->n-1)) { + in = (p->n-1); + i0 = in - 2 * span; + } + pn[0] = p->v[in].xy[1] - p->v[i0].xy[1]; + pn[1] = -(p->v[in].xy[0] - p->v[i0].xy[0]); + +// a1logd(g_log, 1,"i0 = %d, in = %d\n",i0, in); +// a1logd(g_log, 1,"i0 %d = %f %f\n",i0,p->v[i0].xy[0],p->v[i0].xy[1]); +// a1logd(g_log, 1,"in %d = %f %f\n",in,p->v[in].xy[0],p->v[i0].xy[1]); +// a1logd(g_log, 1,"pn = %f %f\n",pn[0],pn[1]); + + mm = sqrt(pn[0] * pn[0] + pn[1] * pn[1]); + pn[0] /= mm; + pn[1] /= mm; + + p->v[i].xy_n[0] = pn[0]; + p->v[i].xy_n[1] = pn[1]; + } + +#ifdef NEVER + /* Compute v2 sub sampled values */ +#endif + + if (p->sp == 0) { /* If spectral locus */ + /* Select 3 points for inner triangle in RGB order */ + p->tx[0] = p->v[p->n - 1].xy[0]; + p->ty[0] = p->v[p->n - 1].xy[1]; + + xyz[0] = value_xspect(sp[0], 517.0); + xyz[1] = value_xspect(sp[1], 517.0); + xyz[2] = value_xspect(sp[2], 517.0); + if (p->uv == 0) + icmXYZ2Yxy(Yxy, xyz); + else + icmXYZ21976UCS(Yxy, xyz); + p->tx[1] = Yxy[1]; + p->ty[1] = Yxy[2]; + + p->tx[2] = p->v[0].xy[0]; + p->ty[2] = p->v[0].xy[1]; + + /* Compute distance from triangles to 0.3, 0.3 */ +// for (i = 0; i < 3; i++) { +// p->eed[i] = sqrt((p->tx[i] - 0.3) * (p->tx[i] - 0.3) +// + (p->ty[i] - 0.3) * (p->ty[i] - 0.3)); +// } + + /* Compute baricentric equations */ + for (i = 0; i < 3; i++) { + tt[0][i] = p->tx[i]; + tt[1][i] = p->ty[i]; + tt[2][i] = 1.0; + } + if (icmInverse3x3(p->be, tt)) { + a1loge(g_log, 2, "icx_init_locus_poly: Matrix inversion failed"); + amutex_unlock(lock); + return 2; + } + + /* Compute baricentric of 0.3 0.3 */ + /* (Not currently used. How to move center to 0.3 0.3 ?? */ +// for (i = 0; i < 3; i++) +// p->eed[i] = p->be[i][0] * 0.3 + p->be[i][1] * 0.3 + p->be[i][2]; + } } + amutex_unlock(lock); return 0; } +/* Spectral locus */ +static xslpoly splo_CIE_1931_2_xy = { 0, icxOT_CIE_1931_2, 0, 0 }; +static xslpoly splo_CIE_1931_2_uv = { 0, icxOT_CIE_1931_2, 1, 0 }; +static xslpoly splo_CIE_1964_10_xy = { 0, icxOT_CIE_1964_10, 0, 0 }; +static xslpoly splo_CIE_1964_10_uv = { 0, icxOT_CIE_1964_10, 1, 0 }; +static xslpoly splo_Stiles_Burch_2_xy = { 0, icxOT_Stiles_Burch_2, 0, 0 }; +static xslpoly splo_Stiles_Burch_2_uv = { 0, icxOT_Stiles_Burch_2, 1, 0 }; +static xslpoly splo_Judd_Voss_2_xy = { 0, icxOT_Judd_Voss_2, 0, 0 }; +static xslpoly splo_Judd_Voss_2_uv = { 0, icxOT_Judd_Voss_2, 1, 0 }; +static xslpoly splo_CIE_1964_10c_xy = { 0, icxOT_CIE_1964_10c, 0, 0 }; +static xslpoly splo_CIE_1964_10c_uv = { 0, icxOT_CIE_1964_10c, 1, 0 }; +static xslpoly splo_Shaw_Fairchild_2_xy = { 0, icxOT_Shaw_Fairchild_2, 0, 0 }; +static xslpoly splo_Shaw_Fairchild_2_uv = { 0, icxOT_Shaw_Fairchild_2, 1, 0 }; + +/* Illuminant locus */ +static xslpoly illo_D_CIE_1931_2_xy = { 1, icxOT_CIE_1931_2, 0, 0 }; +static xslpoly illo_D_CIE_1931_2_uv = { 1, icxOT_CIE_1931_2, 1, 0 }; +static xslpoly illo_D_CIE_1964_10_xy = { 1, icxOT_CIE_1964_10, 0, 0 }; +static xslpoly illo_D_CIE_1964_10_uv = { 1, icxOT_CIE_1964_10, 1, 0 }; +static xslpoly illo_P_CIE_1931_2_xy = { 2, icxOT_CIE_1931_2, 0, 0 }; +static xslpoly illo_P_CIE_1931_2_uv = { 2, icxOT_CIE_1931_2, 1, 0 }; +static xslpoly illo_P_CIE_1964_10_xy = { 2, icxOT_CIE_1964_10, 0, 0 }; +static xslpoly illo_P_CIE_1964_10_uv = { 2, icxOT_CIE_1964_10, 1, 0 }; + +/* Return a pointer to the chromaticity locus poligon */ +/* return NULL on failure. */ +xslpoly *chrom_locus_poligon( +icxLocusType loty, /* Locus type, 1 = spectral, 2 = Daylight, 3 = Plankian */ +icxObserverType obType, /* Type of observer */ +int uv /* 0 = xy, 1 = u'v' space */ +) { + xslpoly *rv = NULL; + + if (loty == icxLT_none) + return NULL; + + switch (obType) { + case icxOT_default: + case icxOT_CIE_1931_2: + if (uv == 0) { + if (loty == icxLT_spectral) + rv = &splo_CIE_1931_2_xy; + else if (loty == icxLT_daylight) + rv = &illo_D_CIE_1931_2_xy; + else if (loty == icxLT_plankian) + rv = &illo_P_CIE_1931_2_xy; + } else { + if (loty == icxLT_spectral) + rv = &splo_CIE_1931_2_uv; + else if (loty == icxLT_daylight) + rv = &illo_D_CIE_1931_2_uv; + else if (loty == icxLT_plankian) + rv = &illo_P_CIE_1931_2_uv; + } + break; + case icxOT_CIE_1964_10: + if (uv == 0) { + if (loty == icxLT_spectral) + rv = &splo_CIE_1964_10_xy; + else if (loty == icxLT_daylight) + rv = &illo_D_CIE_1964_10_xy; + else if (loty == icxLT_plankian) + rv = &illo_P_CIE_1964_10_xy; + } else { + if (loty == icxLT_spectral) + rv = &splo_CIE_1964_10_uv; + else if (loty == icxLT_daylight) + rv = &illo_D_CIE_1964_10_uv; + else if (loty == icxLT_plankian) + rv = &illo_P_CIE_1964_10_uv; + } + break; + default: + rv = NULL; + } + if (rv == NULL) + return rv; + + + if (rv->n == 0 && icx_init_locus_poly(rv)) + return NULL; + + return rv; +} + + /* Determine whether the given XYZ is outside the spectrum locus */ /* Return 0 if within locus */ /* Return 1 if outside locus */ -/* Return 2 if unknown (bad observer) */ -int icx_outside_spec_locus(double xyz[3], icxObserverType obType) { +int icx_outside_spec_locus(xslpoly *p, double xyz[3]) { int i, j, c; xslpoly *poly; double Yxy[3]; - if ((poly = spectral_locus_poligon(obType)) == NULL) - return 2; - - /* Init poly if needed */ - if (poly->n == 0 && icx_init_locus_poly(obType)) - return 2; - icmXYZ2Yxy(Yxy, xyz); /* Quick test - bounding box */ - if (Yxy[1] < poly->xmin || Yxy[1] > poly->xmax - || Yxy[2] < poly->ymin || Yxy[2] > poly->ymax) + if (Yxy[1] < p->xmin || Yxy[1] > p->xmax + || Yxy[2] < p->ymin || Yxy[2] > p->ymax) return 1; /* Quick test - inner triangle */ for (c = 1, i = 0, j = 3-1; i < 3; j = i++) { - if ( ((poly->ty[i] > Yxy[2]) != (poly->ty[j] > Yxy[2])) - && (Yxy[1] < (poly->tx[j] - poly->tx[i]) * (Yxy[2] - poly->ty[i]) - / (poly->ty[j] - poly->ty[i]) + poly->tx[i]) ) + if ( ((p->ty[i] > Yxy[2]) != (p->ty[j] > Yxy[2])) + && (Yxy[1] < (p->tx[j] - p->tx[i]) * (Yxy[2] - p->ty[i]) + / (p->ty[j] - p->ty[i]) + p->tx[i]) ) c = !c; } if (c == 0) @@ -4080,91 +5881,52 @@ int icx_outside_spec_locus(double xyz[3], icxObserverType obType) { /* Do point in poligon test */ /* (This could be speeded up in many ways) */ - for (c = 1, i = 0, j = poly->n-1; i < poly->n; j = i++) { - if ( ((poly->y[i] > Yxy[2]) != (poly->y[j] > Yxy[2])) - && (Yxy[1] < (poly->x[j] - poly->x[i]) * (Yxy[2] - poly->y[i]) - / (poly->y[j] - poly->y[i]) + poly->x[i]) ) + for (c = 1, i = 0, j = p->n-1; i < p->n; j = i++) { + if ( ((p->v[i].xy[1] > Yxy[2]) != (p->v[j].xy[1] > Yxy[2])) + && (Yxy[1] < (p->v[j].xy[0] - p->v[i].xy[0]) * (Yxy[2] - p->v[i].xy[1]) + / (p->v[j].xy[1] - p->v[i].xy[1]) + p->v[i].xy[0]) ) c = !c; } return c; } -/* Return an aproximate RGB value for coloring within the spectrum locus */ -void icx_spec_locus_color(double rgb[3], double xyz[3], icxObserverType obType) { - int i, j; - xslpoly *poly; - double Yxy[3]; - double dtt[3]; /* Distances to triangle points */ - double v[3]; - double max; - - if ((poly = spectral_locus_poligon(obType)) == NULL) - return; - - /* Init poly if needed */ - if (poly->n == 0 && icx_init_locus_poly(obType)) - return; - - icmXYZ2Yxy(Yxy, xyz); - - /* Compute the baricentric coord for the input point, */ - for (max = -1e6, i = 0; i < 3; i++) { - v[i] = poly->be[i][0] * Yxy[1] + poly->be[i][1] * Yxy[2] + poly->be[i][2]; - if (v[i] < 0.0) - v[i] = 0.0; - else if (v[i] > 1.0) - v[i] = 1.0; - - /* Normalise to put wp at 0.3 0.3 */ - // ~~99 - - v[i] = pow(v[i], 1.0/2.2); - - if (v[i] > max) - max = v[i]; - } - - for (i = 0; i < 3; i++) { - rgb[i] = v[i]/max; - } -} - /* -------------------------------------------------------- */ + /* Status T log10 weightings */ -/* CMYV */ +/* CMY + ISO V */ static xspect denT[4] = { { 44, 340.0, 770.0, /* 44 bands from 340 to 770 nm in 10nm steps */ 1.0, /* Log10 Scale factor */ { - 0.000, - 0.000, 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000, 0.000, 0.000, - 0.000, 0.500, 1.778, 2.653, 4.477, + -10.0, + -10.0, -10.0, -10.0, -10.0, -10.0, + -10.0, -10.0, -10.0, -10.0, -10.0, + -10.0, -10.0, -10.0, -10.0, -10.0, + -10.0, -10.0, -10.0, -10.0, -10.0, + -10.0, 0.500, 1.778, 2.653, 4.477, 5.000, 4.929, 4.740, 4.398, 4.000, 3.699, 3.176, 2.699, 2.477, 2.176, - 1.699, 1.000, 0.500, 0.000, 0.000, - 0.000, 0.000, 0.000 + 1.699, 1.000, 0.500, -10.0, -10.0, + -10.0, -10.0, -10.0 } }, { 44, 340.0, 770.0, /* 44 bands from 340 to 770 nm in 10nm steps */ 1.0, /* Log10 Scale factor */ { - 0.000, - 0.000, 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.500, 3.000, 3.699, + -10.0, + -10.0, -10.0, -10.0, -10.0, -10.0, + -10.0, -10.0, -10.0, -10.0, -10.0, + -10.0, -10.0, 0.500, 3.000, 3.699, 4.447, 4.833, 4.964, 5.000, 4.944, 4.820, 4.623, 4.342, 3.954, 3.398, - 2.845, 1.954, 1.000, 0.500, 0.000, - 0.000, 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000 + 2.845, 1.954, 1.000, 0.500, -10.0, + -10.0, -10.0, -10.0, -10.0, -10.0, + -10.0, -10.0, -10.0, -10.0, -10.0, + -10.0, -10.0, -10.0 } }, { @@ -4176,19 +5938,19 @@ static xspect denT[4] = { 3.778, 4.230, 4.602, 4.778, 4.914, 4.973, 5.000, 4.987, 4.929, 4.813, 4.602, 4.255, 3.699, 2.301, 1.602, - 0.500, 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000 + 0.500, -10.0, -10.0, -10.0, -10.0, + -10.0, -10.0, -10.0, -10.0, -10.0, + -10.0, -10.0, -10.0, -10.0, -10.0, + -10.0, -10.0, -10.0, -10.0, -10.0, + -10.0, -10.0, -10.0 } }, { 44, 340.0, 770.0, /* 44 bands from 340 to 770 nm in 10nm steps */ 1.0, /* Log10 Scale factor */ { - 0.000, - 0.000, 0.000, 0.000, 0.000, 0.000, + -10.0, + -10.0, -10.0, -10.0, -10.0, -10.0, 0.500, 1.332, 1.914, 2.447, 2.881, 3.090, 3.346, 3.582, 3.818, 4.041, 4.276, 4.513, 4.702, 4.825, 4.905, @@ -4201,6 +5963,7 @@ static xspect denT[4] = { } }; + /* Given a reflectance or transmition spectral product, (Relative */ /* to the scale factor), return status T CMYV log10 density values */ void xsp_Tdensity( @@ -4226,10 +5989,10 @@ xspect *in /* Spectral product to be converted */ out[j] += S * W; } out[j] /= sum; /* Normalise */ - if (out[j] < 0.00001) - out[j] = 0.00001; /* Just to be sure we don't get silly values */ - else if (out[j] > 1.0) - out[j] = 1.0; + if (out[j] < 1e-8) + out[j] = 1e-8; /* Just to be sure we don't get silly values */ + else if (out[j] > 2.0) + out[j] = 2.0; out[j] = -log10(out[j]); /* Convert to density */ } @@ -4294,17 +6057,17 @@ double *in /* Input XYZ values */ } } -/* Given an XYZ value, */ -/* return approximate sRGB values */ +/* Given an XYZ value, return sRGB values. */ +/* This is a little slow if wp used */ void icx_XYZ2sRGB( -double *out, /* Return aproximate CMYV log10 density */ +double *out, /* Return approximate sRGB values */ double *wp, /* Input XYZ white point (may be NULL) */ double *in /* Input XYZ values */ ) { int i, j; double XYZ[3]; - double d65[3] = { 0.950543, 1.0, 1.089303 }; - double mat[3][3] = { + double d65[3] = { 0.950543, 1.0, 1.089303 }; /* D65 */ + double mat[3][3] = { /* sRGB absolute XYZ->RGB ? */ { 3.2406, -1.5372, -0.4986 }, { -0.9689, 1.8758, 0.0415 }, { 0.0557, -0.2040, 1.0570 } @@ -4312,8 +6075,13 @@ double *in /* Input XYZ values */ /* Do a simple Von Kries between input white point and D65 */ if (wp != NULL) { - for (j = 0; j < 3; j++) - XYZ[j] = d65[j] * in[j]/wp[j]; + icmXYZNumber dst, src; + double vkmat[3][3]; + + icmAry2XYZ(src, wp); + icmAry2XYZ(dst, d65); + icmChromAdaptMatrix(ICM_CAM_BRADFORD | ICM_CAM_BRADFORD, dst, src, vkmat); + icmMulBy3x3(XYZ, vkmat, in); } else { for (j = 0; j < 3; j++) XYZ[j] = in[j]; @@ -4341,6 +6109,87 @@ double *in /* Input XYZ values */ } } +/* Given an XYZ value, return approximate RGB value */ +/* Desaurate to white by the given amount */ +void icx_XYZ2RGB_ds( +double *out, /* Return approximate sRGB values */ +double *in, /* Input XYZ */ +double desat /* 0.0 = full saturation, 1.0 = white */ +) { + int i, j; + double mat[3][3] = { /* XYZ to D65 sRGB */ + { 1.490715, -0.075680, -0.313279 }, /* Triangle that occupies spectrum locus */ + { -0.492678, 1.364383, 0.095391 }, + { 0.049610, -0.137386, 1.001080 } + }; + double white[3] = { 1.0, 1.0, 1.0 } ; + double max; + + /* Normalize */ + in[0] /= in[1]; + in[2] /= in[1]; + in[1] = 1.0; + +//a1logd(g_log, 1,"icx_XYZ2sRGB_ds: norm XYZ %f %f %f\n", in[0], in[1], in[2]); + + /* Convert to sRGB cromaticities */ + for (i = 0; i < 3; i++) { + out[i] = 0.0; + for (j = 0; j < 3; j++) { + out[i] += in[j] * mat[i][j]; + } + } +//a1logd(g_log, 1,"icx_XYZ2sRGB_ds: raw RGB %f %f %f\n", out[0], out[1], out[2]); + + /* Clip */ + max = -1e6; + for (i = 0; i < 3; i++) { + if (out[i] > max) + max = out[i]; + } + for (i = 0; i < 3; i++) { + out[i] /= max; + if (out[i] < 0.0) + out[i] = 0.0; + } +//a1logd(g_log, 1,"icx_XYZ2sRGB_ds: clip RGB %f %f %f\n", out[0], out[1], out[2]); + + /* Desaturate */ + icmBlend3(out, out, white, desat); + +//a1logd(g_log, 1,"icx_XYZ2sRGB_ds: desat RGB %f %f %f\n", out[0], out[1], out[2]); + + /* Apply gamma */ + for (j = 0; j < 3; j++) { + if (out[j] <= (0.03928/12.92)) { + out[j] *= 12.92; + if (out[j] < 0.0) + out[j] = 0.0; + } else { + out[j] = pow(out[j], 1.0/2.4) * 1.055 - 0.055; + if (out[j] > 1.0) + out[j] = 1.0; + } + } + +//a1logd(g_log, 1,"icx_XYZ2sRGB_ds: final RGB %f %f %f\n", out[0], out[1], out[2]); +} + +/* Given a wavelengthm return approximate RGB value */ +/* Desaurate to white by the given amount */ +void icx_wl2RGB_ds( +double *out, /* Return approximate sRGB values */ +double wl, /* Input wavelength in nm */ +double desat /* 0.0 = full saturation, 1.0 = white */ +) { + double XYZ[3]; + + icx_spectrum_locus(XYZ, wl, icxOT_CIE_1931_2); +//a1logd(g_log, 1,"cx_wl2sRGB_ds: wl %f -> XYZ %f %f %f\n",wl, XYZ[0], XYZ[1], XYZ[2]); + + icx_XYZ2RGB_ds(out, XYZ, desat); +} + /* ------------------- */ #ifdef NEVER /* Deprecated */ @@ -4348,11 +6197,16 @@ double *in /* Input XYZ values */ /* Given a daylight color temperature in degrees K, */ /* return the corresponding XYZ value (standard 2 degree observer) */ void icx_DTEMP2XYZ( -double *out, /* Return XYZ value with Y == 1 */ +double *out, /* Return XYZ value with Y == 1, -1 on error */ double ct /* Input temperature in degrees K */ ) { double Yxy[3]; + if (ct < 2500.0 || ct > 25000.0) { /* Only accurate down to 4000 */ + out[0] = out[1] = out[2] = -1.0; + return; + } + //DBGF((DBGA,"computing temperature %f\n",ct)); /* Compute chromaticity coordinates */ if (ct < 7000.0) { @@ -4465,7 +6319,6 @@ static double cct_func(void *fdata, double tp[]) { /* return the closest correlated color temperature to the given spectrum or XYZ. */ /* An observer type can be chosen for interpretting the spectrum of the input and */ /* the illuminant. */ -/* Note we can use CIEDE2000, rather than the traditional L*u*v* 2/3 space for CCT */ /* Return -1 on erorr */ double icx_XYZ2ill_ct( double txyz[3], /* If not NULL, return the XYZ of the locus temperature */ @@ -4705,6 +6558,137 @@ xspect *sample /* Illuminant sample to compute CRI of */ return cri; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* Compute Australian Radiation Protection and Nuclear Safety Agency (ARPANSA) */ +/* Exposure to Ultraviolet Radiation exposure limits from a spectrum in mw/m-2/nm. */ +/* To be accurate, the spectrum must capture any significant */ +/* exposure wavelengths between 180 - 400 nm */ + +/* Raw RSE from Table 1 of "Radiation Protection Series No. 12 December 2006" */ +struct { + double wl; /* Wavelength */ + double rse; /* Relative Spectral Effectiveness */ +} raw_rse[57] = { + { 180.0, 0.012 }, + { 190.0, 0.019 }, + { 200.0, 0.030 }, + { 205.0, 0.051 }, + { 210.0, 0.075 }, + { 215.0, 0.095 }, + { 220.0, 0.120 }, + { 225.0, 0.150 }, + { 230.0, 0.190 }, + { 235.0, 0.240 }, + { 240.0, 0.300 }, + { 245.0, 0.360 }, + { 250.0, 0.430 }, + { 254.0, 0.500 }, + { 255.0, 0.520 }, + { 260.0, 0.650 }, + { 265.0, 0.810 }, + { 270.0, 1.000 }, + { 275.0, 0.960 }, + { 280.0, 0.880 }, + { 285.0, 0.770 }, + { 290.0, 0.640 }, + { 295.0, 0.540 }, + { 297.0, 0.460 }, + { 300.0, 0.300 }, + { 303.0, 0.120 }, + { 305.0, 0.060 }, + { 308.0, 0.026 }, + { 310.0, 0.015 }, + { 313.0, 0.006 }, + { 315.0, 0.003 }, + { 316.0, 0.0024 }, + { 317.0, 0.0020 }, + { 318.0, 0.0016 }, + { 319.0, 0.0012 }, + { 320.0, 0.0010 }, + { 322.0, 0.00067 }, + { 323.0, 0.00054 }, + { 325.0, 0.00050 }, + { 328.0, 0.00044 }, + { 330.0, 0.00041 }, + { 333.0, 0.00037 }, + { 335.0, 0.00034 }, + { 340.0, 0.00028 }, + { 345.0, 0.00024 }, + { 350.0, 0.00020 }, + { 355.0, 0.00016 }, + { 360.0, 0.00013 }, + { 365.0, 0.00011 }, + { 370.0, 0.000093 }, + { 375.0, 0.000077 }, + { 380.0, 0.000064 }, + { 385.0, 0.000053 }, + { 390.0, 0.000044 }, + { 395.0, 0.000036 }, + { 400.0, 0.000030 } +}; + +/* Compute 1nm sampling rse from raw table using linear interpolation */ +static void compute_rse(xspect *dst) { + int i; + + dst->spec_n = 221; + dst->spec_wl_short = 180.0; + dst->spec_wl_long = 400.0; + dst->norm = 1.0; + + /* Linearly interpolate between each raw point */ + for (i = 0; i < (57-1); i++) { + int j, n, ix; + + n = (int)(raw_rse[i+1].wl - raw_rse[i].wl + 0.5); + for (j = 0; j <= n; j++) { + double bl = j/(double)n; + double wl = raw_rse[i].wl + j; + + ix = XSPECT_XIX(dst, wl); + dst->spec[ix] = (1.0 - bl) * raw_rse[i].rse + bl * raw_rse[i+1].rse; + +//a1logd(g_log, 1,"UV rse ix %d wl %f rse = %f\n",ix,wl,dst->spec[ix]); + } + } +} + +xspect ARPANSA_rse = { 0 }; + +/* Return the maximum 24 hour exposure in seconds. */ +/* Maximum return value is 8 hours */ +/* Returns -1.0 if the source sample doesn't go down to at least 350 nm */ +double icx_ARPANSA_UV_exp( +xspect *sample /* Illuminant sample to compute UV_exp of */ +) { + double wl_short, wl_long; + double effwpsm; /* Effective Watt/m^2 */ + double wl; + double secs; + if (ARPANSA_rse.spec_n == 0) + compute_rse(&ARPANSA_rse); + + wl_short = ARPANSA_rse.spec_wl_short; + wl_long = ARPANSA_rse.spec_wl_long; + + if (sample->spec_wl_short > wl_short) + wl_short = sample->spec_wl_short; + + if (wl_short > 350.0) + return -1.0; + + effwpsm = 0.0; + for (wl = wl_short; wl <= (wl_long + 1e-6); wl++) + effwpsm += value_xspect(sample, wl) * value_xspect(&ARPANSA_rse, wl); + + effwpsm /= 1000.0; /* Convert to W from mW */ + + secs = 30.0/effwpsm; + + if (secs > (8 * 60 * 60)) /* Limit to 8 hours */ + secs = 8 * 60 * 60; + + return secs; +} #endif /* !SALONEINSTLIB */ -- cgit v1.2.3