00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "spectrum.h"
00025 #include "spectrumwavelengths.h"
00026 #include "regular.h"
00027 #include "memory.h"
00028
00029 #include <boost/thread/tss.hpp>
00030
00031 using namespace lux;
00032
00033
00034 ostream &operator<<(ostream &os, const Spectrum &s) {
00035 for (int i = 0; i < COLOR_SAMPLES; ++i) {
00036 os << s.c[i];
00037 if (i != COLOR_SAMPLES-1)
00038 os << ", ";
00039 }
00040 return os;
00041 }
00042 float Spectrum::XWeight[COLOR_SAMPLES] = {
00043 0.412453f, 0.357580f, 0.180423f
00044 };
00045 float Spectrum::YWeight[COLOR_SAMPLES] = {
00046 0.212671f, 0.715160f, 0.072169f
00047 };
00048 float Spectrum::ZWeight[COLOR_SAMPLES] = {
00049 0.019334f, 0.119193f, 0.950227f
00050 };
00051
00052 Spectrum lux::FromXYZ(float x, float y, float z) {
00053 float c[3];
00054 c[0] = 3.240479f * x + -1.537150f * y + -0.498535f * z;
00055 c[1] = -0.969256f * x + 1.875991f * y + 0.041556f * z;
00056 c[2] = 0.055648f * x + -0.204043f * y + 1.057311f * z;
00057 return Spectrum(c);
00058 }
00059
00060
00061 boost::thread_specific_ptr<SpectrumWavelengths> thread_wavelengths;
00062
00063 XYZColor SWCSpectrum::ToXYZ() const {
00064 SpectrumWavelengths *sw = thread_wavelengths.get();
00065 float xyz[3];
00066 xyz[0] = xyz[1] = xyz[2] = 0.;
00067 if (sw->single) {
00068 const int j = sw->single_w;
00069 xyz[0] = sw->cie_X[j] * c[j];
00070 xyz[1] = sw->cie_Y[j] * c[j];
00071 xyz[2] = sw->cie_Z[j] * c[j];
00072 } else {
00073 for (unsigned int j = 0; j < WAVELENGTH_SAMPLES; ++j) {
00074 xyz[0] += sw->cie_X[j] * c[j];
00075 xyz[1] += sw->cie_Y[j] * c[j];
00076 xyz[2] += sw->cie_Z[j] * c[j];
00077 }
00078 xyz[0] *= inv_WAVELENGTH_SAMPLES;
00079 xyz[1] *= inv_WAVELENGTH_SAMPLES;
00080 xyz[2] *= inv_WAVELENGTH_SAMPLES;
00081 }
00082
00083 return XYZColor(xyz);
00084 }
00085
00086 Scalar SWCSpectrum::y() const {
00087 SpectrumWavelengths *sw = thread_wavelengths.get();
00088 Scalar y = 0.f;
00089
00090 if (sw->single) {
00091 const int j = sw->single_w;
00092 y = sw->cie_Y[j] * c[j];
00093 } else {
00094 for (unsigned int j = 0; j < WAVELENGTH_SAMPLES; ++j) {
00095 y += sw->cie_Y[j] * c[j];
00096 }
00097 y *= inv_WAVELENGTH_SAMPLES;
00098 }
00099
00100 return y;
00101 }
00102 Scalar SWCSpectrum::filter() const
00103 {
00104 SpectrumWavelengths *sw = thread_wavelengths.get();
00105 Scalar result = 0.f;
00106 if (sw->single) {
00107 result = c[sw->single_w];
00108 } else {
00109 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00110 result += c[i];
00111 result *= inv_WAVELENGTH_SAMPLES;
00112 }
00113 return result;
00114 }
00115
00116 SWCSpectrum::SWCSpectrum(const SPD *s) {
00117 SpectrumWavelengths *sw = thread_wavelengths.get();
00118 for (unsigned int j = 0; j < WAVELENGTH_SAMPLES; ++j) {
00119 c[j] = s->sample(sw->w[j]);
00120 }
00121 }
00122
00123 SWCSpectrum::SWCSpectrum(Spectrum s) {
00124 SpectrumWavelengths *sw = thread_wavelengths.get();
00125 const float r = s.c[0];
00126 const float g = s.c[1];
00127 const float b = s.c[2];
00128
00129 for (unsigned int j = 0; j < WAVELENGTH_SAMPLES; ++j)
00130 c[j] = 0.;
00131
00132 if (r <= g && r <= b)
00133 {
00134 AddWeighted(r, sw->spect_w);
00135
00136 if (g <= b)
00137 {
00138 AddWeighted(g - r, sw->spect_c);
00139 AddWeighted(b - g, sw->spect_b);
00140 }
00141 else
00142 {
00143 AddWeighted(b - r, sw->spect_c);
00144 AddWeighted(g - b, sw->spect_g);
00145 }
00146 }
00147 else if (g <= r && g <= b)
00148 {
00149 AddWeighted(g, sw->spect_w);
00150
00151 if (r <= b)
00152 {
00153 AddWeighted(r - g, sw->spect_m);
00154 AddWeighted(b - r, sw->spect_b);
00155 }
00156 else
00157 {
00158 AddWeighted(b - g, sw->spect_m);
00159 AddWeighted(r - b, sw->spect_r);
00160 }
00161 }
00162 else
00163 {
00164 AddWeighted(b, sw->spect_w);
00165
00166 if (r <= g)
00167 {
00168 AddWeighted(r - b, sw->spect_y);
00169 AddWeighted(g - r, sw->spect_g);
00170 }
00171 else
00172 {
00173 AddWeighted(g - b, sw->spect_y);
00174 AddWeighted(r - g, sw->spect_r);
00175 }
00176 }
00177 }