00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef LUX_RGBColor_H
00024 #define LUX_RGBColor_H
00025
00026 #include "lux.h"
00027 #include "color.h"
00028
00029 namespace lux
00030 {
00031
00032 #define WAVELENGTH_SAMPLES 4
00033 #define WAVELENGTH_START 380.f
00034 #define WAVELENGTH_END 720.f
00035 static const float inv_WAVELENGTH_SAMPLES = 1.f / WAVELENGTH_SAMPLES;
00036
00037 #define Scalar float
00038
00039 class SWCSpectrum {
00040 friend class boost::serialization::access;
00041 public:
00042
00043 SWCSpectrum(Scalar v = 0.f) {
00044 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00045 c[i] = v;
00046 }
00047 SWCSpectrum(const TsPack *tspack, const RGBColor &s);
00048
00049 SWCSpectrum(const TsPack *tspack, const SPD *s);
00050
00051 SWCSpectrum(const float cs[WAVELENGTH_SAMPLES]) {
00052 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00053 c[i] = cs[i];
00054 }
00055 friend ostream &operator<<(ostream &, const SWCSpectrum &);
00056 SWCSpectrum operator+(const SWCSpectrum &s2) const {
00057 SWCSpectrum ret = *this;
00058 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00059 ret.c[i] += s2.c[i];
00060 return ret;
00061 }
00062 SWCSpectrum &operator+=(const SWCSpectrum &s2) {
00063 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00064 c[i] += s2.c[i];
00065 return *this;
00066 }
00067 SWCSpectrum operator-(const SWCSpectrum &s2) const {
00068 SWCSpectrum ret = *this;
00069 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00070 ret.c[i] -= s2.c[i];
00071 return ret;
00072 }
00073 SWCSpectrum &operator-=(const SWCSpectrum &s2) {
00074 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00075 c[i] -= s2.c[i];
00076 return *this;
00077 }
00078 SWCSpectrum operator/(const SWCSpectrum &s2) const {
00079 SWCSpectrum ret = *this;
00080 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00081 ret.c[i] /= s2.c[i];
00082 return ret;
00083 }
00084 SWCSpectrum &operator/=(const SWCSpectrum &sp) {
00085 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00086 c[i] /= sp.c[i];
00087 return *this;
00088 }
00089 SWCSpectrum operator*(const SWCSpectrum &sp) const {
00090 SWCSpectrum ret = *this;
00091 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00092 ret.c[i] *= sp.c[i];
00093 return ret;
00094 }
00095 SWCSpectrum &operator*=(const SWCSpectrum &sp) {
00096 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00097 c[i] *= sp.c[i];
00098 return *this;
00099 }
00100 SWCSpectrum operator*(Scalar a) const {
00101 SWCSpectrum ret = *this;
00102 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00103 ret.c[i] *= a;
00104 return ret;
00105 }
00106 SWCSpectrum &operator*=(Scalar a) {
00107 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00108 c[i] *= a;
00109 return *this;
00110 }
00111 friend inline
00112 SWCSpectrum operator*(Scalar a, const SWCSpectrum &s) {
00113 return s * a;
00114 }
00115 SWCSpectrum operator/(Scalar a) const {
00116 return *this * (1.f / a);
00117 }
00118 SWCSpectrum &operator/=(Scalar a) {
00119 return *this *= (1.f / a);
00120 }
00121 void AddWeighted(Scalar w, const SWCSpectrum &s) {
00122 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00123 c[i] += w * s.c[i];
00124 }
00125 bool operator==(const SWCSpectrum &sp) const {
00126 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00127 if (c[i] != sp.c[i]) return false;
00128 return true;
00129 }
00130 bool operator!=(const SWCSpectrum &sp) const {
00131 return !(*this == sp);
00132 }
00133 bool Black() const {
00134 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00135 if (c[i] != 0.f) return false;
00136 return true;
00137 }
00138 SWCSpectrum Sqrt() const {
00139 SWCSpectrum ret;
00140 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00141 ret.c[i] = sqrtf(c[i]);
00142 return ret;
00143 }
00144 SWCSpectrum Pow(const SWCSpectrum &e) const {
00145 SWCSpectrum ret;
00146 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00147 ret.c[i] = c[i] > 0.f ? powf(c[i], e.c[i]) : 0.f;
00148 return ret;
00149 }
00150 SWCSpectrum operator-() const {
00151 SWCSpectrum ret;
00152 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00153 ret.c[i] = -c[i];
00154 return ret;
00155 }
00156 friend SWCSpectrum Exp(const SWCSpectrum &s) {
00157 SWCSpectrum ret;
00158 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00159 ret.c[i] = expf(s.c[i]);
00160 return ret;
00161 }
00162 SWCSpectrum Clamp(Scalar low = 0.f,
00163 Scalar high = INFINITY) const {
00164 SWCSpectrum ret;
00165 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00166 ret.c[i] = ::Clamp(c[i], low, high);
00167 return ret;
00168 }
00169 bool IsNaN() const {
00170 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00171 if (isnan(c[i])) return true;
00172 return false;
00173 }
00174 void Print(FILE *f) const {
00175 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00176 fprintf(f, "%f ", c[i]);
00177 }
00178 XYZColor ToXYZ(const TsPack *tspack) const;
00179 Scalar Y(const TsPack *tspack) const;
00180 Scalar Filter(const TsPack *tspack) const;
00181
00182
00183
00184
00185
00186 friend class lux::ParamSet;
00187
00188
00189 Scalar c[WAVELENGTH_SAMPLES];
00190
00191 private:
00192 template<class Archive>
00193 void serialize(Archive & ar, const unsigned int version)
00194 {
00195 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00196 ar & c[i];
00197 }
00198 };
00199
00200 }
00201
00202 #endif // LUX_RGBColor_H