예제 #1
0
void spectrum_to_ciexyz_standard(
    const float         spectrum[],
    float               ciexyz[3])
{
    const LightingConditions lighting_conditions(IlluminantCIED65, XYZCMFCIE196410Deg);

    const Color3f c =
        spectrum_to_ciexyz<float, Spectrum31f>(
            lighting_conditions,
            Spectrum31f(spectrum));

    ciexyz[0] = c[0];
    ciexyz[1] = c[1];
    ciexyz[2] = c[2];
}
예제 #2
0
namespace foundation
{

const char* color_space_name(const ColorSpace color_space)
{
    switch (color_space)
    {
    case ColorSpaceLinearRGB:
        return "linear_rgb";
    case ColorSpaceSRGB:
        return "srgb";
    case ColorSpaceHSV:
        return "hsv";
    case ColorSpaceHLS:
        return "hls";
    case ColorSpaceCIEXYZ:
        return "ciexyz";
    case ColorSpaceCIExyY:
        return "ciexyy";
    case ColorSpaceSpectral:
        return "spectral";
        assert_otherwise;
    }

    // Keep the compiler happy.
    return "";
}


//
// Basis vectors to convert the CIE xy chromaticity of a D series (daylight) illuminant to a spectrum.
//

namespace
{
static const float DaylightS0Amplitudes[31] =
{
    94.8f,             // 400 nm
    104.8f,             // 410 nm
    105.9f,             // 420 nm
    96.8f,             // 430 nm
    113.9f,             // 440 nm
    125.6f,             // 450 nm
    125.5f,             // 460 nm
    121.3f,             // 470 nm
    121.3f,             // 480 nm
    113.5f,             // 490 nm
    113.1f,             // 500 nm
    110.8f,             // 510 nm
    106.5f,             // 520 nm
    108.8f,             // 530 nm
    105.3f,             // 540 nm
    104.4f,             // 550 nm
    100.0f,             // 560 nm
    96.0f,             // 570 nm
    95.1f,             // 580 nm
    89.1f,             // 590 nm
    90.5f,             // 600 nm
    90.3f,             // 610 nm
    88.4f,             // 620 nm
    84.0f,             // 630 nm
    85.1f,             // 640 nm
    81.9f,             // 650 nm
    82.6f,             // 660 nm
    84.9f,             // 670 nm
    81.3f,             // 680 nm
    71.9f,             // 690 nm
    74.3f              // 700 nm
};

static const float DaylightS1Amplitudes[31] =
{
    43.4f,             // 400 nm
    46.3f,             // 410 nm
    43.9f,             // 420 nm
    37.1f,             // 430 nm
    36.7f,             // 440 nm
    35.9f,             // 450 nm
    32.6f,             // 460 nm
    27.9f,             // 470 nm
    24.3f,             // 480 nm
    20.1f,             // 490 nm
    16.2f,             // 500 nm
    13.2f,             // 510 nm
    8.6f,             // 520 nm
    6.1f,             // 530 nm
    4.2f,             // 540 nm
    1.9f,             // 550 nm
    0.0f,             // 560 nm
    -1.6f,             // 570 nm
    -3.5f,             // 580 nm
    -3.5f,             // 590 nm
    -5.8f,             // 600 nm
    -7.2f,             // 610 nm
    -8.6f,             // 620 nm
    -9.5f,             // 630 nm
    -10.9f,             // 640 nm
    -10.7f,             // 650 nm
    -12.0f,             // 660 nm
    -14.0f,             // 670 nm
    -13.6f,             // 680 nm
    -12.0f,             // 690 nm
    -13.3f              // 700 nm
};

static const float DaylightS2Amplitudes[31] =
{
    -1.1f,              // 400 nm
    -0.5f,              // 410 nm
    -0.7f,              // 420 nm
    -1.2f,              // 430 nm
    -2.6f,              // 440 nm
    -2.9f,              // 450 nm
    -2.8f,              // 460 nm
    -2.6f,              // 470 nm
    -2.6f,              // 480 nm
    -1.8f,              // 490 nm
    -1.5f,              // 500 nm
    -1.3f,              // 510 nm
    -1.2f,              // 520 nm
    -1.0f,              // 530 nm
    -0.5f,              // 540 nm
    -0.3f,              // 550 nm
    0.0f,              // 560 nm
    0.2f,              // 570 nm
    0.5f,              // 580 nm
    2.1f,              // 590 nm
    3.2f,              // 600 nm
    4.1f,              // 610 nm
    4.7f,              // 620 nm
    5.1f,              // 630 nm
    6.7f,              // 640 nm
    7.3f,              // 650 nm
    8.6f,              // 660 nm
    9.8f,              // 670 nm
    10.2f,              // 680 nm
    8.3f,              // 690 nm
    9.6f               // 700 nm
};
}

const Spectrum31f DaylightS0(DaylightS0Amplitudes);
const Spectrum31f DaylightS1(DaylightS1Amplitudes);
const Spectrum31f DaylightS2(DaylightS2Amplitudes);


//
// Standard illuminants.
//

namespace
{
const float IlluminantCIED65Tab[31] =
{
    82.754900f,        // 400 nm
    91.486000f,        // 410 nm
    93.431800f,        // 420 nm
    86.682300f,        // 430 nm
    104.865000f,        // 440 nm
    117.008000f,        // 450 nm
    117.812000f,        // 460 nm
    114.861000f,        // 470 nm
    115.923000f,        // 480 nm
    108.811000f,        // 490 nm
    109.354000f,        // 500 nm
    107.802000f,        // 510 nm
    104.790000f,        // 520 nm
    107.689000f,        // 530 nm
    104.405000f,        // 540 nm
    104.046000f,        // 550 nm
    100.000000f,        // 560 nm
    96.334200f,        // 570 nm
    95.788000f,        // 580 nm
    88.685600f,        // 590 nm
    90.006200f,        // 600 nm
    89.599100f,        // 610 nm
    87.698700f,        // 620 nm
    83.288600f,        // 630 nm
    83.699200f,        // 640 nm
    80.026800f,        // 650 nm
    80.214600f,        // 660 nm
    82.277800f,        // 670 nm
    78.284200f,        // 680 nm
    69.721300f,        // 690 nm
    71.609100f         // 700 nm
};

const float IlluminantCIEATab[31] =
{
    14.708000f,        // 400 nm
    17.675300f,        // 410 nm
    20.995000f,        // 420 nm
    24.670900f,        // 430 nm
    28.702700f,        // 440 nm
    33.085900f,        // 450 nm
    37.812100f,        // 460 nm
    42.869300f,        // 470 nm
    48.242300f,        // 480 nm
    53.913200f,        // 490 nm
    59.861100f,        // 500 nm
    66.063500f,        // 510 nm
    72.495900f,        // 520 nm
    79.132600f,        // 530 nm
    85.947000f,        // 540 nm
    92.912000f,        // 550 nm
    100.000000f,        // 560 nm
    107.184000f,        // 570 nm
    114.436000f,        // 580 nm
    121.731000f,        // 590 nm
    129.043000f,        // 600 nm
    136.346000f,        // 610 nm
    143.618000f,        // 620 nm
    150.836000f,        // 630 nm
    157.979000f,        // 640 nm
    165.028000f,        // 650 nm
    171.963000f,        // 660 nm
    178.769000f,        // 670 nm
    185.429000f,        // 680 nm
    191.931000f,        // 690 nm
    198.261000f         // 700 nm
};
}

// Daylight illuminants.
const Spectrum31f IlluminantCIED65(IlluminantCIED65Tab);

// Incandescent lighting illuminants.
const Spectrum31f IlluminantCIEA(IlluminantCIEATab);


//
// Color Matching Functions (CMF).
//

namespace
{
// XYZ color matching functions -- CIE 1931 2-deg.
const float XYZCMFCIE19312DegTabX[31] =
{
    0.014310000000f,    // 400 nm
    0.043510000000f,    // 410 nm
    0.134380000000f,    // 420 nm
    0.283900000000f,    // 430 nm
    0.348280000000f,    // 440 nm
    0.336200000000f,    // 450 nm
    0.290800000000f,    // 460 nm
    0.195360000000f,    // 470 nm
    0.095640000000f,    // 480 nm
    0.032010000000f,    // 490 nm
    0.004900000000f,    // 500 nm
    0.009300000000f,    // 510 nm
    0.063270000000f,    // 520 nm
    0.165500000000f,    // 530 nm
    0.290400000000f,    // 540 nm
    0.433449900000f,    // 550 nm
    0.594500000000f,    // 560 nm
    0.762100000000f,    // 570 nm
    0.916300000000f,    // 580 nm
    1.026300000000f,    // 590 nm
    1.062200000000f,    // 600 nm
    1.002600000000f,    // 610 nm
    0.854449900000f,    // 620 nm
    0.642400000000f,    // 630 nm
    0.447900000000f,    // 640 nm
    0.283500000000f,    // 650 nm
    0.164900000000f,    // 660 nm
    0.087400000000f,    // 670 nm
    0.046770000000f,    // 680 nm
    0.022700000000f,    // 690 nm
    0.011359160000f     // 700 nm
};
const float XYZCMFCIE19312DegTabY[31] =
{
    0.000396000000f,    // 400 nm
    0.001210000000f,    // 410 nm
    0.004000000000f,    // 420 nm
    0.011600000000f,    // 430 nm
    0.023000000000f,    // 440 nm
    0.038000000000f,    // 450 nm
    0.060000000000f,    // 460 nm
    0.090980000000f,    // 470 nm
    0.139020000000f,    // 480 nm
    0.208020000000f,    // 490 nm
    0.323000000000f,    // 500 nm
    0.503000000000f,    // 510 nm
    0.710000000000f,    // 520 nm
    0.862000000000f,    // 530 nm
    0.954000000000f,    // 540 nm
    0.994950100000f,    // 550 nm
    0.995000000000f,    // 560 nm
    0.952000000000f,    // 570 nm
    0.870000000000f,    // 580 nm
    0.757000000000f,    // 590 nm
    0.631000000000f,    // 600 nm
    0.503000000000f,    // 610 nm
    0.381000000000f,    // 620 nm
    0.265000000000f,    // 630 nm
    0.175000000000f,    // 640 nm
    0.107000000000f,    // 650 nm
    0.061000000000f,    // 660 nm
    0.032000000000f,    // 670 nm
    0.017000000000f,    // 680 nm
    0.008210000000f,    // 690 nm
    0.004102000000f     // 700 nm
};
const float XYZCMFCIE19312DegTabZ[31] =
{
    0.067850010000f,    // 400 nm
    0.207400000000f,    // 410 nm
    0.645600000000f,    // 420 nm
    1.385600000000f,    // 430 nm
    1.747060000000f,    // 440 nm
    1.772110000000f,    // 450 nm
    1.669200000000f,    // 460 nm
    1.287640000000f,    // 470 nm
    0.812950100000f,    // 480 nm
    0.465180000000f,    // 490 nm
    0.272000000000f,    // 500 nm
    0.158200000000f,    // 510 nm
    0.078249990000f,    // 520 nm
    0.042160000000f,    // 530 nm
    0.020300000000f,    // 540 nm
    0.008749999000f,    // 550 nm
    0.003900000000f,    // 560 nm
    0.002100000000f,    // 570 nm
    0.001650001000f,    // 580 nm
    0.001100000000f,    // 590 nm
    0.000800000000f,    // 600 nm
    0.000340000000f,    // 610 nm
    0.000190000000f,    // 620 nm
    0.000049999990f,    // 630 nm
    0.000020000000f,    // 640 nm
    0.000000000000f,    // 650 nm
    0.000000000000f,    // 660 nm
    0.000000000000f,    // 670 nm
    0.000000000000f,    // 680 nm
    0.000000000000f,    // 690 nm
    0.000000000000f     // 700 nm
};

// XYZ color matching functions -- CIE 1931 2-deg, modified by Judd (1951).
const float XYZCMFCIE1931Judd2DegTabX[31] =
{
    0.0611f,            // 400 nm
    0.1267f,            // 410 nm
    0.2285f,            // 420 nm
    0.3081f,            // 430 nm
    0.3312f,            // 440 nm
    0.2888f,            // 450 nm
    0.2323f,            // 460 nm
    0.1745f,            // 470 nm
    0.0920f,            // 480 nm
    0.0318f,            // 490 nm
    0.0048f,            // 500 nm
    0.0093f,            // 510 nm
    0.0636f,            // 520 nm
    0.1668f,            // 530 nm
    0.2926f,            // 540 nm
    0.4364f,            // 550 nm
    0.5970f,            // 560 nm
    0.7642f,            // 570 nm
    0.9159f,            // 580 nm
    1.0225f,            // 590 nm
    1.0544f,            // 600 nm
    0.9922f,            // 610 nm
    0.8432f,            // 620 nm
    0.6327f,            // 630 nm
    0.4404f,            // 640 nm
    0.2787f,            // 650 nm
    0.1619f,            // 660 nm
    0.0858f,            // 670 nm
    0.0459f,            // 680 nm
    0.0222f,            // 690 nm
    0.0113f             // 700 nm
};
const float XYZCMFCIE1931Judd2DegTabY[31] =
{
    0.0045f,            // 400 nm
    0.0093f,            // 410 nm
    0.0175f,            // 420 nm
    0.0273f,            // 430 nm
    0.0379f,            // 440 nm
    0.0468f,            // 450 nm
    0.0600f,            // 460 nm
    0.0910f,            // 470 nm
    0.1390f,            // 480 nm
    0.2080f,            // 490 nm
    0.3230f,            // 500 nm
    0.5030f,            // 510 nm
    0.7100f,            // 520 nm
    0.8620f,            // 530 nm
    0.9540f,            // 540 nm
    0.9950f,            // 550 nm
    0.9950f,            // 560 nm
    0.9520f,            // 570 nm
    0.8700f,            // 580 nm
    0.7570f,            // 590 nm
    0.6310f,            // 600 nm
    0.5030f,            // 610 nm
    0.3810f,            // 620 nm
    0.2650f,            // 630 nm
    0.1750f,            // 640 nm
    0.1070f,            // 650 nm
    0.0610f,            // 660 nm
    0.0320f,            // 670 nm
    0.0170f,            // 680 nm
    0.0082f,            // 690 nm
    0.0041f             // 700 nm
};
const float XYZCMFCIE1931Judd2DegTabZ[31] =
{
    0.2799f,            // 400 nm
    0.5835f,            // 410 nm
    1.0622f,            // 420 nm
    1.4526f,            // 430 nm
    1.6064f,            // 440 nm
    1.4717f,            // 450 nm
    1.2880f,            // 460 nm
    1.1133f,            // 470 nm
    0.7552f,            // 480 nm
    0.4461f,            // 490 nm
    0.2644f,            // 500 nm
    0.1541f,            // 510 nm
    0.0763f,            // 520 nm
    0.0412f,            // 530 nm
    0.0200f,            // 540 nm
    0.0088f,            // 550 nm
    0.0039f,            // 560 nm
    0.0020f,            // 570 nm
    0.0016f,            // 580 nm
    0.0011f,            // 590 nm
    0.0007f,            // 600 nm
    0.0003f,            // 610 nm
    0.0002f,            // 620 nm
    0.0001f,            // 630 nm
    0.0000f,            // 640 nm
    0.0000f,            // 650 nm
    0.0000f,            // 660 nm
    0.0000f,            // 670 nm
    0.0000f,            // 680 nm
    0.0000f,            // 690 nm
    0.0000f             // 700 nm
};

// XYZ color matching functions -- CIE 1931 2-deg, modified by Judd (1951) and Vos (1978).
const float XYZCMFCIE1931JuddVos2DegTabX[31] =
{
    3.798100e-002f,     // 400 nm
    9.994100e-002f,     // 410 nm
    2.294800e-001f,     // 420 nm
    3.109500e-001f,     // 430 nm
    3.333600e-001f,     // 440 nm
    2.888200e-001f,     // 450 nm
    2.327600e-001f,     // 460 nm
    1.747600e-001f,     // 470 nm
    9.194400e-002f,     // 480 nm
    3.173100e-002f,     // 490 nm
    4.849100e-003f,     // 500 nm
    9.289900e-003f,     // 510 nm
    6.379100e-002f,     // 520 nm
    1.669200e-001f,     // 530 nm
    2.926900e-001f,     // 540 nm
    4.363500e-001f,     // 550 nm
    5.974800e-001f,     // 560 nm
    7.642500e-001f,     // 570 nm
    9.163500e-001f,     // 580 nm
    1.023000e+000f,     // 590 nm
    1.055000e+000f,     // 600 nm
    9.923900e-001f,     // 610 nm
    8.434600e-001f,     // 620 nm
    6.328900e-001f,     // 630 nm
    4.406200e-001f,     // 640 nm
    2.786200e-001f,     // 650 nm
    1.616100e-001f,     // 660 nm
    8.575300e-002f,     // 670 nm
    4.583400e-002f,     // 680 nm
    2.218700e-002f,     // 690 nm
    1.109800e-002f      // 700 nm
};
const float XYZCMFCIE1931JuddVos2DegTabY[31] =
{
    2.800000e-003f,     // 400 nm
    7.400000e-003f,     // 410 nm
    1.750000e-002f,     // 420 nm
    2.730000e-002f,     // 430 nm
    3.790000e-002f,     // 440 nm
    4.680000e-002f,     // 450 nm
    6.000000e-002f,     // 460 nm
    9.098000e-002f,     // 470 nm
    1.390200e-001f,     // 480 nm
    2.080200e-001f,     // 490 nm
    3.230000e-001f,     // 500 nm
    5.030000e-001f,     // 510 nm
    7.100000e-001f,     // 520 nm
    8.620000e-001f,     // 530 nm
    9.540000e-001f,     // 540 nm
    9.949500e-001f,     // 550 nm
    9.950000e-001f,     // 560 nm
    9.520000e-001f,     // 570 nm
    8.700000e-001f,     // 580 nm
    7.570000e-001f,     // 590 nm
    6.310000e-001f,     // 600 nm
    5.030000e-001f,     // 610 nm
    3.810000e-001f,     // 620 nm
    2.650000e-001f,     // 630 nm
    1.750000e-001f,     // 640 nm
    1.070000e-001f,     // 650 nm
    6.100000e-002f,     // 660 nm
    3.200000e-002f,     // 670 nm
    1.700000e-002f,     // 680 nm
    8.210000e-003f,     // 690 nm
    4.102000e-003f      // 700 nm
};
const float XYZCMFCIE1931JuddVos2DegTabZ[31] =
{
    1.740900e-001f,     // 400 nm
    4.605300e-001f,     // 410 nm
    1.065800e+000f,     // 420 nm
    1.467200e+000f,     // 430 nm
    1.616600e+000f,     // 440 nm
    1.471700e+000f,     // 450 nm
    1.291700e+000f,     // 460 nm
    1.113800e+000f,     // 470 nm
    7.559600e-001f,     // 480 nm
    4.466900e-001f,     // 490 nm
    2.643700e-001f,     // 500 nm
    1.544500e-001f,     // 510 nm
    7.658500e-002f,     // 520 nm
    4.136600e-002f,     // 530 nm
    2.004200e-002f,     // 540 nm
    8.782300e-003f,     // 550 nm
    4.049300e-003f,     // 560 nm
    2.277100e-003f,     // 570 nm
    1.806600e-003f,     // 580 nm
    1.234800e-003f,     // 590 nm
    9.056400e-004f,     // 600 nm
    4.288500e-004f,     // 610 nm
    2.559800e-004f,     // 620 nm
    9.769400e-005f,     // 630 nm
    5.116500e-005f,     // 640 nm
    2.423800e-005f,     // 650 nm
    1.190600e-005f,     // 660 nm
    5.600600e-006f,     // 670 nm
    2.791200e-006f,     // 680 nm
    1.313500e-006f,     // 690 nm
    6.476700e-007f      // 700 nm
};

// XYZ color matching functions -- CIE 1964 10-deg.
const float XYZCMFCIE196410DegTabX[31] =
{
    0.019109700000f,    // 400 nm
    0.084736000000f,    // 410 nm
    0.204492000000f,    // 420 nm
    0.314679000000f,    // 430 nm
    0.383734000000f,    // 440 nm
    0.370702000000f,    // 450 nm
    0.302273000000f,    // 460 nm
    0.195618000000f,    // 470 nm
    0.080507000000f,    // 480 nm
    0.016172000000f,    // 490 nm
    0.003816000000f,    // 500 nm
    0.037465000000f,    // 510 nm
    0.117749000000f,    // 520 nm
    0.236491000000f,    // 530 nm
    0.376772000000f,    // 540 nm
    0.529826000000f,    // 550 nm
    0.705224000000f,    // 560 nm
    0.878655000000f,    // 570 nm
    1.014160000000f,    // 580 nm
    1.118520000000f,    // 590 nm
    1.123990000000f,    // 600 nm
    1.030480000000f,    // 610 nm
    0.856297000000f,    // 620 nm
    0.647467000000f,    // 630 nm
    0.431567000000f,    // 640 nm
    0.268329000000f,    // 650 nm
    0.152568000000f,    // 660 nm
    0.081260600000f,    // 670 nm
    0.040850800000f,    // 680 nm
    0.019941300000f,    // 690 nm
    0.009576880000f     // 700 nm
};
const float XYZCMFCIE196410DegTabY[31] =
{
    0.002004400000f,    // 400 nm
    0.008756000000f,    // 410 nm
    0.021391000000f,    // 420 nm
    0.038676000000f,    // 430 nm
    0.062077000000f,    // 440 nm
    0.089456000000f,    // 450 nm
    0.128201000000f,    // 460 nm
    0.185190000000f,    // 470 nm
    0.253589000000f,    // 480 nm
    0.339133000000f,    // 490 nm
    0.460777000000f,    // 500 nm
    0.606741000000f,    // 510 nm
    0.761757000000f,    // 520 nm
    0.875211000000f,    // 530 nm
    0.961988000000f,    // 540 nm
    0.991761000000f,    // 550 nm
    0.997340000000f,    // 560 nm
    0.955552000000f,    // 570 nm
    0.868934000000f,    // 580 nm
    0.777405000000f,    // 590 nm
    0.658341000000f,    // 600 nm
    0.527963000000f,    // 610 nm
    0.398057000000f,    // 620 nm
    0.283493000000f,    // 630 nm
    0.179828000000f,    // 640 nm
    0.107633000000f,    // 650 nm
    0.060281000000f,    // 660 nm
    0.031800400000f,    // 670 nm
    0.015905100000f,    // 680 nm
    0.007748800000f,    // 690 nm
    0.003717740000f     // 700 nm
};
const float XYZCMFCIE196410DegTabZ[31] =
{
    0.086010900000f,    // 400 nm
    0.389366000000f,    // 410 nm
    0.972542000000f,    // 420 nm
    1.553480000000f,    // 430 nm
    1.967280000000f,    // 440 nm
    1.994800000000f,    // 450 nm
    1.745370000000f,    // 460 nm
    1.317560000000f,    // 470 nm
    0.772125000000f,    // 480 nm
    0.415254000000f,    // 490 nm
    0.218502000000f,    // 500 nm
    0.112044000000f,    // 510 nm
    0.060709000000f,    // 520 nm
    0.030451000000f,    // 530 nm
    0.013676000000f,    // 540 nm
    0.003988000000f,    // 550 nm
    0.000000000000f,    // 560 nm
    0.000000000000f,    // 570 nm
    0.000000000000f,    // 580 nm
    0.000000000000f,    // 590 nm
    0.000000000000f,    // 600 nm
    0.000000000000f,    // 610 nm
    0.000000000000f,    // 620 nm
    0.000000000000f,    // 630 nm
    0.000000000000f,    // 640 nm
    0.000000000000f,    // 650 nm
    0.000000000000f,    // 660 nm
    0.000000000000f,    // 670 nm
    0.000000000000f,    // 680 nm
    0.000000000000f,    // 690 nm
    0.000000000000f     // 700 nm
};

// RGB color matching functions -- Stiles and Burch (1955) 2-deg.
const float RGBCMFStilesBurch19552DegTabX[31] =
{
    9.62640e-003f,     // 400 nm
    3.08030e-002f,     // 410 nm
    5.16620e-002f,     // 420 nm
    4.42870e-002f,     // 430 nm
    1.47630e-002f,     // 440 nm
    -2.91300e-002f,     // 450 nm
    -9.62240e-002f,     // 460 nm
    -1.74860e-001f,     // 470 nm
    -2.37800e-001f,     // 480 nm
    -2.77270e-001f,     // 490 nm
    -2.95000e-001f,     // 500 nm
    -2.67590e-001f,     // 510 nm
    -1.47680e-001f,     // 520 nm
    1.06140e-001f,     // 530 nm
    4.19760e-001f,     // 540 nm
    7.90040e-001f,     // 550 nm
    1.22830e+000f,     // 560 nm
    1.74760e+000f,     // 570 nm
    2.27240e+000f,     // 580 nm
    2.67250e+000f,     // 590 nm
    2.87170e+000f,     // 600 nm
    2.76010e+000f,     // 610 nm
    2.37430e+000f,     // 620 nm
    1.81450e+000f,     // 630 nm
    1.25430e+000f,     // 640 nm
    7.86420e-001f,     // 650 nm
    4.43200e-001f,     // 660 nm
    2.34550e-001f,     // 670 nm
    1.20860e-001f,     // 680 nm
    6.02600e-002f,     // 690 nm
    2.81140e-002f      // 700 nm
};
const float RGBCMFStilesBurch19552DegTabY[31] =
{
    -2.16890e-003f,     // 400 nm
    -7.20480e-003f,     // 410 nm
    -1.66510e-002f,     // 420 nm
    -1.99360e-002f,     // 430 nm
    -7.34570e-003f,     // 440 nm
    1.96100e-002f,     // 450 nm
    7.09540e-002f,     // 460 nm
    1.50880e-001f,     // 470 nm
    2.40420e-001f,     // 480 nm
    3.33530e-001f,     // 490 nm
    4.90600e-001f,     // 500 nm
    7.01840e-001f,     // 510 nm
    9.10760e-001f,     // 520 nm
    1.03390e+000f,     // 530 nm
    1.05120e+000f,     // 540 nm
    1.03680e+000f,     // 550 nm
    9.37830e-001f,     // 560 nm
    8.28350e-001f,     // 570 nm
    6.49300e-001f,     // 580 nm
    4.76750e-001f,     // 590 nm
    3.00690e-001f,     // 600 nm
    1.65750e-001f,     // 610 nm
    7.46820e-002f,     // 620 nm
    2.63330e-002f,     // 630 nm
    4.50330e-003f,     // 640 nm
    -1.96450e-003f,     // 650 nm
    -2.62620e-003f,     // 660 nm
    -1.87000e-003f,     // 670 nm
    -1.07550e-003f,     // 680 nm
    -5.67650e-004f,     // 690 nm
    -2.62310e-004f      // 700 nm
};
const float RGBCMFStilesBurch19552DegTabZ[31] =
{
    6.23710e-002f,     // 400 nm
    2.27500e-001f,     // 410 nm
    5.23960e-001f,     // 420 nm
    7.96040e-001f,     // 430 nm
    9.63950e-001f,     // 440 nm
    9.18750e-001f,     // 450 nm
    7.85540e-001f,     // 460 nm
    6.10980e-001f,     // 470 nm
    3.61950e-001f,     // 480 nm
    1.95930e-001f,     // 490 nm
    1.07490e-001f,     // 500 nm
    5.02480e-002f,     // 510 nm
    1.33090e-002f,     // 520 nm
    -4.15740e-003f,     // 530 nm
    -1.21910e-002f,     // 540 nm
    -1.46810e-002f,     // 550 nm
    -1.46130e-002f,     // 560 nm
    -1.26500e-002f,     // 570 nm
    -9.93170e-003f,     // 580 nm
    -7.02100e-003f,     // 590 nm
    -4.27430e-003f,     // 600 nm
    -2.26930e-003f,     // 610 nm
    -1.50690e-003f,     // 620 nm
    -5.53160e-004f,     // 630 nm
    -1.43190e-004f,     // 640 nm
    1.10810e-004f,     // 650 nm
    2.26560e-004f,     // 660 nm
    1.63610e-004f,     // 670 nm
    5.10330e-005f,     // 680 nm
    3.12110e-005f,     // 690 nm
    1.65210e-005f      // 700 nm
};

// RGB color matching functions -- Stiles and Burch (1959) 10-deg.
const float RGBCMFStilesBurch195910DegTabX[31] =
{
    8.9000E-03f,       // 400 nm
    3.5000E-02f,       // 410 nm
    7.0200E-02f,       // 420 nm
    7.4500E-02f,       // 430 nm
    3.2300E-02f,       // 440 nm
    -4.7800E-02f,       // 450 nm
    -1.5860E-01f,       // 460 nm
    -2.8480E-01f,       // 470 nm
    -3.7760E-01f,       // 480 nm
    -4.3170E-01f,       // 490 nm
    -4.3500E-01f,       // 500 nm
    -3.6730E-01f,       // 510 nm
    -1.8550E-01f,       // 520 nm
    1.2700E-01f,       // 530 nm
    5.3620E-01f,       // 540 nm
    1.0059E+00f,       // 550 nm
    1.5574E+00f,       // 560 nm
    2.1511E+00f,       // 570 nm
    2.6574E+00f,       // 580 nm
    3.0779E+00f,       // 590 nm
    3.1673E+00f,       // 600 nm
    2.9462E+00f,       // 610 nm
    2.4526E+00f,       // 620 nm
    1.8358E+00f,       // 630 nm
    1.2428E+00f,       // 640 nm
    7.8270E-01f,       // 650 nm
    4.4420E-01f,       // 660 nm
    2.3940E-01f,       // 670 nm
    1.2210E-01f,       // 680 nm
    5.8600E-02f,       // 690 nm
    2.8400E-02f        // 700 nm
};
const float RGBCMFStilesBurch195910DegTabY[31] =
{
    -2.5000E-03f,       // 400 nm
    -1.1900E-02f,       // 410 nm
    -2.8900E-02f,       // 420 nm
    -3.4900E-02f,       // 430 nm
    -1.6900E-02f,       // 440 nm
    2.8300E-02f,       // 450 nm
    1.0820E-01f,       // 460 nm
    2.2010E-01f,       // 470 nm
    3.4280E-01f,       // 480 nm
    4.7160E-01f,       // 490 nm
    6.2600E-01f,       // 500 nm
    7.9350E-01f,       // 510 nm
    9.4770E-01f,       // 520 nm
    1.0203E+00f,       // 530 nm
    1.0517E+00f,       // 540 nm
    1.0029E+00f,       // 550 nm
    9.1620E-01f,       // 560 nm
    7.8230E-01f,       // 570 nm
    5.9660E-01f,       // 580 nm
    4.2030E-01f,       // 590 nm
    2.5910E-01f,       // 600 nm
    1.3670E-01f,       // 610 nm
    6.1100E-02f,       // 620 nm
    2.1500E-02f,       // 630 nm
    4.4000E-03f,       // 640 nm
    -1.3680E-03f,       // 650 nm
    -2.1680E-03f,       // 660 nm
    -1.6420E-03f,       // 670 nm
    -9.4700E-04f,       // 680 nm
    -4.7800E-04f,       // 690 nm
    -2.3500E-04f        // 700 nm
};
const float RGBCMFStilesBurch195910DegTabZ[31] =
{
    4.0000E-02f,       // 400 nm
    1.8020E-01f,       // 410 nm
    4.6700E-01f,       // 420 nm
    7.6380E-01f,       // 430 nm
    9.7550E-01f,       // 440 nm
    9.9960E-01f,       // 450 nm
    8.2970E-01f,       // 460 nm
    6.1340E-01f,       // 470 nm
    3.4950E-01f,       // 480 nm
    1.8190E-01f,       // 490 nm
    9.1000E-02f,       // 500 nm
    3.5700E-02f,       // 510 nm
    9.5000E-03f,       // 520 nm
    -4.3000E-03f,       // 530 nm
    -8.2000E-03f,       // 540 nm
    -9.7000E-03f,       // 550 nm
    -9.3000E-03f,       // 560 nm
    -8.0000E-03f,       // 570 nm
    -6.3000E-03f,       // 580 nm
    -4.4500E-03f,       // 590 nm
    -2.7700E-03f,       // 600 nm
    -1.5000E-03f,       // 610 nm
    -6.8000E-04f,       // 620 nm
    -2.7200E-04f,       // 630 nm
    -5.4900E-05f,       // 640 nm
    2.3700E-05f,       // 650 nm
    2.6100E-05f,       // 660 nm
    1.8200E-05f,       // 670 nm
    1.0300E-05f,       // 680 nm
    5.2200E-06f,       // 690 nm
    2.5600E-06f        // 700 nm
};
}

// XYZ color matching functions.
const Spectrum31f XYZCMFCIE19312Deg[3] =
{
    Spectrum31f(XYZCMFCIE19312DegTabX),
    Spectrum31f(XYZCMFCIE19312DegTabY),
    Spectrum31f(XYZCMFCIE19312DegTabZ)
};
const Spectrum31f XYZCMFCIE1931Judd2Deg[3] =
{
    Spectrum31f(XYZCMFCIE1931Judd2DegTabX),
    Spectrum31f(XYZCMFCIE1931Judd2DegTabY),
    Spectrum31f(XYZCMFCIE1931Judd2DegTabZ)
};
const Spectrum31f XYZCMFCIE1931JuddVos2Deg[3] =
{
    Spectrum31f(XYZCMFCIE1931JuddVos2DegTabX),
    Spectrum31f(XYZCMFCIE1931JuddVos2DegTabY),
    Spectrum31f(XYZCMFCIE1931JuddVos2DegTabZ)
};
const Spectrum31f XYZCMFCIE196410Deg[3] =
{
    Spectrum31f(XYZCMFCIE196410DegTabX),
    Spectrum31f(XYZCMFCIE196410DegTabY),
    Spectrum31f(XYZCMFCIE196410DegTabZ)
};

// RGB color matching functions.
const Spectrum31f RGBCMFStilesBurch19552Deg[3] =
{
    Spectrum31f(RGBCMFStilesBurch19552DegTabX),
    Spectrum31f(RGBCMFStilesBurch19552DegTabY),
    Spectrum31f(RGBCMFStilesBurch19552DegTabZ)
};
const Spectrum31f RGBCMFStilesBurch195910Deg[3] =
{
    Spectrum31f(RGBCMFStilesBurch195910DegTabX),
    Spectrum31f(RGBCMFStilesBurch195910DegTabY),
    Spectrum31f(RGBCMFStilesBurch195910DegTabZ)
};


//
// Basis spectra for RGB-to-spectrum conversion.
//

namespace
{
const float RGBToSpectrumWhiteReflectanceTab[31] =
{
    1.061387f,         // 400 nm
    1.062091f,         // 410 nm
    1.062237f,         // 420 nm
    1.062381f,         // 430 nm
    1.062469f,         // 440 nm
    1.062411f,         // 450 nm
    1.062487f,         // 460 nm
    1.062502f,         // 470 nm
    1.062409f,         // 480 nm
    1.062052f,         // 490 nm
    1.061349f,         // 500 nm
    1.061037f,         // 510 nm
    1.061312f,         // 520 nm
    1.061379f,         // 530 nm
    1.061760f,         // 540 nm
    1.062337f,         // 550 nm
    1.062536f,         // 560 nm
    1.062453f,         // 570 nm
    1.062512f,         // 580 nm
    1.062427f,         // 590 nm
    1.062479f,         // 600 nm
    1.062553f,         // 610 nm
    1.062541f,         // 620 nm
    1.062416f,         // 630 nm
    1.062356f,         // 640 nm
    1.062562f,         // 650 nm
    1.061957f,         // 660 nm
    1.060339f,         // 670 nm
    1.059459f,         // 680 nm
    1.060084f,         // 690 nm
    1.060248f          // 700 nm
};

const float RGBToSpectrumCyanReflectanceTab[31] =
{
    1.013784f,         // 400 nm
    1.031559f,         // 410 nm
    1.014911f,         // 420 nm
    1.025949f,         // 430 nm
    1.044892f,         // 440 nm
    1.049293f,         // 450 nm
    1.044493f,         // 460 nm
    1.019764f,         // 470 nm
    1.046143f,         // 480 nm
    1.053069f,         // 490 nm
    1.053699f,         // 500 nm
    1.053409f,         // 510 nm
    1.053772f,         // 520 nm
    1.053003f,         // 530 nm
    1.052717f,         // 540 nm
    1.054052f,         // 550 nm
    1.055816f,         // 560 nm
    1.067498f,         // 570 nm
    0.974937f,         // 580 nm
    0.557098f,         // 590 nm
    0.162351f,         // 600 nm
    -0.004918f,         // 610 nm
    -0.001546f,         // 620 nm
    -0.006570f,         // 630 nm
    -0.003945f,         // 640 nm
    -0.000951f,         // 650 nm
    0.008167f,         // 660 nm
    0.004759f,         // 670 nm
    0.001682f,         // 680 nm
    0.015969f,         // 690 nm
    0.004066f          // 700 nm
};

const float RGBToSpectrumMagentaReflectanceTab[31] =
{
    0.982980f,         // 400 nm
    0.991489f,         // 410 nm
    1.013132f,         // 420 nm
    1.018938f,         // 430 nm
    1.020450f,         // 440 nm
    1.012822f,         // 450 nm
    0.997617f,         // 460 nm
    1.018910f,         // 470 nm
    0.996257f,         // 480 nm
    0.624846f,         // 490 nm
    0.023716f,         // 500 nm
    0.000435f,         // 510 nm
    0.003808f,         // 520 nm
    0.001347f,         // 530 nm
    -0.006551f,         // 540 nm
    -0.002995f,         // 550 nm
    -0.009466f,         // 560 nm
    0.046101f,         // 570 nm
    0.307088f,         // 580 nm
    0.688640f,         // 590 nm
    0.983592f,         // 600 nm
    0.971656f,         // 610 nm
    1.014684f,         // 620 nm
    1.005811f,         // 630 nm
    0.966371f,         // 640 nm
    0.876699f,         // 650 nm
    0.898889f,         // 660 nm
    0.952359f,         // 670 nm
    0.968253f,         // 680 nm
    0.969608f,         // 690 nm
    0.859295f          // 700 nm
};

const float RGBToSpectrumYellowReflectanceTab[31] =
{
    -0.005256f,         // 400 nm
    -0.006240f,         // 410 nm
    -0.006453f,         // 420 nm
    -0.005079f,         // 430 nm
    0.002202f,         // 440 nm
    0.041046f,         // 450 nm
    0.126522f,         // 460 nm
    0.240308f,         // 470 nm
    0.381160f,         // 480 nm
    0.545267f,         // 490 nm
    0.732706f,         // 500 nm
    0.899055f,         // 510 nm
    1.026172f,         // 520 nm
    1.054259f,         // 530 nm
    1.051548f,         // 540 nm
    1.051072f,         // 550 nm
    1.051318f,         // 560 nm
    1.051766f,         // 570 nm
    1.051519f,         // 580 nm
    1.051164f,         // 590 nm
    1.051176f,         // 600 nm
    1.051657f,         // 610 nm
    1.051418f,         // 620 nm
    1.051589f,         // 630 nm
    1.051238f,         // 640 nm
    1.051408f,         // 650 nm
    1.051198f,         // 660 nm
    1.051017f,         // 670 nm
    1.049825f,         // 680 nm
    1.048018f,         // 690 nm
    1.048736f          // 700 nm
};

const float RGBToSpectrumRedReflectanceTab[31] =
{
    0.123370f,         // 400 nm
    0.118612f,         // 410 nm
    0.093120f,         // 420 nm
    0.053243f,         // 430 nm
    0.007507f,         // 440 nm
    -0.003131f,         // 450 nm
    0.016717f,         // 460 nm
    0.006158f,         // 470 nm
    0.012482f,         // 480 nm
    -0.006159f,         // 490 nm
    -0.001790f,         // 500 nm
    -0.010045f,         // 510 nm
    -0.004015f,         // 520 nm
    -0.008488f,         // 530 nm
    -0.009905f,         // 540 nm
    -0.005552f,         // 550 nm
    0.002525f,         // 560 nm
    -0.018421f,         // 570 nm
    0.098336f,         // 580 nm
    0.679751f,         // 590 nm
    0.998411f,         // 600 nm
    0.993848f,         // 610 nm
    1.003718f,         // 620 nm
    0.993893f,         // 630 nm
    0.996498f,         // 640 nm
    1.007329f,         // 650 nm
    0.994003f,         // 660 nm
    0.994352f,         // 670 nm
    0.999046f,         // 680 nm
    0.975771f,         // 690 nm
    0.978881f          // 700 nm
};

const float RGBToSpectrumGreenReflectanceTab[31] =
{
    -0.011856f,         // 400 nm
    -0.010107f,         // 410 nm
    -0.011761f,         // 420 nm
    -0.010045f,         // 430 nm
    -0.007570f,         // 440 nm
    -0.011862f,         // 450 nm
    -0.000730f,         // 460 nm
    0.116436f,         // 470 nm
    0.437371f,         // 480 nm
    0.760744f,         // 490 nm
    0.956170f,         // 500 nm
    0.996844f,         // 510 nm
    1.000443f,         // 520 nm
    0.999553f,         // 530 nm
    0.999740f,         // 540 nm
    0.999719f,         // 550 nm
    1.001184f,         // 560 nm
    0.999628f,         // 570 nm
    0.903812f,         // 580 nm
    0.578153f,         // 590 nm
    0.239696f,         // 600 nm
    0.013386f,         // 610 nm
    -0.003558f,         // 620 nm
    -0.004351f,         // 630 nm
    -0.006185f,         // 640 nm
    -0.008415f,         // 650 nm
    -0.008937f,         // 660 nm
    -0.008493f,         // 670 nm
    -0.008510f,         // 680 nm
    -0.006252f,         // 690 nm
    0.001272f          // 700 nm
};

const float RGBToSpectrumBlueReflectanceTab[31] =
{
    0.994496f,         // 400 nm
    0.995734f,         // 410 nm
    0.992298f,         // 420 nm
    0.996506f,         // 430 nm
    1.000538f,         // 440 nm
    1.000383f,         // 450 nm
    1.002111f,         // 460 nm
    0.957210f,         // 470 nm
    0.764892f,         // 480 nm
    0.554058f,         // 490 nm
    0.343920f,         // 500 nm
    0.161104f,         // 510 nm
    0.038247f,         // 520 nm
    0.001238f,         // 530 nm
    -0.001204f,         // 540 nm
    -0.000583f,         // 550 nm
    0.000324f,         // 560 nm
    0.002647f,         // 570 nm
    0.003114f,         // 580 nm
    -0.000802f,         // 590 nm
    0.000202f,         // 600 nm
    0.007214f,         // 610 nm
    0.023857f,         // 620 nm
    0.035788f,         // 630 nm
    0.047014f,         // 640 nm
    0.050053f,         // 650 nm
    0.050377f,         // 660 nm
    0.046082f,         // 670 nm
    0.036494f,         // 680 nm
    0.028174f,         // 690 nm
    0.018875f          // 700 nm
};

const float RGBToSpectrumWhiteIlluminanceTab[31] =
{
    1.156698f,         // 400 nm
    1.155758f,         // 410 nm
    1.155931f,         // 420 nm
    1.156565f,         // 430 nm
    1.156822f,         // 440 nm
    1.156811f,         // 450 nm
    1.156651f,         // 460 nm
    1.156388f,         // 470 nm
    1.156707f,         // 480 nm
    1.156509f,         // 490 nm
    1.156426f,         // 500 nm
    1.157271f,         // 510 nm
    1.150024f,         // 520 nm
    1.137745f,         // 530 nm
    1.130518f,         // 540 nm
    1.133846f,         // 550 nm
    1.098581f,         // 560 nm
    1.045236f,         // 570 nm
    1.036640f,         // 580 nm
    0.987287f,         // 590 nm
    0.953973f,         // 600 nm
    0.925293f,         // 610 nm
    0.916277f,         // 620 nm
    0.901951f,         // 630 nm
    0.896439f,         // 640 nm
    0.891381f,         // 650 nm
    0.884983f,         // 660 nm
    0.881022f,         // 670 nm
    0.878510f,         // 680 nm
    0.876875f,         // 690 nm
    0.880276f          // 700 nm
};

const float RGBToSpectrumCyanIlluminanceTab[31] =
{
    1.133496f,         // 400 nm
    1.135722f,         // 410 nm
    1.135677f,         // 420 nm
    1.135899f,         // 430 nm
    1.136179f,         // 440 nm
    1.136363f,         // 450 nm
    1.136230f,         // 460 nm
    1.135595f,         // 470 nm
    1.136418f,         // 480 nm
    1.136031f,         // 490 nm
    1.136028f,         // 500 nm
    1.135439f,         // 510 nm
    1.136184f,         // 520 nm
    1.135807f,         // 530 nm
    1.135432f,         // 540 nm
    1.136641f,         // 550 nm
    1.135842f,         // 560 nm
    1.061325f,         // 570 nm
    0.843320f,         // 580 nm
    0.565191f,         // 590 nm
    0.280469f,         // 600 nm
    0.100495f,         // 610 nm
    -0.004459f,         // 620 nm
    -0.013942f,         // 630 nm
    -0.011351f,         // 640 nm
    -0.012158f,         // 650 nm
    -0.008124f,         // 660 nm
    -0.005750f,         // 670 nm
    -0.008846f,         // 680 nm
    -0.008741f,         // 690 nm
    -0.005066f          // 700 nm
};

const float RGBToSpectrumMagentaIlluminanceTab[31] =
{
    1.074704f,         // 400 nm
    1.076600f,         // 410 nm
    1.078852f,         // 420 nm
    1.076860f,         // 430 nm
    1.073222f,         // 440 nm
    1.072362f,         // 450 nm
    1.075529f,         // 460 nm
    1.085388f,         // 470 nm
    1.076622f,         // 480 nm
    0.948043f,         // 490 nm
    0.577859f,         // 500 nm
    0.133047f,         // 510 nm
    0.006134f,         // 520 nm
    -0.004691f,         // 530 nm
    -0.001787f,         // 540 nm
    -0.000471f,         // 550 nm
    -0.000761f,         // 560 nm
    -0.004745f,         // 570 nm
    0.055622f,         // 580 nm
    0.296176f,         // 590 nm
    0.548960f,         // 600 nm
    0.901497f,         // 610 nm
    1.058057f,         // 620 nm
    1.089931f,         // 630 nm
    1.073832f,         // 640 nm
    1.034064f,         // 650 nm
    1.017433f,         // 660 nm
    1.054028f,         // 670 nm
    1.048301f,         // 680 nm
    0.995864f,         // 690 nm
    1.075629f          // 700 nm
};

const float RGBToSpectrumYellowIlluminanceTab[31] =
{
    0.000371f,         // 400 nm
    0.000189f,         // 410 nm
    -0.000055f,         // 420 nm
    -0.000159f,         // 430 nm
    -0.000136f,         // 440 nm
    -0.002447f,         // 450 nm
    -0.000851f,         // 460 nm
    0.112473f,         // 470 nm
    0.547520f,         // 480 nm
    1.037173f,         // 490 nm
    1.033988f,         // 500 nm
    1.036503f,         // 510 nm
    1.036619f,         // 520 nm
    1.036492f,         // 530 nm
    1.036760f,         // 540 nm
    1.036743f,         // 550 nm
    1.036461f,         // 560 nm
    1.036481f,         // 570 nm
    1.036714f,         // 580 nm
    1.036487f,         // 590 nm
    1.036149f,         // 600 nm
    1.035322f,         // 610 nm
    1.014072f,         // 620 nm
    0.874031f,         // 630 nm
    0.764727f,         // 640 nm
    0.685721f,         // 650 nm
    0.625980f,         // 660 nm
    0.597532f,         // 670 nm
    0.595525f,         // 680 nm
    0.587864f,         // 690 nm
    0.562571f          // 700 nm
};

const float RGBToSpectrumRedIlluminanceTab[31] =
{
    0.060372f,         // 400 nm
    0.058076f,         // 410 nm
    0.049804f,         // 420 nm
    0.041882f,         // 430 nm
    0.032383f,         // 440 nm
    0.016357f,         // 450 nm
    0.001227f,         // 460 nm
    -0.000600f,         // 470 nm
    0.000994f,         // 480 nm
    0.000352f,         // 490 nm
    -0.000416f,         // 500 nm
    -0.000134f,         // 510 nm
    -0.000109f,         // 520 nm
    -0.000136f,         // 530 nm
    -0.000159f,         // 540 nm
    -0.002088f,         // 550 nm
    0.003661f,         // 560 nm
    0.060596f,         // 570 nm
    0.200799f,         // 580 nm
    0.382020f,         // 590 nm
    0.585726f,         // 600 nm
    0.759210f,         // 610 nm
    0.879348f,         // 620 nm
    0.953040f,         // 630 nm
    0.984016f,         // 640 nm
    0.997430f,         // 650 nm
    0.992023f,         // 660 nm
    0.990260f,         // 670 nm
    0.988620f,         // 680 nm
    0.976626f,         // 690 nm
    0.991906f          // 700 nm
};

const float RGBToSpectrumGreenIlluminanceTab[31] =
{
    0.010635f,         // 400 nm
    0.006551f,         // 410 nm
    0.002472f,         // 420 nm
    0.001207f,         // 430 nm
    -0.012218f,         // 440 nm
    -0.009396f,         // 450 nm
    0.005333f,         // 460 nm
    0.041161f,         // 470 nm
    0.393510f,         // 480 nm
    1.026335f,         // 490 nm
    1.033528f,         // 500 nm
    1.032193f,         // 510 nm
    1.036581f,         // 520 nm
    1.019782f,         // 530 nm
    1.025242f,         // 540 nm
    1.036703f,         // 550 nm
    1.037640f,         // 560 nm
    1.034223f,         // 570 nm
    1.032591f,         // 580 nm
    0.866002f,         // 590 nm
    -0.030362f,         // 600 nm
    0.000527f,         // 610 nm
    0.006544f,         // 620 nm
    0.000415f,         // 630 nm
    0.017375f,         // 640 nm
    0.012188f,         // 650 nm
    0.002288f,         // 660 nm
    0.001011f,         // 670 nm
    -0.002722f,         // 680 nm
    -0.004106f,         // 690 nm
    0.015684f          // 700 nm
};

const float RGBToSpectrumBlueIlluminanceTab[31] =
{
    1.054973f,         // 400 nm
    1.053157f,         // 410 nm
    1.056342f,         // 420 nm
    1.058145f,         // 430 nm
    1.058072f,         // 440 nm
    1.058307f,         // 450 nm
    1.057469f,         // 460 nm
    1.056468f,         // 470 nm
    1.060424f,         // 480 nm
    1.031067f,         // 490 nm
    0.359200f,         // 500 nm
    0.025142f,         // 510 nm
    -0.008347f,         // 520 nm
    -0.001384f,         // 530 nm
    -0.001313f,         // 540 nm
    -0.001800f,         // 550 nm
    -0.000581f,         // 560 nm
    0.000669f,         // 570 nm
    -0.001740f,         // 580 nm
    -0.001339f,         // 590 nm
    -0.001779f,         // 600 nm
    -0.001401f,         // 610 nm
    0.008460f,         // 620 nm
    0.024439f,         // 630 nm
    0.071304f,         // 640 nm
    0.122407f,         // 650 nm
    0.151016f,         // 660 nm
    0.152744f,         // 670 nm
    0.153725f,         // 680 nm
    0.168626f,         // 690 nm
    0.168186f          // 700 nm
};
}

// Basis spectra for reflectance conversions.
const Spectrum31f RGBToSpectrumWhiteReflectance(RGBToSpectrumWhiteReflectanceTab);
const Spectrum31f RGBToSpectrumCyanReflectance(RGBToSpectrumCyanReflectanceTab);
const Spectrum31f RGBToSpectrumMagentaReflectance(RGBToSpectrumMagentaReflectanceTab);
const Spectrum31f RGBToSpectrumYellowReflectance(RGBToSpectrumYellowReflectanceTab);
const Spectrum31f RGBToSpectrumRedReflectance(RGBToSpectrumRedReflectanceTab);
const Spectrum31f RGBToSpectrumGreenReflectance(RGBToSpectrumGreenReflectanceTab);
const Spectrum31f RGBToSpectrumBlueReflectance(RGBToSpectrumBlueReflectanceTab);

// Basis spectra for illuminance conversions.
const Spectrum31f RGBToSpectrumWhiteIlluminance(RGBToSpectrumWhiteIlluminanceTab);
const Spectrum31f RGBToSpectrumCyanIlluminance(RGBToSpectrumCyanIlluminanceTab);
const Spectrum31f RGBToSpectrumMagentaIlluminance(RGBToSpectrumMagentaIlluminanceTab);
const Spectrum31f RGBToSpectrumYellowIlluminance(RGBToSpectrumYellowIlluminanceTab);
const Spectrum31f RGBToSpectrumRedIlluminance(RGBToSpectrumRedIlluminanceTab);
const Spectrum31f RGBToSpectrumGreenIlluminance(RGBToSpectrumGreenIlluminanceTab);
const Spectrum31f RGBToSpectrumBlueIlluminance(RGBToSpectrumBlueIlluminanceTab);


//
// Lighting conditions class implementation.
//

LightingConditions::LightingConditions()
{
}

LightingConditions::LightingConditions(
    const Spectrum31f&  illuminant,
    const Spectrum31f   cmf[3])
{
    // Precompute convolution of color matching functions and illuminant.
    for (size_t w = 0; w < 32; ++w)
    {
        m_cmf[w][0] = cmf[0][w] * illuminant[w];
        m_cmf[w][1] = cmf[1][w] * illuminant[w];
        m_cmf[w][2] = cmf[2][w] * illuminant[w];
        m_cmf[w][3] = 0.0f;
    }

    // Integrate the luminance.
    float n = 0.0f;
    for (size_t w = 0; w < 31; ++w)
        n += m_cmf[w][1];
    float rcp_n = 1.0f / n;

    // Rescale the color matching functions such that luminance integrates to 1.
    for (size_t w = 0; w < 31; ++w)
        m_cmf[w] *= rcp_n;
}


//
// Spectrum <-> CIE XYZ transformations implementation.
//

void spectrum_to_ciexyz_standard(
    const float         spectrum[],
    float               ciexyz[3])
{
    const LightingConditions lighting_conditions(IlluminantCIED65, XYZCMFCIE196410Deg);

    const Color3f c =
        spectrum_to_ciexyz<float, Spectrum31f>(
            lighting_conditions,
            Spectrum31f(spectrum));

    ciexyz[0] = c[0];
    ciexyz[1] = c[1];
    ciexyz[2] = c[2];
}

}   // namespace foundation
예제 #3
0
namespace foundation
{

const char* color_space_name(const ColorSpace color_space)
{
    switch (color_space)
    {
      case ColorSpaceLinearRGB: return "linear_rgb";
      case ColorSpaceSRGB:      return "srgb";
      case ColorSpaceCIEXYZ:    return "ciexyz";
      case ColorSpaceSpectral:  return "spectral";
      default:                  return "";
    }
}


//
// Standard illuminants.
//

namespace
{
    const float IlluminantCIED65Tab[31] =
    {
         82.754900f,        // 400 nm
         91.486000f,        // 410 nm
         93.431800f,        // 420 nm
         86.682300f,        // 430 nm
        104.865000f,        // 440 nm
        117.008000f,        // 450 nm
        117.812000f,        // 460 nm
        114.861000f,        // 470 nm
        115.923000f,        // 480 nm
        108.811000f,        // 490 nm
        109.354000f,        // 500 nm
        107.802000f,        // 510 nm
        104.790000f,        // 520 nm
        107.689000f,        // 530 nm
        104.405000f,        // 540 nm
        104.046000f,        // 550 nm
        100.000000f,        // 560 nm
         96.334200f,        // 570 nm
         95.788000f,        // 580 nm
         88.685600f,        // 590 nm
         90.006200f,        // 600 nm
         89.599100f,        // 610 nm
         87.698700f,        // 620 nm
         83.288600f,        // 630 nm
         83.699200f,        // 640 nm
         80.026800f,        // 650 nm
         80.214600f,        // 660 nm
         82.277800f,        // 670 nm
         78.284200f,        // 680 nm
         69.721300f,        // 690 nm
         71.609100f         // 700 nm
    };

    const float IlluminantCIEATab[31] =
    {
         14.708000f,        // 400 nm
         17.675300f,        // 410 nm
         20.995000f,        // 420 nm
         24.670900f,        // 430 nm
         28.702700f,        // 440 nm
         33.085900f,        // 450 nm
         37.812100f,        // 460 nm
         42.869300f,        // 470 nm
         48.242300f,        // 480 nm
         53.913200f,        // 490 nm
         59.861100f,        // 500 nm
         66.063500f,        // 510 nm
         72.495900f,        // 520 nm
         79.132600f,        // 530 nm
         85.947000f,        // 540 nm
         92.912000f,        // 550 nm
        100.000000f,        // 560 nm
        107.184000f,        // 570 nm
        114.436000f,        // 580 nm
        121.731000f,        // 590 nm
        129.043000f,        // 600 nm
        136.346000f,        // 610 nm
        143.618000f,        // 620 nm
        150.836000f,        // 630 nm
        157.979000f,        // 640 nm
        165.028000f,        // 650 nm
        171.963000f,        // 660 nm
        178.769000f,        // 670 nm
        185.429000f,        // 680 nm
        191.931000f,        // 690 nm
        198.261000f         // 700 nm
    };
}

// Daylight illuminants.
const Spectrum31f IlluminantCIED65(IlluminantCIED65Tab);

// Incandescent lighting illuminants.
const Spectrum31f IlluminantCIEA(IlluminantCIEATab);


//
// Color Matching Functions (CMF).
//

namespace
{
    // XYZ color matching functions -- CIE 1931 2-deg.
    const float XYZCMFCIE19312DegTabX[31] =
    {
        0.014310000000f,    // 400 nm
        0.043510000000f,    // 410 nm
        0.134380000000f,    // 420 nm
        0.283900000000f,    // 430 nm
        0.348280000000f,    // 440 nm
        0.336200000000f,    // 450 nm
        0.290800000000f,    // 460 nm
        0.195360000000f,    // 470 nm
        0.095640000000f,    // 480 nm
        0.032010000000f,    // 490 nm
        0.004900000000f,    // 500 nm
        0.009300000000f,    // 510 nm
        0.063270000000f,    // 520 nm
        0.165500000000f,    // 530 nm
        0.290400000000f,    // 540 nm
        0.433449900000f,    // 550 nm
        0.594500000000f,    // 560 nm
        0.762100000000f,    // 570 nm
        0.916300000000f,    // 580 nm
        1.026300000000f,    // 590 nm
        1.062200000000f,    // 600 nm
        1.002600000000f,    // 610 nm
        0.854449900000f,    // 620 nm
        0.642400000000f,    // 630 nm
        0.447900000000f,    // 640 nm
        0.283500000000f,    // 650 nm
        0.164900000000f,    // 660 nm
        0.087400000000f,    // 670 nm
        0.046770000000f,    // 680 nm
        0.022700000000f,    // 690 nm
        0.011359160000f     // 700 nm
    };
    const float XYZCMFCIE19312DegTabY[31] =
    {
        0.000396000000f,    // 400 nm
        0.001210000000f,    // 410 nm
        0.004000000000f,    // 420 nm
        0.011600000000f,    // 430 nm
        0.023000000000f,    // 440 nm
        0.038000000000f,    // 450 nm
        0.060000000000f,    // 460 nm
        0.090980000000f,    // 470 nm
        0.139020000000f,    // 480 nm
        0.208020000000f,    // 490 nm
        0.323000000000f,    // 500 nm
        0.503000000000f,    // 510 nm
        0.710000000000f,    // 520 nm
        0.862000000000f,    // 530 nm
        0.954000000000f,    // 540 nm
        0.994950100000f,    // 550 nm
        0.995000000000f,    // 560 nm
        0.952000000000f,    // 570 nm
        0.870000000000f,    // 580 nm
        0.757000000000f,    // 590 nm
        0.631000000000f,    // 600 nm
        0.503000000000f,    // 610 nm
        0.381000000000f,    // 620 nm
        0.265000000000f,    // 630 nm
        0.175000000000f,    // 640 nm
        0.107000000000f,    // 650 nm
        0.061000000000f,    // 660 nm
        0.032000000000f,    // 670 nm
        0.017000000000f,    // 680 nm
        0.008210000000f,    // 690 nm
        0.004102000000f     // 700 nm
    };
    const float XYZCMFCIE19312DegTabZ[31] =
    {
        0.067850010000f,    // 400 nm
        0.207400000000f,    // 410 nm
        0.645600000000f,    // 420 nm
        1.385600000000f,    // 430 nm
        1.747060000000f,    // 440 nm
        1.772110000000f,    // 450 nm
        1.669200000000f,    // 460 nm
        1.287640000000f,    // 470 nm
        0.812950100000f,    // 480 nm
        0.465180000000f,    // 490 nm
        0.272000000000f,    // 500 nm
        0.158200000000f,    // 510 nm
        0.078249990000f,    // 520 nm
        0.042160000000f,    // 530 nm
        0.020300000000f,    // 540 nm
        0.008749999000f,    // 550 nm
        0.003900000000f,    // 560 nm
        0.002100000000f,    // 570 nm
        0.001650001000f,    // 580 nm
        0.001100000000f,    // 590 nm
        0.000800000000f,    // 600 nm
        0.000340000000f,    // 610 nm
        0.000190000000f,    // 620 nm
        0.000049999990f,    // 630 nm
        0.000020000000f,    // 640 nm
        0.000000000000f,    // 650 nm
        0.000000000000f,    // 660 nm
        0.000000000000f,    // 670 nm
        0.000000000000f,    // 680 nm
        0.000000000000f,    // 690 nm
        0.000000000000f     // 700 nm
    };

    // XYZ color matching functions -- CIE 1931 2-deg, modified by Judd (1951).
    const float XYZCMFCIE1931Judd2DegTabX[31] =
    {
        0.0611f,            // 400 nm
        0.1267f,            // 410 nm
        0.2285f,            // 420 nm
        0.3081f,            // 430 nm
        0.3312f,            // 440 nm
        0.2888f,            // 450 nm
        0.2323f,            // 460 nm
        0.1745f,            // 470 nm
        0.0920f,            // 480 nm
        0.0318f,            // 490 nm
        0.0048f,            // 500 nm
        0.0093f,            // 510 nm
        0.0636f,            // 520 nm
        0.1668f,            // 530 nm
        0.2926f,            // 540 nm
        0.4364f,            // 550 nm
        0.5970f,            // 560 nm
        0.7642f,            // 570 nm
        0.9159f,            // 580 nm
        1.0225f,            // 590 nm
        1.0544f,            // 600 nm
        0.9922f,            // 610 nm
        0.8432f,            // 620 nm
        0.6327f,            // 630 nm
        0.4404f,            // 640 nm
        0.2787f,            // 650 nm
        0.1619f,            // 660 nm
        0.0858f,            // 670 nm
        0.0459f,            // 680 nm
        0.0222f,            // 690 nm
        0.0113f             // 700 nm
    };
    const float XYZCMFCIE1931Judd2DegTabY[31] =
    {
        0.0045f,            // 400 nm
        0.0093f,            // 410 nm
        0.0175f,            // 420 nm
        0.0273f,            // 430 nm
        0.0379f,            // 440 nm
        0.0468f,            // 450 nm
        0.0600f,            // 460 nm
        0.0910f,            // 470 nm
        0.1390f,            // 480 nm
        0.2080f,            // 490 nm
        0.3230f,            // 500 nm
        0.5030f,            // 510 nm
        0.7100f,            // 520 nm
        0.8620f,            // 530 nm
        0.9540f,            // 540 nm
        0.9950f,            // 550 nm
        0.9950f,            // 560 nm
        0.9520f,            // 570 nm
        0.8700f,            // 580 nm
        0.7570f,            // 590 nm
        0.6310f,            // 600 nm
        0.5030f,            // 610 nm
        0.3810f,            // 620 nm
        0.2650f,            // 630 nm
        0.1750f,            // 640 nm
        0.1070f,            // 650 nm
        0.0610f,            // 660 nm
        0.0320f,            // 670 nm
        0.0170f,            // 680 nm
        0.0082f,            // 690 nm
        0.0041f             // 700 nm
    };
    const float XYZCMFCIE1931Judd2DegTabZ[31] =
    {
        0.2799f,            // 400 nm
        0.5835f,            // 410 nm
        1.0622f,            // 420 nm
        1.4526f,            // 430 nm
        1.6064f,            // 440 nm
        1.4717f,            // 450 nm
        1.2880f,            // 460 nm
        1.1133f,            // 470 nm
        0.7552f,            // 480 nm
        0.4461f,            // 490 nm
        0.2644f,            // 500 nm
        0.1541f,            // 510 nm
        0.0763f,            // 520 nm
        0.0412f,            // 530 nm
        0.0200f,            // 540 nm
        0.0088f,            // 550 nm
        0.0039f,            // 560 nm
        0.0020f,            // 570 nm
        0.0016f,            // 580 nm
        0.0011f,            // 590 nm
        0.0007f,            // 600 nm
        0.0003f,            // 610 nm
        0.0002f,            // 620 nm
        0.0001f,            // 630 nm
        0.0000f,            // 640 nm
        0.0000f,            // 650 nm
        0.0000f,            // 660 nm
        0.0000f,            // 670 nm
        0.0000f,            // 680 nm
        0.0000f,            // 690 nm
        0.0000f             // 700 nm
    };

    // XYZ color matching functions -- CIE 1931 2-deg, modified by Judd (1951) and Vos (1978).
    const float XYZCMFCIE1931JuddVos2DegTabX[31] =
    {
        3.798100e-002f,     // 400 nm
        9.994100e-002f,     // 410 nm
        2.294800e-001f,     // 420 nm
        3.109500e-001f,     // 430 nm
        3.333600e-001f,     // 440 nm
        2.888200e-001f,     // 450 nm
        2.327600e-001f,     // 460 nm
        1.747600e-001f,     // 470 nm
        9.194400e-002f,     // 480 nm
        3.173100e-002f,     // 490 nm
        4.849100e-003f,     // 500 nm
        9.289900e-003f,     // 510 nm
        6.379100e-002f,     // 520 nm
        1.669200e-001f,     // 530 nm
        2.926900e-001f,     // 540 nm
        4.363500e-001f,     // 550 nm
        5.974800e-001f,     // 560 nm
        7.642500e-001f,     // 570 nm
        9.163500e-001f,     // 580 nm
        1.023000e+000f,     // 590 nm
        1.055000e+000f,     // 600 nm
        9.923900e-001f,     // 610 nm
        8.434600e-001f,     // 620 nm
        6.328900e-001f,     // 630 nm
        4.406200e-001f,     // 640 nm
        2.786200e-001f,     // 650 nm
        1.616100e-001f,     // 660 nm
        8.575300e-002f,     // 670 nm
        4.583400e-002f,     // 680 nm
        2.218700e-002f,     // 690 nm
        1.109800e-002f      // 700 nm
    };
    const float XYZCMFCIE1931JuddVos2DegTabY[31] =
    {
        2.800000e-003f,     // 400 nm
        7.400000e-003f,     // 410 nm
        1.750000e-002f,     // 420 nm
        2.730000e-002f,     // 430 nm
        3.790000e-002f,     // 440 nm
        4.680000e-002f,     // 450 nm
        6.000000e-002f,     // 460 nm
        9.098000e-002f,     // 470 nm
        1.390200e-001f,     // 480 nm
        2.080200e-001f,     // 490 nm
        3.230000e-001f,     // 500 nm
        5.030000e-001f,     // 510 nm
        7.100000e-001f,     // 520 nm
        8.620000e-001f,     // 530 nm
        9.540000e-001f,     // 540 nm
        9.949500e-001f,     // 550 nm
        9.950000e-001f,     // 560 nm
        9.520000e-001f,     // 570 nm
        8.700000e-001f,     // 580 nm
        7.570000e-001f,     // 590 nm
        6.310000e-001f,     // 600 nm
        5.030000e-001f,     // 610 nm
        3.810000e-001f,     // 620 nm
        2.650000e-001f,     // 630 nm
        1.750000e-001f,     // 640 nm
        1.070000e-001f,     // 650 nm
        6.100000e-002f,     // 660 nm
        3.200000e-002f,     // 670 nm
        1.700000e-002f,     // 680 nm
        8.210000e-003f,     // 690 nm
        4.102000e-003f      // 700 nm
    };
    const float XYZCMFCIE1931JuddVos2DegTabZ[31] =
    {
        1.740900e-001f,     // 400 nm
        4.605300e-001f,     // 410 nm
        1.065800e+000f,     // 420 nm
        1.467200e+000f,     // 430 nm
        1.616600e+000f,     // 440 nm
        1.471700e+000f,     // 450 nm
        1.291700e+000f,     // 460 nm
        1.113800e+000f,     // 470 nm
        7.559600e-001f,     // 480 nm
        4.466900e-001f,     // 490 nm
        2.643700e-001f,     // 500 nm
        1.544500e-001f,     // 510 nm
        7.658500e-002f,     // 520 nm
        4.136600e-002f,     // 530 nm
        2.004200e-002f,     // 540 nm
        8.782300e-003f,     // 550 nm
        4.049300e-003f,     // 560 nm
        2.277100e-003f,     // 570 nm
        1.806600e-003f,     // 580 nm
        1.234800e-003f,     // 590 nm
        9.056400e-004f,     // 600 nm
        4.288500e-004f,     // 610 nm
        2.559800e-004f,     // 620 nm
        9.769400e-005f,     // 630 nm
        5.116500e-005f,     // 640 nm
        2.423800e-005f,     // 650 nm
        1.190600e-005f,     // 660 nm
        5.600600e-006f,     // 670 nm
        2.791200e-006f,     // 680 nm
        1.313500e-006f,     // 690 nm
        6.476700e-007f      // 700 nm
    };

    // XYZ color matching functions -- CIE 1964 10-deg.
    const float XYZCMFCIE196410DegTabX[31] =
    {
        0.019109700000f,    // 400 nm
        0.084736000000f,    // 410 nm
        0.204492000000f,    // 420 nm
        0.314679000000f,    // 430 nm
        0.383734000000f,    // 440 nm
        0.370702000000f,    // 450 nm
        0.302273000000f,    // 460 nm
        0.195618000000f,    // 470 nm
        0.080507000000f,    // 480 nm
        0.016172000000f,    // 490 nm
        0.003816000000f,    // 500 nm
        0.037465000000f,    // 510 nm
        0.117749000000f,    // 520 nm
        0.236491000000f,    // 530 nm
        0.376772000000f,    // 540 nm
        0.529826000000f,    // 550 nm
        0.705224000000f,    // 560 nm
        0.878655000000f,    // 570 nm
        1.014160000000f,    // 580 nm
        1.118520000000f,    // 590 nm
        1.123990000000f,    // 600 nm
        1.030480000000f,    // 610 nm
        0.856297000000f,    // 620 nm
        0.647467000000f,    // 630 nm
        0.431567000000f,    // 640 nm
        0.268329000000f,    // 650 nm
        0.152568000000f,    // 660 nm
        0.081260600000f,    // 670 nm
        0.040850800000f,    // 680 nm
        0.019941300000f,    // 690 nm
        0.009576880000f     // 700 nm
    };
    const float XYZCMFCIE196410DegTabY[31] =
    {
        0.002004400000f,    // 400 nm
        0.008756000000f,    // 410 nm
        0.021391000000f,    // 420 nm
        0.038676000000f,    // 430 nm
        0.062077000000f,    // 440 nm
        0.089456000000f,    // 450 nm
        0.128201000000f,    // 460 nm
        0.185190000000f,    // 470 nm
        0.253589000000f,    // 480 nm
        0.339133000000f,    // 490 nm
        0.460777000000f,    // 500 nm
        0.606741000000f,    // 510 nm
        0.761757000000f,    // 520 nm
        0.875211000000f,    // 530 nm
        0.961988000000f,    // 540 nm
        0.991761000000f,    // 550 nm
        0.997340000000f,    // 560 nm
        0.955552000000f,    // 570 nm
        0.868934000000f,    // 580 nm
        0.777405000000f,    // 590 nm
        0.658341000000f,    // 600 nm
        0.527963000000f,    // 610 nm
        0.398057000000f,    // 620 nm
        0.283493000000f,    // 630 nm
        0.179828000000f,    // 640 nm
        0.107633000000f,    // 650 nm
        0.060281000000f,    // 660 nm
        0.031800400000f,    // 670 nm
        0.015905100000f,    // 680 nm
        0.007748800000f,    // 690 nm
        0.003717740000f     // 700 nm
    };
    const float XYZCMFCIE196410DegTabZ[31] =
    {
        0.086010900000f,    // 400 nm
        0.389366000000f,    // 410 nm
        0.972542000000f,    // 420 nm
        1.553480000000f,    // 430 nm
        1.967280000000f,    // 440 nm
        1.994800000000f,    // 450 nm
        1.745370000000f,    // 460 nm
        1.317560000000f,    // 470 nm
        0.772125000000f,    // 480 nm
        0.415254000000f,    // 490 nm
        0.218502000000f,    // 500 nm
        0.112044000000f,    // 510 nm
        0.060709000000f,    // 520 nm
        0.030451000000f,    // 530 nm
        0.013676000000f,    // 540 nm
        0.003988000000f,    // 550 nm
        0.000000000000f,    // 560 nm
        0.000000000000f,    // 570 nm
        0.000000000000f,    // 580 nm
        0.000000000000f,    // 590 nm
        0.000000000000f,    // 600 nm
        0.000000000000f,    // 610 nm
        0.000000000000f,    // 620 nm
        0.000000000000f,    // 630 nm
        0.000000000000f,    // 640 nm
        0.000000000000f,    // 650 nm
        0.000000000000f,    // 660 nm
        0.000000000000f,    // 670 nm
        0.000000000000f,    // 680 nm
        0.000000000000f,    // 690 nm
        0.000000000000f     // 700 nm
    };

    // RGB color matching functions -- Stiles and Burch (1955) 2-deg.
    const float RGBCMFStilesBurch19552DefTabX[31] =
    {
         9.62640e-003f,     // 400 nm
         3.08030e-002f,     // 410 nm
         5.16620e-002f,     // 420 nm
         4.42870e-002f,     // 430 nm
         1.47630e-002f,     // 440 nm
        -2.91300e-002f,     // 450 nm
        -9.62240e-002f,     // 460 nm
        -1.74860e-001f,     // 470 nm
        -2.37800e-001f,     // 480 nm
        -2.77270e-001f,     // 490 nm
        -2.95000e-001f,     // 500 nm
        -2.67590e-001f,     // 510 nm
        -1.47680e-001f,     // 520 nm
         1.06140e-001f,     // 530 nm
         4.19760e-001f,     // 540 nm
         7.90040e-001f,     // 550 nm
         1.22830e+000f,     // 560 nm
         1.74760e+000f,     // 570 nm
         2.27240e+000f,     // 580 nm
         2.67250e+000f,     // 590 nm
         2.87170e+000f,     // 600 nm
         2.76010e+000f,     // 610 nm
         2.37430e+000f,     // 620 nm
         1.81450e+000f,     // 630 nm
         1.25430e+000f,     // 640 nm
         7.86420e-001f,     // 650 nm
         4.43200e-001f,     // 660 nm
         2.34550e-001f,     // 670 nm
         1.20860e-001f,     // 680 nm
         6.02600e-002f,     // 690 nm
         2.81140e-002f      // 700 nm
    };
    const float RGBCMFStilesBurch19552DefTabY[31] =
    {
        -2.16890e-003f,     // 400 nm
        -7.20480e-003f,     // 410 nm
        -1.66510e-002f,     // 420 nm
        -1.99360e-002f,     // 430 nm
        -7.34570e-003f,     // 440 nm
         1.96100e-002f,     // 450 nm
         7.09540e-002f,     // 460 nm
         1.50880e-001f,     // 470 nm
         2.40420e-001f,     // 480 nm
         3.33530e-001f,     // 490 nm
         4.90600e-001f,     // 500 nm
         7.01840e-001f,     // 510 nm
         9.10760e-001f,     // 520 nm
         1.03390e+000f,     // 530 nm
         1.05120e+000f,     // 540 nm
         1.03680e+000f,     // 550 nm
         9.37830e-001f,     // 560 nm
         8.28350e-001f,     // 570 nm
         6.49300e-001f,     // 580 nm
         4.76750e-001f,     // 590 nm
         3.00690e-001f,     // 600 nm
         1.65750e-001f,     // 610 nm
         7.46820e-002f,     // 620 nm
         2.63330e-002f,     // 630 nm
         4.50330e-003f,     // 640 nm
        -1.96450e-003f,     // 650 nm
        -2.62620e-003f,     // 660 nm
        -1.87000e-003f,     // 670 nm
        -1.07550e-003f,     // 680 nm
        -5.67650e-004f,     // 690 nm
        -2.62310e-004f      // 700 nm
    };
    const float RGBCMFStilesBurch19552DefTabZ[31] =
    {
         6.23710e-002f,     // 400 nm
         2.27500e-001f,     // 410 nm
         5.23960e-001f,     // 420 nm
         7.96040e-001f,     // 430 nm
         9.63950e-001f,     // 440 nm
         9.18750e-001f,     // 450 nm
         7.85540e-001f,     // 460 nm
         6.10980e-001f,     // 470 nm
         3.61950e-001f,     // 480 nm
         1.95930e-001f,     // 490 nm
         1.07490e-001f,     // 500 nm
         5.02480e-002f,     // 510 nm
         1.33090e-002f,     // 520 nm
        -4.15740e-003f,     // 530 nm
        -1.21910e-002f,     // 540 nm
        -1.46810e-002f,     // 550 nm
        -1.46130e-002f,     // 560 nm
        -1.26500e-002f,     // 570 nm
        -9.93170e-003f,     // 580 nm
        -7.02100e-003f,     // 590 nm
        -4.27430e-003f,     // 600 nm
        -2.26930e-003f,     // 610 nm
        -1.50690e-003f,     // 620 nm
        -5.53160e-004f,     // 630 nm
        -1.43190e-004f,     // 640 nm
         1.10810e-004f,     // 650 nm
         2.26560e-004f,     // 660 nm
         1.63610e-004f,     // 670 nm
         5.10330e-005f,     // 680 nm
         3.12110e-005f,     // 690 nm
         1.65210e-005f      // 700 nm
    };

    // RGB color matching functions -- Stiles and Burch (1959) 10-deg.
    const float RGBCMFStilesBurch195910DefTabX[31] =
    {
         8.9000E-03f,       // 400 nm
         3.5000E-02f,       // 410 nm
         7.0200E-02f,       // 420 nm
         7.4500E-02f,       // 430 nm
         3.2300E-02f,       // 440 nm
        -4.7800E-02f,       // 450 nm
        -1.5860E-01f,       // 460 nm
        -2.8480E-01f,       // 470 nm
        -3.7760E-01f,       // 480 nm
        -4.3170E-01f,       // 490 nm
        -4.3500E-01f,       // 500 nm
        -3.6730E-01f,       // 510 nm
        -1.8550E-01f,       // 520 nm
         1.2700E-01f,       // 530 nm
         5.3620E-01f,       // 540 nm
         1.0059E+00f,       // 550 nm
         1.5574E+00f,       // 560 nm
         2.1511E+00f,       // 570 nm
         2.6574E+00f,       // 580 nm
         3.0779E+00f,       // 590 nm
         3.1673E+00f,       // 600 nm
         2.9462E+00f,       // 610 nm
         2.4526E+00f,       // 620 nm
         1.8358E+00f,       // 630 nm
         1.2428E+00f,       // 640 nm
         7.8270E-01f,       // 650 nm
         4.4420E-01f,       // 660 nm
         2.3940E-01f,       // 670 nm
         1.2210E-01f,       // 680 nm
         5.8600E-02f,       // 690 nm
         2.8400E-02f        // 700 nm
    };
    const float RGBCMFStilesBurch195910DefTabY[31] =
    {
        -2.5000E-03f,       // 400 nm
        -1.1900E-02f,       // 410 nm
        -2.8900E-02f,       // 420 nm
        -3.4900E-02f,       // 430 nm
        -1.6900E-02f,       // 440 nm
         2.8300E-02f,       // 450 nm
         1.0820E-01f,       // 460 nm
         2.2010E-01f,       // 470 nm
         3.4280E-01f,       // 480 nm
         4.7160E-01f,       // 490 nm
         6.2600E-01f,       // 500 nm
         7.9350E-01f,       // 510 nm
         9.4770E-01f,       // 520 nm
         1.0203E+00f,       // 530 nm
         1.0517E+00f,       // 540 nm
         1.0029E+00f,       // 550 nm
         9.1620E-01f,       // 560 nm
         7.8230E-01f,       // 570 nm
         5.9660E-01f,       // 580 nm
         4.2030E-01f,       // 590 nm
         2.5910E-01f,       // 600 nm
         1.3670E-01f,       // 610 nm
         6.1100E-02f,       // 620 nm
         2.1500E-02f,       // 630 nm
         4.4000E-03f,       // 640 nm
        -1.3680E-03f,       // 650 nm
        -2.1680E-03f,       // 660 nm
        -1.6420E-03f,       // 670 nm
        -9.4700E-04f,       // 680 nm
        -4.7800E-04f,       // 690 nm
        -2.3500E-04f        // 700 nm
    };
    const float RGBCMFStilesBurch195910DefTabZ[31] =
    {
         4.0000E-02f,       // 400 nm
         1.8020E-01f,       // 410 nm
         4.6700E-01f,       // 420 nm
         7.6380E-01f,       // 430 nm
         9.7550E-01f,       // 440 nm
         9.9960E-01f,       // 450 nm
         8.2970E-01f,       // 460 nm
         6.1340E-01f,       // 470 nm
         3.4950E-01f,       // 480 nm
         1.8190E-01f,       // 490 nm
         9.1000E-02f,       // 500 nm
         3.5700E-02f,       // 510 nm
         9.5000E-03f,       // 520 nm
        -4.3000E-03f,       // 530 nm
        -8.2000E-03f,       // 540 nm
        -9.7000E-03f,       // 550 nm
        -9.3000E-03f,       // 560 nm
        -8.0000E-03f,       // 570 nm
        -6.3000E-03f,       // 580 nm
        -4.4500E-03f,       // 590 nm
        -2.7700E-03f,       // 600 nm
        -1.5000E-03f,       // 610 nm
        -6.8000E-04f,       // 620 nm
        -2.7200E-04f,       // 630 nm
        -5.4900E-05f,       // 640 nm
         2.3700E-05f,       // 650 nm
         2.6100E-05f,       // 660 nm
         1.8200E-05f,       // 670 nm
         1.0300E-05f,       // 680 nm
         5.2200E-06f,       // 690 nm
         2.5600E-06f        // 700 nm
    };
}

// XYZ color matching functions.
const Spectrum31f XYZCMFCIE19312Deg[3] =
{
    Spectrum31f(XYZCMFCIE19312DegTabX),
    Spectrum31f(XYZCMFCIE19312DegTabY),
    Spectrum31f(XYZCMFCIE19312DegTabZ)
};
const Spectrum31f XYZCMFCIE1931Judd2Deg[3] =
{
    Spectrum31f(XYZCMFCIE1931Judd2DegTabX),
    Spectrum31f(XYZCMFCIE1931Judd2DegTabY),
    Spectrum31f(XYZCMFCIE1931Judd2DegTabZ)
};
const Spectrum31f XYZCMFCIE1931JuddVos2Deg[3] =
{
    Spectrum31f(XYZCMFCIE1931JuddVos2DegTabX),
    Spectrum31f(XYZCMFCIE1931JuddVos2DegTabY),
    Spectrum31f(XYZCMFCIE1931JuddVos2DegTabZ)
};
const Spectrum31f XYZCMFCIE196410Deg[3] =
{
    Spectrum31f(XYZCMFCIE196410DegTabX),
    Spectrum31f(XYZCMFCIE196410DegTabY),
    Spectrum31f(XYZCMFCIE196410DegTabZ)
};

// RGB color matching functions.
const Spectrum31f RGBCMFStilesBurch19552Def[3] =
{
    Spectrum31f(RGBCMFStilesBurch19552DefTabX),
    Spectrum31f(RGBCMFStilesBurch19552DefTabY),
    Spectrum31f(RGBCMFStilesBurch19552DefTabZ)
};
const Spectrum31f RGBCMFStilesBurch195910Def[3] =
{
    Spectrum31f(RGBCMFStilesBurch195910DefTabX),
    Spectrum31f(RGBCMFStilesBurch195910DefTabY),
    Spectrum31f(RGBCMFStilesBurch195910DefTabZ)
};


//
// Lighting conditions class implementation.
//

LightingConditions::LightingConditions(
    const Spectrum31f&  illuminant,
    const Spectrum31f   cmf[3])
{
    // Precompute convolution of color matching functions and illuminant.
    for (size_t w = 0; w < 31; ++w)
    {
        m_cmf[w][0] = cmf[0][w] * illuminant[w];
        m_cmf[w][1] = cmf[1][w] * illuminant[w];
        m_cmf[w][2] = cmf[2][w] * illuminant[w];
    }

    // Compute 1/N.
    float n = 0.0f;
    for (size_t w = 0; w < 31; ++w)
        n += m_cmf[w][1];
    float rcp_n = 1.0f / n;

    // Multiply the color matching functions by 1/N.
    for (size_t w = 0; w < 31; ++w)
        m_cmf[w] *= rcp_n;
}

}   // namespace foundation