1
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
9 // Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 // THE SOFTWARE.
28 //
29
30 // appleseed.foundation headers.
31 #include "foundation/image/color.h"
32 #include "foundation/image/colorspace.h"
33 #include "foundation/image/regularspectrum.h"
34 #include "foundation/math/vector.h"
35 #include "foundation/utility/gnuplotfile.h"
36 #include "foundation/utility/iostreamop.h"
37 #include "foundation/utility/test.h"
38
39 // Standard headers.
40 #include <cstddef>
41 #include <cstdio>
42 #include <vector>
43
44 using namespace foundation;
45 using namespace std;
46
TEST_SUITE(Foundation_Image_ColorSpace)47 TEST_SUITE(Foundation_Image_ColorSpace)
48 {
49 void resample_and_write(
50 FILE* file,
51 const size_t input_count,
52 const double input_wavelength[],
53 const double input_spectrum[],
54 const char* variable_name)
55 {
56 static const double output_wavelength[31] =
57 {
58 400.0, 410.0, 420.0, 430.0, 440.0, 450.0, 460.0, 470.0, 480.0, 490.0,
59 500.0, 510.0, 520.0, 530.0, 540.0, 550.0, 560.0, 570.0, 580.0, 590.0,
60 600.0, 610.0, 620.0, 630.0, 640.0, 650.0, 660.0, 670.0, 680.0, 690.0,
61 700.0
62 };
63
64 RegularSpectrum<double, 31> output_spectrum;
65 spectrum_to_spectrum(
66 input_count, input_wavelength, input_spectrum,
67 31, output_wavelength, &output_spectrum[0]);
68
69 fprintf(file, "const float %s[31] =\n", variable_name);
70 fprintf(file, "{\n");
71
72 for (int i = 0; i < 31; ++i)
73 {
74 const int wavelength = 400 + i * 10;
75 const double amplitude = output_spectrum[i];
76 fprintf(file, " %s%ff%s // %d nm\n",
77 amplitude >= 0.0f ? " " : "",
78 amplitude,
79 i < 30 ? "," : " ",
80 wavelength);
81 }
82
83 fprintf(file, "};\n\n");
84 }
85
86 TEST_CASE(ResamplePBRTBasisSpectra)
87 {
88 //
89 // Input basis spectra come from PBRT v3:
90 //
91 // https://github.com/mmp/pbrt-v3/blob/master/src/core/spectrum.cpp
92 //
93
94 const size_t SampleCount = 32;
95
96 static const double RGB2SpectLambda[SampleCount] =
97 {
98 380.000000, 390.967743, 401.935486, 412.903229, 423.870972, 434.838715,
99 445.806458, 456.774200, 467.741943, 478.709686, 489.677429, 500.645172,
100 511.612915, 522.580627, 533.548340, 544.516052, 555.483765, 566.451477,
101 577.419189, 588.386902, 599.354614, 610.322327, 621.290039, 632.257751,
102 643.225464, 654.193176, 665.160889, 676.128601, 687.096313, 698.064026,
103 709.031738, 720.000000f
104 };
105
106 static const double RGBRefl2SpectWhite[SampleCount] =
107 {
108 1.0618958571272863e+00, 1.0615019980348779e+00, 1.0614335379927147e+00,
109 1.0622711654692485e+00, 1.0622036218416742e+00, 1.0625059965187085e+00,
110 1.0623938486985884e+00, 1.0624706448043137e+00, 1.0625048144827762e+00,
111 1.0624366131308856e+00, 1.0620694238892607e+00, 1.0613167586932164e+00,
112 1.0610334029377020e+00, 1.0613868564828413e+00, 1.0614215366116762e+00,
113 1.0620336151299086e+00, 1.0625497454805051e+00, 1.0624317487992085e+00,
114 1.0625249140554480e+00, 1.0624277664486914e+00, 1.0624749854090769e+00,
115 1.0625538581025402e+00, 1.0625326910104864e+00, 1.0623922312225325e+00,
116 1.0623650980354129e+00, 1.0625256476715284e+00, 1.0612277619533155e+00,
117 1.0594262608698046e+00, 1.0599810758292072e+00, 1.0602547314449409e+00,
118 1.0601263046243634e+00, 1.0606565756823634e+00f};
119
120 static const double RGBRefl2SpectCyan[SampleCount] =
121 {
122 1.0414628021426751e+00, 1.0328661533771188e+00, 1.0126146228964314e+00,
123 1.0350460524836209e+00, 1.0078661447098567e+00, 1.0422280385081280e+00,
124 1.0442596738499825e+00, 1.0535238290294409e+00, 1.0180776226938120e+00,
125 1.0442729908727713e+00, 1.0529362541920750e+00, 1.0537034271160244e+00,
126 1.0533901869215969e+00, 1.0537782700979574e+00, 1.0527093770467102e+00,
127 1.0530449040446797e+00, 1.0550554640191208e+00, 1.0553673610724821e+00,
128 1.0454306634683976e+00, 6.2348950639230805e-01, 1.8038071613188977e-01,
129 -7.6303759201984539e-03, -1.5217847035781367e-04, -7.5102257347258311e-03,
130 -2.1708639328491472e-03, 6.5919466602369636e-04, 1.2278815318539780e-02,
131 -4.4669775637208031e-03, 1.7119799082865147e-02, 4.9211089759759801e-03,
132 5.8762925143334985e-03, 2.5259399415550079e-02f
133 };
134
135 static const double RGBRefl2SpectMagenta[SampleCount] =
136 {
137 9.9422138151236850e-01, 9.8986937122975682e-01, 9.8293658286116958e-01,
138 9.9627868399859310e-01, 1.0198955019000133e+00, 1.0166395501210359e+00,
139 1.0220913178757398e+00, 9.9651666040682441e-01, 1.0097766178917882e+00,
140 1.0215422470827016e+00, 6.4031953387790963e-01, 2.5012379477078184e-03,
141 6.5339939555769944e-03, 2.8334080462675826e-03, -5.1209675389074505e-11,
142 -9.0592291646646381e-03, 3.3936718323331200e-03, -3.0638741121828406e-03,
143 2.2203936168286292e-01, 6.3141140024811970e-01, 9.7480985576500956e-01,
144 9.7209562333590571e-01, 1.0173770302868150e+00, 9.9875194322734129e-01,
145 9.4701725739602238e-01, 8.5258623154354796e-01, 9.4897798581660842e-01,
146 9.4751876096521492e-01, 9.9598944191059791e-01, 8.6301351503809076e-01,
147 8.9150987853523145e-01, 8.4866492652845082e-01f
148 };
149
150 static const double RGBRefl2SpectYellow[SampleCount] =
151 {
152 5.5740622924920873e-03, -4.7982831631446787e-03, -5.2536564298613798e-03,
153 -6.4571480044499710e-03, -5.9693514658007013e-03, -2.1836716037686721e-03,
154 1.6781120601055327e-02, 9.6096355429062641e-02, 2.1217357081986446e-01,
155 3.6169133290685068e-01, 5.3961011543232529e-01, 7.4408810492171507e-01,
156 9.2209571148394054e-01, 1.0460304298411225e+00, 1.0513824989063714e+00,
157 1.0511991822135085e+00, 1.0510530911991052e+00, 1.0517397230360510e+00,
158 1.0516043086790485e+00, 1.0511944032061460e+00, 1.0511590325868068e+00,
159 1.0516612465483031e+00, 1.0514038526836869e+00, 1.0515941029228475e+00,
160 1.0511460436960840e+00, 1.0515123758830476e+00, 1.0508871369510702e+00,
161 1.0508923708102380e+00, 1.0477492815668303e+00, 1.0493272144017338e+00,
162 1.0435963333422726e+00, 1.0392280772051465e+00f
163 };
164
165 static const double RGBRefl2SpectRed[SampleCount] =
166 {
167 1.6575604867086180e-01, 1.1846442802747797e-01, 1.2408293329637447e-01,
168 1.1371272058349924e-01, 7.8992434518899132e-02, 3.2205603593106549e-02,
169 -1.0798365407877875e-02, 1.8051975516730392e-02, 5.3407196598730527e-03,
170 1.3654918729501336e-02, -5.9564213545642841e-03, -1.8444365067353252e-03,
171 -1.0571884361529504e-02, -2.9375521078000011e-03, -1.0790476271835936e-02,
172 -8.0224306697503633e-03, -2.2669167702495940e-03, 7.0200240494706634e-03,
173 -8.1528469000299308e-03, 6.0772866969252792e-01, 9.8831560865432400e-01,
174 9.9391691044078823e-01, 1.0039338994753197e+00, 9.9234499861167125e-01,
175 9.9926530858855522e-01, 1.0084621557617270e+00, 9.8358296827441216e-01,
176 1.0085023660099048e+00, 9.7451138326568698e-01, 9.8543269570059944e-01,
177 9.3495763980962043e-01, 9.8713907792319400e-01f
178 };
179
180 static const double RGBRefl2SpectGreen[SampleCount] =
181 {
182 2.6494153587602255e-03, -5.0175013429732242e-03, -1.2547236272489583e-02,
183 -9.4554964308388671e-03, -1.2526086181600525e-02, -7.9170697760437767e-03,
184 -7.9955735204175690e-03, -9.3559433444469070e-03, 6.5468611982999303e-02,
185 3.9572875517634137e-01, 7.5244022299886659e-01, 9.6376478690218559e-01,
186 9.9854433855162328e-01, 9.9992977025287921e-01, 9.9939086751140449e-01,
187 9.9994372267071396e-01, 9.9939121813418674e-01, 9.9911237310424483e-01,
188 9.6019584878271580e-01, 6.3186279338432438e-01, 2.5797401028763473e-01,
189 9.4014888527335638e-03, -3.0798345608649747e-03, -4.5230367033685034e-03,
190 -6.8933410388274038e-03, -9.0352195539015398e-03, -8.5913667165340209e-03,
191 -8.3690869120289398e-03, -7.8685832338754313e-03, -8.3657578711085132e-06,
192 5.4301225442817177e-03, -2.7745589759259194e-03f
193 };
194
195 static const double RGBRefl2SpectBlue[SampleCount] =
196 {
197 9.9209771469720676e-01, 9.8876426059369127e-01, 9.9539040744505636e-01,
198 9.9529317353008218e-01, 9.9181447411633950e-01, 1.0002584039673432e+00,
199 9.9968478437342512e-01, 9.9988120766657174e-01, 9.8504012146370434e-01,
200 7.9029849053031276e-01, 5.6082198617463974e-01, 3.3133458513996528e-01,
201 1.3692410840839175e-01, 1.8914906559664151e-02, -5.1129770932550889e-06,
202 -4.2395493167891873e-04, -4.1934593101534273e-04, 1.7473028136486615e-03,
203 3.7999160177631316e-03, -5.5101474906588642e-04, -4.3716662898480967e-05,
204 7.5874501748732798e-03, 2.5795650780554021e-02, 3.8168376532500548e-02,
205 4.9489586408030833e-02, 4.9595992290102905e-02, 4.9814819505812249e-02,
206 3.9840911064978023e-02, 3.0501024937233868e-02, 2.1243054765241080e-02,
207 6.9596532104356399e-03, 4.1733649330980525e-03f
208 };
209
210 static const double RGBIllum2SpectWhite[SampleCount] =
211 {
212 1.1565232050369776e+00, 1.1567225000119139e+00, 1.1566203150243823e+00,
213 1.1555782088080084e+00, 1.1562175509215700e+00, 1.1567674012207332e+00,
214 1.1568023194808630e+00, 1.1567677445485520e+00, 1.1563563182952830e+00,
215 1.1567054702510189e+00, 1.1565134139372772e+00, 1.1564336176499312e+00,
216 1.1568023181530034e+00, 1.1473147688514642e+00, 1.1339317140561065e+00,
217 1.1293876490671435e+00, 1.1290515328639648e+00, 1.0504864823782283e+00,
218 1.0459696042230884e+00, 9.9366687168595691e-01, 9.5601669265393940e-01,
219 9.2467482033511805e-01, 9.1499944702051761e-01, 8.9939467658453465e-01,
220 8.9542520751331112e-01, 8.8870566693814745e-01, 8.8222843814228114e-01,
221 8.7998311373826676e-01, 8.7635244612244578e-01, 8.8000368331709111e-01,
222 8.8065665428441120e-01, 8.8304706460276905e-01f
223 };
224
225 static const double RGBIllum2SpectCyan[SampleCount] =
226 {
227 1.1334479663682135e+00, 1.1266762330194116e+00, 1.1346827504710164e+00,
228 1.1357395805744794e+00, 1.1356371830149636e+00, 1.1361152989346193e+00,
229 1.1362179057706772e+00, 1.1364819652587022e+00, 1.1355107110714324e+00,
230 1.1364060941199556e+00, 1.1360363621722465e+00, 1.1360122641141395e+00,
231 1.1354266882467030e+00, 1.1363099407179136e+00, 1.1355450412632506e+00,
232 1.1353732327376378e+00, 1.1349496420726002e+00, 1.1111113947168556e+00,
233 9.0598740429727143e-01, 6.1160780787465330e-01, 2.9539752170999634e-01,
234 9.5954200671150097e-02, -1.1650792030826267e-02, -1.2144633073395025e-02,
235 -1.1148167569748318e-02, -1.1997606668458151e-02, -5.0506855475394852e-03,
236 -7.9982745819542154e-03, -9.4722817708236418e-03, -5.5329541006658815e-03,
237 -4.5428914028274488e-03, -1.2541015360921132e-02f
238 };
239
240 static const double RGBIllum2SpectMagenta[SampleCount] =
241 {
242 1.0371892935878366e+00, 1.0587542891035364e+00, 1.0767271213688903e+00,
243 1.0762706844110288e+00, 1.0795289105258212e+00, 1.0743644742950074e+00,
244 1.0727028691194342e+00, 1.0732447452056488e+00, 1.0823760816041414e+00,
245 1.0840545681409282e+00, 9.5607567526306658e-01, 5.5197896855064665e-01,
246 8.4191094887247575e-02, 8.7940070557041006e-05, -2.3086408335071251e-03,
247 -1.1248136628651192e-03, -7.7297612754989586e-11, -2.7270769006770834e-04,
248 1.4466473094035592e-02, 2.5883116027169478e-01, 5.2907999827566732e-01,
249 9.0966624097105164e-01, 1.0690571327307956e+00, 1.0887326064796272e+00,
250 1.0637622289511852e+00, 1.0201812918094260e+00, 1.0262196688979945e+00,
251 1.0783085560613190e+00, 9.8333849623218872e-01, 1.0707246342802621e+00,
252 1.0634247770423768e+00, 1.0150875475729566e+00f
253 };
254
255 static const double RGBIllum2SpectYellow[SampleCount] =
256 {
257 2.7756958965811972e-03, 3.9673820990646612e-03, -1.4606936788606750e-04,
258 3.6198394557748065e-04, -2.5819258699309733e-04, -5.0133191628082274e-05,
259 -2.4437242866157116e-04, -7.8061419948038946e-05, 4.9690301207540921e-02,
260 4.8515973574763166e-01, 1.0295725854360589e+00, 1.0333210878457741e+00,
261 1.0368102644026933e+00, 1.0364884018886333e+00, 1.0365427939411784e+00,
262 1.0368595402854539e+00, 1.0365645405660555e+00, 1.0363938240707142e+00,
263 1.0367205578770746e+00, 1.0365239329446050e+00, 1.0361531226427443e+00,
264 1.0348785007827348e+00, 1.0042729660717318e+00, 8.4218486432354278e-01,
265 7.3759394894801567e-01, 6.5853154500294642e-01, 6.0531682444066282e-01,
266 5.9549794132420741e-01, 5.9419261278443136e-01, 5.6517682326634266e-01,
267 5.6061186014968556e-01, 5.8228610381018719e-01f
268 };
269
270 static const double RGBIllum2SpectRed[SampleCount] =
271 {
272 5.4711187157291841e-02, 5.5609066498303397e-02, 6.0755873790918236e-02,
273 5.6232948615962369e-02, 4.6169940535708678e-02, 3.8012808167818095e-02,
274 2.4424225756670338e-02, 3.8983580581592181e-03, -5.6082252172734437e-04,
275 9.6493871255194652e-04, 3.7341198051510371e-04, -4.3367389093135200e-04,
276 -9.3533962256892034e-05, -1.2354967412842033e-04, -1.4524548081687461e-04,
277 -2.0047691915543731e-04, -4.9938587694693670e-04, 2.7255083540032476e-02,
278 1.6067405906297061e-01, 3.5069788873150953e-01, 5.7357465538418961e-01,
279 7.6392091890718949e-01, 8.9144466740381523e-01, 9.6394609909574891e-01,
280 9.8879464276016282e-01, 9.9897449966227203e-01, 9.8605140403564162e-01,
281 9.9532502805345202e-01, 9.7433478377305371e-01, 9.9134364616871407e-01,
282 9.8866287772174755e-01, 9.9713856089735531e-01f
283 };
284
285 static const double RGBIllum2SpectGreen[SampleCount] =
286 {
287 2.5168388755514630e-02, 3.9427438169423720e-02, 6.2059571596425793e-03,
288 7.1120859807429554e-03, 2.1760044649139429e-04, 7.3271839984290210e-12,
289 -2.1623066217181700e-02, 1.5670209409407512e-02, 2.8019603188636222e-03,
290 3.2494773799897647e-01, 1.0164917292316602e+00, 1.0329476657890369e+00,
291 1.0321586962991549e+00, 1.0358667411948619e+00, 1.0151235476834941e+00,
292 1.0338076690093119e+00, 1.0371372378155013e+00, 1.0361377027692558e+00,
293 1.0229822432557210e+00, 9.6910327335652324e-01, -5.1785923899878572e-03,
294 1.1131261971061429e-03, 6.6675503033011771e-03, 7.4024315686001957e-04,
295 2.1591567633473925e-02, 5.1481620056217231e-03, 1.4561928645728216e-03,
296 1.6414511045291513e-04, -6.4630764968453287e-03, 1.0250854718507939e-02,
297 4.2387394733956134e-02, 2.1252716926861620e-02f
298 };
299
300 static const double RGBIllum2SpectBlue[SampleCount] =
301 {
302 1.0570490759328752e+00, 1.0538466912851301e+00, 1.0550494258140670e+00,
303 1.0530407754701832e+00, 1.0579930596460185e+00, 1.0578439494812371e+00,
304 1.0583132387180239e+00, 1.0579712943137616e+00, 1.0561884233578465e+00,
305 1.0571399285426490e+00, 1.0425795187752152e+00, 3.2603084374056102e-01,
306 -1.9255628442412243e-03, -1.2959221137046478e-03, -1.4357356276938696e-03,
307 -1.2963697250337886e-03, -1.9227081162373899e-03, 1.2621152526221778e-03,
308 -1.6095249003578276e-03, -1.3029983817879568e-03, -1.7666600873954916e-03,
309 -1.2325281140280050e-03, 1.0316809673254932e-02, 3.1284512648354357e-02,
310 8.8773879881746481e-02, 1.3873621740236541e-01, 1.5535067531939065e-01,
311 1.4878477178237029e-01, 1.6624255403475907e-01, 1.6997613960634927e-01,
312 1.5769743995852967e-01, 1.9069090525482305e-01f
313 };
314
315 FILE* file = fopen("unit tests/outputs/test_colorspace_basis_spectra.cpp", "wt");
316
317 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBRefl2SpectWhite, "RGBToSpectrumWhiteReflectanceTab");
318 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBRefl2SpectCyan, "RGBToSpectrumCyanReflectanceTab");
319 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBRefl2SpectMagenta, "RGBToSpectrumMagentaReflectanceTab");
320 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBRefl2SpectYellow, "RGBToSpectrumYellowReflectanceTab");
321 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBRefl2SpectRed, "RGBToSpectrumRedReflectanceTab");
322 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBRefl2SpectGreen, "RGBToSpectrumGreenReflectanceTab");
323 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBRefl2SpectBlue, "RGBToSpectrumBlueReflectanceTab");
324
325 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBIllum2SpectWhite, "RGBToSpectrumWhiteIlluminanceTab");
326 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBIllum2SpectCyan, "RGBToSpectrumCyanIlluminanceTab");
327 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBIllum2SpectMagenta, "RGBToSpectrumMagentaIlluminanceTab");
328 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBIllum2SpectYellow, "RGBToSpectrumYellowIlluminanceTab");
329 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBIllum2SpectRed, "RGBToSpectrumRedIlluminanceTab");
330 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBIllum2SpectGreen, "RGBToSpectrumGreenIlluminanceTab");
331 resample_and_write(file, SampleCount, RGB2SpectLambda, RGBIllum2SpectBlue, "RGBToSpectrumBlueIlluminanceTab");
332
333 fclose(file);
334 }
335
336 #pragma warning (push)
337 #pragma warning (disable : 4723) // potential division by 0
338
339 TEST_CASE(TestHSVToLinearRGBConversion)
340 {
341 EXPECT_FEQ(Color3d(0.0, 0.0, 0.0), hsv_to_linear_rgb(Color3d(0.0, 0.0, 0.0)));
342 EXPECT_FEQ(Color3d(1.0, 0.0, 0.0), hsv_to_linear_rgb(Color3d(0.0, 1.0, 1.0)));
343 EXPECT_FEQ(Color3d(0.75, 0.75, 0.0), hsv_to_linear_rgb(Color3d(60.0, 1.0, 0.75)));
344 EXPECT_FEQ(Color3d(0.0, 0.5, 0.0), hsv_to_linear_rgb(Color3d(120.0, 1.0, 0.5)));
345 EXPECT_FEQ(Color3d(0.5, 0.5, 1.0), hsv_to_linear_rgb(Color3d(240.0, 0.5, 1.0)));
346 EXPECT_FEQ(Color3d(0.75, 0.25, 0.75), hsv_to_linear_rgb(Color3d(300.0, 2.0/3.0, 0.75)));
347 }
348
349 TEST_CASE(TestLinearRGBToHSVConversion)
350 {
351 EXPECT_FEQ(Color3d(0.0, 0.0, 0.0), linear_rgb_to_hsv(Color3d(0.0, 0.0, 0.0)));
352 EXPECT_FEQ(Color3d(0.0, 1.0, 1.0), linear_rgb_to_hsv(Color3d(1.0, 0.0, 0.0)));
353 EXPECT_FEQ(Color3d(60.0, 1.0, 0.75), linear_rgb_to_hsv(Color3d(0.75, 0.75, 0.0)));
354 EXPECT_FEQ(Color3d(120.0, 1.0, 0.5), linear_rgb_to_hsv(Color3d(0.0, 0.5, 0.0)));
355 EXPECT_FEQ(Color3d(240.0, 0.5, 1.0), linear_rgb_to_hsv(Color3d(0.5, 0.5, 1.0)));
356 EXPECT_FEQ(Color3d(300.0, 2.0/3.0, 0.75), linear_rgb_to_hsv(Color3d(0.75, 0.25, 0.75)));
357 }
358
359 TEST_CASE(TestHSLToLinearRGBConversion)
360 {
361 EXPECT_FEQ(Color3d(0.0, 0.0, 0.0), hsl_to_linear_rgb(Color3d(0.0, 0.0, 0.0)));
362 EXPECT_FEQ(Color3d(1.0, 0.0, 0.0), hsl_to_linear_rgb(Color3d(0.0, 1.0, 0.5)));
363 EXPECT_FEQ(Color3d(0.75, 0.75, 0.0), hsl_to_linear_rgb(Color3d(60.0, 1.0, 0.375)));
364 EXPECT_FEQ(Color3d(0.0, 0.5, 0.0), hsl_to_linear_rgb(Color3d(120.0, 1.0, 0.25)));
365 EXPECT_FEQ(Color3d(0.5, 0.5, 1.0), hsl_to_linear_rgb(Color3d(240.0, 1.0, 0.75)));
366 EXPECT_FEQ(Color3d(0.75, 0.25, 0.75), hsl_to_linear_rgb(Color3d(300.0, 0.5, 0.5)));
367 }
368
369 TEST_CASE(TestLinearRGBToHSLConversion)
370 {
371 EXPECT_FEQ(Color3d(0.0, 0.0, 0.0), linear_rgb_to_hsl(Color3d(0.0, 0.0, 0.0)));
372 EXPECT_FEQ(Color3d(0.0, 1.0, 0.5), linear_rgb_to_hsl(Color3d(1.0, 0.0, 0.0)));
373 EXPECT_FEQ(Color3d(60.0, 1.0, 0.375), linear_rgb_to_hsl(Color3d(0.75, 0.75, 0.0)));
374 EXPECT_FEQ(Color3d(120.0, 1.0, 0.25), linear_rgb_to_hsl(Color3d(0.0, 0.5, 0.0)));
375 EXPECT_FEQ(Color3d(240.0, 1.0, 0.75), linear_rgb_to_hsl(Color3d(0.5, 0.5, 1.0)));
376 EXPECT_FEQ(Color3d(300.0, 0.5, 0.5), linear_rgb_to_hsl(Color3d(0.75, 0.25, 0.75)));
377 }
378
379 #pragma warning (pop)
380
381 TEST_CASE(TestCIEXYZToLinearRGBConversion)
382 {
383 const Color3d ciexyz(0.5, 0.7, 0.2);
384 const Color3d linear_rgb = ciexyz_to_linear_rgb(ciexyz);
385
386 EXPECT_FEQ_EPS(
387 Color3d(0.44452747702598583, 0.83687689900398254, 0.096456110477447538),
388 linear_rgb,
389 1.0e-6);
390 }
391
392 TEST_CASE(TestLinearRGBToCIEXYZConversion)
393 {
394 const Color3d linear_rgb(0.44452747702598583, 0.83687689900398254, 0.096456110477447538);
395 const Color3d ciexyz = linear_rgb_to_ciexyz(linear_rgb);
396
397 EXPECT_FEQ_EPS(
398 Color3d(0.5, 0.7, 0.2),
399 ciexyz,
400 1.0e-5);
401 }
402
403 TEST_CASE(TestCIEXYZToCIExyYConversion)
404 {
405 const Color3d ciexyz(0.5, 0.7, 0.2);
406 const Color3d ciexyy = ciexyz_to_ciexyy(ciexyz);
407
408 EXPECT_FEQ_EPS(
409 Color3d(0.357143, 0.5, 0.7),
410 ciexyy,
411 1.0e-6);
412 }
413
414 TEST_CASE(TestCIExyYToCIEXYZConversion)
415 {
416 const Color3d ciexyy(0.357143, 0.5, 0.7);
417 const Color3d ciexyz = ciexyy_to_ciexyz(ciexyy);
418
419 EXPECT_FEQ_EPS(
420 Color3d(0.5, 0.7, 0.2),
421 ciexyz,
422 1.0e-5);
423 }
424
425 TEST_CASE(TestLinearRGBTosRGBConversion)
426 {
427 const Color3d linear_rgb(0.5, 0.7, 0.2);
428 const Color3d srgb = linear_rgb_to_srgb(linear_rgb);
429
430 EXPECT_FEQ_EPS(
431 Color3d(0.73535698305244945, 0.85430583154494000, 0.48452920448170694),
432 srgb,
433 1.0e-6);
434 }
435
436 TEST_CASE(TestsRGBToLinearRGBConversion)
437 {
438 const Color3d srgb(0.73535698305244945, 0.85430583154494000, 0.48452920448170694);
439 const Color3d linear_rgb = srgb_to_linear_rgb(srgb);
440
441 EXPECT_FEQ_EPS(
442 Color3d(0.5, 0.7, 0.2),
443 linear_rgb,
444 1.0e-6);
445 }
446
447 TEST_CASE(TestFastLinearRGBTosRGBConversion)
448 {
449 const Color3f linear_rgb(0.5f, 0.7f, 0.2f);
450 const Color3f srgb = fast_linear_rgb_to_srgb(linear_rgb);
451
452 EXPECT_FEQ_EPS(
453 Color3f(0.735361f, 0.854277f, 0.484509f),
454 srgb,
455 1.0e-5f);
456 }
457
458 TEST_CASE(TestFastsRGBToLinearRGBConversion)
459 {
460 const Color3f srgb(0.73535698f, 0.85430583f, 0.48452920f);
461 const Color3f linear_rgb = fast_srgb_to_linear_rgb(srgb);
462
463 EXPECT_FEQ_EPS(
464 Color3f(0.499996f, 0.69986f, 0.199976f),
465 linear_rgb,
466 1.0e-5f);
467 }
468
469 static RegularSpectrum31f get_white_spectrum()
470 {
471 // The white color from the Cornell Box scene.
472 static const float Values[31] =
473 {
474 0.343000f, 0.591563f, 0.687000f, 0.720250f, 0.745000f, 0.751188f, 0.765000f, 0.747312f,
475 0.745000f, 0.751500f, 0.747000f, 0.735625f, 0.725000f, 0.729312f, 0.743000f, 0.739000f,
476 0.733000f, 0.724813f, 0.764000f, 0.733563f, 0.740000f, 0.751063f, 0.744000f, 0.739438f,
477 0.712000f, 0.731000f, 0.707000f, 0.740500f, 0.751000f, 0.725438f, 0.737000f
478 };
479 return RegularSpectrum31f::from_array(Values);
480 }
481
482 TEST_CASE(TestSpectrumToCIEXYZConversion)
483 {
484 const RegularSpectrum31f spectrum = get_white_spectrum();
485 const LightingConditions lighting_conditions(IlluminantCIED65, XYZCMFCIE19312Deg);
486 const Color3f ciexyz = spectrum_to_ciexyz<float>(lighting_conditions, spectrum);
487
488 EXPECT_FEQ_EPS(
489 Color3f(0.701480f, 0.73824f, 0.804104f),
490 ciexyz,
491 1.0e-6f);
492 }
493
494 TEST_CASE(TestCIEXYZReflectanceToSpectrumConversion)
495 {
496 const Color3f ciexyz(0.699385f, 0.738633f, 0.790319f);
497
498 RegularSpectrum31f spectrum;
499 ciexyz_reflectance_to_spectrum(ciexyz, spectrum);
500
501 const float ExpectedSpectrumValues[31] =
502 {
503 0.768140f, 0.768643f, 0.768740f, 0.768869f, 0.769037f, 0.769489f, 0.770708f, 0.772643f,
504 0.775606f, 0.778692f, 0.781363f, 0.783471f, 0.785352f, 0.785766f, 0.786007f, 0.786419f,
505 0.786571f, 0.786511f, 0.786198f, 0.784935f, 0.783728f, 0.782956f, 0.782881f, 0.782790f,
506 0.782736f, 0.782879f, 0.782436f, 0.781264f, 0.780612f, 0.781049f, 0.781204f
507 };
508
509 EXPECT_FEQ_EPS(
510 RegularSpectrum31f::from_array(ExpectedSpectrumValues),
511 spectrum,
512 1.0e-6f);
513 }
514
515 TEST_CASE(TestSpectrumToSpectrumConversion)
516 {
517 static const float InputWavelength[RegularSpectrum31f::Samples] =
518 {
519 400.0f, 410.0f, 420.0f, 430.0f, 440.0f, 450.0f, 460.0f, 470.0f, 480.0f, 490.0f,
520 500.0f, 510.0f, 520.0f, 530.0f, 540.0f, 550.0f, 560.0f, 570.0f, 580.0f, 590.0f,
521 600.0f, 610.0f, 620.0f, 630.0f, 640.0f, 650.0f, 660.0f, 670.0f, 680.0f, 690.0f,
522 700.0f
523 };
524 const RegularSpectrum31f input_spectrum = get_white_spectrum();
525
526 typedef RegularSpectrum<float, 4> RegularSpectrum4f;
527
528 static const float OutputWavelength[RegularSpectrum4f::Samples] =
529 {
530 400.0f, 500.0f, 600.0f, 700.0f
531 };
532
533 RegularSpectrum4f output_spectrum;
534 spectrum_to_spectrum(
535 input_spectrum.Samples,
536 InputWavelength,
537 &input_spectrum[0],
538 output_spectrum.Samples,
539 OutputWavelength,
540 &output_spectrum[0]);
541
542 const float ExpectedOutputSpectrumValues[4] =
543 {
544 0.343f, 0.747f, 0.74f, 0.737f
545 };
546
547 EXPECT_FEQ_EPS(
548 RegularSpectrum4f::from_array(ExpectedOutputSpectrumValues),
549 output_spectrum,
550 1.0e-6f);
551 }
552
553 vector<Vector2d> zip(const double x[], const double y[], const size_t count)
554 {
555 vector<Vector2d> points(count);
556
557 for (size_t i = 0; i < count; ++i)
558 {
559 points[i].x = x[i];
560 points[i].y = y[i];
561 }
562
563 return points;
564 }
565
566 TEST_CASE(GeneratePlotFilesToVisualizeSpectrumResampling)
567 {
568 // Input wavelengths for white, green and red spectra.
569 static const size_t InputSpectrumCount = 76;
570 static const double InputSpectrumWavelength[InputSpectrumCount] =
571 {
572 400.0, 404.0, 408.0, 412.0, 416.0, 420.0, 424.0, 428.0, 432.0, 436.0,
573 440.0, 444.0, 448.0, 452.0, 456.0, 460.0, 464.0, 468.0, 472.0, 476.0,
574 480.0, 484.0, 488.0, 492.0, 496.0, 500.0, 504.0, 508.0, 512.0, 516.0,
575 520.0, 524.0, 528.0, 532.0, 536.0, 540.0, 544.0, 548.0, 552.0, 556.0,
576 560.0, 564.0, 568.0, 572.0, 576.0, 580.0, 584.0, 588.0, 592.0, 596.0,
577 600.0, 604.0, 608.0, 612.0, 616.0, 620.0, 624.0, 628.0, 632.0, 636.0,
578 640.0, 644.0, 648.0, 652.0, 656.0, 660.0, 664.0, 668.0, 672.0, 676.0,
579 680.0, 684.0, 688.0, 692.0, 696.0, 700.0
580 };
581
582 // Input white spectrum.
583 static const double InputWhiteSpectrum[InputSpectrumCount] =
584 {
585 0.343, 0.445, 0.551, 0.624, 0.665, 0.687, 0.708, 0.723, 0.715, 0.710,
586 0.745, 0.758, 0.739, 0.767, 0.777, 0.765, 0.751, 0.745, 0.748, 0.729,
587 0.745, 0.757, 0.753, 0.750, 0.746, 0.747, 0.735, 0.732, 0.739, 0.734,
588 0.725, 0.721, 0.733, 0.725, 0.732, 0.743, 0.744, 0.748, 0.728, 0.716,
589 0.733, 0.726, 0.713, 0.740, 0.754, 0.764, 0.752, 0.736, 0.734, 0.741,
590 0.740, 0.732, 0.745, 0.755, 0.751, 0.744, 0.731, 0.733, 0.744, 0.731,
591 0.712, 0.708, 0.729, 0.730, 0.727, 0.707, 0.703, 0.729, 0.750, 0.760,
592 0.751, 0.739, 0.724, 0.730, 0.740, 0.737
593 };
594
595 // Input green spectrum.
596 static const double InputGreenSpectrum[InputSpectrumCount] =
597 {
598 0.092, 0.096, 0.098, 0.097, 0.098, 0.095, 0.095, 0.097, 0.095, 0.094,
599 0.097, 0.098, 0.096, 0.101, 0.103, 0.104, 0.107, 0.109, 0.112, 0.115,
600 0.125, 0.140, 0.160, 0.187, 0.229, 0.285, 0.343, 0.390, 0.435, 0.464,
601 0.472, 0.476, 0.481, 0.462, 0.447, 0.441, 0.426, 0.406, 0.373, 0.347,
602 0.337, 0.314, 0.285, 0.277, 0.266, 0.250, 0.230, 0.207, 0.186, 0.171,
603 0.160, 0.148, 0.141, 0.136, 0.130, 0.126, 0.123, 0.121, 0.122, 0.119,
604 0.114, 0.115, 0.117, 0.117, 0.118, 0.120, 0.122, 0.128, 0.132, 0.139,
605 0.144, 0.146, 0.150, 0.152, 0.157, 0.159
606 };
607
608 // Input red spectrum.
609 static const double InputRedSpectrum[InputSpectrumCount] =
610 {
611 0.040, 0.046, 0.048, 0.053, 0.049, 0.050, 0.053, 0.055, 0.057, 0.056,
612 0.059, 0.057, 0.061, 0.061, 0.060, 0.062, 0.062, 0.062, 0.061, 0.062,
613 0.060, 0.059, 0.057, 0.058, 0.058, 0.058, 0.056, 0.055, 0.056, 0.059,
614 0.057, 0.055, 0.059, 0.059, 0.058, 0.059, 0.061, 0.061, 0.063, 0.063,
615 0.067, 0.068, 0.072, 0.080, 0.090, 0.099, 0.124, 0.154, 0.192, 0.255,
616 0.287, 0.349, 0.402, 0.443, 0.487, 0.513, 0.558, 0.584, 0.620, 0.606,
617 0.609, 0.651, 0.612, 0.610, 0.650, 0.638, 0.627, 0.620, 0.630, 0.628,
618 0.642, 0.639, 0.657, 0.639, 0.635, 0.642
619 };
620
621 // Input wavelengths for camera response.
622 static const size_t InputCameraResponseCount = 73;
623 static const double InputCameraResponseWavelength[InputCameraResponseCount] =
624 {
625 380.0, 390.0, 400.0, 410.0, 420.0, 430.0, 440.0, 450.0, 460.0, 470.0,
626 480.0, 490.0, 500.0, 510.0, 520.0, 530.0, 540.0, 550.0, 560.0, 570.0,
627 580.0, 590.0, 600.0, 610.0, 620.0, 630.0, 640.0, 650.0, 660.0, 670.0,
628 680.0, 690.0, 700.0, 710.0, 720.0, 730.0, 740.0, 750.0, 760.0, 770.0,
629 780.0, 790.0, 800.0, 810.0, 820.0, 830.0, 840.0, 850.0, 860.0, 870.0,
630 880.0, 890.0, 900.0, 910.0, 920.0, 930.0, 940.0, 950.0, 960.0, 970.0,
631 980.0, 990.0, 1000.0, 1010.0, 1020.0, 1030.0, 1040.0, 1050.0, 1060.0, 1070.0,
632 1080.0, 1090.0, 1100.0
633 };
634
635 // Input camera response.
636 static const double InputCameraResponse[InputCameraResponseCount] =
637 {
638 0.0000, 0.0000, 2.7262, 4.5846, 6.9099, 9.3752, 12.3971, 14.6141, 16.4340, 14.8158,
639 15.3257, 19.6840, 24.0263, 26.7845, 29.5855, 36.3664, 42.6439, 44.6308, 46.7100, 47.7365,
640 44.6948, 39.7790, 36.3939, 34.7148, 36.2459, 40.2827, 41.8437, 40.1703, 38.5798, 37.8546,
641 37.8727, 38.9440, 41.7185, 45.9209, 49.2163, 50.2404, 49.3917, 48.2287, 47.0943, 46.2036,
642 45.9869, 46.4835, 47.7591, 49.4473, 50.4596, 50.1918, 48.7579, 46.8426, 44.4647, 42.0801,
643 39.8541, 37.5268, 34.9810, 32.3554, 29.2819, 26.0035, 22.7539, 19.4374, 16.8918, 13.7415,
644 11.3124, 9.3019, 7.4702, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
645 0.0000, 0.0000, 0.0000
646 };
647
648 // Input wavelengths for light source emission spectrum.
649 static const size_t InputSourceSpectrumCount = 1024;
650 static const double InputSourceSpectrumWavelength[InputSourceSpectrumCount] =
651 {
652 386.0000, 386.3176, 386.6352, 386.9528, 387.2704, 387.5880, 387.9056, 388.2232, 388.5408, 388.8584,
653 389.1760, 389.4936, 389.8112, 390.1288, 390.4464, 390.7640, 391.0816, 391.3992, 391.7168, 392.0344,
654 392.3520, 392.6696, 392.9872, 393.3048, 393.6224, 393.9400, 394.2576, 394.5752, 394.8928, 395.2104,
655 395.5280, 395.8456, 396.1632, 396.4808, 396.7984, 397.1160, 397.4336, 397.7512, 398.0688, 398.3864,
656 398.7040, 399.0216, 399.3392, 399.6568, 399.9744, 400.2920, 400.6096, 400.9272, 401.2448, 401.5624,
657 401.8800, 402.1976, 402.5152, 402.8328, 403.1504, 403.4680, 403.7856, 404.1032, 404.4208, 404.7384,
658 405.0560, 405.3736, 405.6912, 406.0088, 406.3264, 406.6440, 406.9616, 407.2792, 407.5968, 407.9144,
659 408.2320, 408.5496, 408.8672, 409.1848, 409.5024, 409.8200, 410.1376, 410.4552, 410.7728, 411.0904,
660 411.4080, 411.7256, 412.0432, 412.3608, 412.6784, 412.9960, 413.3136, 413.6312, 413.9488, 414.2664,
661 414.5840, 414.9016, 415.2192, 415.5368, 415.8544, 416.1720, 416.4896, 416.8072, 417.1248, 417.4424,
662 417.7600, 418.0776, 418.3952, 418.7128, 419.0304, 419.3480, 419.6656, 419.9832, 420.3008, 420.6184,
663 420.9360, 421.2536, 421.5712, 421.8888, 422.2064, 422.5240, 422.8416, 423.1592, 423.4768, 423.7944,
664 424.1120, 424.4296, 424.7472, 425.0648, 425.3824, 425.7000, 426.0176, 426.3352, 426.6528, 426.9704,
665 427.2880, 427.6056, 427.9232, 428.2408, 428.5584, 428.8760, 429.1936, 429.5112, 429.8288, 430.1464,
666 430.4640, 430.7816, 431.0992, 431.4168, 431.7344, 432.0520, 432.3696, 432.6872, 433.0048, 433.3224,
667 433.6400, 433.9576, 434.2752, 434.5928, 434.9104, 435.2280, 435.5456, 435.8632, 436.1808, 436.4984,
668 436.8160, 437.1336, 437.4512, 437.7688, 438.0864, 438.4040, 438.7216, 439.0392, 439.3568, 439.6744,
669 439.9920, 440.3096, 440.6272, 440.9448, 441.2624, 441.5800, 441.8976, 442.2152, 442.5328, 442.8504,
670 443.1680, 443.4856, 443.8032, 444.1208, 444.4384, 444.7560, 445.0736, 445.3912, 445.7088, 446.0264,
671 446.3440, 446.6616, 446.9792, 447.2968, 447.6144, 447.9320, 448.2496, 448.5672, 448.8848, 449.2024,
672 449.5200, 449.8376, 450.1552, 450.4728, 450.7904, 451.1080, 451.4256, 451.7432, 452.0608, 452.3784,
673 452.6960, 453.0136, 453.3312, 453.6488, 453.9664, 454.2840, 454.6016, 454.9192, 455.2368, 455.5544,
674 455.8720, 456.1896, 456.5072, 456.8248, 457.1424, 457.4600, 457.7776, 458.0952, 458.4128, 458.7304,
675 459.0480, 459.3656, 459.6832, 460.0008, 460.3184, 460.6360, 460.9536, 461.2712, 461.5888, 461.9064,
676 462.2240, 462.5416, 462.8592, 463.1768, 463.4944, 463.8120, 464.1296, 464.4472, 464.7648, 465.0824,
677 465.4000, 465.7176, 466.0352, 466.3528, 466.6704, 466.9880, 467.3056, 467.6232, 467.9408, 468.2584,
678 468.5760, 468.8936, 469.2112, 469.5288, 469.8464, 470.1640, 470.4816, 470.7992, 471.1168, 471.4344,
679 471.7520, 472.0696, 472.3872, 472.7048, 473.0224, 473.3400, 473.6576, 473.9752, 474.2928, 474.6104,
680 474.9280, 475.2456, 475.5632, 475.8808, 476.1984, 476.5160, 476.8336, 477.1512, 477.4688, 477.7864,
681 478.1040, 478.4216, 478.7392, 479.0568, 479.3744, 479.6920, 480.0096, 480.3272, 480.6448, 480.9624,
682 481.2800, 481.5976, 481.9152, 482.2328, 482.5504, 482.8680, 483.1856, 483.5032, 483.8208, 484.1384,
683 484.4560, 484.7736, 485.0912, 485.4088, 485.7264, 486.0440, 486.3616, 486.6792, 486.9968, 487.3144,
684 487.6320, 487.9496, 488.2672, 488.5848, 488.9024, 489.2200, 489.5376, 489.8552, 490.1728, 490.4904,
685 490.8080, 491.1256, 491.4432, 491.7608, 492.0784, 492.3960, 492.7136, 493.0312, 493.3488, 493.6664,
686 493.9840, 494.3016, 494.6192, 494.9368, 495.2544, 495.5720, 495.8896, 496.2072, 496.5248, 496.8424,
687 497.1600, 497.4776, 497.7952, 498.1128, 498.4304, 498.7480, 499.0656, 499.3832, 499.7008, 500.0184,
688 500.3360, 500.6536, 500.9712, 501.2888, 501.6064, 501.9240, 502.2416, 502.5592, 502.8768, 503.1944,
689 503.5120, 503.8296, 504.1472, 504.4648, 504.7824, 505.1000, 505.4176, 505.7352, 506.0528, 506.3704,
690 506.6880, 507.0056, 507.3232, 507.6408, 507.9584, 508.2760, 508.5936, 508.9112, 509.2288, 509.5464,
691 509.8640, 510.1816, 510.4992, 510.8168, 511.1344, 511.4520, 511.7696, 512.0872, 512.4048, 512.7224,
692 513.0400, 513.3576, 513.6752, 513.9928, 514.3104, 514.6280, 514.9456, 515.2632, 515.5808, 515.8984,
693 516.2160, 516.5336, 516.8512, 517.1688, 517.4864, 517.8040, 518.1216, 518.4392, 518.7568, 519.0744,
694 519.3920, 519.7096, 520.0272, 520.3448, 520.6624, 520.9800, 521.2976, 521.6152, 521.9328, 522.2504,
695 522.5680, 522.8856, 523.2032, 523.5208, 523.8384, 524.1560, 524.4736, 524.7912, 525.1088, 525.4264,
696 525.7440, 526.0616, 526.3792, 526.6968, 527.0144, 527.3320, 527.6496, 527.9672, 528.2848, 528.6024,
697 528.9200, 529.2376, 529.5552, 529.8728, 530.1904, 530.5080, 530.8256, 531.1432, 531.4608, 531.7784,
698 532.0960, 532.4136, 532.7312, 533.0488, 533.3664, 533.6840, 534.0016, 534.3192, 534.6368, 534.9544,
699 535.2720, 535.5896, 535.9072, 536.2248, 536.5424, 536.8600, 537.1776, 537.4952, 537.8128, 538.1304,
700 538.4480, 538.7656, 539.0832, 539.4008, 539.7184, 540.0360, 540.3536, 540.6712, 540.9888, 541.3064,
701 541.6240, 541.9416, 542.2592, 542.5768, 542.8944, 543.2120, 543.5296, 543.8472, 544.1648, 544.4824,
702 544.8000, 545.1176, 545.4352, 545.7528, 546.0704, 546.3880, 546.7056, 547.0232, 547.3408, 547.6584,
703 547.9760, 548.2936, 548.6112, 548.9288, 549.2464, 549.5640, 549.8816, 550.1992, 550.5168, 550.8344,
704 551.1520, 551.4696, 551.7872, 552.1048, 552.4224, 552.7400, 553.0576, 553.3752, 553.6928, 554.0104,
705 554.3280, 554.6456, 554.9632, 555.2808, 555.5984, 555.9160, 556.2336, 556.5512, 556.8688, 557.1864,
706 557.5040, 557.8216, 558.1392, 558.4568, 558.7744, 559.0920, 559.4096, 559.7272, 560.0448, 560.3624,
707 560.6800, 560.9976, 561.3152, 561.6328, 561.9504, 562.2680, 562.5856, 562.9032, 563.2208, 563.5384,
708 563.8560, 564.1736, 564.4912, 564.8088, 565.1264, 565.4440, 565.7616, 566.0792, 566.3968, 566.7144,
709 567.0320, 567.3496, 567.6672, 567.9848, 568.3024, 568.6200, 568.9376, 569.2552, 569.5728, 569.8904,
710 570.2080, 570.5256, 570.8432, 571.1608, 571.4784, 571.7960, 572.1136, 572.4312, 572.7488, 573.0664,
711 573.3840, 573.7016, 574.0192, 574.3368, 574.6544, 574.9720, 575.2896, 575.6072, 575.9248, 576.2424,
712 576.5600, 576.8776, 577.1952, 577.5128, 577.8304, 578.1480, 578.4656, 578.7832, 579.1008, 579.4184,
713 579.7360, 580.0536, 580.3712, 580.6888, 581.0064, 581.3240, 581.6416, 581.9592, 582.2768, 582.5944,
714 582.9120, 583.2296, 583.5472, 583.8648, 584.1824, 584.5000, 584.8176, 585.1352, 585.4528, 585.7704,
715 586.0880, 586.4056, 586.7232, 587.0408, 587.3584, 587.6760, 587.9936, 588.3112, 588.6288, 588.9464,
716 589.2640, 589.5816, 589.8992, 590.2168, 590.5344, 590.8520, 591.1696, 591.4872, 591.8048, 592.1224,
717 592.4400, 592.7576, 593.0752, 593.3928, 593.7104, 594.0280, 594.3456, 594.6632, 594.9808, 595.2984,
718 595.6160, 595.9336, 596.2512, 596.5688, 596.8864, 597.2040, 597.5216, 597.8392, 598.1568, 598.4744,
719 598.7920, 599.1096, 599.4272, 599.7448, 600.0624, 600.3800, 600.6976, 601.0152, 601.3328, 601.6504,
720 601.9680, 602.2856, 602.6032, 602.9208, 603.2384, 603.5560, 603.8736, 604.1912, 604.5088, 604.8264,
721 605.1440, 605.4616, 605.7792, 606.0968, 606.4144, 606.7320, 607.0496, 607.3672, 607.6848, 608.0024,
722 608.3200, 608.6376, 608.9552, 609.2728, 609.5904, 609.9080, 610.2256, 610.5432, 610.8608, 611.1784,
723 611.4960, 611.8136, 612.1312, 612.4488, 612.7664, 613.0840, 613.4016, 613.7192, 614.0368, 614.3544,
724 614.6720, 614.9896, 615.3072, 615.6248, 615.9424, 616.2600, 616.5776, 616.8952, 617.2128, 617.5304,
725 617.8480, 618.1656, 618.4832, 618.8008, 619.1184, 619.4360, 619.7536, 620.0712, 620.3888, 620.7064,
726 621.0240, 621.3416, 621.6592, 621.9768, 622.2944, 622.6120, 622.9296, 623.2472, 623.5648, 623.8824,
727 624.2000, 624.5176, 624.8352, 625.1528, 625.4704, 625.7880, 626.1056, 626.4232, 626.7408, 627.0584,
728 627.3760, 627.6936, 628.0112, 628.3288, 628.6464, 628.9640, 629.2816, 629.5992, 629.9168, 630.2344,
729 630.5520, 630.8696, 631.1872, 631.5048, 631.8224, 632.1400, 632.4576, 632.7752, 633.0928, 633.4104,
730 633.7280, 634.0456, 634.3632, 634.6808, 634.9984, 635.3160, 635.6336, 635.9512, 636.2688, 636.5864,
731 636.9040, 637.2216, 637.5392, 637.8568, 638.1744, 638.4920, 638.8096, 639.1272, 639.4448, 639.7624,
732 640.0800, 640.3976, 640.7152, 641.0328, 641.3504, 641.6680, 641.9856, 642.3032, 642.6208, 642.9384,
733 643.2560, 643.5736, 643.8912, 644.2088, 644.5264, 644.8440, 645.1616, 645.4792, 645.7968, 646.1144,
734 646.4320, 646.7496, 647.0672, 647.3848, 647.7024, 648.0200, 648.3376, 648.6552, 648.9728, 649.2904,
735 649.6080, 649.9256, 650.2432, 650.5608, 650.8784, 651.1960, 651.5136, 651.8312, 652.1488, 652.4664,
736 652.7840, 653.1016, 653.4192, 653.7368, 654.0544, 654.3720, 654.6896, 655.0072, 655.3248, 655.6424,
737 655.9600, 656.2776, 656.5952, 656.9128, 657.2304, 657.5480, 657.8656, 658.1832, 658.5008, 658.8184,
738 659.1360, 659.4536, 659.7712, 660.0888, 660.4064, 660.7240, 661.0416, 661.3592, 661.6768, 661.9944,
739 662.3120, 662.6296, 662.9472, 663.2648, 663.5824, 663.9000, 664.2176, 664.5352, 664.8528, 665.1704,
740 665.4880, 665.8056, 666.1232, 666.4408, 666.7584, 667.0760, 667.3936, 667.7112, 668.0288, 668.3464,
741 668.6640, 668.9816, 669.2992, 669.6168, 669.9344, 670.2520, 670.5696, 670.8872, 671.2048, 671.5224,
742 671.8400, 672.1576, 672.4752, 672.7928, 673.1104, 673.4280, 673.7456, 674.0632, 674.3808, 674.6984,
743 675.0160, 675.3336, 675.6512, 675.9688, 676.2864, 676.6040, 676.9216, 677.2392, 677.5568, 677.8744,
744 678.1920, 678.5096, 678.8272, 679.1448, 679.4624, 679.7800, 680.0976, 680.4152, 680.7328, 681.0504,
745 681.3680, 681.6856, 682.0032, 682.3208, 682.6384, 682.9560, 683.2736, 683.5912, 683.9088, 684.2264,
746 684.5440, 684.8616, 685.1792, 685.4968, 685.8144, 686.1320, 686.4496, 686.7672, 687.0848, 687.4024,
747 687.7200, 688.0376, 688.3552, 688.6728, 688.9904, 689.3080, 689.6256, 689.9432, 690.2608, 690.5784,
748 690.8960, 691.2136, 691.5312, 691.8488, 692.1664, 692.4840, 692.8016, 693.1192, 693.4368, 693.7544,
749 694.0720, 694.3896, 694.7072, 695.0248, 695.3424, 695.6600, 695.9776, 696.2952, 696.6128, 696.9304,
750 697.2480, 697.5656, 697.8832, 698.2008, 698.5184, 698.8360, 699.1536, 699.4712, 699.7888, 700.1064,
751 700.4240, 700.7416, 701.0592, 701.3768, 701.6944, 702.0120, 702.3296, 702.6472, 702.9648, 703.2824,
752 703.6000, 703.9176, 704.2352, 704.5528, 704.8704, 705.1880, 705.5056, 705.8232, 706.1408, 706.4584,
753 706.7760, 707.0936, 707.4112, 707.7288, 708.0464, 708.3640, 708.6816, 708.9992, 709.3168, 709.6344,
754 709.9520, 710.2696, 710.5872, 710.9048
755 };
756
757 // Input light source emission spectrum.
758 static const double InputSourceSpectrum[InputSourceSpectrumCount] =
759 {
760 4.92835727367249, 4.95023640271299, 4.87167292742142, 4.85039921142434, 4.85475580394960,
761 4.80956281547945, 4.77826218004708, 4.75116142146560, 4.69755889037721, 4.66649574802206,
762 4.65519461168247, 4.63443441820992, 4.61113952310921, 4.58537629312006, 4.50554345458709,
763 4.46331279517320, 4.45395241720818, 4.46502019801438, 4.41766996445181, 4.39838089299169,
764 4.40903414622371, 4.31906190749876, 4.29160301757074, 4.23493045638940, 4.21922691342780,
765 4.19496304110966, 4.14768160859809, 4.12731779396439, 4.09533142677633, 4.05208115732076,
766 4.00638023897947, 3.99806185170084, 3.94598963601655, 3.90530572029335, 3.89192331433258,
767 3.84189391558862, 3.80734009619861, 3.77057298996717, 3.76079115433504, 3.68718653034558,
768 3.67040429194027, 3.64547231303425, 3.60396275237111, 3.60246259721929, 3.59170544437162,
769 3.57765441323359, 3.57533983749332, 3.54385920997010, 3.55140379578212, 3.53685074292438,
770 3.54053110397631, 3.53452475146693, 3.54617625024226, 3.54812405490011, 3.54015626575630,
771 3.58280680228990, 3.62491123369037, 3.60758575570167, 3.61251344503421, 3.65544931879874,
772 3.69239884097020, 3.70221932176488, 3.73093703106271, 3.75150734877093, 3.76142521183794,
773 3.79115494300296, 3.78858795794808, 3.81544892870445, 3.79755015063810, 3.80348125873695,
774 3.81406552960722, 3.81668466357248, 3.82162623431797, 3.82318482904885, 3.82395402740146,
775 3.82329460940511, 3.81952184556189, 3.83521351421094, 3.83840922786668, 3.85216398538485,
776 3.86120934836836, 3.88787011066720, 3.90896078800000, 3.94768945105165, 3.97612358846632,
777 4.00194611026509, 4.04595967066901, 4.09217344592315, 4.12217906019002, 4.15048702534741,
778 4.18975942673645, 4.21281307693181, 4.26033120454497, 4.29281746003645, 4.33297969724406,
779 4.35829327325444, 4.38503818988945, 4.42539408537505, 4.43887952065373, 4.46264602928912,
780 4.48390515934975, 4.52602185610096, 4.53983730165631, 4.56657194479674, 4.59490684532894,
781 4.62791974589427, 4.65670045417244, 4.69110222730295, 4.72254958703293, 4.74050425047271,
782 4.76876667713555, 4.80888814368501, 4.82379462706667, 4.84422629371079, 4.86289906101570,
783 4.87858012652333, 4.89095248251457, 4.90415848219590, 4.91457056232708, 4.93948424433779,
784 4.95677458982607, 4.97895380445710, 5.01438735571817, 5.03957210674465, 5.05976462462309,
785 5.08762297092039, 5.12633430403273, 5.15713232731281, 5.21046498310257, 5.25101603039045,
786 5.30316550466633, 5.36160479302598, 5.40998542228681, 5.47363071792891, 5.52623376913842,
787 5.57903298031617, 5.62451523998544, 5.67368076570148, 5.72678803342444, 5.77418930759581,
788 5.82062094735516, 5.85697833762068, 5.89874525184282, 5.91979898588009, 5.93623534037158,
789 5.97273706916525, 5.99248443536382, 6.00596954551065, 6.02391135349251, 6.03499790070022,
790 6.05182805048050, 6.06175143381919, 6.07154863247196, 6.08413901110595, 6.10816742583396,
791 6.12409861736059, 6.14993596814711, 6.17795416929401, 6.21009036097155, 6.24720290848504,
792 6.29442103520580, 6.34025558382214, 6.39561698847542, 6.45722913719182, 6.53145793086557,
793 6.59133530430947, 6.64910616618317, 6.72089255688848, 6.80122073733940, 6.87314448884226,
794 6.93449289917520, 7.01423515606806, 7.07733481278839, 7.15026290207858, 7.22661488675360,
795 7.29606138445174, 7.35524174377133, 7.41567347210106, 7.47587213803126, 7.53222835738739,
796 7.58356426807221, 7.63308940041581, 7.69371703650559, 7.72501373906878, 7.76442579847960,
797 7.81368926436789, 7.86740380938358, 7.90421079286005, 7.94583024026008, 7.99671563708003,
798 8.04244340239606, 8.09185349728779, 8.13181093846529, 8.19753260427575, 8.23719704088131,
799 8.30605821636440, 8.34763957780890, 8.40377164008712, 8.45850190451208, 8.50689521959712,
800 8.55880378414300, 8.62199954623019, 8.67023128685909, 8.72579939081860, 8.77654327509603,
801 8.82703722960192, 8.87234745275413, 8.92298873699862, 8.96183230128869, 8.99959945199256,
802 9.02190421564648, 9.07021876389415, 9.14171865909998, 9.17648133356737, 9.23501491433004,
803 9.27081558815322, 9.33127360138348, 9.37546361810810, 9.42685055197297, 9.47173114044686,
804 9.52499601160681, 9.59225427983750, 9.63452295883245, 9.71017367730259, 9.75544957527789,
805 9.81633196341860, 9.85444975882294, 9.92005872253106, 9.97082968289184, 10.03449699174470,
806 10.09122455063550, 10.13389416965560, 10.17837658254170, 10.21773545898330, 10.26744042097590,
807 10.29056919034800, 10.34150281323410, 10.37786995379330, 10.41407219044100, 10.44484102770980,
808 10.48570812308140, 10.53218630359190, 10.56512838158260, 10.62006067151270, 10.65887457061470,
809 10.69741291849750, 10.76304496488800, 10.79931280850780, 10.85703517697970, 10.92574554866050,
810 10.98331363033000, 11.06307710332800, 11.13985746945070, 11.21504740591010, 11.30211296891140,
811 11.36699941337580, 11.45784698231140, 11.52291388418790, 11.61101817368620, 11.69846243375700,
812 11.77479062604180, 11.86833376348470, 11.93298189517650, 12.00576930240830, 12.06813240917040,
813 12.15218992011410, 12.21946030465890, 12.27984732114790, 12.35702565784200, 12.41636699285090,
814 12.46990434447820, 12.52456539849360, 12.58567800699240, 12.65352478766170, 12.69413440791780,
815 12.74686113142120, 12.80246461153120, 12.84146482477360, 12.90663700679580, 12.96117766963330,
816 13.01274242403170, 13.06615836279630, 13.11619534836710, 13.18279152205640, 13.24036511425530,
817 13.29239094969960, 13.38152016994780, 13.43294283660300, 13.50443946410150, 13.55685819057320,
818 13.61965238032380, 13.67226613256500, 13.71989509247660, 13.77979876248850, 13.83180052020310,
819 13.84430227935160, 13.89482616183360, 13.93275292471270, 13.98796853844590, 14.02120281970040,
820 14.06469501339430, 14.09613766080790, 14.14338696518080, 14.18403496186730, 14.21806607531730,
821 14.25772335788710, 14.29669029454240, 14.33194679288560, 14.37758361831550, 14.42119985137430,
822 14.44971099119800, 14.50741581408920, 14.56118017427560, 14.62092534162650, 14.68515260398560,
823 14.73491963050900, 14.80907502694460, 14.88815737354350, 14.94616320376450, 15.02558463532820,
824 15.11203094864740, 15.19717271480480, 15.27718243851370, 15.36567171899760, 15.45184153402890,
825 15.53754196944420, 15.64788249678310, 15.72509581415320, 15.81429427662460, 15.92707653156050,
826 16.01731134738170, 16.11600746350080, 16.20892471361740, 16.29225189359360, 16.39359707298030,
827 16.47066209226870, 16.55917178645840, 16.62561782023400, 16.70841038659590, 16.78676522974520,
828 16.83121370364950, 16.90970725578240, 16.98273901593150, 17.04871601788730, 17.11268063089090,
829 17.17982076876960, 17.22381424217040, 17.30314819933530, 17.35746332322000, 17.43112885625660,
830 17.48204699145510, 17.55696117862960, 17.60494634967520, 17.65502592392060, 17.71403934285840,
831 17.78598100126920, 17.85655375376110, 17.92058866864030, 17.99230099864570, 18.06707477223760,
832 18.13436354489630, 18.21311730172240, 18.28960928763870, 18.32967134578120, 18.39692296776050,
833 18.45656375462550, 18.52390272062570, 18.57529417810770, 18.62673762859450, 18.67788480420940,
834 18.75249257489740, 18.80462636945440, 18.87542569644120, 18.91158693077320, 18.96570817482920,
835 19.01692378371080, 19.04623736623600, 19.10227678132730, 19.14509502041990, 19.18970799817970,
836 19.23873108495060, 19.26780950369100, 19.31419402308830, 19.36528274806400, 19.40118097179560,
837 19.46035853227560, 19.52064162839660, 19.58170590260900, 19.63171035807460, 19.70336844700920,
838 19.77064368819760, 19.80392383408410, 19.85992006541590, 19.93738561338900, 20.02284410602150,
839 20.08669014565640, 20.15900956530060, 20.23440699499200, 20.30600184698670, 20.40066552213020,
840 20.48273233514580, 20.57931739732480, 20.65593145165050, 20.73726859510960, 20.81966265151350,
841 20.89923317324460, 20.99521486578730, 21.08979561119570, 21.16193414010030, 21.22341789026790,
842 21.27993341829660, 21.34027406739970, 21.40159850749630, 21.47436457110910, 21.55347337103140,
843 21.59119691076710, 21.62606604994440, 21.67467413647190, 21.70707069322430, 21.75858598819490,
844 21.75450883462950, 21.77856004667370, 21.80338220169380, 21.82430409207460, 21.84731432278300,
845 21.83921535624070, 21.82707643340360, 21.81788806235140, 21.83770638889470, 21.82709299095180,
846 21.82200452897680, 21.83182112073370, 21.81370576529070, 21.80076601334910, 21.81652119802770,
847 21.81694442986100, 21.82757391397910, 21.82478527187680, 21.84147779909220, 21.85287888972480,
848 21.89030789562500, 21.91890397432130, 21.93885180364230, 21.97121208961480, 22.01583652136870,
849 22.07517328845300, 22.10910723435870, 22.19019852119270, 22.27408994666450, 22.35997186695490,
850 22.40815085255450, 22.45819760947410, 22.55296946624010, 22.61233512963040, 22.68122483254160,
851 22.78230399665030, 22.83508167743760, 22.93786266495910, 23.02439055811430, 23.11940579254900,
852 23.20009585626350, 23.30795385400430, 23.36914451887960, 23.47258967592180, 23.55535974010960,
853 23.66610522886750, 23.74556169630170, 23.84982446270390, 23.90955529155090, 23.98157811043960,
854 24.07896017887990, 24.14704691615930, 24.22687315607770, 24.28862482756210, 24.34056252400220,
855 24.38992656534960, 24.45594790811740, 24.48258955643180, 24.56667776513020, 24.59445536450440,
856 24.62805700416400, 24.67003032390420, 24.67523437840420, 24.68408743469140, 24.70882462500420,
857 24.68773496316310, 24.68083688210240, 24.68884785906170, 24.69179894931380, 24.68383355606880,
858 24.68026272388530, 24.66519738431140, 24.66385015373380, 24.72241293753290, 24.81399519754810,
859 24.80832879273080, 24.82645691608680, 24.84343603710690, 24.86139493322710, 24.88725735634150,
860 24.92005801503100, 24.96863912290040, 25.03206105522360, 25.08095377821620, 25.15205603034190,
861 25.21193094780020, 25.29663104275120, 25.40483573615490, 25.48281226144420, 25.56685407258250,
862 25.68614278697970, 25.80896360074120, 25.91262556143080, 26.03463859309800, 26.16935490775920,
863 26.28109060851750, 26.44978666349210, 26.58744659856100, 26.74027759505110, 26.88720372811530,
864 27.02579688843010, 27.18921747721150, 27.38550254634900, 27.52613393343870, 27.68919558229660,
865 27.86693283355410, 28.04847885771420, 28.19197395276460, 28.37872109017280, 28.56497190383570,
866 28.68044776130840, 28.86310256322110, 29.00447106969210, 29.18116506431980, 29.33743334927930,
867 29.49194157166570, 29.65054267048530, 29.78297475865880, 29.91797056649910, 30.03569309218670,
868 30.17708406364710, 30.30409065410740, 30.45612977341240, 30.53107447317290, 30.67196082910110,
869 30.77986552522620, 30.89224657253820, 30.96622308509980, 31.07220318693750, 31.15718595861960,
870 31.20383583227280, 31.30377856140940, 31.40414808266530, 31.43611018221700, 31.52801653226750,
871 31.60102442653360, 31.72621718204230, 31.79591280500360, 31.86826527478240, 31.94853434185450,
872 32.02539482506510, 32.13974161224190, 32.20423181540680, 32.28018677692370, 32.28395726824170,
873 32.40494318511320, 32.46749445066700, 32.52980425678560, 32.63380453616110, 32.68092259650560,
874 32.77319964225100, 32.90104863150770, 33.02129329230090, 33.15087824382160, 33.16424665430360,
875 33.23137293644180, 33.28290115780930, 33.35484158302640, 33.43853487313680, 33.60929049682170,
876 33.70046828899200, 33.79738115234160, 33.85206201950270, 33.94663872932400, 33.96045104171260,
877 34.05475363448850, 34.10062428612370, 34.18215916052220, 34.25004129884530, 34.32150418867920,
878 34.39610542452530, 34.46044843156990, 34.51687045926410, 34.55209146623040, 34.59658135254390,
879 34.64960558805920, 34.70425712813580, 34.72836102434770, 34.77389830912350, 34.80967030593960,
880 34.85796100803080, 34.90914755830490, 34.92277339608200, 34.93897843389750, 34.96598147672490,
881 35.02237511781240, 35.06262194597710, 35.11140592220290, 35.14137452932910, 35.16239737127000,
882 35.20296586992050, 35.24898755877660, 35.29335977034030, 35.37355689179760, 35.37678456095530,
883 35.46886556304630, 35.52168787701290, 35.56242018045580, 35.60966168176520, 35.65975868233490,
884 35.73275359519800, 35.76218208991110, 35.86790780049770, 35.91765316548140, 36.02584644500090,
885 36.10398104619080, 36.20544100103450, 36.31996143336560, 36.43499302114470, 36.53317969266010,
886 36.67017925325560, 36.79399513857610, 36.85507056219050, 36.95126480436820, 37.05372727870340,
887 37.15059134951820, 37.29182879749320, 37.36382982923950, 37.44132457886000, 37.49166785778120,
888 37.57717129112090, 37.64735391250410, 37.71130174926090, 37.82473094660950, 37.91546830389120,
889 37.99067831268420, 38.09451284902960, 38.15758953743980, 38.23615790463980, 38.32197158067270,
890 38.43134475176400, 38.53659884487360, 38.62544847176190, 38.73075853955870, 38.81319121216220,
891 38.90295298639700, 38.95350872577000, 39.06616089019790, 39.13501614390540, 39.22624636126210,
892 39.23983187175450, 39.30548595962250, 39.36147734872170, 39.40495530656890, 39.47796375277410,
893 39.57629997171180, 39.62225843940690, 39.68200991305980, 39.73714559398590, 39.79931521717210,
894 39.85767403971500, 39.92737671585440, 40.00014684630660, 40.06188424545710, 40.11552243648740,
895 40.18301915095550, 40.23953960887440, 40.32017452534290, 40.40280466236230, 40.47402128974550,
896 40.54780868162140, 40.61686055743300, 40.66449293067440, 40.74033856641390, 40.79884863366840,
897 40.85113626978660, 40.89327993208460, 40.92709196131660, 41.02932850901520, 41.07870172640470,
898 41.15208090444430, 41.20719958249480, 41.22779665202910, 41.30340521946180, 41.37463561990510,
899 41.43581449180160, 41.53237538481520, 41.62442610703640, 41.67685766480740, 41.70551621209030,
900 41.79387528993570, 41.87249022499630, 41.96748580710450, 41.96066425184290, 42.00236919506070,
901 42.06691271868140, 42.14453462221240, 42.17232865317080, 42.21308654606010, 42.29682092288380,
902 42.28020989259000, 42.33453119996890, 42.42249257093860, 42.45259373439840, 42.52678228221080,
903 42.62360174189350, 42.65108357605410, 42.69529079131090, 42.76506482589140, 42.76866147327120,
904 42.84197399799980, 42.88348405910990, 42.93480463891800, 42.93029206285050, 42.96927781746760,
905 43.03102555127540, 43.06837620082900, 43.07944143286120, 43.11894499317990, 43.14621770363800,
906 43.21178505966750, 43.22262263267730, 43.23217246930500, 43.27929678731450, 43.33474352075870,
907 43.33186074018300, 43.38691324155310, 43.47481497408200, 43.48959909739700, 43.53385056560400,
908 43.52006236460410, 43.54288106068920, 43.58467808312320, 43.65098008442400, 43.68014893728780,
909 43.77655831776850, 43.82158431110590, 43.87133619942870, 43.89857776752220, 43.90895708958380,
910 43.93924688076010, 43.94311255617310, 44.00206298314270, 44.06016926166370, 44.08464841439000,
911 44.14974194116070, 44.16360932249060, 44.21550172914360, 44.24645163821880, 44.31413103396010,
912 44.37582255973850, 44.44290243938980, 44.46713847006880, 44.54954762719370, 44.61770085941470,
913 44.62707255364330, 44.68776382854840, 44.75644795704410, 44.82017049514460, 44.86731775028840,
914 44.93669847762410, 44.94323079360680, 45.00289235842400, 45.06074445928730, 45.10070072771480,
915 45.12535413487300, 45.18971616198560, 45.22800594544770, 45.28256242647910, 45.33033970320710,
916 45.40157892892660, 45.40990798048930, 45.45005102097290, 45.49876470897600, 45.55719413446290,
917 45.57558835135730, 45.65806900650620, 45.71135372605290, 45.73646800236430, 45.75159872871630,
918 45.78821768722850, 45.84825244733540, 45.99560549778800, 46.20313088822660, 46.22034059337770,
919 46.27787413361390, 46.32758131762610, 46.35512346817560, 46.43510848595720, 46.50490991827820,
920 46.46179852904980, 46.26014174457510, 46.23810710782930, 46.30556813310900, 46.36527013549460,
921 46.37721630907690, 46.45252810085410, 46.50466755772400, 46.55813315248220, 46.66800552130970,
922 46.76963943822540, 46.82246498060560, 46.84003287543710, 46.80448017917460, 46.83841548307860,
923 46.86048386561490, 46.91957734088020, 46.91730690365440, 46.98966653214880, 47.00517008730720,
924 47.01315112187740, 47.07074221081100, 47.05280548322350, 47.10234054509240, 47.14878533434680,
925 47.18764807236820, 47.20302242802520, 47.19090909577390, 47.24496063401410, 47.27799257806610,
926 47.24473681961440, 47.26632585935810, 47.29130144819630, 47.38028322287670, 47.36536210587930,
927 47.40946164674690, 47.42629682558840, 47.44011415765250, 47.49471639778660, 47.50993333608530,
928 47.60153139746630, 47.59098752530950, 47.60599414543740, 47.72138917242870, 47.73101049133920,
929 47.77351224566690, 47.80221279327420, 47.82379204552780, 47.89507117817290, 47.91381255065170,
930 47.95655013828690, 47.99009680892420, 48.00757694740830, 48.07195217026400, 48.11071100450270,
931 48.18321233686060, 48.20431083391930, 48.25896998104100, 48.28514079791270, 48.30760284864470,
932 48.33195778345520, 48.38468946527180, 48.40754424775460, 48.41721780513190, 48.43762980691400,
933 48.47003292390880, 48.53107971286060, 48.56893872838810, 48.62557292516310, 48.61079540288420,
934 48.61346964133380, 48.64024108367710, 48.64691454658780, 48.73450924908860, 48.71115321332660,
935 48.72454994541860, 48.65239888576690, 48.71463654728540, 48.67255147927480, 48.70777995399180,
936 48.69123070112490, 48.76049250446820, 48.71636847272490, 48.85251266457350, 48.82720687148140,
937 48.86710958576830, 48.89669398464330, 48.89202595348700, 48.90438606498260, 48.86129690970630,
938 48.98704016472160, 48.91035469778120, 48.90886968746060, 48.96240538807380, 48.98812573916050,
939 48.90082552081360, 48.98011640015980, 49.11690487416240, 49.12383559393310, 49.16479829306740,
940 49.15441032001890, 49.20513908434000, 49.19469791774490, 49.17543552886840, 49.17685633821150,
941 49.07816045299530, 49.06696566214730, 49.08073590280000, 49.08073079577200, 49.12930738996090,
942 49.20825350918470, 49.17186181058630, 49.22176095988120, 49.25749772083510, 49.22595428368510,
943 49.29514363225830, 49.26629340436610, 49.19897346191790, 49.29684832561600, 49.21207757481190,
944 49.26279980291820, 49.25745023713690, 49.16981892047690, 49.16472388085190, 49.16827588538560,
945 49.12194271618720, 49.19377189624870, 49.14953717217270, 49.13487981820580, 49.09854699671190,
946 49.08310226494570, 49.10346596782800, 49.02822031544520, 49.05569923993890, 49.00651755002290,
947 48.93481065983130, 48.99284161811070, 48.85219580565640, 48.82600862507190, 48.84196777240100,
948 48.69357868381790, 48.80868832002350, 48.85607948311330, 48.73882088809720, 48.80816651451680,
949 48.64757547013110, 48.57371357777440, 48.56579373582720, 48.50410324028500, 48.35860141223540,
950 48.24394471734060, 48.21392991778470, 48.14547473189630, 47.99672507987360, 47.98082853294720,
951 47.87383481217780, 47.81606591067890, 47.68176414032230, 47.66006320644340, 47.55384819627930,
952 47.41638676490530, 47.32727872241500, 47.23891584842230, 47.09295003421260, 47.01618839720610,
953 46.87025697008420, 46.81067613735140, 46.61253912221300, 46.48170334194630, 46.30064566476440,
954 46.17873900417390, 46.02126472107910, 45.82149354364510, 45.74013547031190, 45.59135952586340,
955 45.35455311570520, 45.19473268803280, 45.02259432367430, 44.88341894949910, 44.60207461974350,
956 44.41965592797250, 44.19481139858310, 43.95425484068060, 43.68767137468690, 43.50054933484870,
957 43.18287393218360, 42.94164176287200, 42.69301585048210, 42.38647146868720, 42.16091175320670,
958 41.86384398941410, 41.48093302599290, 41.20862279018740, 40.85976255982450, 40.51784102028600,
959 40.19085497357880, 39.89106781396070, 39.56141360761760, 39.08806529917160, 38.80399629669640,
960 38.46100812627460, 38.03595413835370, 37.74622068467920, 37.28595910233180, 36.93238223035530,
961 36.51088680226470, 36.08309041078630, 35.71388875294900, 35.31156189809560, 34.86588513381560,
962 34.50542730589920, 34.02103201416430, 33.65805797241870, 33.23401307672130, 32.76192764295640,
963 32.34575040730360, 31.95277910223730, 31.53115586525900, 31.16620917858590, 30.72240903329530,
964 30.30990604744090, 29.88332309573020, 29.48625157300980, 29.15599898784370
965 };
966
967 // Output wavelengths.
968 static const size_t OutputCount = 31;
969 static const double OutputWavelength[OutputCount] =
970 {
971 400.0, 410.0, 420.0, 430.0, 440.0, 450.0, 460.0, 470.0, 480.0, 490.0,
972 500.0, 510.0, 520.0, 530.0, 540.0, 550.0, 560.0, 570.0, 580.0, 590.0,
973 600.0, 610.0, 620.0, 630.0, 640.0, 650.0, 660.0, 670.0, 680.0, 690.0,
974 700.0
975 };
976
977 typedef RegularSpectrum<double, OutputCount> Spectrum;
978
979 // White spectrum.
980 {
981 Spectrum white_spectrum;
982 spectrum_to_spectrum(
983 InputSpectrumCount,
984 InputSpectrumWavelength,
985 InputWhiteSpectrum,
986 OutputCount,
987 OutputWavelength,
988 &white_spectrum[0]);
989
990 GnuplotFile plotfile;
991 plotfile.set_title("White Spectrum");
992 plotfile.set_xlabel("Wavelength (nm)");
993 plotfile
994 .new_plot()
995 .set_points(zip(&InputSpectrumWavelength[0], &InputWhiteSpectrum[0], InputSpectrumCount))
996 .set_title("Input")
997 .set_color("gray");
998 plotfile
999 .new_plot()
1000 .set_points(zip(&OutputWavelength[0], &white_spectrum[0], OutputCount))
1001 .set_title("Output")
1002 .set_color("red");
1003 plotfile.write("unit tests/outputs/test_colorspace_white.gnuplot");
1004 }
1005
1006 // Green spectrum.
1007 {
1008 Spectrum green_spectrum;
1009 spectrum_to_spectrum(
1010 InputSpectrumCount,
1011 InputSpectrumWavelength,
1012 InputGreenSpectrum,
1013 OutputCount,
1014 OutputWavelength,
1015 &green_spectrum[0]);
1016
1017 GnuplotFile plotfile;
1018 plotfile.set_title("Green Spectrum");
1019 plotfile.set_xlabel("Wavelength (nm)");
1020 plotfile
1021 .new_plot()
1022 .set_points(zip(&InputSpectrumWavelength[0], &InputGreenSpectrum[0], InputSpectrumCount))
1023 .set_title("Input")
1024 .set_color("gray");
1025 plotfile
1026 .new_plot()
1027 .set_points(zip(&OutputWavelength[0], &green_spectrum[0], OutputCount))
1028 .set_title("Output")
1029 .set_color("red");
1030 plotfile.write("unit tests/outputs/test_colorspace_green.gnuplot");
1031 }
1032
1033 // Red spectrum.
1034 {
1035 Spectrum red_spectrum;
1036 spectrum_to_spectrum(
1037 InputSpectrumCount,
1038 InputSpectrumWavelength,
1039 InputRedSpectrum,
1040 OutputCount,
1041 OutputWavelength,
1042 &red_spectrum[0]);
1043
1044 GnuplotFile plotfile;
1045 plotfile.set_title("Red Spectrum");
1046 plotfile.set_xlabel("Wavelength (nm)");
1047 plotfile
1048 .new_plot()
1049 .set_points(zip(&InputSpectrumWavelength[0], &InputRedSpectrum[0], InputSpectrumCount))
1050 .set_title("Input")
1051 .set_color("gray");
1052 plotfile
1053 .new_plot()
1054 .set_points(zip(&OutputWavelength[0], &red_spectrum[0], OutputCount))
1055 .set_title("Output")
1056 .set_color("red");
1057 plotfile.write("unit tests/outputs/test_colorspace_red.gnuplot");
1058 }
1059
1060 // Camera response.
1061 {
1062 Spectrum camera_response;
1063 spectrum_to_spectrum(
1064 InputCameraResponseCount,
1065 InputCameraResponseWavelength,
1066 InputCameraResponse,
1067 OutputCount,
1068 OutputWavelength,
1069 &camera_response[0]);
1070
1071 GnuplotFile plotfile;
1072 plotfile.set_title("Camera Response");
1073 plotfile.set_xlabel("Wavelength (nm)");
1074 plotfile
1075 .new_plot()
1076 .set_points(zip(&InputCameraResponseWavelength[0], &InputCameraResponse[0], InputCameraResponseCount))
1077 .set_title("Input")
1078 .set_color("gray");
1079 plotfile
1080 .new_plot()
1081 .set_points(zip(&OutputWavelength[0], &camera_response[0], OutputCount))
1082 .set_title("Output")
1083 .set_color("red");
1084 plotfile.write("unit tests/outputs/test_colorspace_camera.gnuplot");
1085 }
1086
1087 // Light source emission spectrum.
1088 {
1089 Spectrum source_spectrum;
1090 spectrum_to_spectrum(
1091 InputSourceSpectrumCount,
1092 InputSourceSpectrumWavelength,
1093 InputSourceSpectrum,
1094 OutputCount,
1095 OutputWavelength,
1096 &source_spectrum[0]);
1097
1098 GnuplotFile plotfile;
1099 plotfile.set_title("Light Source Emission Spectrum");
1100 plotfile.set_xlabel("Wavelength (nm)");
1101 plotfile
1102 .new_plot()
1103 .set_points(zip(&InputSourceSpectrumWavelength[0], &InputSourceSpectrum[0], InputSourceSpectrumCount))
1104 .set_title("Input")
1105 .set_color("gray");
1106 plotfile
1107 .new_plot()
1108 .set_points(zip(&OutputWavelength[0], &source_spectrum[0], OutputCount))
1109 .set_title("Output")
1110 .set_color("red");
1111 plotfile.write("unit tests/outputs/test_colorspace_light.gnuplot");
1112 }
1113 }
1114 }
1115