/*
* International Color Consortium color transform expanded support
*
* Author: Graeme W. Gill
* Date: 21/6/01
* Version: 1.00
*
* Copyright 2000 - 2006 Graeme W. Gill
* All rights reserved.
*
* This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
* see the License2.txt file for licencing details.
*
* Based on the old iccXfm class.
*/
/*
* This module supports converting spectral samples
* into CIE XYZ (1.0) or D50 Lab tristimulous values.
*/
/*
* TTBD:
*
* 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,
* but doesn't represent actually viewing under a (say) M2 illuminant.
* But is M0 actual A illuminant, or notional D50 measured by an A illuminant ?]
*/
#include
#include
#include
#include
#include
#ifndef SALONEINSTLIB
# include "numlib.h"
# include "cgats.h"
# include "plot.h" /* For debugging */
#else
# include "numsup.h"
#endif
#include "conv.h"
#include "xspect.h"
#define CLAMP_XYZ /* [def] Clamp XYZ to be >= 0.0 */
#ifndef SALONEINSTLIB
#undef STOCKFWA /* [und] Use table shape else compute from flat line estimate*/
#undef DEBUG /* [und] Extra printouts + debugging messages */
#undef DOPLOT /* [und] Plot FWA setup */
#undef DOPLOT_ALL_FWA /* [und] Plot all FWA corrected conversions */
#undef WRITE_FWA1_STIM /* [und] Write file "fwa1_stip.sp" when FWA is setup */
#endif /* !SALONEINSTLIB */
#ifndef CLAMP_XYZ
# pragma message("###### CLAMP_XYZ is not defined ######")
#endif
#if defined(DEBUG) || defined(DOPLOT) || defined(DOPLOT_ALL_FWA) || defined(WRITE_FWA1_STIM)
# pragma message("###### xspect debugging is on ######")
#endif
#ifdef DEBUG
# define DBG(xx) a1logd(g_log, 0, xx )
# define DBGA g_log, 0 /* First argument to DBGF() */
# define DBGF(xx) a1logd xx
#else
# define DBG(xx)
# define DBGF(xx)
#endif
/* ======================================================== */
#if defined(__APPLE__) && defined(__POWERPC__)
/* Workaround for a PPC gcc 3.3 optimiser bug... */
/* It seems to cause a segmentation fault instead of */
/* converting an integer loop index into a float, */
/* when there are sufficient variables in play. */
static int gcc_bug_fix(int i) {
static int nn;
nn += i;
return nn;
}
#endif /* APPLE */
/* ======================================================== */
/* Define various standard spectra */
/* ------------------ */
/* Illuminant spectra */
/* Dummy "no illuminant" illuminant spectra used to signal an emmission */
/* or equal energy 'E' illuminant */
static xspect il_none = {
531, 300.0, 830.0, /* 531 bands from 300 to 830 in 1nm steps */
1.0, /* Scale factor */
{
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0
}
};
#ifdef NEVER
static xspect il_none = {
54, 300.0, 830.0, /* 54 bands from 300 to 830 in 10nm steps */
1.0, /* Scale factor */
{
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
}
};
#endif /* NEVER */
/* CIE 15.2-1986 Table 1.1 */
/* Part 1: CIE Standard Illuminant A relative spectral power distribution */
/* This is a 2848K tungsten filament lamp (Acording to the old temperature scale) */
/* and 2856 according to the newer temerature scale. */
static xspect il_A = {
107, 300.0, 830.0, /* 107 bands from 300 to 830 nm in 5nm steps */
100.0, /* Arbitrary scale factor */
{
0.930483, 1.128210, 1.357690, 1.622190, 1.925080,
2.269800, 2.659810, 3.098610, 3.589680, 4.136480,
4.742380, 5.410700, 6.144620, 6.947200, 7.821350,
8.769800, 9.795100, 10.899600, 12.085300, 13.354300,
14.708000, 16.148000, 17.675300, 19.290700, 20.995000,
22.788300, 24.670900, 26.642500, 28.702700, 30.850800,
33.085900, 35.406800, 37.812100, 40.300200, 42.869300,
45.517400, 48.242300, 51.041800, 53.913200, 56.853900,
59.861100, 62.932000, 66.063500, 69.252500, 72.495900,
75.790300, 79.132600, 82.519300, 85.947000, 89.412400,
92.912000, 96.442300, 100.000000, 103.582000, 107.184000,
110.803000, 114.436000, 118.080000, 121.731000, 125.386000,
129.043000, 132.697000, 136.346000, 139.988000, 143.618000,
147.235000, 150.836000, 154.418000, 157.979000, 161.516000,
165.028000, 168.510000, 171.963000, 175.383000, 178.769000,
182.118000, 185.429000, 188.701000, 191.931000, 195.118000,
198.261000, 201.359000, 204.409000, 207.411000, 210.365000,
213.268000, 216.120000, 218.920000, 221.667000, 224.361000,
227.000000, 229.585000, 232.115000, 234.589000, 237.008000,
239.370000, 241.675000, 243.924000, 246.116000, 248.251000,
250.329000, 252.350000, 254.314000, 256.221000, 258.071000,
259.865000, 261.602000
}
};
/* CIE 15.2-1986 Table 1.1 */
/* Part 1: CIE Standard Illuminant C relative spectral power distribution */
/* This is a CIE Illuminant A combined with a filter to simulate daylight. */
static xspect il_C = {
93, 320.0, 780.0, /* 107 bands from 300 to 830 nm in 5nm steps */
100.0, /* Arbitrary factor */
{
0.01, 0.20, 0.40, 1.55, 2.70, 4.85, 7.00, 9.95, 12.90, 17.20,
21.40, 27.50, 33.00, 39.92, 47.40, 55.17, 63.30, 71.81, 80.60, 89.53,
98.10, 105.80, 112.40, 117.75, 121.50, 123.45, 124.00, 123.60, 123.10, 123.30,
123.80, 124.09, 123.90, 122.92, 120.70, 116.90, 112.10, 106.98, 102.30, 98.81,
96.90, 96.78, 98.00, 99.94, 102.10, 103.95, 105.20, 105.67, 105.30, 104.11,
102.30, 100.15, 97.80, 95.43, 93.20, 91.22, 89.70, 88.83, 88.40, 88.19,
88.10, 88.06, 88.00, 87.86, 87.80, 87.99, 88.20, 88.20, 87.90, 87.22,
86.30, 85.30, 84.00, 82.21, 80.20, 78.24, 76.30, 74.36, 72.40, 70.40,
68.30, 66.30, 64.40, 62.80, 61.50, 60.20, 59.20, 58.50, 58.10, 58.00,
58.20, 58.50, 59.10
}
};
/* D50 illuminant spectra */
static xspect il_D50 = {
107, 300.0, 830.0, /* 107 bands from 300 to 830 nm in 5nm steps */
100.0, /* Arbitrary factor */
{
0.02, 1.03, 2.05, 4.91, 7.78, 11.26, 14.75, 16.35, 17.95, 19.48,
21.01, 22.48, 23.94, 25.45, 26.96, 25.72, 24.49, 27.18, 29.87, 39.59,
49.31, 52.91, 56.51, 58.27, 60.03, 58.93, 57.82, 66.32, 74.82, 81.04,
87.25, 88.93, 90.61, 90.99, 91.37, 93.24, 95.11, 93.54, 91.96, 93.84,
95.72, 96.17, 96.61, 96.87, 97.13, 99.61, 102.10, 101.43, 100.75, 101.54,
102.32, 101.16, 100.00, 98.87, 97.74, 98.33, 98.92, 96.21, 93.50, 95.59,
97.69, 98.48, 99.27, 99.16, 99.04, 97.38, 95.72, 97.29, 98.86, 97.26,
95.67, 96.93, 98.19, 100.60, 103.00, 101.07, 99.13, 93.26, 87.38, 89.49,
91.60, 92.25, 92.89, 84.87, 76.85, 81.68, 86.51, 89.55, 92.58, 85.40,
78.23, 67.96, 57.69, 70.31, 82.92, 80.60, 78.27, 78.91, 79.55, 76.48,
73.40, 68.66, 63.92, 67.35, 70.78, 72.61, 74.44
}
};
/* D50M2 illuminant spectra, UV filtered */
/* Computed from il_D50 */
static xspect il_D50M2 = {
0, 0.0, 0.0,
0.0
};
/* CIE 15.2-1986 Table 1.1 */
/* Part 2: CIE Standard Illuminant D65 relative spectral power distribution */
static xspect il_D65 = {
107, 300.0, 830.0, /* 107 bands from 300 to 830 nm in 5nm steps */
100.0, /* Arbitrary factor */
{
0.03410, 1.66430, 3.29450, 11.76520, 20.23600,
28.64470, 37.05350, 38.50110, 39.94880, 42.43020,
44.91170, 45.77500, 46.63830, 49.36370, 52.08910,
51.03230, 49.97550, 52.31180, 54.64820, 68.70150,
82.75490, 87.12040, 91.48600, 92.45890, 93.43180,
90.05700, 86.68230, 95.77360, 104.86500, 110.93600,
117.00800, 117.41000, 117.81200, 116.33600, 114.86100,
115.39200, 115.92300, 112.36700, 108.81100, 109.08200,
109.35400, 108.57800, 107.80200, 106.29600, 104.79000,
106.23900, 107.68900, 106.04700, 104.40500, 104.22500,
104.04600, 102.02300, 100.00000, 98.16710, 96.33420,
96.06110, 95.78800, 92.23680, 88.68560, 89.34590,
90.00620, 89.80260, 89.59910, 88.64890, 87.69870,
85.49360, 83.28860, 83.49390, 83.69920, 81.86300,
80.02680, 80.12070, 80.21460, 81.24620, 82.27780,
80.28100, 78.28420, 74.00270, 69.72130, 70.66520,
71.60910, 72.97900, 74.34900, 67.97650, 61.60400,
65.74480, 69.88560, 72.48630, 75.08700, 69.33980,
63.59270, 55.00540, 46.41820, 56.61180, 66.80540,
65.09410, 63.38280, 63.84340, 64.30400, 61.87790,
59.45190, 55.70540, 51.95900, 54.69980, 57.44060,
58.87650, 60.31250
}
};
#ifndef SALONEINSTLIB
/* General temperature Daylight spectra (Using CIE 1960 u,v CCT) */
/* Fill in the given xspect with the specified daylight illuminant */
/* Return nz if temperature is out of range */
static int daylight_il(xspect *sp, double ct) {
static double s0[107] = {
0.04, 3.02, 6.00, 17.80, 29.60, 42.45, 55.30, 56.30, 57.30, 59.55,
61.80, 61.65, 61.50, 65.15, 68.80, 66.10, 63.40, 64.60, 65.80, 80.30,
94.80, 99.80, 104.80, 105.35, 105.90, 101.35, 96.80, 105.35, 113.90, 119.75,
125.60, 125.55, 125.50, 123.40, 121.30, 121.30, 121.30, 117.40, 113.50, 113.30,
113.10, 111.95, 110.80, 108.65, 106.50, 107.65, 108.80, 107.05, 105.30, 104.85,
104.40, 102.20, 100.00, 98.00, 96.00, 95.55, 95.10, 92.10, 89.10, 89.80,
90.50, 90.40, 90.30, 89.35, 88.40, 86.20, 84.00, 84.55, 85.10, 83.50,
81.90, 82.25, 82.60, 83.75, 84.90, 83.10, 81.30, 76.60, 71.90, 73.10,
74.30, 75.35, 76.40, 69.85, 63.30, 67.50, 71.70, 74.35, 77.00, 71.10,
65.20, 56.45, 47.70, 58.15, 68.60, 66.80, 65.00, 65.50, 66.00, 63.50,
61.00, 57.15, 53.30, 56.10, 58.90, 60.40, 61.90
};
static double s1[107] = {
0.02, 2.26, 4.50, 13.45, 22.40, 32.20, 42.00, 41.30, 40.60, 41.10,
41.60, 39.80, 38.00, 40.20, 42.40, 40.45, 38.50, 36.75, 35.00, 39.20,
43.40, 44.85, 46.30, 45.10, 43.90, 40.50, 37.10, 36.90, 36.70, 36.30,
35.90, 34.25, 32.60, 30.25, 27.90, 26.10, 24.30, 22.20, 20.10, 18.15,
16.20, 14.70, 13.20, 10.90, 8.60, 7.35, 6.10, 5.15, 4.20, 3.05,
1.90, 0.95, 0.00, -0.80, -1.60, -2.55, -3.50, -3.50, -3.50, -4.65,
-5.80, -6.50, -7.20, -7.90, -8.60, -9.05, -9.50, -10.20, -10.90, -10.80,
-10.70, -11.35, -12.00, -13.00, -14.00, -13.80, -13.60, -12.80, -12.00, -12.65,
-13.30, -13.10, -12.90, -11.75, -10.60, -11.10, -11.60, -11.90, -12.20, -11.20,
-10.20, -9.00, -7.80, -9.50, -11.20, -10.80, -10.40, -10.50, -10.60, -10.15,
-9.70, -9.00, -8.30, -8.80, -9.30, -9.55, -9.80
};
static double s2[107] = {
0.00, 1.00, 2.00, 3.00, 4.00, 6.25, 8.50, 8.15, 7.80, 7.25,
6.70, 6.00, 5.30, 5.70, 6.10, 4.55, 3.00, 2.10, 1.20, 0.05,
-1.10, -0.80, -0.50, -0.60, -0.70, -0.95, -1.20, -1.90, -2.60, -2.75,
-2.90, -2.85, -2.80, -2.70, -2.60, -2.60, -2.60, -2.20, -1.80, -1.65,
-1.50, -1.40, -1.30, -1.25, -1.20, -1.10, -1.00, -0.75, -0.50, -0.40,
-0.30, -0.15, 0.00, 0.10, 0.20, 0.35, 0.50, 1.30, 2.10, 2.65,
3.20, 3.65, 4.10, 4.40, 4.70, 4.90, 5.10, 5.90, 6.70, 7.00,
7.30, 7.95, 8.60, 9.20, 9.80, 10.00, 10.20, 9.25, 8.30, 8.95,
9.60, 9.05, 8.50, 7.75, 7.00, 7.30, 7.60, 7.80, 8.00, 7.35,
6.70, 5.95, 5.20, 6.30, 7.40, 7.10, 6.80, 6.90, 7.00, 6.70,
6.40, 5.95, 5.50, 5.80, 6.10, 6.30, 6.50
};
int i;
double xd, yd;
double m1, m2;
if (ct < 4000.0 || ct > 25000.0) { /* Only accurate down to 4000 */
return 1;
}
/* Compute chromaticity coordinates */
if (ct < 7000.0) {
xd = -4.6070e9/(ct * ct * ct) + 2.9678e6/(ct * ct) + 0.09911e3/ct + 0.244063;
} else {
xd = -2.0064e9/(ct * ct * ct) + 1.9018e6/(ct * ct) + 0.24748e3/ct + 0.237040;
}
yd = -3.000 * xd * xd + 2.870 * xd - 0.275;
/* Compute m factors */
m1 = (-1.3515 - 1.7703 * xd + 5.9114 * yd)/(0.0241 + 0.2562 * xd - 0.7341 * yd);
m2 = (0.0300 - 31.4424 * xd + 30.0717 * yd)/(0.0241 + 0.2562 * xd - 0.7341 * yd);
/* Compute spectral values */
for (i = 0; i < 107; i++) {
sp->spec[i] = s0[i] + m1 * s1[i] + m2 * s2[i];
}
sp->spec_n = 107;
sp->spec_wl_short = 300.0;
sp->spec_wl_long = 830;
sp->norm = 100.0; /* Arbitrary */
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 */
static int planckian_il(xspect *sp, double ct) {
int i;
double wl, norm;
if (ct < 1.0 || ct > 1e6) /* set some arbitrary limits */
return 1;
/* Set out targets */
sp->spec_n = 531; /* 1nm */
sp->spec_wl_short = 300.0;
sp->spec_wl_long = 830;
/* Compute spectral values using Plank's radiation law: */
/* Normalise numbers by energy at 560 nm */
wl = 1e-9 * 560;
norm = 0.01 * (3.74183e-16 * pow(wl, -5.0)) / (exp(1.4388e-2 / (wl * ct)) - 1.0);
for (i = 0; i < sp->spec_n; i++) {
wl = 1e-9 * XSPECT_XWL(sp, i); /* Wavelength in meters */
sp->spec[i] = (3.74183e-16 * pow(wl, -5.0)) / (exp(1.4388e-2 / (wl * ct)) - 1.0);
sp->spec[i] /= norm;
}
sp->norm = 100.0; /* Arbitrary */
return 0;
}
#ifndef SALONEINSTLIB
/* CIE F5 */
/* Fluorescent, Standard, 6350K, CRI 72 */
static xspect il_F5 = {
107, 300.0, 830.0, /* 109 bands from 300 to 830 nm in 5nm steps */
20.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,
/* 380 */ 1.87, 2.35, 2.92, 3.45, 5.10, 18.91, 6.00, 6.11, 6.85, 7.58,
/* 430 */ 8.31, 40.76, 16.06, 10.32, 10.91, 11.40, 11.83, 12.17, 12.40, 12.54,
/* 480 */ 12.58, 12.52, 12.47, 12.20, 11.89, 11.61, 11.33, 11.10, 10.96, 10.97,
/* 530 */ 11.16, 11.54, 12.12, 27.78, 17.73, 14.47, 15.20, 15.77, 16.10, 18.54,
/* 580 */ 19.50, 15.39, 14.64, 13.72, 12.69, 11.57, 10.45, 9.35, 8.29, 7.32,
/* 630 */ 6.41, 5.63, 4.90, 4.26, 3.72, 3.25, 2.83, 2.49, 2.19, 1.93,
/* 680 */ 1.71, 1.52, 1.48, 1.26, 1.13, 1.05, 0.96, 0.85, 0.78, 0.72,
/* 730 */ 0.68, 0.67, 0.65, 0.61, 0.62, 0.59, 0.62, 0.64, 0.55, 0.47,
/* 780 */ 0.40,
/* 785 */ 0.0, 0.0, 0.0, 0.0, 0.0,
/* 810 */ 0.0, 0.0, 0.0, 0.0, 0.0
}
};
/* CIE F8 */
/* 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 */
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,
/* 380 */ 1.21, 1.5, 1.81, 2.13, 3.17, 13.08, 3.83, 3.45, 3.86, 4.42,
/* 430 */ 5.09, 34.10, 12.42, 7.68, 8.6, 9.46, 10.24, 10.84, 11.33, 11.71,
/* 480 */ 11.98, 12.17, 12.28, 12.32, 12.35, 12.44, 12.55, 12.68, 12.77, 12.72,
/* 530 */ 12.60, 12.43, 12.22, 28.96, 16.51, 11.79, 11.76, 11.77, 11.84, 14.61,
/* 580 */ 16.11, 12.34, 12.53, 12.72, 12.92, 13.12, 13.34, 13.61, 13.87, 14.07,
/* 630 */ 14.20, 14.16, 14.13, 14.34, 14.50, 14.46, 14.00, 12.58, 10.99, 9.98,
/* 680 */ 9.22, 8.62, 8.07, 7.39, 6.71, 6.16, 5.63, 5.03, 4.46, 4.02,
/* 730 */ 3.66, 3.36, 3.09, 2.85, 2.65, 2.51, 2.37, 2.15, 1.89, 1.61,
/* 780 */ 1.32,
/* 785 */ 0.0, 0.0, 0.0, 0.0, 0.0,
/* 810 */ 0.0, 0.0, 0.0, 0.0, 0.0
}
};
/* CIE F10 */
/* 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 */
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,
1.11, 0.80, 0.62, 0.57, 1.48, 12.16, 2.12, 2.70, 3.74, 5.14,
6.75, 34.39, 14.86, 10.40, 10.76, 10.67, 10.11, 9.27, 8.29, 7.29,
7.91, 16.64, 16.73, 10.44, 5.94, 3.34, 2.35, 1.88, 1.59, 1.47,
1.80, 5.71, 40.98, 73.69, 33.61, 8.24, 3.38, 2.47, 2.14, 4.86,
11.45, 14.79, 12.16, 8.97, 6.53, 8.31, 44.12, 34.55, 12.09, 12.15,
10.52, 4.43, 1.95, 2.19, 3.19, 2.77, 2.29, 2.00, 1.52, 1.35,
1.47, 1.79, 1.74, 1.02, 1.14, 3.32, 4.49, 2.05, 0.49, 0.24,
0.21, 0.21, 0.24, 0.24, 0.21, 0.17, 0.21, 0.22, 0.17, 0.12,
0.09,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0
}
};
/* Spectrocam Xenon Lamp */
static xspect il_Spectrocam = {
95, 325.0, 795.0, /* 95 bands from 325 to 795 nm in 5nm steps */
1.0, /* Arbitrary scale factor */
{
0.220794, 0.240550, 0.281212, 0.363042, 0.493282,
0.582279, 0.657489, 0.715563, 0.797559, 0.916343,
1.066625, 1.228461, 1.298467, 1.373143, 1.457366,
1.496117, 1.509290, 1.573544, 1.596359, 1.495740,
1.477898, 1.521371, 1.479780, 1.453196, 1.532119,
1.548128, 1.503433, 1.428481, 1.357290, 1.354425,
1.317263, 1.237048, 1.169737, 1.109248, 1.085784,
1.080186, 1.104001, 1.131713, 1.161153, 1.158589,
1.148998, 1.123934, 1.077395, 1.017907, 1.026532,
1.045921, 1.083780, 1.081868, 1.048489, 1.021549,
0.993572, 0.956559, 0.942657, 0.952544, 0.957087,
0.958472, 0.945666, 0.923988, 0.890418, 0.852044,
0.812935, 0.792055, 0.791141, 0.825459, 0.829230,
0.818171, 0.851752, 0.913113, 1.038844, 1.116913,
1.164211, 1.133376, 1.109062, 1.129427, 1.086885,
0.991213, 0.924226, 0.875499, 0.894231, 0.922219,
0.960372, 0.896142, 0.819477, 0.879305, 0.912777,
0.908489, 0.775942, 0.598118, 0.532988, 0.484102,
0.465986, 0.414848, 0.346473, 0.324622, 0.309978
}
};
#endif /* !SALONEINSTLIB */
/* Apply ISO 13655:2009 UV filter to the given spectrum. */
/* The filter is applied point by point. */
static void uv_filter(xspect *dst, xspect *src) {
int i;
XSPECT_COPY_INFO(dst, src);
for (i = 0; i < src->spec_n; i++) {
double wl = XSPECT_XWL(src, i);
double ff = 1.0;
if (wl <= 395.0) {
ff = 0.0;
} else if (wl < 425.0) {
ff = (wl - 395.0)/(425.0 - 395.0);
ff = ff * ff * (3.0 - 2.0 * ff); /* Cubic spline */
}
dst->spec[i] = ff * src->spec[i];
}
}
/* Fill in an xpsect with a standard illuminant spectrum */
/* return 0 on sucecss, nz if not matched */
int standardIlluminant(
xspect *sp, /* Xspect to fill in */
icxIllumeType ilType, /* Type of illuminant */
double temp /* Optional temperature in degrees kelvin, for Dtemp and Ptemp */
) {
switch (ilType) {
case icxIT_none:
return 1;
case icxIT_custom:
return 1;
case icxIT_A:
*sp = il_A; /* Struct copy */
return 0;
case icxIT_C:
*sp = il_C; /* " */
return 0;
case icxIT_default:
case icxIT_D50:
*sp = il_D50; /* etc */
return 0;
case icxIT_D50M2:
if (il_D50M2.spec_n == 0)
uv_filter(&il_D50M2, &il_D50);
*sp = il_D50M2;
return 0;
case icxIT_D55:
return daylight_il(sp, 5500.0);
case icxIT_D65:
*sp = il_D65;
return 0;
case icxIT_D75:
return daylight_il(sp, 7500.0);
case icxIT_E:
*sp = il_none;
return 0;
#ifndef SALONEINSTLIB
case icxIT_F5:
*sp = il_F5;
return 0;
case icxIT_F8:
*sp = il_F8;
return 0;
case icxIT_F10:
*sp = il_F10;
return 0;
case icxIT_Spectrocam:
*sp = il_Spectrocam;
return 0;
case icxIT_Dtemp:
return daylight_il(sp, temp);
#endif
case icxIT_Ptemp:
return planckian_il(sp, temp);
}
return 1;
}
/* ------------- */
/* Observer Data */
/* Standard CIE 1931 2 degree */
static xspect ob_CIE_1931_2[3] = {
{
471, 360.0, 830.0, /* 471 bands from 360 to 830 nm in 1nm steps */
1.0, /* Scale factor */
{
0.000129900000, 0.000145847000, 0.000163802100, 0.000184003700, 0.000206690200,
0.000232100000, 0.000260728000, 0.000293075000, 0.000329388000, 0.000369914000,
0.000414900000, 0.000464158700, 0.000518986000, 0.000581854000, 0.000655234700,
0.000741600000, 0.000845029600, 0.000964526800, 0.001094949000, 0.001231154000,
0.001368000000, 0.001502050000, 0.001642328000, 0.001802382000, 0.001995757000,
0.002236000000, 0.002535385000, 0.002892603000, 0.003300829000, 0.003753236000,
0.004243000000, 0.004762389000, 0.005330048000, 0.005978712000, 0.006741117000,
0.007650000000, 0.008751373000, 0.010028880000, 0.011421700000, 0.012869010000,
0.014310000000, 0.015704430000, 0.017147440000, 0.018781220000, 0.020748010000,
0.023190000000, 0.026207360000, 0.029782480000, 0.033880920000, 0.038468240000,
0.043510000000, 0.048995600000, 0.055022600000, 0.061718800000, 0.069212000000,
0.077630000000, 0.086958110000, 0.097176720000, 0.108406300000, 0.120767200000,
0.134380000000, 0.149358200000, 0.165395700000, 0.181983100000, 0.198611000000,
0.214770000000, 0.230186800000, 0.244879700000, 0.258777300000, 0.271807900000,
0.283900000000, 0.294943800000, 0.304896500000, 0.313787300000, 0.321645400000,
0.328500000000, 0.334351300000, 0.339210100000, 0.343121300000, 0.346129600000,
0.348280000000, 0.349599900000, 0.350147400000, 0.350013000000, 0.349287000000,
0.348060000000, 0.346373300000, 0.344262400000, 0.341808800000, 0.339094100000,
0.336200000000, 0.333197700000, 0.330041100000, 0.326635700000, 0.322886800000,
0.318700000000, 0.314025100000, 0.308884000000, 0.303290400000, 0.297257900000,
0.290800000000, 0.283970100000, 0.276721400000, 0.268917800000, 0.260422700000,
0.251100000000, 0.240847500000, 0.229851200000, 0.218407200000, 0.206811500000,
0.195360000000, 0.184213600000, 0.173327300000, 0.162688100000, 0.152283300000,
0.142100000000, 0.132178600000, 0.122569600000, 0.113275200000, 0.104297900000,
0.095640000000, 0.087299550000, 0.079308040000, 0.071717760000, 0.064580990000,
0.057950010000, 0.051862110000, 0.046281520000, 0.041150880000, 0.036412830000,
0.032010000000, 0.027917200000, 0.024144400000, 0.020687000000, 0.017540400000,
0.014700000000, 0.012161790000, 0.009919960000, 0.007967240000, 0.006296346000,
0.004900000000, 0.003777173000, 0.002945320000, 0.002424880000, 0.002236293000,
0.002400000000, 0.002925520000, 0.003836560000, 0.005174840000, 0.006982080000,
0.009300000000, 0.012149490000, 0.015535880000, 0.019477520000, 0.023992770000,
0.029100000000, 0.034814850000, 0.041120160000, 0.047985040000, 0.055378610000,
0.063270000000, 0.071635010000, 0.080462240000, 0.089739960000, 0.099456450000,
0.109600000000, 0.120167400000, 0.131114500000, 0.142367900000, 0.153854200000,
0.165500000000, 0.177257100000, 0.189140000000, 0.201169400000, 0.213365800000,
0.225749900000, 0.238320900000, 0.251066800000, 0.263992200000, 0.277101700000,
0.290400000000, 0.303891200000, 0.317572600000, 0.331438400000, 0.345482800000,
0.359700000000, 0.374083900000, 0.388639600000, 0.403378400000, 0.418311500000,
0.433449900000, 0.448795300000, 0.464336000000, 0.480064000000, 0.495971300000,
0.512050100000, 0.528295900000, 0.544691600000, 0.561209400000, 0.577821500000,
0.594500000000, 0.611220900000, 0.627975800000, 0.644760200000, 0.661569700000,
0.678400000000, 0.695239200000, 0.712058600000, 0.728828400000, 0.745518800000,
0.762100000000, 0.778543200000, 0.794825600000, 0.810926400000, 0.826824800000,
0.842500000000, 0.857932500000, 0.873081600000, 0.887894400000, 0.902318100000,
0.916300000000, 0.929799500000, 0.942798400000, 0.955277600000, 0.967217900000,
0.978600000000, 0.989385600000, 0.999548800000, 1.009089200000, 1.018006400000,
1.026300000000, 1.033982700000, 1.040986000000, 1.047188000000, 1.052466700000,
1.056700000000, 1.059794400000, 1.061799200000, 1.062806800000, 1.062909600000,
1.062200000000, 1.060735200000, 1.058443600000, 1.055224400000, 1.050976800000,
1.045600000000, 1.039036900000, 1.031360800000, 1.022666200000, 1.013047700000,
1.002600000000, 0.991367500000, 0.979331400000, 0.966491600000, 0.952847900000,
0.938400000000, 0.923194000000, 0.907244000000, 0.890502000000, 0.872920000000,
0.854449900000, 0.835084000000, 0.814946000000, 0.794186000000, 0.772954000000,
0.751400000000, 0.729583600000, 0.707588800000, 0.685602200000, 0.663810400000,
0.642400000000, 0.621514900000, 0.601113800000, 0.581105200000, 0.561397700000,
0.541900000000, 0.522599500000, 0.503546400000, 0.484743600000, 0.466193900000,
0.447900000000, 0.429861300000, 0.412098000000, 0.394644000000, 0.377533300000,
0.360800000000, 0.344456300000, 0.328516800000, 0.313019200000, 0.298001100000,
0.283500000000, 0.269544800000, 0.256118400000, 0.243189600000, 0.230727200000,
0.218700000000, 0.207097100000, 0.195923200000, 0.185170800000, 0.174832300000,
0.164900000000, 0.155366700000, 0.146230000000, 0.137490000000, 0.129146700000,
0.121200000000, 0.113639700000, 0.106465000000, 0.099690440000, 0.093330610000,
0.087400000000, 0.081900960000, 0.076804280000, 0.072077120000, 0.067686640000,
0.063600000000, 0.059806850000, 0.056282160000, 0.052971040000, 0.049818610000,
0.046770000000, 0.043784050000, 0.040875360000, 0.038072640000, 0.035404610000,
0.032900000000, 0.030564190000, 0.028380560000, 0.026344840000, 0.024452750000,
0.022700000000, 0.021084290000, 0.019599880000, 0.018237320000, 0.016987170000,
0.015840000000, 0.014790640000, 0.013831320000, 0.012948680000, 0.012129200000,
0.011359160000, 0.010629350000, 0.009938846000, 0.009288422000, 0.008678854000,
0.008110916000, 0.007582388000, 0.007088746000, 0.006627313000, 0.006195408000,
0.005790346000, 0.005409826000, 0.005052583000, 0.004717512000, 0.004403507000,
0.004109457000, 0.003833913000, 0.003575748000, 0.003334342000, 0.003109075000,
0.002899327000, 0.002704348000, 0.002523020000, 0.002354168000, 0.002196616000,
0.002049190000, 0.001910960000, 0.001781438000, 0.001660110000, 0.001546459000,
0.001439971000, 0.001340042000, 0.001246275000, 0.001158471000, 0.001076430000,
0.000999949300, 0.000928735800, 0.000862433200, 0.000800750300, 0.000743396000,
0.000690078600, 0.000640515600, 0.000594502100, 0.000551864600, 0.000512429000,
0.000476021300, 0.000442453600, 0.000411511700, 0.000382981400, 0.000356649100,
0.000332301100, 0.000309758600, 0.000288887100, 0.000269539400, 0.000251568200,
0.000234826100, 0.000219171000, 0.000204525800, 0.000190840500, 0.000178065400,
0.000166150500, 0.000155023600, 0.000144621900, 0.000134909800, 0.000125852000,
0.000117413000, 0.000109551500, 0.000102224500, 0.000095394450, 0.000089023900,
0.000083075270, 0.000077512690, 0.000072313040, 0.000067457780, 0.000062928440,
0.000058706520, 0.000054770280, 0.000051099180, 0.000047676540, 0.000044485670,
0.000041509940, 0.000038733240, 0.000036142030, 0.000033723520, 0.000031464870,
0.000029353260, 0.000027375730, 0.000025524330, 0.000023793760, 0.000022178700,
0.000020673830, 0.000019272260, 0.000017966400, 0.000016749910, 0.000015616480,
0.000014559770, 0.000013573870, 0.000012654360, 0.000011797230, 0.000010998440,
0.000010253980, 0.000009559646, 0.000008912044, 0.000008308358, 0.000007745769,
0.000007221456, 0.000006732475, 0.000006276423, 0.000005851304, 0.000005455118,
0.000005085868, 0.000004741466, 0.000004420236, 0.000004120783, 0.000003841716,
0.000003581652, 0.000003339127, 0.000003112949, 0.000002902121, 0.000002705645,
0.000002522525, 0.000002351726, 0.000002192415, 0.000002043902, 0.000001905497,
0.000001776509, 0.000001656215, 0.000001544022, 0.000001439440, 0.000001341977,
0.000001251141
}
},
{
471, 360.0, 830.0, /* 471 bands from 360 to 830 nm in 1nm steps */
1.0, /* Scale factor */
{
0.000003917000, 0.000004393581, 0.000004929604, 0.000005532136, 0.000006208245,
0.000006965000, 0.000007813219, 0.000008767336, 0.000009839844, 0.000011043230,
0.000012390000, 0.000013886410, 0.000015557280, 0.000017442960, 0.000019583750,
0.000022020000, 0.000024839650, 0.000028041260, 0.000031531040, 0.000035215210,
0.000039000000, 0.000042826400, 0.000046914600, 0.000051589600, 0.000057176400,
0.000064000000, 0.000072344210, 0.000082212240, 0.000093508160, 0.000106136100,
0.000120000000, 0.000134984000, 0.000151492000, 0.000170208000, 0.000191816000,
0.000217000000, 0.000246906700, 0.000281240000, 0.000318520000, 0.000357266700,
0.000396000000, 0.000433714700, 0.000473024000, 0.000517876000, 0.000572218700,
0.000640000000, 0.000724560000, 0.000825500000, 0.000941160000, 0.001069880000,
0.001210000000, 0.001362091000, 0.001530752000, 0.001720368000, 0.001935323000,
0.002180000000, 0.002454800000, 0.002764000000, 0.003117800000, 0.003526400000,
0.004000000000, 0.004546240000, 0.005159320000, 0.005829280000, 0.006546160000,
0.007300000000, 0.008086507000, 0.008908720000, 0.009767680000, 0.010664430000,
0.011600000000, 0.012573170000, 0.013582720000, 0.014629680000, 0.015715090000,
0.016840000000, 0.018007360000, 0.019214480000, 0.020453920000, 0.021718240000,
0.023000000000, 0.024294610000, 0.025610240000, 0.026958570000, 0.028351250000,
0.029800000000, 0.031310830000, 0.032883680000, 0.034521120000, 0.036225710000,
0.038000000000, 0.039846670000, 0.041768000000, 0.043766000000, 0.045842670000,
0.048000000000, 0.050243680000, 0.052573040000, 0.054980560000, 0.057458720000,
0.060000000000, 0.062601970000, 0.065277520000, 0.068042080000, 0.070911090000,
0.073900000000, 0.077016000000, 0.080266400000, 0.083666800000, 0.087232800000,
0.090980000000, 0.094917550000, 0.099045840000, 0.103367400000, 0.107884600000,
0.112600000000, 0.117532000000, 0.122674400000, 0.127992800000, 0.133452800000,
0.139020000000, 0.144676400000, 0.150469300000, 0.156461900000, 0.162717700000,
0.169300000000, 0.176243100000, 0.183558100000, 0.191273500000, 0.199418000000,
0.208020000000, 0.217119900000, 0.226734500000, 0.236857100000, 0.247481200000,
0.258600000000, 0.270184900000, 0.282293900000, 0.295050500000, 0.308578000000,
0.323000000000, 0.338402100000, 0.354685800000, 0.371698600000, 0.389287500000,
0.407300000000, 0.425629900000, 0.444309600000, 0.463394400000, 0.482939500000,
0.503000000000, 0.523569300000, 0.544512000000, 0.565690000000, 0.586965300000,
0.608200000000, 0.629345600000, 0.650306800000, 0.670875200000, 0.690842400000,
0.710000000000, 0.728185200000, 0.745463600000, 0.761969400000, 0.777836800000,
0.793200000000, 0.808110400000, 0.822496200000, 0.836306800000, 0.849491600000,
0.862000000000, 0.873810800000, 0.884962400000, 0.895493600000, 0.905443200000,
0.914850100000, 0.923734800000, 0.932092400000, 0.939922600000, 0.947225200000,
0.954000000000, 0.960256100000, 0.966007400000, 0.971260600000, 0.976022500000,
0.980300000000, 0.984092400000, 0.987418200000, 0.990312800000, 0.992811600000,
0.994950100000, 0.996710800000, 0.998098300000, 0.999112000000, 0.999748200000,
1.000000000000, 0.999856700000, 0.999304600000, 0.998325500000, 0.996898700000,
0.995000000000, 0.992600500000, 0.989742600000, 0.986444400000, 0.982724100000,
0.978600000000, 0.974083700000, 0.969171200000, 0.963856800000, 0.958134900000,
0.952000000000, 0.945450400000, 0.938499200000, 0.931162800000, 0.923457600000,
0.915400000000, 0.907006400000, 0.898277200000, 0.889204800000, 0.879781600000,
0.870000000000, 0.859861300000, 0.849392000000, 0.838622000000, 0.827581300000,
0.816300000000, 0.804794700000, 0.793082000000, 0.781192000000, 0.769154700000,
0.757000000000, 0.744754100000, 0.732422400000, 0.720003600000, 0.707496500000,
0.694900000000, 0.682219200000, 0.669471600000, 0.656674400000, 0.643844800000,
0.631000000000, 0.618155500000, 0.605314400000, 0.592475600000, 0.579637900000,
0.566800000000, 0.553961100000, 0.541137200000, 0.528352800000, 0.515632300000,
0.503000000000, 0.490468800000, 0.478030400000, 0.465677600000, 0.453403200000,
0.441200000000, 0.429080000000, 0.417036000000, 0.405032000000, 0.393032000000,
0.381000000000, 0.368918400000, 0.356827200000, 0.344776800000, 0.332817600000,
0.321000000000, 0.309338100000, 0.297850400000, 0.286593600000, 0.275624500000,
0.265000000000, 0.254763200000, 0.244889600000, 0.235334400000, 0.226052800000,
0.217000000000, 0.208161600000, 0.199548800000, 0.191155200000, 0.182974400000,
0.175000000000, 0.167223500000, 0.159646400000, 0.152277600000, 0.145125900000,
0.138200000000, 0.131500300000, 0.125024800000, 0.118779200000, 0.112769100000,
0.107000000000, 0.101476200000, 0.096188640000, 0.091122960000, 0.086264850000,
0.081600000000, 0.077120640000, 0.072825520000, 0.068710080000, 0.064769760000,
0.061000000000, 0.057396210000, 0.053955040000, 0.050673760000, 0.047549650000,
0.044580000000, 0.041758720000, 0.039084960000, 0.036563840000, 0.034200480000,
0.032000000000, 0.029962610000, 0.028076640000, 0.026329360000, 0.024708050000,
0.023200000000, 0.021800770000, 0.020501120000, 0.019281080000, 0.018120690000,
0.017000000000, 0.015903790000, 0.014837180000, 0.013810680000, 0.012834780000,
0.011920000000, 0.011068310000, 0.010273390000, 0.009533311000, 0.008846157000,
0.008210000000, 0.007623781000, 0.007085424000, 0.006591476000, 0.006138485000,
0.005723000000, 0.005343059000, 0.004995796000, 0.004676404000, 0.004380075000,
0.004102000000, 0.003838453000, 0.003589099000, 0.003354219000, 0.003134093000,
0.002929000000, 0.002738139000, 0.002559876000, 0.002393244000, 0.002237275000,
0.002091000000, 0.001953587000, 0.001824580000, 0.001703580000, 0.001590187000,
0.001484000000, 0.001384496000, 0.001291268000, 0.001204092000, 0.001122744000,
0.001047000000, 0.000976589600, 0.000911108800, 0.000850133200, 0.000793238400,
0.000740000000, 0.000690082700, 0.000643310000, 0.000599496000, 0.000558454700,
0.000520000000, 0.000483913600, 0.000450052800, 0.000418345200, 0.000388718400,
0.000361100000, 0.000335383500, 0.000311440400, 0.000289165600, 0.000268453900,
0.000249200000, 0.000231301900, 0.000214685600, 0.000199288400, 0.000185047500,
0.000171900000, 0.000159778100, 0.000148604400, 0.000138301600, 0.000128792500,
0.000120000000, 0.000111859500, 0.000104322400, 0.000097335600, 0.000090845870,
0.000084800000, 0.000079146670, 0.000073858000, 0.000068916000, 0.000064302670,
0.000060000000, 0.000055981870, 0.000052225600, 0.000048718400, 0.000045447470,
0.000042400000, 0.000039561040, 0.000036915120, 0.000034448680, 0.000032148160,
0.000030000000, 0.000027991250, 0.000026113560, 0.000024360240, 0.000022724610,
0.000021200000, 0.000019778550, 0.000018452850, 0.000017216870, 0.000016064590,
0.000014990000, 0.000013987280, 0.000013051550, 0.000012178180, 0.000011362540,
0.000010600000, 0.000009885877, 0.000009217304, 0.000008592362, 0.000008009133,
0.000007465700, 0.000006959567, 0.000006487995, 0.000006048699, 0.000005639396,
0.000005257800, 0.000004901771, 0.000004569720, 0.000004260194, 0.000003971739,
0.000003702900, 0.000003452163, 0.000003218302, 0.000003000300, 0.000002797139,
0.000002607800, 0.000002431220, 0.000002266531, 0.000002113013, 0.000001969943,
0.000001836600, 0.000001712230, 0.000001596228, 0.000001488090, 0.000001387314,
0.000001293400, 0.000001205820, 0.000001124143, 0.000001048009, 0.000000977058,
0.000000910930, 0.000000849251, 0.000000791721, 0.000000738090, 0.000000688110,
0.000000641530, 0.000000598090, 0.000000557575, 0.000000519808, 0.000000484612,
0.000000451810
}
},
{
471, 360.0, 830.0, /* 471 bands from 360 to 830 nm in 1nm steps */
1.0, /* Scale factor */
{
0.000606100000, 0.000680879200, 0.000765145600, 0.000860012400, 0.000966592800,
0.001086000000, 0.001220586000, 0.001372729000, 0.001543579000, 0.001734286000,
0.001946000000, 0.002177777000, 0.002435809000, 0.002731953000, 0.003078064000,
0.003486000000, 0.003975227000, 0.004540880000, 0.005158320000, 0.005802907000,
0.006450001000, 0.007083216000, 0.007745488000, 0.008501152000, 0.009414544000,
0.010549990000, 0.011965800000, 0.013655870000, 0.015588050000, 0.017730150000,
0.020050010000, 0.022511360000, 0.025202880000, 0.028279720000, 0.031897040000,
0.036210000000, 0.041437710000, 0.047503720000, 0.054119880000, 0.060998030000,
0.067850010000, 0.074486320000, 0.081361560000, 0.089153640000, 0.098540480000,
0.110200000000, 0.124613300000, 0.141701700000, 0.161303500000, 0.183256800000,
0.207400000000, 0.233692100000, 0.262611400000, 0.294774600000, 0.330798500000,
0.371300000000, 0.416209100000, 0.465464200000, 0.519694800000, 0.579530300000,
0.645600000000, 0.718483800000, 0.796713300000, 0.877845900000, 0.959439000000,
1.039050100000, 1.115367300000, 1.188497100000, 1.258123300000, 1.323929600000,
1.385600000000, 1.442635200000, 1.494803500000, 1.542190300000, 1.584880700000,
1.622960000000, 1.656404800000, 1.685295900000, 1.709874500000, 1.730382100000,
1.747060000000, 1.760044600000, 1.769623300000, 1.776263700000, 1.780433400000,
1.782600000000, 1.782968200000, 1.781699800000, 1.779198200000, 1.775867100000,
1.772110000000, 1.768258900000, 1.764039000000, 1.758943800000, 1.752466300000,
1.744100000000, 1.733559500000, 1.720858100000, 1.705936900000, 1.688737200000,
1.669200000000, 1.647528700000, 1.623412700000, 1.596022300000, 1.564528000000,
1.528100000000, 1.486111400000, 1.439521500000, 1.389879900000, 1.338736200000,
1.287640000000, 1.237422300000, 1.187824300000, 1.138761100000, 1.090148000000,
1.041900000000, 0.994197600000, 0.947347300000, 0.901453100000, 0.856619300000,
0.812950100000, 0.770517300000, 0.729444800000, 0.689913600000, 0.652104900000,
0.616200000000, 0.582328600000, 0.550416200000, 0.520337600000, 0.491967300000,
0.465180000000, 0.439924600000, 0.416183600000, 0.393882200000, 0.372945900000,
0.353300000000, 0.334857800000, 0.317552100000, 0.301337500000, 0.286168600000,
0.272000000000, 0.258817100000, 0.246483800000, 0.234771800000, 0.223453300000,
0.212300000000, 0.201169200000, 0.190119600000, 0.179225400000, 0.168560800000,
0.158200000000, 0.148138300000, 0.138375800000, 0.128994200000, 0.120075100000,
0.111700000000, 0.103904800000, 0.096667480000, 0.089982720000, 0.083845310000,
0.078249990000, 0.073208990000, 0.068678160000, 0.064567840000, 0.060788350000,
0.057250010000, 0.053904350000, 0.050746640000, 0.047752760000, 0.044898590000,
0.042160000000, 0.039507280000, 0.036935640000, 0.034458360000, 0.032088720000,
0.029840000000, 0.027711810000, 0.025694440000, 0.023787160000, 0.021989250000,
0.020300000000, 0.018718050000, 0.017240360000, 0.015863640000, 0.014584610000,
0.013400000000, 0.012307230000, 0.011301880000, 0.010377920000, 0.009529306000,
0.008749999000, 0.008035200000, 0.007381600000, 0.006785400000, 0.006242800000,
0.005749999000, 0.005303600000, 0.004899800000, 0.004534200000, 0.004202400000,
0.003900000000, 0.003623200000, 0.003370600000, 0.003141400000, 0.002934800000,
0.002749999000, 0.002585200000, 0.002438600000, 0.002309400000, 0.002196800000,
0.002100000000, 0.002017733000, 0.001948200000, 0.001889800000, 0.001840933000,
0.001800000000, 0.001766267000, 0.001737800000, 0.001711200000, 0.001683067000,
0.001650001000, 0.001610133000, 0.001564400000, 0.001513600000, 0.001458533000,
0.001400000000, 0.001336667000, 0.001270000000, 0.001205000000, 0.001146667000,
0.001100000000, 0.001068800000, 0.001049400000, 0.001035600000, 0.001021200000,
0.001000000000, 0.000968640000, 0.000929920000, 0.000886880000, 0.000842560000,
0.000800000000, 0.000760960000, 0.000723680000, 0.000685920000, 0.000645440000,
0.000600000000, 0.000547866700, 0.000491600000, 0.000435400000, 0.000383466700,
0.000340000000, 0.000307253300, 0.000283160000, 0.000265440000, 0.000251813300,
0.000240000000, 0.000229546700, 0.000220640000, 0.000211960000, 0.000202186700,
0.000190000000, 0.000174213300, 0.000155640000, 0.000135960000, 0.000116853300,
0.000100000000, 0.000086133330, 0.000074600000, 0.000065000000, 0.000056933330,
0.000049999990, 0.000044160000, 0.000039480000, 0.000035720000, 0.000032640000,
0.000030000000, 0.000027653330, 0.000025560000, 0.000023640000, 0.000021813330,
0.000020000000, 0.000018133330, 0.000016200000, 0.000014200000, 0.000012133330,
0.000010000000, 0.000007733333, 0.000005400000, 0.000003200000, 0.000001333333,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000
}
}
};
/* Standard CIE 1964 10 degree */
static xspect ob_CIE_1964_10[3] = {
{
471, 360.0, 830.0, /* 471 bands from 360 to 830 nm in 1nm steps */
1.0, /* Scale factor */
{
0.000000122200, 0.000000185138, 0.000000278830, 0.000000417470, 0.000000621330,
0.000000919270, 0.000001351980, 0.000001976540, 0.000002872500, 0.000004149500,
0.000005958600, 0.000008505600, 0.000012068600, 0.000017022600, 0.000023868000,
0.000033266000, 0.000046087000, 0.000063472000, 0.000086892000, 0.000118246000,
0.000159952000, 0.000215080000, 0.000287490000, 0.000381990000, 0.000504550000,
0.000662440000, 0.000864500000, 0.001121500000, 0.001446160000, 0.001853590000,
0.002361600000, 0.002990600000, 0.003764500000, 0.004710200000, 0.005858100000,
0.007242300000, 0.008899600000, 0.010870900000, 0.013198900000, 0.015929200000,
0.019109700000, 0.022788000000, 0.027011000000, 0.031829000000, 0.037278000000,
0.043400000000, 0.050223000000, 0.057764000000, 0.066038000000, 0.075033000000,
0.084736000000, 0.095041000000, 0.105836000000, 0.117066000000, 0.128682000000,
0.140638000000, 0.152893000000, 0.165416000000, 0.178191000000, 0.191214000000,
0.204492000000, 0.217650000000, 0.230267000000, 0.242311000000, 0.253793000000,
0.264737000000, 0.275195000000, 0.285301000000, 0.295143000000, 0.304869000000,
0.314679000000, 0.324355000000, 0.333570000000, 0.342243000000, 0.350312000000,
0.357719000000, 0.364482000000, 0.370493000000, 0.375727000000, 0.380158000000,
0.383734000000, 0.386327000000, 0.387858000000, 0.388396000000, 0.387978000000,
0.386726000000, 0.384696000000, 0.382006000000, 0.378709000000, 0.374915000000,
0.370702000000, 0.366089000000, 0.361045000000, 0.355518000000, 0.349486000000,
0.342957000000, 0.335893000000, 0.328284000000, 0.320150000000, 0.311475000000,
0.302273000000, 0.292858000000, 0.283502000000, 0.274044000000, 0.264263000000,
0.254085000000, 0.243392000000, 0.232187000000, 0.220488000000, 0.208198000000,
0.195618000000, 0.183034000000, 0.170222000000, 0.157348000000, 0.144650000000,
0.132349000000, 0.120584000000, 0.109456000000, 0.099042000000, 0.089388000000,
0.080507000000, 0.072034000000, 0.063710000000, 0.055694000000, 0.048117000000,
0.041072000000, 0.034642000000, 0.028896000000, 0.023876000000, 0.019628000000,
0.016172000000, 0.013300000000, 0.010759000000, 0.008542000000, 0.006661000000,
0.005132000000, 0.003982000000, 0.003239000000, 0.002934000000, 0.003114000000,
0.003816000000, 0.005095000000, 0.006936000000, 0.009299000000, 0.012147000000,
0.015444000000, 0.019156000000, 0.023250000000, 0.027690000000, 0.032444000000,
0.037465000000, 0.042956000000, 0.049114000000, 0.055920000000, 0.063349000000,
0.071358000000, 0.079901000000, 0.088909000000, 0.098293000000, 0.107949000000,
0.117749000000, 0.127839000000, 0.138450000000, 0.149516000000, 0.161041000000,
0.172953000000, 0.185209000000, 0.197755000000, 0.210538000000, 0.223460000000,
0.236491000000, 0.249633000000, 0.262972000000, 0.276515000000, 0.290269000000,
0.304213000000, 0.318361000000, 0.332705000000, 0.347232000000, 0.361926000000,
0.376772000000, 0.391683000000, 0.406594000000, 0.421539000000, 0.436517000000,
0.451584000000, 0.466782000000, 0.482147000000, 0.497738000000, 0.513606000000,
0.529826000000, 0.546440000000, 0.563426000000, 0.580726000000, 0.598290000000,
0.616053000000, 0.633948000000, 0.651901000000, 0.669824000000, 0.687632000000,
0.705224000000, 0.722773000000, 0.740483000000, 0.758273000000, 0.776083000000,
0.793832000000, 0.811436000000, 0.828822000000, 0.845879000000, 0.862525000000,
0.878655000000, 0.894208000000, 0.909206000000, 0.923672000000, 0.937638000000,
0.951162000000, 0.964283000000, 0.977068000000, 0.989590000000, 1.001910000000,
1.014160000000, 1.026500000000, 1.038800000000, 1.051000000000, 1.062900000000,
1.074300000000, 1.085200000000, 1.095200000000, 1.104200000000, 1.112000000000,
1.118520000000, 1.123800000000, 1.128000000000, 1.131100000000, 1.133200000000,
1.134300000000, 1.134300000000, 1.133300000000, 1.131200000000, 1.128100000000,
1.123990000000, 1.118900000000, 1.112900000000, 1.105900000000, 1.098000000000,
1.089100000000, 1.079200000000, 1.068400000000, 1.056700000000, 1.044000000000,
1.030480000000, 1.016000000000, 1.000800000000, 0.984790000000, 0.968080000000,
0.950740000000, 0.932800000000, 0.914340000000, 0.895390000000, 0.876030000000,
0.856297000000, 0.836350000000, 0.816290000000, 0.796050000000, 0.775610000000,
0.754930000000, 0.733990000000, 0.712780000000, 0.691290000000, 0.669520000000,
0.647467000000, 0.625110000000, 0.602520000000, 0.579890000000, 0.557370000000,
0.535110000000, 0.513240000000, 0.491860000000, 0.471080000000, 0.450960000000,
0.431567000000, 0.412870000000, 0.394750000000, 0.377210000000, 0.360190000000,
0.343690000000, 0.327690000000, 0.312170000000, 0.297110000000, 0.282500000000,
0.268329000000, 0.254590000000, 0.241300000000, 0.228480000000, 0.216140000000,
0.204300000000, 0.192950000000, 0.182110000000, 0.171770000000, 0.161920000000,
0.152568000000, 0.143670000000, 0.135200000000, 0.127130000000, 0.119480000000,
0.112210000000, 0.105310000000, 0.098786000000, 0.092610000000, 0.086773000000,
0.081260600000, 0.076048000000, 0.071114000000, 0.066454000000, 0.062062000000,
0.057930000000, 0.054050000000, 0.050412000000, 0.047006000000, 0.043823000000,
0.040850800000, 0.038072000000, 0.035468000000, 0.033031000000, 0.030753000000,
0.028623000000, 0.026635000000, 0.024781000000, 0.023052000000, 0.021441000000,
0.019941300000, 0.018544000000, 0.017241000000, 0.016027000000, 0.014896000000,
0.013842000000, 0.012862000000, 0.011949000000, 0.011100000000, 0.010311000000,
0.009576880000, 0.008894000000, 0.008258100000, 0.007666400000, 0.007116300000,
0.006605200000, 0.006130600000, 0.005690300000, 0.005281900000, 0.004903300000,
0.004552630000, 0.004227500000, 0.003925800000, 0.003645700000, 0.003385900000,
0.003144700000, 0.002920800000, 0.002713000000, 0.002520200000, 0.002341100000,
0.002174960000, 0.002020600000, 0.001877300000, 0.001744100000, 0.001620500000,
0.001505700000, 0.001399200000, 0.001300400000, 0.001208700000, 0.001123600000,
0.001044760000, 0.000971560000, 0.000903600000, 0.000840480000, 0.000781870000,
0.000727450000, 0.000676900000, 0.000629960000, 0.000586370000, 0.000545870000,
0.000508258000, 0.000473300000, 0.000440800000, 0.000410580000, 0.000382490000,
0.000356380000, 0.000332110000, 0.000309550000, 0.000288580000, 0.000269090000,
0.000250969000, 0.000234130000, 0.000218470000, 0.000203910000, 0.000190350000,
0.000177730000, 0.000165970000, 0.000155020000, 0.000144800000, 0.000135280000,
0.000126390000, 0.000118100000, 0.000110370000, 0.000103150000, 0.000096427000,
0.000090151000, 0.000084294000, 0.000078830000, 0.000073729000, 0.000068969000,
0.000064525800, 0.000060376000, 0.000056500000, 0.000052880000, 0.000049498000,
0.000046339000, 0.000043389000, 0.000040634000, 0.000038060000, 0.000035657000,
0.000033411700, 0.000031315000, 0.000029355000, 0.000027524000, 0.000025811000,
0.000024209000, 0.000022711000, 0.000021308000, 0.000019994000, 0.000018764000,
0.000017611500, 0.000016532000, 0.000015521000, 0.000014574000, 0.000013686000,
0.000012855000, 0.000012075000, 0.000011345000, 0.000010659000, 0.000010017000,
0.000009413630, 0.000008847900, 0.000008317100, 0.000007819000, 0.000007351600,
0.000006913000, 0.000006501500, 0.000006115300, 0.000005752900, 0.000005412700,
0.000005093470, 0.000004793800, 0.000004512500, 0.000004248300, 0.000004000200,
0.000003767100, 0.000003548000, 0.000003342100, 0.000003148500, 0.000002966500,
0.000002795310, 0.000002634500, 0.000002483400, 0.000002341400, 0.000002207800,
0.000002082000, 0.000001963600, 0.000001851900, 0.000001746500, 0.000001647100,
0.000001553140
}
},
{
471, 360.0, 830.0, /* 471 bands from 360 to 830 nm in 1nm steps */
1.0, /* Scale factor */
{
0.000000013398, 0.000000020294, 0.000000030560, 0.000000045740, 0.000000068050,
0.000000100650, 0.000000147980, 0.000000216270, 0.000000314200, 0.000000453700,
0.000000651100, 0.000000928800, 0.000001317500, 0.000001857200, 0.000002602000,
0.000003625000, 0.000005019000, 0.000006907000, 0.000009449000, 0.000012848000,
0.000017364000, 0.000023327000, 0.000031150000, 0.000041350000, 0.000054560000,
0.000071560000, 0.000093300000, 0.000120870000, 0.000155640000, 0.000199200000,
0.000253400000, 0.000320200000, 0.000402400000, 0.000502300000, 0.000623200000,
0.000768500000, 0.000941700000, 0.001147800000, 0.001390300000, 0.001674000000,
0.002004400000, 0.002386000000, 0.002822000000, 0.003319000000, 0.003880000000,
0.004509000000, 0.005209000000, 0.005985000000, 0.006833000000, 0.007757000000,
0.008756000000, 0.009816000000, 0.010918000000, 0.012058000000, 0.013237000000,
0.014456000000, 0.015717000000, 0.017025000000, 0.018399000000, 0.019848000000,
0.021391000000, 0.022992000000, 0.024598000000, 0.026213000000, 0.027841000000,
0.029497000000, 0.031195000000, 0.032927000000, 0.034738000000, 0.036654000000,
0.038676000000, 0.040792000000, 0.042946000000, 0.045114000000, 0.047333000000,
0.049602000000, 0.051934000000, 0.054337000000, 0.056822000000, 0.059399000000,
0.062077000000, 0.064737000000, 0.067285000000, 0.069764000000, 0.072218000000,
0.074704000000, 0.077272000000, 0.079979000000, 0.082874000000, 0.086000000000,
0.089456000000, 0.092947000000, 0.096275000000, 0.099535000000, 0.102829000000,
0.106256000000, 0.109901000000, 0.113835000000, 0.118167000000, 0.122932000000,
0.128201000000, 0.133457000000, 0.138323000000, 0.143042000000, 0.147787000000,
0.152761000000, 0.158102000000, 0.163941000000, 0.170362000000, 0.177425000000,
0.185190000000, 0.193025000000, 0.200313000000, 0.207156000000, 0.213644000000,
0.219940000000, 0.226170000000, 0.232467000000, 0.239025000000, 0.245997000000,
0.253589000000, 0.261876000000, 0.270643000000, 0.279645000000, 0.288694000000,
0.297665000000, 0.306469000000, 0.315035000000, 0.323335000000, 0.331366000000,
0.339133000000, 0.347860000000, 0.358326000000, 0.370001000000, 0.382464000000,
0.395379000000, 0.408482000000, 0.421588000000, 0.434619000000, 0.447601000000,
0.460777000000, 0.474340000000, 0.488200000000, 0.502340000000, 0.516740000000,
0.531360000000, 0.546190000000, 0.561180000000, 0.576290000000, 0.591500000000,
0.606741000000, 0.622150000000, 0.637830000000, 0.653710000000, 0.669680000000,
0.685660000000, 0.701550000000, 0.717230000000, 0.732570000000, 0.747460000000,
0.761757000000, 0.775340000000, 0.788220000000, 0.800460000000, 0.812140000000,
0.823330000000, 0.834120000000, 0.844600000000, 0.854870000000, 0.865040000000,
0.875211000000, 0.885370000000, 0.895370000000, 0.905150000000, 0.914650000000,
0.923810000000, 0.932550000000, 0.940810000000, 0.948520000000, 0.955600000000,
0.961988000000, 0.967540000000, 0.972230000000, 0.976170000000, 0.979460000000,
0.982200000000, 0.984520000000, 0.986520000000, 0.988320000000, 0.990020000000,
0.991761000000, 0.993530000000, 0.995230000000, 0.996770000000, 0.998090000000,
0.999110000000, 0.999770000000, 1.000000000000, 0.999710000000, 0.998850000000,
0.997340000000, 0.995260000000, 0.992740000000, 0.989750000000, 0.986300000000,
0.982380000000, 0.977980000000, 0.973110000000, 0.967740000000, 0.961890000000,
0.955552000000, 0.948601000000, 0.940981000000, 0.932798000000, 0.924158000000,
0.915175000000, 0.905954000000, 0.896608000000, 0.887249000000, 0.877986000000,
0.868934000000, 0.860164000000, 0.851519000000, 0.842963000000, 0.834393000000,
0.825623000000, 0.816764000000, 0.807544000000, 0.797947000000, 0.787893000000,
0.777405000000, 0.766490000000, 0.755309000000, 0.743845000000, 0.732190000000,
0.720353000000, 0.708281000000, 0.696055000000, 0.683621000000, 0.671048000000,
0.658341000000, 0.645545000000, 0.632718000000, 0.619815000000, 0.606887000000,
0.593878000000, 0.580781000000, 0.567653000000, 0.554490000000, 0.541228000000,
0.527963000000, 0.514634000000, 0.501363000000, 0.488124000000, 0.474935000000,
0.461834000000, 0.448823000000, 0.435917000000, 0.423153000000, 0.410526000000,
0.398057000000, 0.385835000000, 0.373951000000, 0.362311000000, 0.350863000000,
0.339554000000, 0.328309000000, 0.317118000000, 0.305936000000, 0.294737000000,
0.283493000000, 0.272222000000, 0.260990000000, 0.249877000000, 0.238946000000,
0.228254000000, 0.217853000000, 0.207780000000, 0.198072000000, 0.188748000000,
0.179828000000, 0.171285000000, 0.163059000000, 0.155151000000, 0.147535000000,
0.140211000000, 0.133170000000, 0.126400000000, 0.119892000000, 0.113640000000,
0.107633000000, 0.101870000000, 0.096347000000, 0.091063000000, 0.086010000000,
0.081187000000, 0.076583000000, 0.072198000000, 0.068024000000, 0.064052000000,
0.060281000000, 0.056697000000, 0.053292000000, 0.050059000000, 0.046998000000,
0.044096000000, 0.041345000000, 0.038750700000, 0.036297800000, 0.033983200000,
0.031800400000, 0.029739500000, 0.027791800000, 0.025955100000, 0.024226300000,
0.022601700000, 0.021077900000, 0.019650500000, 0.018315300000, 0.017068600000,
0.015905100000, 0.014818300000, 0.013800800000, 0.012849500000, 0.011960700000,
0.011130300000, 0.010355500000, 0.009633200000, 0.008959900000, 0.008332400000,
0.007748800000, 0.007204600000, 0.006697500000, 0.006225100000, 0.005785000000,
0.005375100000, 0.004994100000, 0.004639200000, 0.004309300000, 0.004002800000,
0.003717740000, 0.003452620000, 0.003205830000, 0.002976230000, 0.002762810000,
0.002564560000, 0.002380480000, 0.002209710000, 0.002051320000, 0.001904490000,
0.001768470000, 0.001642360000, 0.001525350000, 0.001416720000, 0.001315950000,
0.001222390000, 0.001135550000, 0.001054940000, 0.000980140000, 0.000910660000,
0.000846190000, 0.000786290000, 0.000730680000, 0.000678990000, 0.000631010000,
0.000586440000, 0.000545110000, 0.000506720000, 0.000471110000, 0.000438050000,
0.000407410000, 0.000378962000, 0.000352543000, 0.000328001000, 0.000305208000,
0.000284041000, 0.000264375000, 0.000246109000, 0.000229143000, 0.000213376000,
0.000198730000, 0.000185115000, 0.000172454000, 0.000160678000, 0.000149730000,
0.000139550000, 0.000130086000, 0.000121290000, 0.000113106000, 0.000105501000,
0.000098428000, 0.000091853000, 0.000085738000, 0.000080048000, 0.000074751000,
0.000069819000, 0.000065222000, 0.000060939000, 0.000056942000, 0.000053217000,
0.000049737000, 0.000046491000, 0.000043464000, 0.000040635000, 0.000038000000,
0.000035540500, 0.000033244800, 0.000031100600, 0.000029099000, 0.000027230700,
0.000025486000, 0.000023856100, 0.000022333200, 0.000020910400, 0.000019580800,
0.000018338400, 0.000017177700, 0.000016093400, 0.000015080000, 0.000014133600,
0.000013249000, 0.000012422600, 0.000011649900, 0.000010927700, 0.000010251900,
0.000009619600, 0.000009028100, 0.000008474000, 0.000007954800, 0.000007468600,
0.000007012800, 0.000006585800, 0.000006185700, 0.000005810700, 0.000005459000,
0.000005129800, 0.000004820600, 0.000004531200, 0.000004259100, 0.000004004200,
0.000003764730, 0.000003539950, 0.000003329140, 0.000003131150, 0.000002945290,
0.000002770810, 0.000002607050, 0.000002453290, 0.000002308940, 0.000002173380,
0.000002046130, 0.000001926620, 0.000001814400, 0.000001708950, 0.000001609880,
0.000001516770, 0.000001429210, 0.000001346860, 0.000001269450, 0.000001196620,
0.000001128090, 0.000001063680, 0.000001003130, 0.000000946220, 0.000000892630,
0.000000842160, 0.000000794640, 0.000000749780, 0.000000707440, 0.000000667480,
0.000000629700
}
},
{
471, 360.0, 830.0, /* 471 bands from 360 to 830 nm in 1nm steps */
1.0, /* Scale factor */
{
0.000000535027, 0.000000810720, 0.000001221200, 0.000001828700, 0.000002722200,
0.000004028300, 0.000005925700, 0.000008665100, 0.000012596000, 0.000018201000,
0.000026143700, 0.000037330000, 0.000052987000, 0.000074764000, 0.000104870000,
0.000146220000, 0.000202660000, 0.000279230000, 0.000382450000, 0.000520720000,
0.000704776000, 0.000948230000, 0.001268200000, 0.001686100000, 0.002228500000,
0.002927800000, 0.003823700000, 0.004964200000, 0.006406700000, 0.008219300000,
0.010482200000, 0.013289000000, 0.016747000000, 0.020980000000, 0.026127000000,
0.032344000000, 0.039802000000, 0.048691000000, 0.059210000000, 0.071576000000,
0.086010900000, 0.102740000000, 0.122000000000, 0.144020000000, 0.168990000000,
0.197120000000, 0.228570000000, 0.263470000000, 0.301900000000, 0.343870000000,
0.389366000000, 0.437970000000, 0.489220000000, 0.542900000000, 0.598810000000,
0.656760000000, 0.716580000000, 0.778120000000, 0.841310000000, 0.906110000000,
0.972542000000, 1.038900000000, 1.103100000000, 1.165100000000, 1.224900000000,
1.282500000000, 1.338200000000, 1.392600000000, 1.446100000000, 1.499400000000,
1.553480000000, 1.607200000000, 1.658900000000, 1.708200000000, 1.754800000000,
1.798500000000, 1.839200000000, 1.876600000000, 1.910500000000, 1.940800000000,
1.967280000000, 1.989100000000, 2.005700000000, 2.017400000000, 2.024400000000,
2.027300000000, 2.026400000000, 2.022300000000, 2.015300000000, 2.006000000000,
1.994800000000, 1.981400000000, 1.965300000000, 1.946400000000, 1.924800000000,
1.900700000000, 1.874100000000, 1.845100000000, 1.813900000000, 1.780600000000,
1.745370000000, 1.709100000000, 1.672300000000, 1.634700000000, 1.595600000000,
1.554900000000, 1.512200000000, 1.467300000000, 1.419900000000, 1.370000000000,
1.317560000000, 1.262400000000, 1.205000000000, 1.146600000000, 1.088000000000,
1.030200000000, 0.973830000000, 0.919430000000, 0.867460000000, 0.818280000000,
0.772125000000, 0.728290000000, 0.686040000000, 0.645530000000, 0.606850000000,
0.570060000000, 0.535220000000, 0.502340000000, 0.471400000000, 0.442390000000,
0.415254000000, 0.390024000000, 0.366399000000, 0.344015000000, 0.322689000000,
0.302356000000, 0.283036000000, 0.264816000000, 0.247848000000, 0.232318000000,
0.218502000000, 0.205851000000, 0.193596000000, 0.181736000000, 0.170281000000,
0.159249000000, 0.148673000000, 0.138609000000, 0.129096000000, 0.120215000000,
0.112044000000, 0.104710000000, 0.098196000000, 0.092361000000, 0.087088000000,
0.082248000000, 0.077744000000, 0.073456000000, 0.069268000000, 0.065060000000,
0.060709000000, 0.056457000000, 0.052609000000, 0.049122000000, 0.045954000000,
0.043050000000, 0.040368000000, 0.037839000000, 0.035384000000, 0.032949000000,
0.030451000000, 0.028029000000, 0.025862000000, 0.023920000000, 0.022174000000,
0.020584000000, 0.019127000000, 0.017740000000, 0.016403000000, 0.015064000000,
0.013676000000, 0.012308000000, 0.011056000000, 0.009915000000, 0.008872000000,
0.007918000000, 0.007030000000, 0.006223000000, 0.005453000000, 0.004714000000,
0.003988000000, 0.003289000000, 0.002646000000, 0.002063000000, 0.001533000000,
0.001091000000, 0.000711000000, 0.000407000000, 0.000184000000, 0.000047000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,
0.000000000000
}
}
};
#ifndef SALONEINSTLIB
/* Standard CIE 1964 10 degree observer, */
/* adjusted for compatibility with 2 degree observer. */
/* This has a problem in that it will return -ve XYZ values !! */
static xspect ob_CIE_1964_10c[3] = {
{
471, 360.0, 830.0, /* 471 bands from 360 to 830 nm in 1nm steps */
1.0, /* Scale factor */
{
0.000000, 0.000000, 0.000000, 0.000000, 0.000001,
0.000001, 0.000001, 0.000002, 0.000003, 0.000004,
0.000006, 0.000008, 0.000012, 0.000016, 0.000023,
0.000032, 0.000044, 0.000061, 0.000083, 0.000114,
0.000154, 0.000207, 0.000276, 0.000367, 0.000485,
0.000636, 0.000830, 0.001077, 0.001389, 0.001780,
0.002268, 0.002872, 0.003616, 0.004524, 0.005626,
0.006956, 0.008547, 0.010440, 0.012675, 0.015297,
0.018351, 0.021882, 0.025937, 0.030562, 0.035793,
0.041670, 0.048218, 0.055455, 0.063395, 0.072026,
0.081334, 0.091218, 0.101571, 0.112339, 0.123475,
0.134934, 0.146676, 0.158671, 0.170901, 0.183362,
0.196059, 0.208632, 0.220678, 0.232166, 0.243106,
0.253521, 0.263459, 0.273052, 0.282379, 0.291584,
0.300858, 0.309993, 0.318677, 0.326834, 0.334402,
0.341323, 0.347615, 0.353171, 0.357967, 0.361976,
0.365148, 0.367370, 0.368575, 0.368826, 0.368155,
0.366675, 0.364435, 0.361545, 0.358052, 0.354057,
0.349627, 0.344810, 0.339593, 0.333917, 0.327752,
0.321095, 0.313902, 0.306154, 0.297863, 0.289008,
0.279595, 0.269978, 0.260456, 0.250851, 0.240930,
0.230604, 0.219745, 0.208345, 0.196419, 0.183863,
0.170973, 0.158090, 0.145040, 0.131973, 0.119113,
0.106660, 0.094739, 0.083435, 0.072806, 0.062881,
0.053655, 0.044761, 0.035965, 0.027445, 0.019347,
0.011775, 0.004818, -0.001448, -0.006980, -0.011730,
-0.015680, -0.019142, -0.022434, -0.025515, -0.028335,
-0.030850, -0.033009, -0.034770, -0.036095, -0.036941,
-0.037294, -0.037113, -0.036399, -0.035191, -0.033525,
-0.031433, -0.028948, -0.026100, -0.022920, -0.019440,
-0.015700, -0.011512, -0.006687, -0.001238, 0.004822,
0.011455, 0.018627, 0.026279, 0.034335, 0.042701,
0.051262, 0.060174, 0.069663, 0.079658, 0.090158,
0.101084, 0.112386, 0.124002, 0.135873, 0.147891,
0.160018, 0.172256, 0.184702, 0.197370, 0.210271,
0.223389, 0.236747, 0.250340, 0.264164, 0.278208,
0.292463, 0.306856, 0.321322, 0.335886, 0.350539,
0.365327, 0.380281, 0.395429, 0.410820, 0.426495,
0.442517, 0.458930, 0.475719, 0.492834, 0.510231,
0.527852, 0.545635, 0.563512, 0.581404, 0.599231,
0.616897, 0.634569, 0.652440, 0.670431, 0.688482,
0.706512, 0.724440, 0.742190, 0.759656, 0.776754,
0.793379, 0.809482, 0.825090, 0.840216, 0.854883,
0.869139, 0.883013, 0.896564, 0.909854, 0.922934,
0.935926, 0.948983, 0.961990, 0.974889, 0.987491,
0.999611, 1.011241, 1.022004, 1.031804, 1.040446,
1.047851, 1.054056, 1.059207, 1.063287, 1.066386,
1.068504, 1.069546, 1.069604, 1.068584, 1.066579,
1.063578, 1.059609, 1.054735, 1.048871, 1.042112,
1.034363, 1.025625, 1.015993, 1.005466, 0.993951,
0.981619, 0.968336, 0.954330, 0.939514, 0.923995,
0.907841, 0.891082, 0.873794, 0.856007, 0.837798,
0.819205, 0.800376, 0.781406, 0.762235, 0.742849,
0.723211, 0.703308, 0.683132, 0.662676, 0.641942,
0.620930, 0.599617, 0.578068, 0.556470, 0.534965,
0.513699, 0.492797, 0.472355, 0.452479, 0.433228,
0.414667, 0.396767, 0.379415, 0.362613, 0.346305,
0.330490, 0.315149, 0.300263, 0.285813, 0.271789,
0.258182, 0.244984, 0.232213, 0.219890, 0.208026,
0.196640, 0.185723, 0.175297, 0.165350, 0.155874,
0.146878, 0.138317, 0.130168, 0.122403, 0.115042,
0.108045, 0.101405, 0.095126, 0.089181, 0.083563,
0.078256, 0.073238, 0.068488, 0.064001, 0.059773,
0.055794, 0.052058, 0.048555, 0.045275, 0.042210,
0.039347, 0.036671, 0.034163, 0.031816, 0.029622,
0.027571, 0.025656, 0.023870, 0.022205, 0.020653,
0.019209, 0.017863, 0.016608, 0.015438, 0.014349,
0.013334, 0.012390, 0.011510, 0.010693, 0.009933,
0.009225, 0.008568, 0.007955, 0.007385, 0.006855,
0.006363, 0.005906, 0.005481, 0.005088, 0.004723,
0.004385, 0.004072, 0.003782, 0.003512, 0.003261,
0.003029, 0.002813, 0.002613, 0.002428, 0.002255,
0.002095, 0.001946, 0.001808, 0.001680, 0.001561,
0.001450, 0.001348, 0.001253, 0.001164, 0.001082,
0.001006, 0.000936, 0.000870, 0.000809, 0.000753,
0.000701, 0.000652, 0.000607, 0.000565, 0.000526,
0.000489, 0.000456, 0.000425, 0.000395, 0.000368,
0.000343, 0.000320, 0.000298, 0.000278, 0.000259,
0.000242, 0.000225, 0.000210, 0.000196, 0.000183,
0.000171, 0.000160, 0.000149, 0.000139, 0.000130,
0.000122, 0.000114, 0.000106, 0.000099, 0.000093,
0.000087, 0.000081, 0.000076, 0.000071, 0.000066,
0.000062, 0.000058, 0.000054, 0.000051, 0.000048,
0.000045, 0.000042, 0.000039, 0.000037, 0.000034,
0.000032, 0.000030, 0.000028, 0.000026, 0.000025,
0.000023, 0.000022, 0.000021, 0.000019, 0.000018,
0.000017, 0.000016, 0.000015, 0.000014, 0.000013,
0.000012, 0.000012, 0.000011, 0.000010, 0.000010,
0.000009, 0.000009, 0.000008, 0.000008, 0.000007,
0.000007, 0.000006, 0.000006, 0.000006, 0.000005,
0.000005, 0.000005, 0.000004, 0.000004, 0.000004,
0.000004, 0.000003, 0.000003, 0.000003, 0.000003,
0.000003, 0.000003, 0.000002, 0.000002, 0.000002,
0.000002, 0.000002, 0.000002, 0.000002, 0.000002,
0.000001
}
},
{
471, 360.0, 830.0, /* 471 bands from 360 to 830 nm in 1nm steps */
1.0, /* Scale factor */
{
-0.000000, -0.000000, -0.000000, -0.000000, -0.000000,
-0.000000, -0.000000, -0.000000, -0.000000, -0.000000,
-0.000000, -0.000000, -0.000001, -0.000001, -0.000001,
-0.000002, -0.000003, -0.000004, -0.000005, -0.000007,
-0.000009, -0.000012, -0.000017, -0.000022, -0.000029,
-0.000039, -0.000051, -0.000066, -0.000086, -0.000111,
-0.000142, -0.000181, -0.000229, -0.000289, -0.000362,
-0.000452, -0.000560, -0.000690, -0.000845, -0.001028,
-0.001243, -0.001494, -0.001786, -0.002121, -0.002505,
-0.002940, -0.003430, -0.003976, -0.004584, -0.005251,
-0.005978, -0.006763, -0.007608, -0.008509, -0.009457,
-0.010445, -0.011465, -0.012506, -0.013548, -0.014581,
-0.015588, -0.016540, -0.017410, -0.018194, -0.018887,
-0.019474, -0.019954, -0.020356, -0.020652, -0.020844,
-0.020966, -0.020987, -0.020899, -0.020710, -0.020374,
-0.019885, -0.019227, -0.018381, -0.017329, -0.016059,
-0.014554, -0.012894, -0.011147, -0.009284, -0.007270,
-0.005073, -0.002659, 0.000006, 0.002956, 0.006209,
0.009845, 0.013596, 0.017297, 0.021039, 0.024915,
0.029010, 0.033403, 0.038157, 0.043368, 0.049064,
0.055306, 0.061573, 0.067495, 0.073309, 0.079203,
0.085372, 0.091959, 0.099098, 0.106881, 0.115363,
0.124611, 0.134041, 0.143043, 0.151664, 0.159962,
0.168055, 0.176039, 0.184021, 0.192166, 0.200605,
0.209524, 0.219014, 0.228895, 0.238933, 0.248950,
0.258827, 0.268480, 0.277842, 0.286890, 0.295622,
0.304046, 0.313314, 0.324171, 0.336130, 0.348800,
0.361865, 0.375076, 0.388254, 0.401320, 0.414291,
0.427388, 0.440818, 0.454528, 0.468501, 0.482717,
0.497136, 0.511747, 0.526497, 0.541348, 0.556275,
0.571209, 0.586279, 0.601590, 0.617079, 0.632648,
0.648223, 0.663715, 0.679010, 0.693991, 0.708553,
0.722563, 0.735901, 0.748570, 0.760630, 0.772158,
0.783222, 0.793907, 0.804300, 0.814498, 0.824603,
0.834716, 0.844817, 0.854762, 0.864494, 0.873959,
0.883100, 0.891844, 0.900135, 0.907907, 0.915088,
0.921619, 0.927360, 0.932278, 0.936482, 0.940066,
0.943128, 0.945794, 0.948157, 0.950335, 0.952425,
0.954563, 0.956738, 0.958855, 0.960827, 0.962596,
0.964083, 0.965229, 0.965966, 0.966206, 0.965899,
0.964967, 0.963491, 0.961602, 0.959270, 0.956503,
0.953289, 0.949616, 0.945492, 0.940884, 0.935810,
0.930259, 0.924111, 0.917313, 0.909967, 0.902174,
0.894043, 0.885675, 0.877179, 0.868664, 0.860233,
0.852001, 0.844039, 0.836194, 0.828430, 0.820645,
0.812656, 0.804568, 0.796113, 0.787273, 0.777966,
0.768211, 0.758017, 0.747540, 0.736765, 0.725779,
0.714594, 0.703154, 0.691541, 0.679699, 0.667698,
0.655540, 0.643271, 0.630947, 0.618523, 0.606050,
0.593471, 0.580782, 0.568037, 0.555234, 0.542308,
0.529357, 0.516318, 0.503314, 0.490317, 0.477348,
0.464445, 0.451610, 0.438859, 0.426230, 0.413718,
0.401346, 0.389202, 0.377375, 0.365775, 0.354350,
0.343050, 0.331804, 0.320601, 0.309399, 0.298173,
0.286897, 0.275586, 0.264305, 0.253136, 0.242143,
0.231384, 0.220911, 0.210763, 0.200977, 0.191575,
0.182575, 0.173953, 0.165647, 0.157658, 0.149962,
0.142556, 0.135433, 0.128580, 0.121988, 0.115652,
0.109560, 0.103711, 0.098103, 0.092734, 0.087598,
0.082694, 0.078011, 0.073550, 0.069303, 0.065262,
0.061425, 0.057778, 0.054312, 0.051021, 0.047905,
0.044950, 0.042148, 0.039506, 0.037007, 0.034649,
0.032426, 0.030326, 0.028341, 0.026469, 0.024707,
0.023051, 0.021498, 0.020042, 0.018681, 0.017410,
0.016224, 0.015115, 0.014078, 0.013108, 0.012201,
0.011354, 0.010564, 0.009827, 0.009140, 0.008500,
0.007905, 0.007350, 0.006833, 0.006351, 0.005902,
0.005484, 0.005095, 0.004733, 0.004397, 0.004084,
0.003793, 0.003523, 0.003271, 0.003036, 0.002819,
0.002616, 0.002429, 0.002254, 0.002093, 0.001943,
0.001804, 0.001676, 0.001556, 0.001445, 0.001342,
0.001247, 0.001158, 0.001076, 0.001000, 0.000929,
0.000863, 0.000802, 0.000745, 0.000693, 0.000644,
0.000598, 0.000556, 0.000517, 0.000481, 0.000447,
0.000416, 0.000387, 0.000360, 0.000335, 0.000311,
0.000290, 0.000270, 0.000251, 0.000234, 0.000218,
0.000203, 0.000189, 0.000176, 0.000164, 0.000153,
0.000142, 0.000133, 0.000124, 0.000115, 0.000108,
0.000100, 0.000094, 0.000087, 0.000082, 0.000076,
0.000071, 0.000066, 0.000062, 0.000058, 0.000054,
0.000051, 0.000047, 0.000044, 0.000041, 0.000039,
0.000036, 0.000034, 0.000032, 0.000030, 0.000028,
0.000026, 0.000024, 0.000023, 0.000021, 0.000020,
0.000019, 0.000018, 0.000016, 0.000015, 0.000014,
0.000013, 0.000013, 0.000012, 0.000011, 0.000010,
0.000010, 0.000009, 0.000009, 0.000008, 0.000008,
0.000007, 0.000007, 0.000006, 0.000006, 0.000006,
0.000005, 0.000005, 0.000005, 0.000004, 0.000004,
0.000004, 0.000004, 0.000003, 0.000003, 0.000003,
0.000003, 0.000003, 0.000002, 0.000002, 0.000002,
0.000002, 0.000002, 0.000002, 0.000002, 0.000002,
0.000002, 0.000001, 0.000001, 0.000001, 0.000001,
0.000001, 0.000001, 0.000001, 0.000001, 0.000001,
0.000001, 0.000001, 0.000001, 0.000001, 0.000001,
0.000001
}
},
{
471, 360.0, 830.0, /* 471 bands from 360 to 830 nm in 1nm steps */
1.0, /* Scale factor */
{
0.000000, 0.000001, 0.000001, 0.000002, 0.000002,
0.000004, 0.000005, 0.000008, 0.000011, 0.000017,
0.000024, 0.000034, 0.000048, 0.000068, 0.000095,
0.000133, 0.000184, 0.000253, 0.000347, 0.000473,
0.000640, 0.000861, 0.001151, 0.001530, 0.002023,
0.002657, 0.003470, 0.004505, 0.005815, 0.007460,
0.009514, 0.012061, 0.015200, 0.019042, 0.023714,
0.029357, 0.036126, 0.044195, 0.053743, 0.064968,
0.078071, 0.093257, 0.110741, 0.130730, 0.153398,
0.178935, 0.207487, 0.239172, 0.274063, 0.312169,
0.353478, 0.397611, 0.444150, 0.492897, 0.543671,
0.596302, 0.650635, 0.706534, 0.763936, 0.822806,
0.883165, 0.943463, 1.001808, 1.058162, 1.112525,
1.164898, 1.215552, 1.265032, 1.313703, 1.362201,
1.411414, 1.460308, 1.507373, 1.552264, 1.594709,
1.634529, 1.671632, 1.705747, 1.736693, 1.764380,
1.788610, 1.808612, 1.823873, 1.834684, 1.841230,
1.844058, 1.843442, 1.839930, 1.833797, 1.825590,
1.815677, 1.803767, 1.789396, 1.772476, 1.753107,
1.731476, 1.707589, 1.681541, 1.653519, 1.623619,
1.591997, 1.559431, 1.526359, 1.492551, 1.457384,
1.420779, 1.382383, 1.342017, 1.299412, 1.254573,
1.207456, 1.157853, 1.106181, 1.053574, 1.000759,
0.948651, 0.897828, 0.848786, 0.801953, 0.757664,
0.716144, 0.676765, 0.638856, 0.602538, 0.567881,
0.534929, 0.503728, 0.474283, 0.446572, 0.420583,
0.396265, 0.373716, 0.352709, 0.332886, 0.314056,
0.296143, 0.279152, 0.263152, 0.248277, 0.234696,
0.222673, 0.211713, 0.201107, 0.190856, 0.180969,
0.171463, 0.162367, 0.153733, 0.145596, 0.138030,
0.131104, 0.124934, 0.119502, 0.114675, 0.110342,
0.106383, 0.102706, 0.099197, 0.095748, 0.092248,
0.088582, 0.084959, 0.081651, 0.078623, 0.075842,
0.073262, 0.070852, 0.068555, 0.066306, 0.064065,
0.061762, 0.059523, 0.057502, 0.055668, 0.053992,
0.052433, 0.050967, 0.049534, 0.048112, 0.046651,
0.045104, 0.043532, 0.042023, 0.040577, 0.039188,
0.037849, 0.036544, 0.035292, 0.034054, 0.032828,
0.031603, 0.030388, 0.029205, 0.028058, 0.026937,
0.025874, 0.024845, 0.023862, 0.022928, 0.022050,
0.021230, 0.020427, 0.019595, 0.018738, 0.017856,
0.016954, 0.016034, 0.015099, 0.014153, 0.013199,
0.012241, 0.011277, 0.010301, 0.009319, 0.008334,
0.007350, 0.006370, 0.005397, 0.004434, 0.003484,
0.002547, 0.001621, 0.000702, -0.000208, -0.001107,
-0.001996, -0.002870, -0.003725, -0.004559, -0.005368,
-0.006147, -0.006898, -0.007619, -0.008311, -0.008971,
-0.009601, -0.010199, -0.010764, -0.011296, -0.011794,
-0.012259, -0.012690, -0.013085, -0.013445, -0.013769,
-0.014058, -0.014311, -0.014530, -0.014715, -0.014865,
-0.014982, -0.015064, -0.015114, -0.015131, -0.015117,
-0.015074, -0.015002, -0.014904, -0.014780, -0.014633,
-0.014462, -0.014272, -0.014059, -0.013828, -0.013579,
-0.013314, -0.013035, -0.012743, -0.012439, -0.012124,
-0.011801, -0.011467, -0.011122, -0.010769, -0.010411,
-0.010052, -0.009695, -0.009340, -0.008992, -0.008650,
-0.008318, -0.007995, -0.007679, -0.007371, -0.007069,
-0.006773, -0.006483, -0.006199, -0.005920, -0.005647,
-0.005378, -0.005116, -0.004859, -0.004609, -0.004366,
-0.004133, -0.003908, -0.003692, -0.003486, -0.003290,
-0.003104, -0.002926, -0.002757, -0.002595, -0.002441,
-0.002294, -0.002155, -0.002023, -0.001898, -0.001780,
-0.001668, -0.001562, -0.001462, -0.001367, -0.001277,
-0.001193, -0.001113, -0.001039, -0.000969, -0.000904,
-0.000843, -0.000786, -0.000732, -0.000682, -0.000635,
-0.000591, -0.000550, -0.000512, -0.000476, -0.000443,
-0.000412, -0.000383, -0.000356, -0.000331, -0.000308,
-0.000286, -0.000266, -0.000247, -0.000230, -0.000213,
-0.000198, -0.000184, -0.000171, -0.000159, -0.000147,
-0.000137, -0.000127, -0.000118, -0.000109, -0.000101,
-0.000094, -0.000087, -0.000081, -0.000075, -0.000070,
-0.000065, -0.000060, -0.000056, -0.000052, -0.000048,
-0.000045, -0.000042, -0.000039, -0.000036, -0.000033,
-0.000031, -0.000029, -0.000027, -0.000025, -0.000023,
-0.000022, -0.000020, -0.000019, -0.000017, -0.000016,
-0.000015, -0.000014, -0.000013, -0.000012, -0.000011,
-0.000010, -0.000010, -0.000009, -0.000008, -0.000008,
-0.000007, -0.000007, -0.000006, -0.000006, -0.000006,
-0.000005, -0.000005, -0.000004, -0.000004, -0.000004,
-0.000004, -0.000003, -0.000003, -0.000003, -0.000003,
-0.000003, -0.000002, -0.000002, -0.000002, -0.000002,
-0.000002, -0.000002, -0.000002, -0.000002, -0.000001,
-0.000001, -0.000001, -0.000001, -0.000001, -0.000001,
-0.000001, -0.000001, -0.000001, -0.000001, -0.000001,
-0.000001, -0.000001, -0.000001, -0.000001, -0.000001,
-0.000000, -0.000000, -0.000000, -0.000000, -0.000000,
-0.000000, -0.000000, -0.000000, -0.000000, -0.000000,
-0.000000, -0.000000, -0.000000, -0.000000, -0.000000,
-0.000000, -0.000000, -0.000000, -0.000000, -0.000000,
-0.000000, -0.000000, -0.000000, -0.000000, -0.000000,
-0.000000, -0.000000, -0.000000, -0.000000, -0.000000,
-0.000000, -0.000000, -0.000000, -0.000000, -0.000000,
-0.000000, -0.000000, -0.000000, -0.000000, -0.000000,
-0.000000, -0.000000, -0.000000, -0.000000, -0.000000,
-0.000000
}
}
};
/* Judd & Voss 1978 2 degree */
static xspect ob_Judd_Voss_2[3] = {
{
90, 380.0, 825.0, /* 90 bands from 380 to 825 nm in 5nm steps */
1.0, /* Scale factor */
{
2.689900e-003, 5.310500e-003, 1.078100e-002, 2.079200e-002, 3.798100e-002,
6.315700e-002, 9.994100e-002, 1.582400e-001, 2.294800e-001, 2.810800e-001,
3.109500e-001, 3.307200e-001, 3.333600e-001, 3.167200e-001, 2.888200e-001,
2.596900e-001, 2.327600e-001, 2.099900e-001, 1.747600e-001, 1.328700e-001,
9.194400e-002, 5.698500e-002, 3.173100e-002, 1.461300e-002, 4.849100e-003,
2.321500e-003, 9.289900e-003, 2.927800e-002, 6.379100e-002, 1.108100e-001,
1.669200e-001, 2.276800e-001, 2.926900e-001, 3.622500e-001, 4.363500e-001,
5.151300e-001, 5.974800e-001, 6.812100e-001, 7.642500e-001, 8.439400e-001,
9.163500e-001, 9.770300e-001, 1.023000e+000, 1.051300e+000, 1.055000e+000,
1.036200e+000, 9.923900e-001, 9.286100e-001, 8.434600e-001, 7.398300e-001,
6.328900e-001, 5.335100e-001, 4.406200e-001, 3.545300e-001, 2.786200e-001,
2.148500e-001, 1.616100e-001, 1.182000e-001, 8.575300e-002, 6.307700e-002,
4.583400e-002, 3.205700e-002, 2.218700e-002, 1.561200e-002, 1.109800e-002,
7.923300e-003, 5.653100e-003, 4.003900e-003, 2.825300e-003, 1.994700e-003,
1.399400e-003, 9.698000e-004, 6.684700e-004, 4.614100e-004, 3.207300e-004,
2.257300e-004, 1.597300e-004, 1.127500e-004, 7.951300e-005, 5.608700e-005,
3.954100e-005, 2.785200e-005, 1.959700e-005, 1.377000e-005, 9.670000e-006,
6.791800e-006, 4.770600e-006, 3.355000e-006, 2.353400e-006, 1.637700e-006
}
},
{
90, 380.0, 825.0, /* 90 bands from 380 to 825 nm in 5nm steps */
1.0, /* Scale factor */
{
2.000000e-004, 3.955600e-004, 8.000000e-004, 1.545700e-003, 2.800000e-003,
4.656200e-003, 7.400000e-003, 1.177900e-002, 1.750000e-002, 2.267800e-002,
2.730000e-002, 3.258400e-002, 3.790000e-002, 4.239100e-002, 4.680000e-002,
5.212200e-002, 6.000000e-002, 7.294200e-002, 9.098000e-002, 1.128400e-001,
1.390200e-001, 1.698700e-001, 2.080200e-001, 2.580800e-001, 3.230000e-001,
4.054000e-001, 5.030000e-001, 6.081100e-001, 7.100000e-001, 7.951000e-001,
8.620000e-001, 9.150500e-001, 9.540000e-001, 9.800400e-001, 9.949500e-001,
1.000100e+000, 9.950000e-001, 9.787500e-001, 9.520000e-001, 9.155800e-001,
8.700000e-001, 8.162300e-001, 7.570000e-001, 6.948300e-001, 6.310000e-001,
5.665400e-001, 5.030000e-001, 4.417200e-001, 3.810000e-001, 3.205200e-001,
2.650000e-001, 2.170200e-001, 1.750000e-001, 1.381200e-001, 1.070000e-001,
8.165200e-002, 6.100000e-002, 4.432700e-002, 3.200000e-002, 2.345400e-002,
1.700000e-002, 1.187200e-002, 8.210000e-003, 5.772300e-003, 4.102000e-003,
2.929100e-003, 2.091000e-003, 1.482200e-003, 1.047000e-003, 7.401500e-004,
5.200000e-004, 3.609300e-004, 2.492000e-004, 1.723100e-004, 1.200000e-004,
8.462000e-005, 6.000000e-005, 4.244600e-005, 3.000000e-005, 2.121000e-005,
1.498900e-005, 1.058400e-005, 7.465600e-006, 5.259200e-006, 3.702800e-006,
2.607600e-006, 1.836500e-006, 1.295000e-006, 9.109200e-007, 6.356400e-007
}
},
{
90, 380.0, 825.0, /* 90 bands from 380 to 825 nm in 5nm steps */
1.0, /* Scale factor */
{
1.226000e-002, 2.422200e-002, 4.925000e-002, 9.513500e-002, 1.740900e-001,
2.901300e-001, 4.605300e-001, 7.316600e-001, 1.065800e+000, 1.314600e+000,
1.467200e+000, 1.579600e+000, 1.616600e+000, 1.568200e+000, 1.471700e+000,
1.374000e+000, 1.291700e+000, 1.235600e+000, 1.113800e+000, 9.422000e-001,
7.559600e-001, 5.864000e-001, 4.466900e-001, 3.411600e-001, 2.643700e-001,
2.059400e-001, 1.544500e-001, 1.091800e-001, 7.658500e-002, 5.622700e-002,
4.136600e-002, 2.935300e-002, 2.004200e-002, 1.331200e-002, 8.782300e-003,
5.857300e-003, 4.049300e-003, 2.921700e-003, 2.277100e-003, 1.970600e-003,
1.806600e-003, 1.544900e-003, 1.234800e-003, 1.117700e-003, 9.056400e-004,
6.946700e-004, 4.288500e-004, 3.181700e-004, 2.559800e-004, 1.567900e-004,
9.769400e-005, 6.894400e-005, 5.116500e-005, 3.601600e-005, 2.423800e-005,
1.691500e-005, 1.190600e-005, 8.148900e-006, 5.600600e-006, 3.954400e-006,
2.791200e-006, 1.917600e-006, 1.313500e-006, 9.151900e-007, 6.476700e-007,
4.635200e-007, 3.330400e-007, 2.382300e-007, 1.702600e-007, 1.220700e-007,
8.710700e-008, 6.145500e-008, 4.316200e-008, 3.037900e-008, 2.155400e-008,
1.549300e-008, 1.120400e-008, 8.087300e-009, 5.834000e-009, 4.211000e-009,
3.038300e-009, 2.190700e-009, 1.577800e-009, 1.134800e-009, 8.156500e-010,
5.862600e-010, 4.213800e-010, 3.031900e-010, 2.175300e-010, 1.547600e-010
}
}
};
/* Stiles & Burch 1955 2 degree, */
/* rotated to align with 1931 XYZ space, */
/* using Mark Shaw's matrix. */
static xspect ob_Stiles_Burch_2[3] = {
{
69, 390.0, 730.0, /* 69 bands from 390 to 730 nm in 5nm steps */
1.0, /* Scale factor */
{
0.005035, 0.012873, 0.025933, 0.054264, 0.093147,
0.144597, 0.207609, 0.266538, 0.303933, 0.336185,
0.356549, 0.364180, 0.328209, 0.286053, 0.262928,
0.210562, 0.182549, 0.131014, 0.081974, 0.045980,
0.020673, 0.008302, 0.004814, 0.008248, 0.024412,
0.050113, 0.084255, 0.131255, 0.186757, 0.243224,
0.298768, 0.359848, 0.428510, 0.500880, 0.571271,
0.650846, 0.742250, 0.829040, 0.905369, 0.971275,
1.024797, 1.060952, 1.071632, 1.054762, 1.012750,
0.947501, 0.861487, 0.761200, 0.654122, 0.548338,
0.450269, 0.361237, 0.281687, 0.213565, 0.158588,
0.115934, 0.083874, 0.060355, 0.043191, 0.030661,
0.021532, 0.014822, 0.010047, 0.006832, 0.004755,
0.003363, 0.002330, 0.001623, 0.001136
}
},
{
69, 390.0, 730.0, /* 69 bands from 390 to 730 nm in 5nm steps */
1.0, /* Scale factor */
{
0.000021, 0.000137, 0.000267, 0.000499, 0.000959,
-0.000352, -0.000535, -0.002306, -0.001139, 0.001507,
0.007142, 0.012389, 0.022879, 0.037200, 0.054616,
0.080087, 0.108008, 0.140411, 0.170719, 0.199791,
0.240641, 0.297681, 0.367645, 0.455184, 0.546333,
0.641762, 0.736259, 0.813393, 0.873858, 0.911828,
0.931983, 0.954960, 0.971754, 0.970171, 0.950790,
0.937240, 0.932444, 0.903026, 0.857070, 0.815886,
0.769666, 0.712437, 0.651257, 0.588631, 0.523557,
0.457801, 0.393963, 0.332964, 0.275541, 0.223722,
0.179091, 0.140943, 0.108310, 0.081218, 0.059780,
0.043398, 0.031238, 0.022406, 0.016003, 0.011340,
0.007953, 0.005473, 0.003713, 0.002527, 0.001759,
0.001244, 0.000863, 0.000602, 0.000422
}
},
{
69, 390.0, 730.0, /* 69 bands from 390 to 730 nm in 5nm steps */
1.0, /* Scale factor */
{
0.023163, 0.059308, 0.118897, 0.250907, 0.433765,
0.684409, 0.999185, 1.308097, 1.518706, 1.707302,
1.840521, 1.906560, 1.756384, 1.578949, 1.505983,
1.283002, 1.178612, 0.947751, 0.709500, 0.529689,
0.398963, 0.310980, 0.240664, 0.188969, 0.145151,
0.110796, 0.087421, 0.069953, 0.059951, 0.051960,
0.042905, 0.037710, 0.033821, 0.028764, 0.023371,
0.018909, 0.015103, 0.009656, 0.003595, -0.001221,
-0.005978, -0.010905, -0.014270, -0.016302, -0.018412,
-0.019889, -0.019510, -0.017854, -0.015815, -0.013632,
-0.011388, -0.009171, -0.007076, -0.005238, -0.003775,
-0.002692, -0.001946, -0.001447, -0.001074, -0.000766,
-0.000527, -0.000357, -0.000242, -0.000164, -0.000113,
-0.000077, -0.000051, -0.000034, -0.000023
}
}
};
/* Shaw & Fairchild 1997 2 degree observer. */
/* From Mark Shaw's Masters thesis: */
/* "Evaluating the 1931 CIE Color Matching Functions" */
static xspect ob_Shaw_Fairchild_2[3] = {
{
61, 400.0, 700.0, /* 61 bands from 400 to 700 nm in 5nm steps */
1.0, /* Scale factor */
{
0.050035085, 0.10599540, 0.17570524, 0.26369069, 0.34385256,
0.36314044, 0.35022338, 0.35921696, 0.37057582, 0.37027683,
0.31092719, 0.24467905, 0.21495057, 0.16408854, 0.15609086,
0.10496585, 0.053550350, 0.016029866, -0.010473666, -0.020635411,
-0.020599591, -0.010774255, 0.013507015, 0.045305699, 0.082609321,
0.13244251, 0.18966495, 0.24710489, 0.30272442, 0.36362744,
0.43329425, 0.50816654, 0.57883305, 0.66085495, 0.75701632,
0.84336950, 0.91608703, 0.98348582, 1.0386456, 1.0699974,
1.0751974, 1.0492333, 1.0010173, 0.92955516, 0.83907524,
0.74332961, 0.64179542, 0.53031723, 0.42814376, 0.34048130,
0.26368241, 0.19677558, 0.14402031, 0.10472063, 0.076398767,
0.054311075, 0.037000030, 0.026240015, 0.018750015, 0.012892199,
0.0081198003
}
},
{
61, 400.0, 700.0, /* 61 bands from 400 to 700 nm in 5nm steps */
1.0, /* Scale factor */
{
0.00073439190, 0.0010295739, 0.0011050375, -0.00057123313, -0.0015421159,
-0.0050492258, -0.0060441241, -0.0050340813, -0.00046015829, 0.0043453053,
0.014594307, 0.028653705, 0.047841334, 0.078039315, 0.11339641,
0.15326829, 0.18931877, 0.22596008, 0.26950734, 0.32894461,
0.39924943, 0.48161678, 0.56603317, 0.65284913, 0.73864212,
0.80870955, 0.86388621, 0.90168525, 0.92331427, 0.94508269,
0.96035974, 0.96084837, 0.94474215, 0.93248079, 0.92686312,
0.89683591, 0.85193527, 0.81446493, 0.77206051, 0.71732417,
0.65749412, 0.59544590, 0.53033945, 0.46382662, 0.39929743,
0.33905951, 0.28179144, 0.22775797, 0.18104592, 0.14195030,
0.10887196, 0.081491712, 0.059933233, 0.043516174, 0.031399280,
0.022402933, 0.015787610, 0.011178068, 0.0078482427, 0.0054361119,
0.0036285556
}
},
{
61, 400.0, 700.0, /* 61 bands from 400 to 700 nm in 5nm steps */
1.0, /* Scale factor */
{
0.19346810, 0.37355444, 0.62641781, 0.98559734, 1.3578634,
1.5413908, 1.6258281, 1.7422823, 1.8184109, 1.7982693,
1.6624945, 1.4917210, 1.3537111, 1.2543216, 1.1444894,
0.94078221, 0.73058355, 0.55774101, 0.42026628, 0.31970216,
0.24388223, 0.18951860, 0.14567319, 0.11603887, 0.094972125,
0.077803903, 0.065288720, 0.055235267, 0.046945157, 0.039405440,
0.033042398, 0.026944585, 0.021626844, 0.016807242, 0.011642648,
0.0061489002, 0.00061480026, -0.0044002687, -0.0090514735, -0.013048603,
-0.016063598, -0.018035874, -0.019053770, -0.019163305, -0.018371066,
-0.016810570, -0.014805852, -0.012650736, -0.010513405, -0.0085481723,
-0.0067628649, -0.0051813692, -0.0038792081, -0.0028536093, -0.0020731313,
-0.0014924891, -0.0010704383, -0.00075273042, -0.00052400943, -0.00036054897,
-0.00025295701
}
}
};
#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 */
/* return 0 on sucecss, nz if not matched */
int standardObserver(
xspect *sp[3], /* Return 3 pointers */
icxObserverType obType /* Type of observer */
) {
switch (obType) {
case icxOT_custom:
return 1;
case icxOT_none:
return 1;
case icxOT_default:
case icxOT_CIE_1931_2:
sp[0] = &ob_CIE_1931_2[0];
sp[1] = &ob_CIE_1931_2[1];
sp[2] = &ob_CIE_1931_2[2];
return 0;
case icxOT_CIE_1964_10:
sp[0] = &ob_CIE_1964_10[0];
sp[1] = &ob_CIE_1964_10[1];
sp[2] = &ob_CIE_1964_10[2];
return 0;
#ifndef SALONEINSTLIB
case icxOT_Stiles_Burch_2:
sp[0] = &ob_Stiles_Burch_2[0];
sp[1] = &ob_Stiles_Burch_2[1];
sp[2] = &ob_Stiles_Burch_2[2];
return 0;
case icxOT_Judd_Voss_2:
sp[0] = &ob_Judd_Voss_2[0];
sp[1] = &ob_Judd_Voss_2[1];
sp[2] = &ob_Judd_Voss_2[2];
return 0;
case icxOT_CIE_1964_10c:
sp[0] = &ob_CIE_1964_10c[0];
sp[1] = &ob_CIE_1964_10c[1];
sp[2] = &ob_CIE_1964_10c[2];
return 0;
case icxOT_Shaw_Fairchild_2:
sp[0] = &ob_Shaw_Fairchild_2[0];
sp[1] = &ob_Shaw_Fairchild_2[1];
sp[2] = &ob_Shaw_Fairchild_2[2];
return 0;
#endif /* !SALONEINSTLIB */
default:
return 1;
}
}
/* Return a string describing the standard observer */
char *standardObserverDescription(icxObserverType obType) {
switch (obType) {
case icxOT_custom:
return "Custom observer";
case icxOT_none:
return "No observer";
case icxOT_default:
case icxOT_CIE_1931_2:
return "CIE 1931 2 degree observer";
case icxOT_CIE_1964_10:
return "CIE 1964 10 degree observer";
#ifndef SALONEINSTLIB
case icxOT_Stiles_Burch_2:
return "Stiles & Burch 1955 2 degree observer (aligned)";
case icxOT_Judd_Voss_2:
return "Judd & Voss 1978 2 degree observer";
case icxOT_CIE_1964_10c:
return "CIE 1964 10 degree observer (aligned)";
case icxOT_Shaw_Fairchild_2:
return "Shaw & Fairchild 1997 2 degree observer";
#endif /* !SALONEINSTLIB */
}
return "Unknown observer";
}
#ifndef SALONEINSTLIB
/* ----------------------------------- */
/* Standard refelective sample spectra */
/* Ra CRI Test Color Samples */
static xspect CIE1995_TCS[] = {
/* TCS01 7.5 R 6/4 Light greyish red */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.12, 0.14, 0.16, 0.19, 0.22, 0.24, 0.25, 0.26, 0.26, 0.25,
0.25, 0.25, 0.24, 0.24, 0.24, 0.23, 0.23, 0.23, 0.23, 0.22,
0.22, 0.22, 0.22, 0.21, 0.21, 0.21, 0.22, 0.22, 0.22, 0.23,
0.23, 0.23, 0.23, 0.23, 0.23, 0.23, 0.24, 0.25, 0.25, 0.26,
0.27, 0.28, 0.3, 0.32, 0.34, 0.37, 0.39, 0.41, 0.42, 0.44,
0.44, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45,
0.45, 0.45, 0.45, 0.45, 0.46, 0.46, 0.46, 0.46, 0.46, 0.46,
0.46, 0.47, 0.47, 0.47, 0.47, 0.47, 0.47, 0.47, 0.47, 0.47,
0.47, 0.47, 0.47, 0.47, 0.47, 0.47, 0.47, 0.47, 0.47, 0.47,
0.47, 0.47, 0.47, 0.46, 0.46
}
},
/* TCS02 5 Y6/4 Dark greyish yellow */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.05, 0.06, 0.06, 0.06, 0.07, 0.08, 0.09, 0.1, 0.11, 0.12,
0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.13, 0.13,
0.13, 0.13, 0.14, 0.14, 0.15, 0.16, 0.17, 0.19, 0.21, 0.23,
0.24, 0.25, 0.26, 0.26, 0.27, 0.27, 0.27, 0.28, 0.28, 0.29,
0.3, 0.31, 0.32, 0.33, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34,
0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34,
0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33,
0.33, 0.33, 0.32, 0.32, 0.32, 0.32, 0.32, 0.32, 0.32, 0.32,
0.32, 0.32, 0.32, 0.31, 0.31, 0.31, 0.31, 0.31, 0.31, 0.31,
0.31, 0.31, 0.31, 0.31, 0.31
}
},
/* TCS03 5 GY 6/8 Strong yellow green */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.06, 0.06, 0.06, 0.06, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.08,
0.08, 0.08, 0.09, 0.09, 0.11, 0.13, 0.15, 0.17, 0.2, 0.22,
0.24, 0.26, 0.28, 0.3, 0.34, 0.37, 0.39, 0.4, 0.4, 0.39,
0.38, 0.37, 0.35, 0.33, 0.32, 0.3, 0.29, 0.27, 0.26, 0.26,
0.25, 0.25, 0.24, 0.24, 0.23, 0.22, 0.22, 0.22, 0.22, 0.22,
0.22, 0.22, 0.23, 0.24, 0.25, 0.27, 0.29, 0.31, 0.34, 0.37,
0.39, 0.41, 0.43, 0.45, 0.46, 0.47, 0.48, 0.49, 0.49, 0.5,
0.5, 0.5, 0.51, 0.51, 0.52, 0.52, 0.52, 0.53, 0.53, 0.54,
0.54, 0.54, 0.55, 0.55, 0.56
}
},
/* TCS04 2.5 G 6/6 Moderate yellowish green */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.06, 0.06, 0.06, 0.07, 0.07, 0.08, 0.09, 0.11, 0.12, 0.12,
0.12, 0.13, 0.13, 0.13, 0.14, 0.14, 0.14, 0.15, 0.16, 0.17,
0.19, 0.21, 0.23, 0.25, 0.28, 0.31, 0.33, 0.35, 0.37, 0.38,
0.39, 0.39, 0.4, 0.39, 0.39, 0.38, 0.37, 0.35, 0.34, 0.33,
0.31, 0.3, 0.28, 0.26, 0.25, 0.23, 0.21, 0.2, 0.19, 0.18,
0.17, 0.16, 0.16, 0.16, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15,
0.15, 0.15, 0.15, 0.15, 0.16, 0.16, 0.17, 0.17, 0.17, 0.17,
0.17, 0.17, 0.17, 0.16, 0.16, 0.17, 0.17, 0.17, 0.18, 0.18,
0.19, 0.19, 0.19, 0.19, 0.2, 0.2, 0.2, 0.21, 0.22, 0.23,
0.23, 0.24, 0.25, 0.26, 0.27
}
},
/* TCS05 10 BG 6/4 Light bluish green */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.14, 0.19, 0.23, 0.27, 0.3, 0.31, 0.31, 0.31, 0.31, 0.32,
0.32, 0.32, 0.33, 0.33, 0.33, 0.34, 0.35, 0.35, 0.36, 0.37,
0.38, 0.39, 0.4, 0.41, 0.42, 0.42, 0.42, 0.42, 0.41, 0.41,
0.4, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.32,
0.31, 0.3, 0.28, 0.27, 0.26, 0.25, 0.23, 0.22, 0.21, 0.2,
0.19, 0.19, 0.19, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18,
0.18, 0.18, 0.18, 0.18, 0.19, 0.19, 0.19, 0.2, 0.2, 0.2,
0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.21,
0.21, 0.21, 0.22, 0.22, 0.22, 0.22, 0.23, 0.23, 0.24, 0.24,
0.25, 0.26, 0.27, 0.27, 0.28
}
},
/* TCS06 5 PB 6/8 Light blue */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.08, 0.08, 0.09, 0.11, 0.15, 0.2, 0.27, 0.34, 0.41, 0.46,
0.49, 0.51, 0.52, 0.52, 0.53, 0.54, 0.54, 0.55, 0.56, 0.56,
0.55, 0.55, 0.54, 0.53, 0.52, 0.5, 0.49, 0.47, 0.45, 0.43,
0.41, 0.4, 0.38, 0.36, 0.34, 0.33, 0.31, 0.29, 0.28, 0.27,
0.25, 0.24, 0.23, 0.23, 0.23, 0.22, 0.22, 0.22, 0.22, 0.22,
0.22, 0.22, 0.22, 0.23, 0.23, 0.24, 0.24, 0.25, 0.26, 0.26,
0.27, 0.27, 0.28, 0.28, 0.28, 0.29, 0.29, 0.3, 0.3, 0.31,
0.33, 0.34, 0.35, 0.36, 0.38, 0.39, 0.4, 0.41, 0.43, 0.44,
0.45, 0.46, 0.47, 0.48, 0.49, 0.49, 0.5, 0.51, 0.51, 0.52,
0.52, 0.53, 0.53, 0.53, 0.54
}
},
/* TCS07 2.5 P 6/8 Y6/4 Light violet */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.15, 0.18, 0.22, 0.29, 0.38, 0.46, 0.52, 0.55, 0.55, 0.56,
0.56, 0.56, 0.56, 0.56, 0.56, 0.55, 0.54, 0.54, 0.52, 0.51,
0.49, 0.47, 0.45, 0.43, 0.41, 0.39, 0.36, 0.34, 0.32, 0.31,
0.3, 0.29, 0.28, 0.27, 0.27, 0.26, 0.26, 0.26, 0.26, 0.26,
0.26, 0.26, 0.26, 0.25, 0.25, 0.26, 0.27, 0.28, 0.3, 0.32,
0.34, 0.36, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45,
0.45, 0.46, 0.46, 0.47, 0.47, 0.47, 0.47, 0.48, 0.48, 0.49,
0.5, 0.5, 0.51, 0.52, 0.53, 0.53, 0.54, 0.55, 0.55, 0.56,
0.57, 0.57, 0.58, 0.58, 0.58, 0.58, 0.59, 0.59, 0.59, 0.59,
0.59, 0.59, 0.59, 0.59, 0.59
}
},
/* TCS08 10 P 6/8 Light reddish purple */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.08, 0.08, 0.08, 0.09, 0.1, 0.13, 0.17, 0.24, 0.32, 0.42,
0.46, 0.48, 0.49, 0.49, 0.48, 0.47, 0.46, 0.45, 0.44, 0.43,
0.41, 0.4, 0.38, 0.37, 0.35, 0.34, 0.33, 0.31, 0.3, 0.29,
0.28, 0.28, 0.27, 0.26, 0.26, 0.25, 0.25, 0.25, 0.25, 0.26,
0.26, 0.27, 0.27, 0.27, 0.28, 0.28, 0.3, 0.32, 0.35, 0.38,
0.43, 0.48, 0.53, 0.57, 0.6, 0.63, 0.65, 0.66, 0.68, 0.69,
0.69, 0.7, 0.71, 0.71, 0.71, 0.72, 0.72, 0.72, 0.72, 0.72,
0.72, 0.72, 0.73, 0.73, 0.73, 0.73, 0.73, 0.73, 0.73, 0.73,
0.73, 0.73, 0.73, 0.73, 0.73, 0.73, 0.73, 0.73, 0.73, 0.73,
0.73, 0.73, 0.73, 0.73, 0.73
}
},
/* TCS09 4.5 R 4/13 Strong red */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.069, 0.072, 0.073, 0.070, 0.066, 0.062, 0.058, 0.055, 0.052, 0.052,
0.051, 0.050, 0.050, 0.049, 0.048, 0.047, 0.046, 0.044, 0.042, 0.041,
0.038, 0.035, 0.033, 0.031, 0.030, 0.029, 0.028, 0.028, 0.028, 0.029,
0.030, 0.030, 0.031, 0.031, 0.032, 0.032, 0.033, 0.034, 0.035, 0.037,
0.041, 0.044, 0.048, 0.052, 0.060, 0.076, 0.102, 0.136, 0.190, 0.256,
0.336, 0.418, 0.505, 0.581, 0.641, 0.682, 0.717, 0.740, 0.758, 0.770,
0.781, 0.790, 0.797, 0.803, 0.809, 0.814, 0.819, 0.824, 0.828, 0.830,
0.831, 0.833, 0.835, 0.836, 0.836, 0.837, 0.838, 0.839, 0.839, 0.839,
0.839, 0.839, 0.839, 0.839, 0.839, 0.839, 0.839, 0.839, 0.839, 0.839,
0.838, 0.837, 0.837, 0.836, 0.836
}
},
/* TCS10 5 Y 8/10 Strong yellow */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.04, 0.04, 0.05, 0.05, 0.05, 0.05, 0.06, 0.06, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.08, 0.08, 0.08, 0.09,
0.1, 0.1, 0.11, 0.13, 0.14, 0.16, 0.19, 0.22, 0.26, 0.31,
0.37, 0.42, 0.47, 0.51, 0.55, 0.58, 0.61, 0.63, 0.65, 0.67,
0.68, 0.69, 0.69, 0.7, 0.7, 0.7, 0.71, 0.71, 0.71, 0.71,
0.71, 0.71, 0.71, 0.71, 0.71, 0.71, 0.71, 0.71, 0.72, 0.72,
0.72, 0.72, 0.73, 0.73, 0.73, 0.74, 0.74, 0.74, 0.75, 0.75,
0.75, 0.75, 0.75, 0.75, 0.76, 0.76, 0.76, 0.76, 0.76, 0.76,
0.76, 0.76, 0.76, 0.76, 0.76, 0.76, 0.76, 0.76, 0.76, 0.76,
0.76, 0.76, 0.76, 0.76, 0.76
}
},
/* TCS11 4.5 G 5/8 Strong green */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.07, 0.08, 0.09, 0.1, 0.11, 0.12, 0.13, 0.13, 0.13, 0.12,
0.12, 0.11, 0.11, 0.11, 0.1, 0.1, 0.11, 0.11, 0.11, 0.12,
0.12, 0.13, 0.15, 0.17, 0.19, 0.22, 0.25, 0.29, 0.33, 0.35,
0.36, 0.35, 0.35, 0.33, 0.31, 0.29, 0.27, 0.25, 0.23, 0.21,
0.19, 0.17, 0.15, 0.14, 0.13, 0.11, 0.11, 0.1, 0.1, 0.09,
0.09, 0.09, 0.09, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08,
0.08, 0.08, 0.09, 0.09, 0.1, 0.11, 0.13, 0.14, 0.16, 0.18,
0.2, 0.22, 0.24, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.31,
0.32, 0.32, 0.33, 0.33, 0.34, 0.34, 0.35, 0.35, 0.36, 0.37,
0.37, 0.38, 0.39, 0.4, 0.4
}
},
/* TCS12 3 PB 3/11 Strong blue */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.19, 0.18, 0.16, 0.14, 0.12, 0.1, 0.09, 0.08, 0.08, 0.07,
0.06, 0.07, 0.08, 0.09, 0.12, 0.16, 0.21, 0.26, 0.3, 0.33,
0.35, 0.35, 0.34, 0.33, 0.31, 0.28, 0.26, 0.23, 0.2, 0.18,
0.15, 0.13, 0.11, 0.09, 0.08, 0.06, 0.05, 0.04, 0.04, 0.03,
0.03, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02,
0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02,
0.02, 0.02, 0.03, 0.03, 0.04, 0.04, 0.06, 0.07, 0.1, 0.13,
0.17, 0.21, 0.26, 0.31, 0.35, 0.4, 0.45, 0.49, 0.52, 0.55,
0.58, 0.6, 0.62, 0.63, 0.65, 0.66, 0.67, 0.67, 0.68, 0.69,
0.69, 0.69, 0.7, 0.7, 0.7
}
},
/* TCS13 5 YR 8/4 Light yellowish pink */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.07, 0.08, 0.08, 0.09, 0.1, 0.13, 0.16, 0.21, 0.26, 0.31,
0.34, 0.35, 0.36, 0.36, 0.36, 0.37, 0.37, 0.37, 0.37, 0.37,
0.38, 0.38, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45,
0.46, 0.47, 0.47, 0.47, 0.47, 0.48, 0.48, 0.49, 0.51, 0.53,
0.55, 0.58, 0.62, 0.65, 0.68, 0.7, 0.72, 0.73, 0.74, 0.74,
0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75,
0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75,
0.75, 0.74, 0.74, 0.74, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75,
0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75,
0.75, 0.75, 0.75, 0.75, 0.75
}
},
/* TCS14 5 GY 4/4 Moderate olive green */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04,
0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.05, 0.05, 0.05,
0.05, 0.05, 0.05, 0.05, 0.06, 0.06, 0.06, 0.07, 0.08, 0.08,
0.09, 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.15, 0.16, 0.15,
0.15, 0.14, 0.13, 0.13, 0.12, 0.11, 0.11, 0.1, 0.1, 0.1,
0.09, 0.09, 0.09, 0.09, 0.09, 0.09, 0.08, 0.08, 0.08, 0.08,
0.09, 0.09, 0.09, 0.1, 0.1, 0.11, 0.12, 0.14, 0.15, 0.17,
0.19, 0.21, 0.23, 0.24, 0.26, 0.28, 0.29, 0.31, 0.33, 0.34,
0.35, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.42, 0.43, 0.43,
0.44, 0.44, 0.45, 0.45, 0.45
}
},
/* TCS15 1 YR 6/4 Asian skin */
{
95, 360.0, 830.0, /* 95 bands from 360 to 830 nm in 5nm steps */
1.0, /* Scale factor */
{
0, 0, 0, 0, 0.13, 0.14, 0.15, 0.15, 0.16, 0.16,
0.16, 0.17, 0.17, 0.18, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23,
0.24, 0.24, 0.25, 0.25, 0.26, 0.26, 0.27, 0.28, 0.28, 0.29,
0.3, 0.3, 0.3, 0.29, 0.28, 0.28, 0.27, 0.28, 0.28, 0.29,
0.29, 0.29, 0.29, 0.28, 0.29, 0.31, 0.35, 0.4, 0.44, 0.47,
0.49, 0.51, 0.52, 0.54, 0.54, 0.55, 0.56, 0.57, 0.57, 0.58,
0.58, 0.59, 0.59, 0.59, 0.6, 0.6, 0.61, 0.61, 0.61, 0.61,
0.62, 0.62, 0.62, 0.62, 0.62, 0.61, 0.61, 0.61, 0.61, 0.61,
0.61, 0.61, 0.61, 0.61, 0.61, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0
}
}
};
/* -------------------------------- */
/* Fluorescent Whitening Agent Data */
/* Generic stimulation/exitation spectrum, used in FWA. */
/* This is also used to estimate the UV content of an illuminant, */
/* by its FWA effect (illumread) */
static xspect FWA1_stim = {
14, 290.0, 420.0, /* 14 bands from 290 to 420 nm in 10nm steps */
1.0, /* Scale factor */
{
/* 290 */ 0.000000,
/* 300 */ 0.075000, 0.158000, 0.228000, 0.318638, 0.393663,
/* 350 */ 0.460003, 0.524409, 0.550955, 0.540374, 0.497947,
/* 400 */ 0.412503, 0.265935, 0.000000
}
};
/* !!! This is not normally used !!! */
#ifdef STOCKFWA /* Use table shape as FWA basis, rather than estimating from spectrum. */
/* Generic emmission spectrum */
static xspect FWA1_emit = {
17, 390.0, 550.0, /* 17 bands from 390 to 550 nm in 10nm steps */
1.0, /* Scale factor */
{
#ifdef NEVER
/* 390 */ 0.00000,
/* 400 */ 0.08989, 0.27831, 0.45278, 0.494, 0.496,
/* 450 */ 0.36872, 0.30495, 0.226, 0.1676, 0.1216,
/* 500 */ 0.08515, 0.06877, 0.04930, 0.0246, 0.0123,
/* 550 */ 0.00000
#else
/* Hacked */
/* 390 */ 0.00000,
/* 400 */ 0.01089, 0.15000, 0.20278, 0.374, 0.496,
/* 450 */ 0.38000, 0.27495, 0.186, 0.1376, 0.1016,
/* 500 */ 0.08515, 0.06877, 0.04930, 0.0246, 0.0123,
/* 550 */ 0.00000
#endif
}
};
#endif /* STOCKFWA */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* save a set of spectrum to a CGATS file */
/* type 0 = SPECT, 1 = CMF */
/* Return NZ on error */
int write_nxspect(char *fname, xspect *sp, int nspec, int type) {
char buf[100];
time_t clk = time(0);
struct tm *tsp = localtime(&clk);
char *atm = asctime(tsp); /* Ascii time */
cgats *ocg; /* output cgats structure */
cgats_set_elem *setel; /* Array of set value elements */
int i, j;
/* Setup output cgats file */
ocg = new_cgats(); /* Create a CGATS structure */
if (type != 0)
ocg->add_other(ocg, "CMF"); /* our special type is spectral color matching func */
else
ocg->add_other(ocg, "SPECT"); /* our special type is spectral power or reflectance */
ocg->add_table(ocg, tt_other, 0); /* Start the first table */
ocg->add_kword(ocg, 0, "DESCRIPTOR", "Argyll Spectral power/reflectance information",NULL);
ocg->add_kword(ocg, 0, "ORIGINATOR", "Argyll CMS", NULL);
atm[strlen(atm)-1] = '\000'; /* Remove \n from end */
ocg->add_kword(ocg, 0, "CREATED",atm, NULL);
sprintf(buf,"%d", sp->spec_n);
ocg->add_kword(ocg, 0, "SPECTRAL_BANDS",buf, NULL);
sprintf(buf,"%f", sp->spec_wl_short);
ocg->add_kword(ocg, 0, "SPECTRAL_START_NM",buf, NULL);
sprintf(buf,"%f", sp->spec_wl_long);
ocg->add_kword(ocg, 0, "SPECTRAL_END_NM",buf, NULL);
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;
/* Compute nearest integer wavelength */
nm = (int)(XSPECT_XWL(sp, i) + 0.5);
sprintf(buf,"SPEC_%03d",nm);
ocg->add_field(ocg, 0, buf, r_t);
}
if ((setel = (cgats_set_elem *)malloc(sizeof(cgats_set_elem) * sp->spec_n)) == NULL) {
ocg->del(ocg);
return 1;
}
for (j = 0; j < nspec; j++) {
for (i = 0; i < sp[j].spec_n; i++) {
setel[i].d = sp[j].spec[i];
}
ocg->add_setarr(ocg, 0, setel);
}
if (ocg->write_name(ocg, fname)) {
DBGF((DBGA,"CGATS file write error : %s\n",ocg->err));
return 1;
}
free(setel);
ocg->del(ocg); /* Clean up */
return 0;
}
/* restore a set of spectrum from a CGATS file. */
/* 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) {
cgats *icg; /* input cgats structure */
char buf[100];
int sflds[XSPECT_MAX_BANDS];
int i, j, ii;
xspect proto;
/* Open and look at the spectrum file */
if ((icg = new_cgats()) == NULL) { /* Create a CGATS structure */
DBG("new_cgats() failed");
icg->del(icg);
return 1;
}
if (type == 0) {
icg->add_other(icg, ""); /* Allow any signature file */
} else {
if (type & 1)
icg->add_other(icg, "SPECT"); /* Spectrum file */
if (type & 2)
icg->add_other(icg, "CMF"); /* Color Matching Functions */
if (type & 4)
icg->add_other(icg, "CCSS"); /* Color Correction Spectral Samples */
}
if (icg->read_name(icg, fname)) {
DBGF((DBGA,"CGATS file read error : %s\n",icg->err));
icg->del(icg);
return 1;
}
if (icg->ntables != 1) {
DBG("Input file doesn't contain exactly one table\n");
icg->del(icg);
return 1;
}
if ((ii = icg->find_kword(icg, 0, "SPECTRAL_BANDS")) < 0) {
DBG ("Input file doesn't contain keyword SPECTRAL_BANDS\n");
icg->del(icg);
return 1;
}
proto.spec_n = atoi(icg->t[0].kdata[ii]);
if ((ii = icg->find_kword(icg, 0, "SPECTRAL_START_NM")) < 0) {
DBG("Input file doesn't contain keyword SPECTRAL_START_NM\n");
icg->del(icg);
return 1;
}
proto.spec_wl_short = atof(icg->t[0].kdata[ii]);
if ((ii = icg->find_kword(icg, 0, "SPECTRAL_END_NM")) < 0) {
DBG("Input file doesn't contain keyword SPECTRAL_END_NM\n");
icg->del(icg);
return 1;
}
proto.spec_wl_long = atof(icg->t[0].kdata[ii]);
if ((ii = icg->find_kword(icg, 0, "SPECTRAL_NORM")) < 0) {
DBG("Input file doesn't contain keyword SPECTRAL_NORM - assuming 1.0\n");
proto.norm = 1.0;
} else {
proto.norm = atof(icg->t[0].kdata[ii]);
}
/* Find the fields for spectral values */
for (i = 0; i < proto.spec_n; i++) {
int nm, fi;
/* Compute nearest integer wavelength */
nm = (int)(XSPECT_XWL(&proto, i) + 0.5);
sprintf(buf,"SPEC_%03d",nm);
if ((fi = icg->find_field(icg, 0, buf)) < 0) {
DBGF((DBGA,"Input file doesn't contain field %s\n",buf));
icg->del(icg);
return 1;
}
if (icg->t[0].ftype[fi] != r_t) {
DBGF((DBGA,"Field %s in specrum is wrong type - should be a float\n",buf));
icg->del(icg);
return 1;
}
sflds[i] = fi;
}
/* Read all the spectra */
for (j = off; j < nspec && j < icg->t[0].nsets; j++) {
XSPECT_COPY_INFO(&sp[j], &proto);
for (i = 0; i < proto.spec_n; i++) {
sp[j].spec[i] = *((double *)icg->t[0].fdata[j][sflds[i]]);
}
}
if (nret != NULL)
*nret = j - off;
icg->del(icg);
return 0;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* save a spectrum to a CGATS file */
/* Return NZ on error */
int write_xspect(char *fname, xspect *sp) {
return write_nxspect(fname, sp, 1, 0);
}
/* restore a spectrum from a CGATS file */
/* Return NZ on error */
/* (Would be nice to return an error message!) */
int read_xspect(xspect *sp, char *fname) {
int rv, nret;
if ((rv = read_nxspect(sp, fname, &nret, 0, 1, 1)) != 0)
return rv;
if (nret != 1) {
DBG("Didn't read one spectra\n");
return 1;
}
return 0;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* save a set of 3 spectrum to a CGATS CMF file */
/* Return NZ on error */
int write_cmf(char *fname, xspect sp[3]) {
return write_nxspect(fname, sp, 3, 1);
}
/* restore a spectrum from a CGATS file */
/* Return NZ on error */
/* (Would be nice to return an error message!) */
int read_cmf(xspect sp[3], char *fname) {
int rv, nret;
if ((rv = read_nxspect(sp, fname, &nret, 0, 3, 2)) != 0)
return rv;
if (nret != 3) {
DBG("Didn't read three spectra\n");
return 1;
}
return 0;
}
/* ------------- */
#endif /* !SALONEINSTLIB */
/* Get a raw 3rd order polinomial interpolated spectrum value. */
/* 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_xspec_poly3(xspect *sp, double *rv, double xw) {
int i, rc = 1;
double spcing, f;
#ifdef NEVER
double w1, w2, w3; /* For Hermite curves */
#endif
double y[4], yw;
double x[4];
if (xw < sp->spec_wl_short) {
xw = sp->spec_wl_short;
rc = 0;
}
if (xw > sp->spec_wl_long) {
xw = sp->spec_wl_long;
rc = 0;
}
/* Compute fraction 0.0 - 1.0 out of known spectrum */
spcing = (sp->spec_wl_long - sp->spec_wl_short)/(sp->spec_n-1.0);
f = (xw - sp->spec_wl_short) / (sp->spec_wl_long - sp->spec_wl_short);
f *= (sp->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->spec_n - 2))
i = (sp->spec_n - 2);
/* Setup the surrounding values */
x[0] = sp->spec_wl_short + (i-1) * spcing;
if (i == 0)
y[0] = sp->spec[i];
else
y[0] = sp->spec[i-1];
x[1] = sp->spec_wl_short + i * spcing;
y[1] = sp->spec[i];
x[2] = sp->spec_wl_short + (i+1) * spcing;
y[2] = sp->spec[i+1];
x[3] = sp->spec_wl_short + (i+2) * spcing;
if ((i+2) < sp->spec_n)
y[3] = sp->spec[i+2];
else
y[3] = sp->spec[i+1];
#ifndef NEVER
/* Compute interpolated value using Lagrange: */
yw = y[0] * (xw-x[1]) * (xw-x[2]) * (xw-x[3])/((x[0]-x[1]) * (x[0]-x[2]) * (x[0]-x[3]))
+ y[1] * (xw-x[0]) * (xw-x[2]) * (xw-x[3])/((x[1]-x[0]) * (x[1]-x[2]) * (x[1]-x[3]))
+ y[2] * (xw-x[0]) * (xw-x[1]) * (xw-x[3])/((x[2]-x[0]) * (x[2]-x[1]) * (x[2]-x[3]))
+ y[3] * (xw-x[0]) * (xw-x[1]) * (xw-x[2])/((x[3]-x[0]) * (x[3]-x[1]) * (x[3]-x[2]));
#else
/* Use Hermite curves */
y[0] = 0.5 * (y[2] - y[0]); /* Convert to tangent */
y[3] = 0.5 * (y[3] - y[1]); /* Not sure about the best weighting here ... */
w1 = f - (double)i; /* Interpolation weighting factor, 0.0 - 1.0 */
w2 = w1 * w1;
w3 = w2 * w1;
yw = y[0] * (w3 - 2.0 * w2 + w1)
+ y[1] * (2.0 * w3 - 3.0 * w2 + 1.0)
+ y[2] * (-2.0 * w3 + 3.0 * w2)
+ y[3] * (w3 - w2);
#endif
#ifdef NEVER // ~~99
/* Calibration issues or interpolation overshoot can give -ve values, */
/* so protect against this. */
/* On the other hand, not allowing -ve values wrecks black level */
/* by not averaging out the noise. */
if (yw < 0.0)
yw = 0.0;
#endif /* NEVER */
*rv = yw;
return rc;
}
/* Get a raw linearly interpolated spectrum value. */
/* 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_xspec_lin(xspect *sp, double *rv, double wl) {
int i, rc = 1;
double f, w;
if (wl < sp->spec_wl_short) {
wl = sp->spec_wl_short;
rc = 0;
}
if (wl > sp->spec_wl_long) {
wl = sp->spec_wl_long;
rc = 0;
}
/* Compute fraction 0.0 - 1.0 out of known spectrum */
f = (wl - sp->spec_wl_short) / (sp->spec_wl_long - sp->spec_wl_short);
f *= (sp->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->spec_n - 2))
i = (sp->spec_n - 2);
w = f - (double)i; /* Interpolation weighting factor */
/* Compute interpolated value */
*rv = (1.0 - w) * sp->spec[i] + w * sp->spec[i+1];
#ifdef NEVER
/* Calibration issues or interpolation overshoot can give -ve values, */
/* so protect against this. */
/* On the other hand, not allowing -ve values wrecks black level */
/* by not averaging out the noise. */
if (*rv < 0.0)
*rv = 0.0;
#endif /* NEVER */
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 */
/* if outside the range */
/* NOTE: Returned value isn't normalised by sp->norm */
static int getval_raw_xspec_nn(xspect *sp, double *rv, double wl) {
int i, rc = 1;
double f;
if (wl < sp->spec_wl_short) {
wl = sp->spec_wl_short;
rc = 0;
}
if (wl > sp->spec_wl_long) {
wl = sp->spec_wl_long;
rc = 0;
}
/* Compute fraction 0.0 - 1.0 out of known spectrum */
f = (wl - sp->spec_wl_short) / (sp->spec_wl_long - sp->spec_wl_short);
f *= (sp->spec_n - 1.0);
i = (int)floor(f + 0.5); /* Base grid coordinate */
if (i < 0) /* Limit to valid cube base index range */
i = 0;
else if (i > (sp->spec_n - 1))
i = (sp->spec_n - 1);
/* Compute interpolated value */
*rv = sp->spec[i];
#ifdef NEVER
/* Calibration issues or interpolation overshoot can give -ve values, */
/* so protect against this. */
/* On the other hand, not allowing -ve values wrecks black level */
/* by not averaging out the noise. */
if (*rv < 0.0)
*rv = 0.0;
#endif /* NEVER */
return rc;
}
#endif /* NEVER */
/* Call the appropriate interpolation routine */
/* 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_xspec(xspect *sp, double *rv, double wl) {
double spcg = (sp->spec_wl_long - sp->spec_wl_short)/(sp->spec_n-1.0);
if (spcg < 5.01) {
return getval_raw_xspec_lin(sp, rv, wl);
} else {
return getval_raw_xspec_poly3(sp, rv, wl);
}
}
/* Get a (normalised) linearly or poly interpolated spectrum value. */
/* Return NZ if value is valid, Z and last valid value */
/* if outside the range */
static int getval_xspec(xspect *sp, double *rv, double wl) {
int sv = getval_raw_xspec(sp, rv, wl);
*rv /= sp->norm;
return sv;
}
/* Public function to get a spectrum value. */
/* Return a spectrum value at the given wavelenth. It */
/* may have been interpolated or extrapolated. */
/* Returned value isn't normalised by sp->norm */
double value_xspect(xspect *sp, double wl) {
double rv;
getval_raw_xspec(sp, &rv, wl);
return rv;
}
/* Get a (normalised) linearly interpolated spectrum value. */
/* Return NZ if value is valid, Z and last valid value */
/* if outside the range */
static int getval_lxspec(xspect *sp, double *rv, double wl) {
int sv = getval_raw_xspec_lin(sp, rv, wl);
*rv /= sp->norm;
return sv;
}
/* De-noramlize and set normalisation factor to 1.0 */
void xspect_denorm(xspect *sp) {
int i;
for (i = 0; i < sp->spec_n; i++) {
sp->spec[i] /= sp->norm;
}
sp->norm = 1.0;
}
#ifndef SALONEINSTLIB
/* Convert from one xspect type to another (targ type) */
/* Linear or polinomial interpolation will be used as appropriate */
/* (converted to targ norm too) */
void xspect2xspect(xspect *dst, xspect *targ, xspect *src) {
xspect dd;
int i;
dd.spec_n = targ->spec_n;
dd.spec_wl_short = targ->spec_wl_short;
dd.spec_wl_long = targ->spec_wl_long;
dd.norm = targ->norm;
if (targ->spec_n != src->spec_n
|| targ->spec_wl_short != src->spec_wl_short
|| targ->spec_wl_long != src->spec_wl_long) {
for (i = 0; i < targ->spec_n; i++) {
double ww = XSPECT_XWL(targ, i);
getval_raw_xspec(src, &dd.spec[i], ww);
}
} else {
for (i = 0; i < targ->spec_n; i++)
dd.spec[i] = src->spec[i];
}
if (targ->norm != src->norm) {
for (i = 0; i < targ->spec_n; i++)
dd.spec[i] *= targ->norm/src->norm;
}
*dst = dd;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Plot up to 3 spectra */
void xspect_plot(xspect *sp1, xspect *sp2, xspect *sp3) {
double xx[XSPECT_MAX_BANDS];
double y1[XSPECT_MAX_BANDS];
double y2[XSPECT_MAX_BANDS];
double y3[XSPECT_MAX_BANDS];
int j;
double wl, wlshort, wllong;
if (sp1 == NULL)
return;
wlshort = sp1->spec_wl_short;
wllong = sp1->spec_wl_long;
if (sp2 != NULL) {
if (sp2->spec_wl_short < wlshort)
wlshort = sp2->spec_wl_short;
if (sp2->spec_wl_long > wllong)
wllong = sp2->spec_wl_long;
}
if (sp3 != NULL) {
if (sp3->spec_wl_short < wlshort)
wlshort = sp3->spec_wl_short;
if (sp3->spec_wl_long > wllong)
wllong = sp3->spec_wl_long;
}
wlshort = floor(wlshort + 0.5);
wllong = floor(wllong + 0.5);
/* Compute at 1nm intervals over the whole range covered */
for (j = 0, wl = wlshort; j < XSPECT_MAX_BANDS && wl < wllong; j++, wl += 1.0) {
#if defined(__APPLE__) && defined(__POWERPC__)
gcc_bug_fix(j);
#endif
xx[j] = wl;
y1[j] = value_xspect(sp1, wl);
if (sp2 != NULL)
y2[j] = value_xspect(sp2, wl);
if (sp3 != NULL)
y3[j] = value_xspect(sp3, wl);
}
do_plot(xx, y1, sp2 != NULL ? y2 : NULL, sp3 != NULL ? y3 : NULL, j);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* 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;
xspect cin; /* Copy of in */
cin = *in;
/* 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;
if (avg < 1e-5) /* Make it do something with 0.0 */
avg = 1e-5;
/* Copy and Extend the range */
*out = cin;
i = (int)floor(XSPECT_XDIX(out, FWA1_stim.spec_wl_short));
ww = XSPECT_XWL(out, i);
if (i < 0)
out->spec_n -= i;
out->spec_wl_short = ww;
/* Copy from input and merge in the UV */
for (i = 0; i < out->spec_n; i++) {
double inv, uvv, bl, nbl, outv;
ww = XSPECT_XWL(out, i);
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);
inv *= bl;
/* Add/subtract UV in */
outv = inv + uvv * uvlevel * avg;;
/* Protect against creating negative output */
if (outv >= out->spec[i])
out->spec[i] = outv;
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Set Media White. This enables extracting and applying the */
/* colorant reflectance value from/to the meadia. */
// ~~99 this is confused. ->media is set from ->imedia in fwa setup.
// ~~99 what's going on here ? The API needs fixing.
static int xsp2cie_set_mw(xsp2cie *p, /* this */
xspect *media /* Spectrum of plain media measured under that instrument */
) {
p->media = *media; /* Take copy of media white */
return 0;
}
/* Extract the colorant reflectance value from the media. Takes FWA */
/* into account if set. Media white or FWA must be set. */
static int xsp2cie_extract(xsp2cie *p, /* this */
xspect *out, /* Extracted colorant refl. spectrum */
xspect *in /* Spectrum to be converted, normalised by norm */
) {
int j;
if (p->media.spec_n == 0)
return 1;
if (p->media.spec_n != in->spec_n
|| p->media.spec_wl_short != in->spec_wl_short
|| p->media.spec_wl_long != in->spec_wl_long)
return 1;
*out = *in;
/* Divide out the media */
for (j = 0; j < p->media.spec_n; j++) {
if (p->media.spec[j] < 0.01)
out->spec[j] = in->spec[j] / 0.01;
else
out->spec[j] = in->spec[j] / p->media.spec[j];
}
out->norm = in->norm / p->media.norm;
return 0;
}
/* Apply the colorant reflectance value from the media. Takes FWA */
/* into account if set. Media white or FWA must be set. */
static int xsp2cie_apply(xsp2cie *p, /* this */
xspect *out, /* Applied refl. spectrum */
xspect *in /* Colorant reflectance to be applied */
) {
int j;
if (p->media.spec_n == 0)
return 1;
if (p->media.spec_n != in->spec_n
|| p->media.spec_wl_short != in->spec_wl_short
|| p->media.spec_wl_long != in->spec_wl_long)
return 1;
*out = *in;
/* Multiply in the media */
for (j = 0; j < p->media.spec_n; j++) {
if (p->media.spec[j] < 0.01)
out->spec[j] = in->spec[j] * 0.01;
else
out->spec[j] = in->spec[j] * p->media.spec[j];
}
out->norm = in->norm * p->media.norm;
return 0;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static void xsp2cie_fwa_convert(xsp2cie *p, double *out, xspect *in);
static void xsp2cie_fwa_sconvert(xsp2cie *p, xspect *sout, double *out, xspect *in);
static int xsp2cie_fwa_extract(xsp2cie *p, xspect *out, xspect *in);
static int xsp2cie_fwa_apply(xsp2cie *p, xspect *out, xspect *in);
/* Set Fluorescent Whitening Agent compensation. */
/* This attempts to compensate for the presense of */
/* Fluorescent whitner in the media, under the possibly */
/* different level of UV radiation of the illuminant being */
/* simulated in the conversion from spectral absorbition */
/* to CIE values, from the illuminant that the media was */
/* measured under by the spectrometer. */
/* Note that the media input spectrum normalisation value is used. */
/* return nz if error */
/*
Limitations of current FWA model:
Scattering: The inking model assumes that the inks are purely
absorbtive. If instead they have a significant scattering
component, then the FWA effect will be over estimated,
as it will be assumed that more UV is reaching the substrate
and not being filtered by the colorant.
Colorant UV transparency: The current model assumes that
the filtering behaviour of the ink can be extrapolated
from the blue reflectance. It could be that inks behave
quite differently, filtering more or less in UV than
they do in blue. Different inks might have different characteristics.
Solution: A solution would be to add a colorant correction model,
that takes as input the colorant levels. To create the model,
illumread would be augmented to read (say) 50% colorant swatches
as well as white, and use the discrepancy between the non-corrected
FWA spectrum and the actual spectrum under the illuminant to
create the correction model. This could be fine tuned by doing
similar measurements of neutral patches.
Other possible limitations:
Instrument illuminant spectrum shape:
It is assumed it is stable and 'A' like. Aging of
the lamp may invalidate this assumption ?
*/
/*
See page 248 of the Proceedings of the IS&T/SID
11th Color Imaging Conference, November 2003:
"A Practical Approach to Measuring and Modelling Paper Fluorescense
for Improved Colorimetric Characterisation of Printing Processes"
ISBN: 0-89208-248-8
for more information about the fwa compensation approach.
*/
static int xsp2cie_set_fwa_imp(xsp2cie *p) {
double ww;
int i, j;
int flag;
double aw = 0.0, bw = 0.0; /* Points wavelength */
double ar, br; /* Points reflection */
#ifdef STOCKFWA /* Use table shape */
double Em; /* Emmision multiplier */
#endif
#ifdef DOPLOT
double xx[XSPECT_MAX_BANDS];
double y1[XSPECT_MAX_BANDS];
double y2[XSPECT_MAX_BANDS];
double y3[XSPECT_MAX_BANDS];
double y4[XSPECT_MAX_BANDS];
#endif /* DOPLOT */
#ifdef WRITE_FWA1_STIM
write_xspect("fwa1_stip.sp", &FWA1_stim);
#endif
DBG("set_fwa started\n");
p->bw = 1.0; /* Intergrate over 1nm bands */
p->oillum = p->illuminant; /* Take copy of observer illuminant */
xspect_denorm(&p->oillum);
if (p->tillum.spec_n == 0) { /* If not set by set_fwa(), copy observer illuminant */
p->tillum = p->oillum; /* as target/simulated instrument illuminant. */
DBG("using observer illum as FWA target\n");
}
/* Compute Y = 1 normalised instrument illuminant spectrum */
{
double scale = 0.0;
double Iim; /* illuminant multiplier */
Iim = 0.0;
for (ww = p->observer[1].spec_wl_short; ww <= p->observer[1].spec_wl_long; ww += p->bw) {
double O, I;
getval_lxspec(&p->iillum, &I, ww);
getval_lxspec(&p->observer[1], &O, ww);
scale += O; /* Integrate Y observer values */
Iim += O * I;
}
Iim /= scale; /* Scale Y observer to unity */
Iim = 1.0/Iim; /* Scale factor to make illuminant integral 1.0 */
for (j = 0; j < p->iillum.spec_n; j++)
p->iillum.spec[j] *= Iim;
DBGF((DBGA,"Instrument Illum normal multiplier Iim = %f\n",Iim));
}
/* Compute Y = 1 normalised target illuminant spectrum */
{
double scale;
double Itm; /* illuminant multiplier */
scale = 0.0;
Itm = 0.0;
for (ww = p->observer[1].spec_wl_short; ww <= p->observer[1].spec_wl_long; ww += p->bw) {
double O, I;
getval_lxspec(&p->tillum, &I, ww);
getval_lxspec(&p->observer[1], &O, ww);
scale += O; /* Integrate Y observer values */
Itm += O * I;
}
Itm /= scale; /* Scale Y observer to unity */
Itm = 1.0/Itm; /* Scale factor to make illuminant integral 1.0 */
for (j = 0; j < p->tillum.spec_n; j++)
p->tillum.spec[j] *= Itm;
}
/* Check if the instrument and target/simulated illuminant are the same. */
/* If they are, FWA compensation can be bypassed. */
/* (We check for an almost exact matcg on the assumption that these will */
/* both be xspect presets) */
#define DEQ(A, B) (fabs(A - B) < 1e-6)
p->insteqtarget = 0;
if (p->iillum.spec_n == p->tillum.spec_n
&& DEQ(p->iillum.spec_wl_short, p->tillum.spec_wl_short)
&& DEQ(p->iillum.spec_wl_long, p->tillum.spec_wl_long)) {
for (i = 0; i < p->iillum.spec_n; i++) {
if (!DEQ(p->tillum.spec[i], p->iillum.spec[i]))
break;
}
if (i >= p->iillum.spec_n) {
p->insteqtarget = 1;
DBGF((DBGA,"###### inst equals target illuminant #####\n"));
}
}
#undef DEQ
/* Compute Y = 1 normalised observer illuminant spectrum */
{
double scale;
double Itm; /* Target illuminant multiplier */
scale = 0.0;
Itm = 0.0;
for (ww = p->observer[1].spec_wl_short; ww <= p->observer[1].spec_wl_long; ww += p->bw) {
double O, I;
getval_lxspec(&p->oillum, &I, ww);
getval_lxspec(&p->observer[1], &O, ww);
scale += O; /* Integrate Y observer values */
Itm += O * I;
}
Itm /= scale; /* Scale Y observer to unity */
Itm = 1.0/Itm; /* Scale factor to make illuminant integral 1.0 */
for (j = 0; j < p->oillum.spec_n; j++)
p->oillum.spec[j] *= Itm;
}
/* Estimate the amount of generic FWA in the media. */
/* and also compute an estimated media minus FWA spectrum */
/* by creating a target white line from the media spectrum */
/* This is quite good for "normal" media, which has a fairly */
/* flat underlying (non FWA) response, but doesn't work so */
/* well for meadia that rolls off at short wavelengths and uses */
/* FWA to compensate for this. */
/* Find darkest point between 450 and 510nm */
ar = 1e6;
for (ww = 450.0; ww <= 510.0; ww += p->bw) {
double rr;
getval_lxspec(&p->imedia, &rr, ww);
DBGF((DBGA,"media %f = %f\n",ww,rr));
if (rr < ar) {
aw = ww;
ar = rr;
}
}
/* Find lightest point between A point+70 and 650 */
br = -1.0;
for (ww = aw+70.0; ww <= 630.0; ww += p->bw) {
double rr;
getval_lxspec(&p->imedia, &rr, ww);
DBGF((DBGA,"media %f = %f\n",ww,rr));
if (rr > br) {
bw = ww;
br = rr;
}
}
if (br < ar)
br = ar; /* Make flat rather than slope to the right */
DBGF((DBGA,"Cuttoff line params: A = %f %f, B = %f %f\n", aw, ar, bw, br));
#ifdef STOCKFWA /* Use table shape as FWA basis */
/* Compute an Em that explains the bump over the flat line */
Em = 0.0;
for (ww = FWA1_emit.spec_wl_short; ww <= (FWA1_emit.spec_wl_long - 100.0); ww += p->bw) {
double Rl, rr;
/* Compute value of line at this wavelength */
Rl = (ww - aw)/(bw - aw) * (br - ar) + ar;
getval_lxspec(&p->imedia, &rr, ww); /* Media at this point */
if (rr > Rl) { /* Media is over the line */
double Ii;
double Eu;
double mm;
getval_lxspec(&p->iillum, &Ii, ww); /* Normalised illuminant at this wavelength */
if (Ii < 1e-9)
Ii = 1e-9;
getval_lxspec(&FWA1_emit, &Eu, ww); /* FWA emission at this wavelength */
mm = ((rr - Rl) * Ii)/Eu;
if (mm > Em) {
DBGF((DBGA,"Update Em to %f at %fnm for target %f\n",mm,ww,rr-Rl));
Em = mm; /* Greater multiplier to explain bump */
}
}
}
DBGF((DBGA,"Em = %f\n",Em));
/* Setup spectrum to hold result over exected range */
/* and base media reflectance */
p->media = p->imedia; /* Take copy of media white */
p->emits = p->imedia; /* Structure copy */
xspect_denorm(&p->media); /* Set norm to 1.0 */
xspect_denorm(&p->emits);
/* Copy emission spectra that explains bump over line */
/* plus estimated media without FWA spectrum. */
for (i = 0; i < p->media.spec_n; i++) {
double Eu, Ii;
double Rm, Rmb;
#if defined(__APPLE__) && defined(__POWERPC__)
gcc_bug_fix(i);
#endif
ww = (p->media.spec_wl_long - p->media.spec_wl_short)
* ((double)i/(p->media.spec_n-1.0)) + p->media.spec_wl_short;
getval_lxspec(&FWA1_emit, &Eu, ww); /* FWA emission at this wavelength */
Eu *= Em;
p->emits.spec[i] = p->emits.norm * Eu; /* Remember FWA spectrum */
Rm = p->media.spec[i]/p->media.norm; /* Media at this point */
getval_lxspec(&p->iillum, &Ii, ww); /* Normalised illuminant at this wavelength */
if (Ii < 1e-9)
Ii = 1e-9;
Rm *= Ii; /* Light reflected from media */
Rmb = Rm - Eu; /* Convert media to base media */
if (Rmb < 0.01)
Rmb = 0.01; /* This would be silly */
p->media.spec[i] = p->media.norm * Rmb/Ii; /* Convert media to base media */
DBGF((DBGA,"ww %f, Eu %f, Rm %f, Rmb %f\n",ww, Eu, Rm, Rmb));
}
/* Prevent silliness */
p->emits.spec[0] = 0.0;
p->emits.spec[p->emits.spec_n-1] = 0.0;
#else /* Not STOCK_FWA */
/* Setup spectrum to hold result over exected range */
/* and base media reflectance */
p->media = p->imedia; /* Take copy of media white */
p->emits = p->imedia; /* Structure copy */
xspect_denorm(&p->media); /* Set norm to 1.0 */
xspect_denorm(&p->emits);
/* Compute emission spectra that explains bump over line */
/* plus estimated media without FWA spectrum. */
/* Do this from long to short to allow for "filter off" trigger */
flag = 1; /* Filter is active */
for (i = (p->media.spec_n-1); i >= 0; i--) {
double Rl, Rm, Rmb;
double fwi = 25.0; /* Smoothing filter width +/- */
int fres = 5; /* Smoothing filter resolution */
double tweight;
#if defined(__APPLE__) && defined(__POWERPC__)
gcc_bug_fix(i);
#endif
/* Wavelength we're generating */
ww = (p->media.spec_wl_long - p->media.spec_wl_short)
* ((double)i/(p->media.spec_n-1.0)) + p->media.spec_wl_short;
/* Compute the base media estimate at this point from */
/* the triangular smoothed filter of the smaller of the */
/* measured media and the line */
tweight = 0.0;
Rmb = 0.0;
for (j = -fres; j <= fres; j++) {
double fww, weight;
#if defined(__APPLE__) && defined(__POWERPC__)
gcc_bug_fix(j);
#endif
fww = ww + (double)j/(double)fres * fwi;
weight = 1.0 - fabs((double)j/(double)fres);
Rl = (fww - aw)/(bw - aw) * (br - ar) + ar; /* Line at this point */
getval_lxspec(&p->imedia, &Rm, fww); /* Media at this point */
if (Rm < Rl)
Rl = Rm;
Rmb += Rl * weight;
tweight += weight;
}
Rmb /= tweight; /* Base media estimate */
/* Compute value of line and media at this wavelength */
Rl = (ww - aw)/(bw - aw) * (br - ar) + ar; /* Line at this point */
getval_lxspec(&p->imedia, &Rm, ww); /* Media at this point */
DBGF((DBGA,"ww %f, Rl %f, Rm %f, Rmb %f\n",ww,Rl,Rm,Rmb));
/* Stop following the filter once the actual media has crossed over it */
if (ww < 450.0 && Rm < Rmb)
flag = 0;
/* Don't follow smoothed at long wl or if media has caught up to filtered */
if (flag == 0 || ww > 570.0)
Rmb = Rm;
if (Rm > Rmb && ww <= 570.0) { /* Media is over the line */
double Ii;
p->media.spec[i] = p->media.norm * Rmb; /* Convert media to base media */
getval_lxspec(&p->iillum, &Ii, ww); /* Normalised illuminant at this wavelength */
if (Ii < 1e-9)
Ii = 1e-9;
p->emits.spec[i] = p->emits.norm * (Rm - Rmb) * Ii;
DBGF((DBGA,"ww %fnm, Rm %f, Rmb %f, Eu %f\n",ww, Rm, Rmb, p->emits.spec[i]/p->emits.norm));
} else {
p->emits.spec[i] = 0.0;
}
#ifdef DOPLOT
xx[i] = ww;
y1[i] = Rl;
y2[i] = Rm;
y3[i] = Rmb;
y4[i] = p->emits.spec[i]/p->emits.norm;
#endif
}
#ifdef DOPLOT
printf("Estimated vs. real media spectrum calculation\n");
do_plot6(xx,y1,y2,y3,y4,NULL,NULL,p->media.spec_n);
#endif
/* Prevent silliness */
p->emits.spec[0] = 0.0;
p->emits.spec[p->emits.spec_n-1] = 0.0;
#endif /* !STOCKFWA */
/* Compute level of UV stimulating FWA */
p->Sm = 0.0;
for (ww = FWA1_stim.spec_wl_short; ww <= FWA1_stim.spec_wl_long; ww += p->bw) {
double Ii;
double Su;
getval_lxspec(&p->iillum, &Ii, ww); /* Normalised illuminant at this wavelength */
if (Ii < 1e-9)
Ii = 1e-9;
getval_lxspec(&FWA1_stim, &Su, ww); /* FWA stimulation profile at this wavelength */
p->Sm += Su * Ii;
}
DBGF((DBGA,"Sm = %f\n",p->Sm));
/* Compute FWA content of this media, for information purposes */
p->FWAc = 0.0;
for (ww = p->emits.spec_wl_short; ww <= p->emits.spec_wl_long; ww += p->bw) {
double Eu;
getval_lxspec(&p->emits, &Eu, ww); /* FWA emission at this wavelength */
p->FWAc += Eu;
}
p->FWAc /= p->Sm; /* Divided by stimulation */
DBGF((DBGA,"FWA content = %f\n",p->FWAc));
/* Turn on FWA compensation */
p->convert = xsp2cie_fwa_convert;
p->sconvert = xsp2cie_fwa_sconvert;
p->extract = xsp2cie_fwa_extract;
p->apply = xsp2cie_fwa_apply;
#if defined(DOPLOT) || defined(DEBUG)
/* Print the estimated vs. real media spectrum */
for (i = 0, ww = p->media.spec_wl_short; ww <= p->media.spec_wl_long; ww += 1.0, i++) {
double Rm; /* Real media reflectance */
double Rmb; /* Media reflectance without FWA */
double Rmd; /* Estimated media reflectance with FWA */
double Ii;
double Eu;
getval_lxspec(&p->imedia, &Rm, ww); /* Media at this point */
getval_lxspec(&p->media, &Rmb, ww); /* Base Media */
getval_lxspec(&p->iillum, &Ii, ww); /* Normalised illuminant at this wavelength */
if (Ii < 1e-9)
Ii = 1e-9;
getval_lxspec(&p->emits, &Eu, ww); /* FWA emission at this wavelength */
Rmd = ((Ii * Rmb) + Eu)/Ii; /* Base Media plus FWA */
DBGF((DBGA,"%fnm, is %f should be %f, Rmb %f, Eu %f\n",ww, Rm, Rmd, Rmb, Eu));
#ifdef DOPLOT
xx[i] = ww;
// y1[i] = Rm;
y1[i] = Rmb;
y2[i] = Eu;
y3[i] = Rmd;
#endif
}
#ifdef DOPLOT
printf("Estimated vs. real media spectrum\n");
do_plot(xx,y1,y2,y3,i);
#endif
#endif /* DEBUG */
DBGF((DBGA,"We're done\n"));
return 0;
}
/* Set FWA given instrument illuminant and white media measurement */
static int xsp2cie_set_fwa(xsp2cie *p, /* this */
xspect *iillum, /* Spectrum of instrument illuminent */
xspect *tillum, /* Spectrum of target/simulated instrument illuminant */
/* NULL to use observer model illuminant. */
xspect *media /* Spectrum of plain media measured under that instrument */
) {
p->iillum = *iillum; /* Take copy of instrument illuminant */
xspect_denorm(&p->iillum); /* Remove normalisation factor */
if (tillum != NULL) {
p->tillum = *tillum; /* Take copy of target/simulated instrument illuminant */
xspect_denorm(&p->tillum); /* Remove normalisation factor */
} else {
p->tillum.spec_n = 0; /* Use observer model illum. as FWA source */
}
p->imedia = *media; /* Take copy of measured media */
return xsp2cie_set_fwa_imp(p);
}
/* Set FWA given updated conversion illuminants. */
/* We assume that xsp2cie_set_fwa has been called first. */
static int xsp2cie_update_fwa_custillum(
xsp2cie *p, /* this */
xspect *tillum, /* Spectrum of target/simulated instrument illuminant, */
/* NULL to use previous set_fwa() value. */
xspect *custIllum /* Spectrum of observer model illuminant */
/* NULL to use previous new_xsp2cie() value. */
) {
if (tillum != NULL) {
p->tillum = *tillum; /* Take copy of target/simulated instrument illuminant */
xspect_denorm(&p->tillum); /* Remove normalisation factor */
} else {
p->tillum.spec_n = 0; /* Use observer model illum. as FWA source */
}
if (custIllum != NULL) {
p->illuminant = *custIllum; /* Updated observer model illuminant */
}
return xsp2cie_set_fwa_imp(p);
}
/* Get Fluorescent Whitening Agent compensation information */
/* return NZ if error */
static void xsp2cie_get_fwa_info(
xsp2cie *p,
double *FWAc) {
if (FWAc != NULL)
*FWAc = p->FWAc;
}
/* Do the FWA corrected spectral to CIE conversion. */
/* If the instrument and target illuminant are the same, */
/* then FWA correction is bypassed. */
/* Note that the input spectrum normalisation value is used. */
/* Emissive spectral values are assumed to be in mW/nm, and sampled */
/* rather than integrated if they are not at 1nm spacing. */
static void xsp2cie_fwa_sconvert(
xsp2cie *p, /* this */
xspect *sout, /* Return corrected input spectrum (may be NULL, or same as imput) */
double *out, /* Return XYZ or D50 Lab value (may be NULL) */
xspect *in /* Spectrum to be converted */
) {
double ww;
int i, j, k;
double Emc, Smc; /* Emission and Stimulation multipiers for instrument meas. */
double Emct, Smct; /* Emission and Stimulation multipiers for target illum. */
double scale = 0.0;
xspect tsout; /* Temporary sout */
double wout[3]; /* Working CIE out */
#ifdef DEBUG
double chout[3]; /* Out check values */
double oout[3];
#endif /* DEBUG */
#ifdef DOPLOT_ALL_FWA
double xx[XSPECT_MAX_BANDS];
double y1[XSPECT_MAX_BANDS];
double y2[XSPECT_MAX_BANDS];
double y3[XSPECT_MAX_BANDS];
int plix = 0;
#endif /* DOPLOT_ALL_FWA */
tsout.spec_n = 0;
tsout.spec_wl_short = 0.0;
tsout.spec_wl_long = 0.0;
tsout.norm = 0.0;
#define MIN_ILLUM 1e-8 /* Minimum assumed illumination level at wavelength */
#define MIN_REFL 1e-6 /* Minimum assumed reflectance at wavelength */
/* With colorant, estimate stimulation level of FWA for instrument illuminant */
/* and for target illuminant. Because the colorant estimate depends on the FWA */
/* estimate, and the FWA emissions can contribute to FWA stimulation, */
/* we itterate a few times to allow this to converge. */
Emc = Emct = 0.0;
for (k = 0; k < 4; k++) {
Smct = Smc = 0.0;
for (ww = FWA1_stim.spec_wl_short; ww <= FWA1_stim.spec_wl_long; ww += p->bw) {
double Kc; /* FWA contribution for instrument illum */
double Kct; /* FWA contribution for target illum */
double Ii; /* Instrument illuminant level */
double It; /* Target illuminant level */
double Eu; /* FWA emmission profile */
double Rc; /* Measured reflectance under inst. illum. */
double Rmb; /* Media reflectance measured on instrument */
double Rcch; /* Half colorant reflectance value */
double Su; /* FWA sensitivity */
getval_lxspec(&p->emits, &Eu, ww); /* FWA emission at this wavelength */
Kc = Emc * Eu; /* FWA contribution under inst. illum. */
Kct = Emct * Eu; /* FWA contribution under target illum. */
getval_lxspec(&p->iillum, &Ii, ww); /* Normalised instr. illuminant at wavelength */
if (Ii < MIN_ILLUM)
Ii = MIN_ILLUM;
getval_lxspec(&p->tillum, &It, ww);/* Normalised target. illuminant at wavelength */
if (It < MIN_ILLUM)
It = MIN_ILLUM;
getval_lxspec(&p->media, &Rmb, ww); /* Base media reflectance at this wavelength */
if (Rmb < MIN_REFL)
Rmb = MIN_REFL;
getval_lxspec(in, &Rc, ww) ; /* Media + colorant reflectance at wavelength */
if (Rc < 0.0)
Rc = 0.0;
#ifdef NEVER
Rcch = sqrt(Rc/Rmb); /* Half reflectance estimate (valid if no FWA) */
#else
/* Solve for underlying colorant half reflectance, discounting FWA */
if (Rmb <= MIN_REFL) /* Hmm. */
Rcch = sqrt(fabs(Rmb));
else
Rcch = (-Kc + sqrt(Kc * Kc + 4.0 * Ii * Ii * Rmb * Rc))/(2.0 * Ii * Rmb);
#endif
getval_lxspec(&FWA1_stim, &Su, ww); /* FWA stimulation sensitivity this wavelength */
Smc += Su * (Ii * Rcch + Kc);
Smct += Su * (It * Rcch + Kct);
DBGF((DBGA,"at %.1fnm, Rmb %f, Rc %f, Rch %f, Rcch %f, Ii %f, It %f, Kct %f, Smc %f, Smct %f,\n",ww,Rmb,Rc,sqrt(Rc),Rcch,Ii,It,Kct,Su * (Ii * Rcch + Kc),Su * (It * Rcch + Kct)));
}
Emc = Smc/p->Sm; /* FWA Emmsion muliplier with colorant for instr. illum. */
Emct = Smct/p->Sm; /* FWA Emmsion muliplier with colorant for target illum. */
DBGF((DBGA,"Itteration %d, Smc %f, Smct %f, Emc %f, Emct %f\n\n",k, Smc,Smct,Emc,Emct));
}
for (j = 0; j < 3; j++) {
wout[j] = 0.0;
#ifdef DEBUG
chout[j] = 0.0;
#endif /* DEBUG */
}
/* Compute CIE output over observer range in 1nm increments */
scale = 0.0;
for (ww = p->observer[1].spec_wl_short; ww <= p->observer[1].spec_wl_long; ww += p->bw) {
double Kc; /* FWA contribution for instrument illum */
double Kct; /* FWA contribution for target illum */
double Ii; /* Instrument illuminant level */
double It; /* Target illuminant level */
double Io; /* Observer illuminant level */
double Rmb; /* Base media reflectance estimate */
double Eu; /* FWA emmission profile */
double Rc; /* Measured reflectance under inst. illum. */
/* Rch Measured half reflectance under inst. illum */
double Rcch; /* Corrected Rc colorant half reflectance */
double Rct; /* Corrected Rc for target illuminant */
getval_lxspec(&p->emits, &Eu, ww); /* FWA emission at this wavelength */
Kc = Emc * Eu; /* FWA contribution under inst. illum. */
Kct = Emct * Eu; /* FWA contribution under target illum. */
getval_lxspec(&p->iillum, &Ii, ww); /* Normalised instr. illuminant at wavelength */
if (Ii < MIN_ILLUM)
Ii = MIN_ILLUM;
getval_lxspec(&p->tillum, &It, ww);/* Normalised target. illuminant at wavelength */
if (It < MIN_ILLUM)
It = MIN_ILLUM;
getval_lxspec(&p->media, &Rmb, ww); /* Base media reflectance at this wavelength */
if (Rmb < MIN_REFL)
Rmb = MIN_REFL;
getval_lxspec(in, &Rc, ww) ; /* Media + colorant reflectance at wavelength */
if (Rc < 0.0)
Rc = 0.0;
/* Solve for underlying colorant half transmittance, discounting FWA */
if (Rmb <= MIN_REFL) /* Hmm. */
Rcch = sqrt(fabs(Rmb));
else
Rcch = (-Kc + sqrt(Kc * Kc + 4.0 * Ii * Ii * Rmb * Rc))/(2.0 * Ii * Rmb);
/* Estimated corrected reflectance */
Rct = ((It * Rcch * Rmb + Kct) * Rcch)/It;
DBGF((DBGA,"at %.1fnm, Rmb %f, Rc %f, Rch %f, Rcch %f, Ii %f, It %f, Kct %f, Rct %f\n",ww,Rmb,Rc,sqrt(Rc),Rcch,Ii,It,Kct,Rct));
if (p->insteqtarget) /* Ignore FWA corrected value if same illuminant */
Rct = Rc;
#ifdef DOPLOT_ALL_FWA
xx[plix] = ww;
y1[plix] = Rc; /* Uncorrected reflectance */
// y2[plix] = Rct - Rc; /* Difference between corrected and uncorrected */
// y2[plix] = Rcch * Rcch; /* Estimated underlying colorant reflectance without FWA */
// y2[plix] = Rmb; /* Base media relectance estimate */
y2[plix] = Kct; /* FWA contribution under target illuminant */
y3[plix++] = Rct; /* Corrected reflectance */
#endif /* DOPLOT_ALL_FWA */
/* Observer illuminant */
getval_lxspec(&p->oillum, &Io, ww); /* Normalised observer illuminant */
/* Compute CIE result */
for (j = 0; j < 3; j++) {
double O;
getval_lxspec(&p->observer[j], &O, ww);
if (j == 1)
scale += Io * O; /* Integrate Y illuminant/observer values */
wout[j] += Rct * Io * O; /* Corrected refl. * Observer illuminant */
#ifdef DEBUG
chout[j] += Rc * It * O;
#endif /* DEBUG */
}
}
if (p->isemis) {
scale = 0.683002; /* Convert from mW/m^2 to Lumens/m^2 */
/* (== 683 Luments/Watt/m^2) */
} else {
scale = 1.0/scale;
}
for (j = 0; j < 3; j++) { /* Scale for illuminant/observer normalisation of Y */
wout[j] *= scale;
#ifdef CLAMP_XYZ
if (p->clamp && wout[j] < 0.0)
wout[j] = 0.0; /* Just to be sure we don't get silly values */
#endif /* CLAMP_XYZ */
}
#ifdef DEBUG
for (j = 0; j < 3; j++) { /* Scale for illuminant/observer normalisation of Y */
chout[j] *= scale;
#ifdef CLAMP_XYZ
if (p->clamp && chout[j] < 0.0)
chout[j] = 0.0; /* Just to be sure we don't get silly values */
#endif /* CLAMP_XYZ */
}
icmXYZ2Lab(&icmD50, oout, wout);
icmXYZ2Lab(&icmD50, chout, chout);
DBGF((DBGA,"Compensated %f %f %f, uncompensated %f %f %f\n",
oout[0], oout[1], oout[2], chout[0], chout[1], chout[2]));
#endif /* DEBUG */
#ifdef DOPLOT_ALL_FWA
printf("FWA compensated spectrum for sample\n");
do_plot(xx,y1,y2,y3,plix);
#endif /* DOPLOT_ALL_FWA */
/* Do it again for output over optional returned spectrum range */
if (sout != NULL) {
tsout.spec_n = in->spec_n;
tsout.spec_wl_short = in->spec_wl_short;
tsout.spec_wl_long = in->spec_wl_long;
tsout.norm = in->norm;
for (i = 0; i < in->spec_n; i++) {
double Kc; /* FWA contribution for instrument illum */
double Kct; /* FWA contribution for target illum */
double Ii; /* Instrument illuminant level */
double It; /* Target/simulated instrument illuminant level */
double Rmb; /* Base media reflectance estimate */
double Eu; /* FWA emmission profile */
double Rc; /* Reflectance under inst. illum. */
double Rcch; /* Corrected Rc half reflectance */
double Rct; /* Corrected Rc for target illuminant */
#if defined(__APPLE__) && defined(__POWERPC__)
gcc_bug_fix(i);
#endif
ww = (in->spec_wl_long - in->spec_wl_short)
* ((double)i/(in->spec_n-1.0)) + in->spec_wl_short;
getval_lxspec(&p->emits, &Eu, ww); /* FWA emission at this wavelength */
Kc = Emc * Eu; /* FWA contribution under inst. illum. */
Kct = Emct * Eu; /* FWA contribution under target illum. */
getval_lxspec(&p->iillum, &Ii, ww); /* Normalised instr. illuminant at wavelength */
if (Ii < MIN_ILLUM)
Ii = MIN_ILLUM;
getval_lxspec(&p->tillum, &It, ww);/* Normalised target. illuminant at wavelength */
if (It < MIN_ILLUM)
It = MIN_ILLUM;
getval_lxspec(&p->media, &Rmb, ww); /* Base media reflectance at this wavelength */
if (Rmb < MIN_REFL)
Rmb = MIN_REFL;
getval_lxspec(in, &Rc, ww) ; /* Media + colorant reflectance at wavelength */
if (Rc < 0.0)
Rc = 0.0;
if (Rmb < MIN_REFL) /* Hmm. */
Rcch = sqrt(fabs(Rmb));
else
Rcch = (-Kc + sqrt(Kc * Kc + 4.0 * Ii * Ii * Rmb * Rc))/(2.0 * Ii * Rmb);
Rct = ((It * Rcch * Rmb + Kct) * Rcch)/It;
if (p->insteqtarget) /* Ignore FWA corrected value if same illuminant */
Rct = Rc;
tsout.spec[i] = tsout.norm * Rct;
}
}
/* If Lab is target, convert to D50 Lab */
if (p->doLab) {
icmXYZ2Lab(&icmD50, wout, wout);
}
if (out != NULL) {
out[0] = wout[0];
out[1] = wout[1];
out[2] = wout[2];
}
if (sout != NULL) {
*sout = tsout; /* Structure copy */
}
#undef MIN_ILLUM
#undef MIN_REFL
}
/* Normal conversion without returning spectrum */
static void xsp2cie_fwa_convert(xsp2cie *p, double *out, xspect *in) {
xsp2cie_fwa_sconvert(p, NULL, out, in);
}
/* Extract the colorant reflectance value from the media. Takes FWA */
/* into account if set. FWA must be set. */
static int xsp2cie_fwa_extract(xsp2cie *p, /* this */
xspect *out, /* Extracted colorant refl. spectrum */
xspect *in /* Spectrum to be converted, normalised by norm */
) {
double ww;
int i, j, k;
double Emc, Smc; /* Emission and Stimulation multipiers for instrument meas. */
#ifdef DOPLOT_ALL_FWA
double xx[XSPECT_MAX_BANDS];
double y1[XSPECT_MAX_BANDS];
double y2[XSPECT_MAX_BANDS];
double y3[XSPECT_MAX_BANDS];
int plix = 0;
#endif /* DOPLOT_ALL_FWA */
/* With colorant, estimate stimulation level of FWA for instrument illuminant */
/* and for target illuminant. Because the colorant estimate depends on the FWA */
/* estimate, and the FWA emissions can contribute to FWA stimulation, */
/* we itterate a few times to allow this to converge. */
Emc = 0.0;
for (k = 0; k < 4; k++) {
Smc = 0.0;
for (ww = FWA1_stim.spec_wl_short; ww <= FWA1_stim.spec_wl_long; ww += p->bw) {
double Kc; /* FWA contribution for instrument illum */
double Ii; /* Instrument illuminant level */
double Su; /* FWA sensitivity */
double Rmb; /* Media reflectance measured on instrument */
double Eu; /* FWA emmission profile */
double Rc; /* Reflectance under inst. illum. */
double Rcch; /* Half colorant reflectance value */
getval_lxspec(&p->emits, &Eu, ww); /* FWA emission at this wavelength */
Kc = Emc * Eu; /* FWA contribution under inst. illum. */
getval_lxspec(&p->media, &Rmb, ww); /* Base Media */
getval_lxspec(in, &Rc, ww); /* Media + colorant reflectance at wavelength + FWA */
getval_lxspec(&p->iillum, &Ii, ww); /* Normalised instrument illuminant */
if (Ii < 1e-9)
Ii = 1e-9;
if (Rmb < 1e-9) /* Hmm. */
Rcch = sqrt(fabs(Rmb));
else
Rcch = (-Kc + sqrt(Kc * Kc + 4.0 * Ii * Ii * Rmb * Rc))/(2.0 * Ii * Rmb);
getval_lxspec(&FWA1_stim, &Su, ww); /* FWA stimulation sensitivity this wavelength */
Smc += Su * (Ii * Rcch + Kc);
//DBGF((DBGA,"ww = %f, Rmb %f, Rcch %f, Ii %f, Su %f, Smc %f\n", ww,Rmb,Rcch,Ii,Su,Smc));
}
Emc = Smc/p->Sm; /* FWA Emmsion muliplier with colorant for instr. illum. */
}
DBGF((DBGA,"extract:\n"));
DBGF((DBGA,"Smc = %f\n",Smc));
DBGF((DBGA,"Emc = %f\n",Emc));
out->spec_n = in->spec_n;
out->spec_wl_short = in->spec_wl_short;
out->spec_wl_long = in->spec_wl_long;
out->norm = in->norm;
for (i = 0; i < in->spec_n; i++) {
double Kc; /* FWA contribution for instrument illum */
double Ii; /* Instrument illuminant level */
double Rmb; /* Base media reflectance estimate */
double Eu; /* FWA emmission profile */
double Rc; /* Reflectance under inst. illum. */
double Rcch; /* Corrected Rc half reflectance */
#if defined(__APPLE__) && defined(__POWERPC__)
gcc_bug_fix(i);
#endif
ww = (in->spec_wl_long - in->spec_wl_short)
* ((double)i/(in->spec_n-1.0)) + in->spec_wl_short;
getval_lxspec(&p->emits, &Eu, ww); /* FWA emission at this wavelength */
Kc = Emc * Eu; /* FWA contribution under inst. illum. */
getval_lxspec(&p->media, &Rmb, ww); /* Base Media */
getval_lxspec(in, &Rc, ww); /* Media + colorant reflectance at wavelength + FWA */
getval_lxspec(&p->iillum, &Ii, ww); /* Normalised instrument illuminant */
if (Ii < 1e-9)
Ii = 1e-9;
if (Rmb < 1e-9) /* Hmm. */
Rcch = sqrt(fabs(Rmb));
else
Rcch = (-Kc + sqrt(Kc * Kc + 4.0 * Ii * Ii * Rmb * Rc))/(2.0 * Ii * Rmb);
Rcch *= Rcch; /* Full reflectance value */
out->spec[i] = out->norm * Rcch;
#ifdef DOPLOT_ALL_FWA
xx[plix] = ww;
y1[plix] = Rmb; /* Base media */
y2[plix] = Rc; /* Uncorrected reflectance */
y3[plix] = Rcch; /* Underlying colorant reflectance without FWA */
plix++;
#endif /* DOPLOT_ALL_FWA */
}
#ifdef DOPLOT_ALL_FWA
printf("FWA compensated extraction for sample\n");
do_plot(xx,y1,y2,y3,plix);
#endif /* DOPLOT_ALL_FWA */
return 0;
}
/* Apply the colorant reflectance value from the media. Takes FWA */
/* into account if set. DOESN'T convert to FWA target illumination! */
/* FWA must be set. */
static int xsp2cie_fwa_apply(xsp2cie *p, /* this */
xspect *out, /* Applied refl. spectrum */
xspect *in /* Colorant reflectance to be applied */
) {
double ww;
int i, j, k;
double Emc, Smc; /* Emission and Stimulation multipiers for instrument meas. */
#ifdef DOPLOT_ALL_FWA
double xx[XSPECT_MAX_BANDS];
double y1[XSPECT_MAX_BANDS];
double y2[XSPECT_MAX_BANDS];
double y3[XSPECT_MAX_BANDS];
int plix = 0;
#endif /* DOPLOT_ALL_FWA */
/* With colorant, estimate stimulation level of FWA for instrument illuminant. */
/* We itterate a few times to allow for FWA self stimulation. */
Emc = 0.0;
for (k = 0; k < 4; k++) {
Smc = 0.0;
for (ww = FWA1_stim.spec_wl_short; ww <= FWA1_stim.spec_wl_long; ww += p->bw) {
double Kc; /* FWA contribution for instrument illum */
double Ii; /* Instrument illuminant level */
double Eu; /* FWA emmission profile */
double Su; /* FWA sensitivity */
double Rcch; /* Half colorant reflectance value */
getval_lxspec(&p->emits, &Eu, ww); /* FWA emission at this wavelength */
Kc = Emc * Eu; /* FWA contribution under inst. illum. */
getval_lxspec(in, &Rcch, ww); /* Colorant reflectance at wavelength */
Rcch = sqrt(Rcch); /* Half reflectance estimate (valid if no FWA) */
getval_lxspec(&p->iillum, &Ii, ww); /* Normalised instr. illuminant at wavelength */
if (Ii < 1e-9)
Ii = 1e-9;
getval_lxspec(&FWA1_stim, &Su, ww); /* FWA stimulation sensitivity this wavelength */
Smc += Su * (Ii * Rcch + Kc);
//DBGF((DBGA,"ww = %f, Rcch %f, Ii %f, Su %f, Smc %f\n", ww,Rcch,Ii,Su,Smc));
}
Emc = Smc/p->Sm; /* FWA Emmsion muliplier with colorant for instr. illum. */
}
DBGF((DBGA,"apply:\n"));
DBGF((DBGA,"Smc = %f\n",Smc));
DBGF((DBGA,"Emc = %f\n",Emc));
out->spec_n = in->spec_n;
out->spec_wl_short = in->spec_wl_short;
out->spec_wl_long = in->spec_wl_long;
out->norm = in->norm;
for (i = 0; i < in->spec_n; i++) {
double Kc; /* FWA contribution for instrument illum */
double Ii; /* Instrument illuminant level */
double Rmb; /* Base media reflectance estimate */
double Eu; /* FWA emmission profile */
double Rc; /* Reflectance under inst. illum. */
double Rcch; /* Rc half reflectance */
double RcI; /* Reconstituted Rc for inst. illuminant times illuminant */
#if defined(__APPLE__) && defined(__POWERPC__)
gcc_bug_fix(i);
#endif
ww = (in->spec_wl_long - in->spec_wl_short)
* ((double)i/(in->spec_n-1.0)) + in->spec_wl_short;
getval_lxspec(&p->emits, &Eu, ww); /* FWA emission at this wavelength */
Kc = Emc * Eu; /* FWA contribution under inst. illum. */
getval_lxspec(&p->media, &Rmb, ww); /* Base Media */
getval_lxspec(in, &Rcch, ww); /* Colorant reflectance at wavelength */
Rcch = sqrt(Rcch); /* Half reflectance at wavelength */
if (Rmb < 1e-9) /* Hmm. */
Rcch = sqrt(fabs(Rmb));
getval_lxspec(&p->iillum, &Ii, ww); /* Normalised instrument illuminant */
if (Ii < 1e-9)
Ii = 1e-9;
RcI = (Ii * Rcch * Rmb + Kc) * Rcch;
out->spec[i] = out->norm * RcI/Ii; /* Reconstituted reflectance */
#ifdef DOPLOT_ALL_FWA
xx[plix] = ww;
y1[plix] = Rmb; /* Base media */
y2[plix] = Rcch; /* Underlying colorant reflectance without FWA */
y3[plix] = RcI/Ii; /* Reconstituted reflectance */
plix++;
#endif /* DOPLOT_ALL_FWA */
}
#ifdef DOPLOT_ALL_FWA
printf("FWA compensated application for sample\n");
do_plot(xx,y1,y2,y3,plix);
#endif /* DOPLOT_ALL_FWA */
return 0;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#endif /* !SALONEINSTLIB */
/* Do the normal spectral to CIE conversion. */
/* Note that the input spectrum normalisation value is used. */
/* Emissive spectral values are assumed to be in mW/nm, and sampled */
/* rather than integrated if they are not at 1nm spacing. */
void xsp2cie_sconvert(
xsp2cie *p, /* this */
xspect *sout, /* Return input spectrum (may be NULL) */
double *out, /* Return XYZ or D50 Lab value */
xspect *in /* Spectrum to be converted */
) {
int j;
double scale = 0.0;
/* Compute the XYZ values (normalised to 1.0) */
for (j = 0; j < 3; j++) {
double ww;
/* Integrate at 1nm intervals over the observer range (as */
/* per CIE recommendations). Lower resolution spectra are */
/* upsampled using linear/3rd order polinomial interpolated */
/* (also as per CIE recommendations), and consistent (?) with the */
/* assumption of a triangular spectral response made in the */
/* ANSI CGATS.5-1993 spec. If illumninant or material spectra */
/* values are truncated at the extremes, then the last valid values */
/* 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 = 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)
scale += I * O; /* Integrate Y illuminant/observer values */
out[j] += I * O * S;
}
}
if (p->isemis) {
scale = 0.683002; /* Convert from mW/m^2 to Lumens/m^2 */
/* (== 683 Luments/Watt/m^2) */
} else {
scale = 1.0/scale;
}
for (j = 0; j < 3; j++) { /* Scale for illuminant/observer normalisation of Y */
out[j] *= scale;
#ifdef CLAMP_XYZ
if (p->clamp && out[j] < 0.0)
out[j] = 0.0; /* Just to be sure we don't get silly values */
#endif /* CLAMP_XYZ */
}
#ifndef SALONEINSTLIB
/* If Lab is target, convert to D50 Lab */
if (p->doLab) {
icmXYZ2Lab(&icmD50, out, out);
}
#endif /* !SALONEINSTLIB */
if (sout != NULL) {
*sout = *in; /* Structure copy */
}
}
/* Normal Tristumulus conversion */
void xsp2cie_convert(xsp2cie *p, double *out, xspect *in) {
xsp2cie_sconvert(p, NULL, out, in);
}
/* Return the illuminant XYZ being used in the CIE XYZ/Lab conversion. */
/* Note that this will returne the 'E' illuminant XYZ for emissive. */
void xsp2cie_get_cie_il(xsp2cie *p, double *xyz) {
xspect sp;
standardIlluminant(&sp, icxIT_E, 0.0);
p->convert(p, xyz, &sp);
if (p->doLab)
icmLab2XYZ(&icmD50, xyz, xyz);
}
void xsp2cie_del(
xsp2cie *p
) {
free(p);
return;
}
/* Create and return a new spectral conversion object */
xsp2cie *new_xsp2cie(
icxIllumeType ilType, /* Illuminant */
xspect *custIllum, /* Optional custom illuminant */
icxObserverType obType, /* Observer */
xspect custObserver[3], /* Optional custom observer */
icColorSpaceSignature rcs, /* Return color space, icSigXYZData or D50 icSigLabData */
/* ** Must be icSigXYZData if SALONEINSTLIB ** */
icxClamping clamp /* NZ to clamp XYZ/Lab to be +ve */
) {
xsp2cie *p;
if ((p = (xsp2cie *) calloc(1,sizeof(xsp2cie))) == NULL)
return NULL;
p->isemis = 0;
switch (ilType) {
case icxIT_none:
p->illuminant = il_none; /* Emissive */
p->isemis = 1;
break;
case icxIT_custom:
p->illuminant = *custIllum; /* Struct copy */
break;
case icxIT_A:
p->illuminant = il_A;
break;
case icxIT_C:
p->illuminant = il_C;
break;
case icxIT_default:
case icxIT_D50:
p->illuminant = il_D50;
break;
case icxIT_D50M2:
if (il_D50M2.spec_n == 0)
uv_filter(&il_D50M2, &il_D50);
p->illuminant = il_D50M2;
break;
case icxIT_D55:
daylight_il(&p->illuminant, 5500.0);
break;
case icxIT_D65:
p->illuminant = il_D65;
break;
case icxIT_D75:
daylight_il(&p->illuminant, 7500.0);
case icxIT_E:
p->illuminant = il_none;
break;
#ifndef SALONEINSTLIB
case icxIT_F5:
p->illuminant = il_F5;
break;
case icxIT_F8:
p->illuminant = il_F8;
break;
case icxIT_F10:
p->illuminant = il_F10;
break;
case icxIT_Spectrocam:
p->illuminant = il_Spectrocam;
break;
#endif /* !SALONEINSTLIB */
default:
DBGF((DBGA,"new_xsp2cie() unrecognised illuminant 0x%x\n",ilType));
free(p);
return NULL;
}
/* Do 3 structure copies to record observer sensitivity curves */
switch (obType) {
case icxOT_custom:
p->observer[0] = custObserver[0];
p->observer[1] = custObserver[1];
p->observer[2] = custObserver[2];
break;
case icxOT_default:
case icxOT_CIE_1931_2:
p->observer[0] = ob_CIE_1931_2[0];
p->observer[1] = ob_CIE_1931_2[1];
p->observer[2] = ob_CIE_1931_2[2];
break;
case icxOT_CIE_1964_10:
p->observer[0] = ob_CIE_1964_10[0];
p->observer[1] = ob_CIE_1964_10[1];
p->observer[2] = ob_CIE_1964_10[2];
break;
#ifndef SALONEINSTLIB
case icxOT_Stiles_Burch_2:
p->observer[0] = ob_Stiles_Burch_2[0];
p->observer[1] = ob_Stiles_Burch_2[1];
p->observer[2] = ob_Stiles_Burch_2[2];
break;
case icxOT_Judd_Voss_2:
p->observer[0] = ob_Judd_Voss_2[0];
p->observer[1] = ob_Judd_Voss_2[1];
p->observer[2] = ob_Judd_Voss_2[2];
break;
case icxOT_CIE_1964_10c:
p->observer[0] = ob_CIE_1964_10c[0];
p->observer[1] = ob_CIE_1964_10c[1];
p->observer[2] = ob_CIE_1964_10c[2];
break;
case icxOT_Shaw_Fairchild_2:
p->observer[0] = ob_Shaw_Fairchild_2[0];
p->observer[1] = ob_Shaw_Fairchild_2[1];
p->observer[2] = ob_Shaw_Fairchild_2[2];
break;
#endif /* !SALONEINSTLIB */
default:
DBGF((DBGA,"new_xsp2cie() unrecognised observer type 0x%x\n",obType));
free(p);
return NULL;
}
if (rcs == icSigXYZData)
p->doLab = 0;
#ifndef SALONEINSTLIB
else if (rcs == icSigLabData)
p->doLab = 1;
#endif /* !SALONEINSTLIB */
else {
DBGF((DBGA,"new_xsp2cie() unrecognised CIE type 0x%x",rcs));
free(p);
return NULL;
}
p->clamp = clamp;
p->convert = xsp2cie_convert;
p->sconvert = xsp2cie_sconvert;
p->get_cie_il = xsp2cie_get_cie_il;
#ifndef SALONEINSTLIB
p->set_mw = xsp2cie_set_mw; /* Default no media white */
p->set_fwa = xsp2cie_set_fwa; /* Default no FWA compensation */
p->update_fwa_custillum = xsp2cie_update_fwa_custillum;
p->get_fwa_info = xsp2cie_get_fwa_info;
p->extract = xsp2cie_extract;
p->apply = xsp2cie_apply;
#endif /* !SALONEINSTLIB */
p->del = xsp2cie_del;
return p;
}
#ifndef SALONEINSTLIB
/* -------------------------------------------------------- */
/* 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];
if (standardObserver(sp, obType))
return 1;
if (min_wl != NULL)
*min_wl = sp[0]->spec_wl_short;
if (max_wl != NULL)
*max_wl = sp[0]->spec_wl_long;
return 0;
}
/* Return an XYZ that is on the spectrum locus for the given observer. */
/* wl is the input wavelength in the range icx_spectrum_locus_range(), */
/* and return clipped result if outside this range. */
/* Return nz if observer unknown. */
int icx_spectrum_locus(double xyz[3], double wl, icxObserverType obType) {
xspect *sp[3];
DBGF((DBGA,"icx_chrom_locus got obs %d wl %f\n",obType, wl));
if (standardObserver(sp, obType))
return 1;
if (wl < sp[0]->spec_wl_short)
wl = sp[0]->spec_wl_short;
if (wl > sp[0]->spec_wl_long)
wl = sp[0]->spec_wl_long;
xyz[0] = value_xspect(sp[0], wl);
xyz[1] = value_xspect(sp[1], wl);
xyz[2] = value_xspect(sp[2], wl);
DBGF((DBGA,"returning %f %f %f\n", xyz[0], xyz[1], xyz[2]));
return 0;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Pre-calculated spectral locuses of Daylight and Plankian at 5 Mired intervals, */
/* created using illlocus.c */
/* 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 */
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];
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);
}
/* Discourage going beyond ends of locus */
if (tp[0] < x->iloc->spec_wl_short ) {
rv += 5000.0 * (x->iloc->spec_wl_short - tp[0]);
} else if (tp[0] > x->iloc->spec_wl_long) {
rv += 5000.0 * (tp[0] - x->iloc->spec_wl_long);
}
//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) {
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];
}
/* Given a choice of temperature dependent illuminant (icxIT_Dtemp or icxIT_Ptemp), */
/* a color temperature and a Y value, return the corresponding XYZ */
/* An observer type can be chosen for interpretting the spectrum of the input and */
/* the illuminant. */
/* Return xyz[0] = -1.0 on erorr */
void icx_ill_ct2XYZ(
double xyz[3], /* Return the XYZ value */
icxIllumeType ilType, /* Type of illuminant, icxIT_Dtemp or icxIT_Ptemp */
icxObserverType obType, /* Observer, CIE_1931_2 or CIE_1964_10 */
int viscct, /* nz to use visual CIEDE2000, 0 to use CCT CIE 1960 UCS. */
double tin, /* Input temperature */
double Yin /* Input Y value */
) {
xspect *iloc; /* Locus to match to */
double cp[1], s[1];
if (ilType != icxIT_Dtemp && ilType != icxIT_Ptemp) {
xyz[0] = -1.0;
return;
}
if (obType != icxOT_CIE_1931_2 && obType != icxOT_CIE_1964_10) {
xyz[0] = -1.0;
return;
}
/* Locus to use */
if (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;
}
}
/* Convert temperature to mired */
tin = 1e6/tin;
/* Get XYZ for given temp in Mired. */
/* Will clip to limits of locus */
getval_raw_xspec3_lin(iloc, xyz, tin);
/* Scale by Yin */
xyz[0] *= Yin/xyz[1];
xyz[2] *= Yin/xyz[1];
xyz[1] = Yin;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - */
/* 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(
xslpoly *p
) {
// static CRITICAL_SECTION lock = { NULL, -1 };
static amutex_static(lock);
// InitializeCriticalSection(&(lock));
/* Prevent threads trying to multiply initialise the xslpoly */
// EnterCriticalSection(&(lock));
amutex_lock(lock);
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];
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];
}
}
/* 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;
}
p->nbb = ii;
//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 (static) 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 */
int icx_outside_spec_locus(xslpoly *p, double xyz[3]) {
int i, j, c;
xslpoly *poly;
double Yxy[3];
icmXYZ2Yxy(Yxy, xyz);
/* Quick test - bounding box */
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 ( ((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)
return 0;
/* Do point in poligon test */
/* (This could be speeded up in many ways) */
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;
}
/* -------------------------------------------------------- */
/* Status T log10 weightings */
/* 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 */
{
-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, -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 */
{
-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, -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.500,
1.000, 1.301, 2.000, 2.477, 3.176,
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, -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 */
{
-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,
4.957, 4.989, 5.000, 4.989, 4.956,
4.902, 4.827, 4.731, 4.593, 4.433,
4.238, 4.013, 3.749, 3.490, 3.188,
2.901, 2.622, 2.334, 2.041, 1.732,
1.431, 1.146, 0.500
}
}
};
/* Given a reflectance or transmition spectral product, (Relative */
/* to the scale factor), return status T CMYV log10 density values */
void xsp_Tdensity(
double *out, /* Return CMYV density */
xspect *in /* Spectral product to be converted */
) {
int j;
/* Compute the CMYV values (normalised to 1.0) */
for (j = 0; j < 4; j++) {
double ww;
double sum;
/* Integrate at 1nm intervals */
sum = out[j] = 0.0;
for (ww = denT[j].spec_wl_short; ww <= denT[j].spec_wl_long; ww += 1.0) {
double W, S;
getval_xspec(&denT[j], &W, ww);
getval_xspec(in, &S, ww);
W = pow(10.0, W); /* Convert from log to linear weighting */
sum += W; /* Sum of weightings */
out[j] += S * W;
}
out[j] /= sum; /* Normalise */
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 */
}
}
/* XYZ to status T density aproximate conversion matrix */
/* (Note we're multiplying by a 0.83 factor below to */
/* avoid some limiting for some XYZ values) */
static double xyz2tden[4][3] = {
{ 1.750557, -0.361811, -0.265150 }, /* Red density */
{ -0.919004, 1.861722, 0.105787 }, /* Green density */
{ -0.047821, 0.093820, 1.163331 }, /* Blue density */
{ 0.369966, 0.708047, -0.076312 } /* Visual density */
};
/* Given a reflectance or transmission XYZ value, */
/* return approximate status T CMYV log10 density values */
void icx_XYZ2Tdens(
double *out, /* Return aproximate CMYV log10 density */
double *in /* Input XYZ values */
) {
int i, j;
double den[4];
//DBGF((DBGA,"icx_XYZ2den got %f %f %f\n",in[0],in[1],in[2]));
for (i = 0; i < 4; i++) {
den[i] = 0.0;
for (j = 0; j < 3; j++)
den[i] += 0.83 * xyz2tden[i][j] * in[j];
//DBGF((DBGA,"icx_XYZ2den raw den %d = %f\n",i,den[i]));
if (den[i] < 0.00001)
den[i] = 0.00001; /* Just to be sure we don't get silly values */
else if (den[i] > 1.0)
den[i] = 1.0;
out[i] = -log10(den[i]); /* Convert to density */
}
//DBGF((DBGA,"icx_XYZ2den returning densities %f %f %f\n",out[0],out[1],out[2]));
}
/* Given a reflectance or transmission XYZ value, */
/* return log10 XYZ density values */
void icx_XYZ2dens(
double *out, /* Return log10 XYZ density */
double *in /* Input XYZ values */
) {
int i;
double den[3];
for (i = 0; i < 3; i++) {
den[i] = in[i];
if (den[i] < 0.00001)
den[i] = 0.00001; /* Just to be sure we don't get silly values */
else if (den[i] > 1.0)
den[i] = 1.0;
out[i] = -log10(den[i]); /* Convert to density */
}
}
/* Given an XYZ value, return sRGB values. */
/* This is a little slow if wp used */
void icx_XYZ2sRGB(
double *out, /* Return sRGB values */
double *wp, /* Input XYZ white point (D65 used if NULL) */
double *in /* Input XYZ values */
) {
int i, j;
double XYZ[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 }
};
/* Do a simple Von Kries between input white point and D65 */
if (wp != NULL) {
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];
}
/* Convert to sRGB cromaticities */
for (i = 0; i < 3; i++) {
out[i] = 0.0;
for (j = 0; j < 3; j++) {
out[i] += XYZ[j] * mat[i][j];
}
}
/* 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;
}
}
}
/* Given an RGB value, return XYZ values. */
/* This is a little slow */
void icx_sRGB2XYZ(
double *out, /* Return XYZ values */
double *wp, /* Output XYZ white point (D65 used if NULL, othewise Bradford) */
double *in /* Input sRGB values */
) {
int i, j;
double tmp[3];
double d65[3] = { 0.950543, 1.0, 1.089303 }; /* D65 */
double imat[3][3] = { /* sRGB absolute XYZ->RGB */
{ 0.4124, 0.3576, 0.1805 },
{ 0.2126, 0.7152, 0.0722 },
{ 0.0193, 0.1192, 0.9505 }
};
/* Undo gamma */
for (j = 0; j < 3; j++) {
if (in[j] < 0.04045)
tmp[j] = in[j]/12.92;
else
tmp[j] = pow((in[j] + 0.055)/1.055, 2.4);
}
/* Convert to XYZ cromaticities */
for (i = 0; i < 3; i++) {
out[i] = 0.0;
for (j = 0; j < 3; j++) {
out[i] += tmp[j] * imat[i][j];
}
}
/* Do a simple Bradford between D65 and wp */
if (wp != NULL) {
icmXYZNumber dst, src;
double vkmat[3][3];
icmAry2XYZ(src, d65);
icmAry2XYZ(dst, wp);
icmChromAdaptMatrix(ICM_CAM_BRADFORD, dst, src, vkmat);
icmMulBy3x3(out, vkmat, out);
}
}
/* 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 */
/* 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, -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) {
Yxy[1] = -4.6070e9/(ct * ct * ct) + 2.9678e6/(ct * ct) + 0.09911e3/ct + 0.244063;
} else {
Yxy[1] = -2.0064e9/(ct * ct * ct) + 1.9018e6/(ct * ct) + 0.24748e3/ct + 0.237040;
}
Yxy[2] = -3.000 * Yxy[1] * Yxy[1] + 2.870 * Yxy[1] - 0.275;
Yxy[0] = 1.0;
//DBGF((DBGA,"Yxy = %f %f %f\n",Yxy[0],Yxy[1],Yxy[2]));
/* Convert to XYZ */
icmYxy2XYZ(out, Yxy);
//DBGF((DBGA,"XYZ = %f %f %f\n",out[0],out[1],out[2]));
}
#endif
/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Given an illuminant definition and an observer model, return */
/* the normalised XYZ value for that spectrum. */
/* Return 0 on sucess, 1 on error */
int icx_ill_sp2XYZ(
double xyz[3], /* Return XYZ value with Y == 1 */
icxObserverType obType, /* Observer */
xspect custObserver[3], /* Optional custom observer */
icxIllumeType ilType, /* Type of illuminant, icxIT_Dtemp or icxIT_Ptemp */
double ct, /* Input temperature in degrees K */
xspect *custIllum /* Optional custom illuminant */
) {
xspect sp; /* Xspect to fill in */
xsp2cie *conv; /* Means of converting spectrum to XYZ */
if (ilType == icxIT_custom)
sp = *custIllum;
else if (standardIlluminant(&sp, ilType, ct) != 0)
return 1;
if ((conv = new_xsp2cie(icxIT_none, NULL, obType, custObserver, icSigXYZData, 1)) == NULL)
return 1;
conv->convert(conv, xyz, &sp);
conv->del(conv);
/* Normalise */
xyz[0] /= xyz[1];
xyz[2] /= xyz[1];
xyz[1] /= xyz[1];
return 0;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Context for optimiser callback */
typedef struct {
icxIllumeType ilType; /* Type of illuminant, icxIT_Dtemp or icxIT_Ptemp */
double xyz[3]; /* Target XYZ */
icmXYZNumber XYZ; /* Target as XYZ number */
xsp2cie *conv; /* Means of converting spectrum to XYZ */
int viscct; /* nz to use visual best match color temperature */
} cctctx;
static double cct_func(void *fdata, double tp[]) {
cctctx *x = (cctctx *)fdata;
double xyz[3]; /* Current value */
double lab1[3], lab2[3];
xspect sp;
double rv = 0.0;
icmXYZNumber *wp = &x->XYZ;
/* Compute the XYZ for the given temperature */
if (x->ilType == icxIT_Dtemp) {
if (daylight_il(&sp, tp[0]) != 0)
rv = 1e6;
} else {
if (planckian_il(&sp, tp[0]) != 0)
rv = 1e6;
}
if (rv == 0.0) {
x->conv->convert(x->conv, xyz, &sp);
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);
}
}
//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 given spectrum or XYZ. */
/* An observer type can be chosen for interpretting the spectrum of the input and */
/* the illuminant. */
/* Return -1 on erorr */
double icx_XYZ2ill_ct(
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 */
xspect custObserver[3], /* Optional custom observer */
double xyz[3], /* Input XYZ value, NULL if spectrum intead */
xspect *insp, /* Input spectrum value, NULL if xyz[] instead */
int viscct /* nz to use visual CIEDE2000, 0 to use CCT CIE 1960 UCS. */
) {
cctctx 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;
x.ilType = ilType;
if ((x.conv = new_xsp2cie(icxIT_none, NULL, obType, custObserver, icSigXYZData, 1)) == NULL)
return -1;
if (xyz == NULL) {
if (insp == NULL)
return -1.0;
x.conv->convert(x.conv, x.xyz, insp);
} else {
icmAry2Ary(x.xyz, xyz);
}
/* Normalise target */
x.xyz[0] /= x.xyz[1];
x.xyz[2] /= x.xyz[1];
x.xyz[1] /= x.xyz[1];
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 = 1000.0 + i * 2000.0;
if ((er = cct_func((void *)&x, &tc)) < ber) {
ber = er;
bct = tc;
}
//DBGF((DBGA,"tc = %f, er = %f\n",tc,er));
}
cp[0] = bct;
s[0] = 500.0;
/* Locate the CCT */
if (powell(&rv, 1, cp, s, 0.01, 1000, cct_func, (void *)&x, NULL, NULL) != 0) {
x.conv->del(x.conv);
return -1.0;
}
if (txyz != NULL) {
xspect sp;
if (x.ilType == icxIT_Dtemp) {
if (daylight_il(&sp, cp[0]) != 0) {
x.conv->del(x.conv);
txyz[0] = txyz[2] = txyz[1] = cp[0] = 0.0;
return cp[0];
}
} else {
if (planckian_il(&sp, cp[0]) != 0) {
x.conv->del(x.conv);
txyz[0] = txyz[2] = txyz[1] = cp[0] = 0.0;
return cp[0];
}
}
x.conv->convert(x.conv, txyz, &sp);
/* Make sure locus XYZ is Normalised */
txyz[0] /= txyz[1];
txyz[2] /= txyz[1];
txyz[1] /= txyz[1];
}
x.conv->del(x.conv);
//DBGF((DBGA,"returning %f with error %f delta E94 %f\n",cp[0],sqrt(rv)));
return cp[0];
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Convert UCS Yuv to chromatic adaptation Ycd */
static void UCSYuv2Ycd(double *out, double *in) {
double u, v;
u = in[1];
v = in[2];
out[0] = in[0];
out[1] = (4.0 - u - 10.0 * v)/v;
out[2] = (1.708 * v - 1.481 * u + 0.404)/v;
}
/* Compute the CIE1995 CRI: Ra */
/* Return < 0.0 on error */
/* If invalid is not NULL, set it to nz if CRI */
/* is invalid because the sample is not white enough. */
double icx_CIE1995_CRI(
int *invalid, /* if not NULL, set to nz if invalid */
xspect *sample /* Illuminant sample to compute CRI of */
) {
int i;
double cct;
xspect wts; /* Reference white spectrum */
xsp2cie *tocie;
double wt[3]; /* Reference white in CIE 1960 UCS */
icmXYZNumber wtn;
double wt_Ycd[3]; /* Ycd reference white */
double sa[3]; /* Sample white in CIE 1960 UCS */
double sa_Ycd[3]; /* Ycd sample white */
double dc; /* delta of sample to reference white in 1960 UCS */
double ref[8][3]; /* reference XYZ/1964 color space */
double sam[8][3]; /* sample XYZ/1964 color space */
double c_ad, d_ad; /* Chromatic adaptation scaling factors */
double cri = 0.0;
//DBGF((DBGA,"icx_CIE1995_CRI called\n"));
/* First find the standard 2 degree observer plankian CCT */
if ((cct = icx_XYZ2ill_ct(NULL, icxIT_Ptemp, icxOT_CIE_1931_2, NULL, NULL, sample, 0)) < 0.0)
return -1.0;
//DBGF((DBGA,"CCT = %f\n", cct));
/* Create a reference white spectrum with the same CCT */
if (cct < 5000.0) {
if (planckian_il(&wts, cct))
return -1.0;
} else {
if (daylight_il(&wts, cct))
return -1.0;
}
if ((tocie = new_xsp2cie(icxIT_none, NULL, icxOT_CIE_1931_2, NULL, icSigXYZData, 1)) == NULL)
return -1.0;
/* Compute the XYZ of the reference white and sample */
tocie->convert(tocie, wt, &wts);
tocie->convert(tocie, sa, sample);
//DBGF((DBGA,"XYZ white = %f %f %f\n",wt[0],wt[1],wt[2]));
//DBGF((DBGA,"XYZ sampl = %f %f %f\n",sa[0],sa[1],sa[2]));
/* Normalize the spectra so as to create a normalized white */
wts.norm *= wt[1];
sample->norm *= sa[1]; /* ~~~ shouldn't change sample!!!! ~~~~ */
tocie->convert(tocie, wt, &wts);
tocie->convert(tocie, sa, sample);
tocie->del(tocie);
//DBGF((DBGA,"norm XYZ white = %f %f %f\n",wt[0],wt[1],wt[2]));
//DBGF((DBGA,"norm XYZ sampl = %f %f %f\n",sa[0],sa[1],sa[2]));
/* Convert to perceptual CIE 1960 UCS */
icmAry2XYZ(wtn, wt); /* Use reference white as UCS white */
icmXYZ21960UCS(wt, wt); /* 1960 UCS Yuv reference white */
UCSYuv2Ycd(wt_Ycd, wt); /* Ycd version for chromatic adapation */
icmXYZ21960UCS(sa, sa); /* 1960 UCS Yuv sample white */
UCSYuv2Ycd(sa_Ycd, sa); /* Ycd version for chromatic adapation */
c_ad = wt_Ycd[1]/sa_Ycd[1]; /* Chromatic adaptation scaling factors */
d_ad = wt_Ycd[2]/sa_Ycd[2];
//DBGF((DBGA,"UCS white = %f %f %f\n",wt[0],wt[1],wt[2]));
//DBGF((DBGA,"UCS sampl = %f %f %f\n",sa[0],sa[1],sa[2]));
dc = sqrt((wt[1] - sa[1]) * (wt[1] - sa[1]) + (wt[2] - sa[2]) * (wt[2] - sa[2]));
//DBGF((DBGA,"dc = %f\n",dc));
//if (dc > 0.0054) DBGF((DBGA,"CRI is invalid\n"));
/* If dc > 0.0054 we should abort computing the CRI, */
/* but this means we fail on lots of real world lighting. */
if (invalid != NULL) {
if (dc > 0.0054)
*invalid = 1;
else
*invalid = 0;
}
/* Check out the delta E for each reflective sample */
if ((tocie = new_xsp2cie(icxIT_custom, &wts, icxOT_CIE_1931_2, NULL, icSigXYZData, 1)) == NULL)
return -1.0;
for (i = 0; i < 8; i++) {
tocie->convert(tocie, ref[i], &CIE1995_TCS[i]);
icmXYZ21964WUV(&wtn, ref[i], ref[i]);
//DBGF((DBGA,"ref samp %d = WUV %f %f %f\n", i,ref[i][0],ref[i][1],ref[i][2]));
}
tocie->del(tocie);
if ((tocie = new_xsp2cie(icxIT_custom, sample, icxOT_CIE_1931_2, NULL, icSigXYZData, 1)) == NULL)
return -1.0;
for (i = 0; i < 8; i++) {
double c, d;
tocie->convert(tocie, sam[i], &CIE1995_TCS[i]);
icmXYZ21960UCS(sam[i], sam[i]);
/* Do chromatic adaptation */
UCSYuv2Ycd(sam[i], sam[i]);
c = sam[i][1];
d = sam[i][2];
sam[i][1] = (10.872 + 0.404 * c * c_ad - 4.0 * d * d_ad)/
(16.518 + 1.481 * c * c_ad - 1.0 * d * d_ad);
sam[i][2] = (5.520)/
(16.518 + 1.481 * c * c_ad - 1.0 * d * d_ad);
icm1960UCS21964WUV(&wtn, sam[i], sam[i]);
//DBGF((DBGA,"sam samp %d = WUV %f %f %f\n", i,sam[i][0],sam[i][1],sam[i][2]));
}
tocie->del(tocie);
/* Compute the CRI */
for (i = 0; i < 8; i++) {
double de, tcri;
de = icmLabDE(ref[i], sam[i]);
tcri = 100.0 - 4.6 * de;
//DBGF((DBGA,"sample %d: de = %f, CRI = %f\n",i,de,tcri));
cri += tcri;
}
cri /= 8.0;
//DBGF((DBGA,"average CRI = %f\n",cri));
if (cri < 0.0)
cri = -1.0;
//DBGF((DBGA,"returning CRI = %f\n",cri));
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 */