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_COLOR_H
00024 #define LUX_COLOR_H
00025
00026 #include "lux.h"
00027
00028
00029 namespace lux
00030 {
00031
00032
00033 class Color {
00034
00035 friend class boost::serialization::access;
00036
00037 public:
00038
00039 Color() {};
00040
00041 friend ostream &operator<<(ostream &, const Color &);
00042 Color &operator+=(const Color &s2) {
00043 c[0] += s2.c[0]; c[1] += s2.c[1]; c[2] += s2.c[2];
00044 return *this;
00045 }
00046 Color operator+(const Color &s2) const {
00047 Color ret = *this;
00048 ret.c[0] += s2.c[0]; ret.c[1] += s2.c[1]; ret.c[2] += s2.c[2];
00049 return ret;
00050 }
00051 Color operator-(const Color &s2) const {
00052 Color ret = *this;
00053 ret.c[0] -= s2.c[0]; ret.c[1] -= s2.c[1]; ret.c[2] -= s2.c[2];
00054 return ret;
00055 }
00056 Color operator/(const Color &s2) const {
00057 Color ret = *this;
00058 ret.c[0] /= s2.c[0]; ret.c[1] /= s2.c[1]; ret.c[2] /= s2.c[2];
00059 return ret;
00060 }
00061 Color operator*(const Color &sp) const {
00062 Color ret = *this;
00063 ret.c[0] *= sp.c[0]; ret.c[1] *= sp.c[1]; ret.c[2] *= sp.c[2];
00064 return ret;
00065 }
00066 Color &operator*=(const Color &sp) {
00067 c[0] *= sp.c[0]; c[1] *= sp.c[1]; c[2] *= sp.c[2];
00068 return *this;
00069 }
00070 Color operator*(float a) const {
00071 Color ret = *this;
00072 ret.c[0] *= a; ret.c[1] *= a; ret.c[2] *= a;
00073 return ret;
00074 }
00075 Color &operator*=(float a) {
00076 c[0] *= a; c[1] *= a; c[2] *= a;
00077 return *this;
00078 }
00079 friend inline
00080 Color operator*(float a, const Color &s) {
00081 return s * a;
00082 }
00083 Color operator/(float a) const {
00084 return *this * (1.f / a);
00085 }
00086 Color &operator/=(float a) {
00087 float inv = 1.f / a;
00088 c[0] *= inv; c[1] *= inv; c[2] *= inv;
00089 return *this;
00090 }
00091 void AddWeighted(float w, const Color &s) {
00092 c[0] += w * s.c[0]; c[1] += w * s.c[1]; c[2] += w * s.c[2];
00093 }
00094 bool operator==(const Color &sp) const {
00095 if (c[0] != sp.c[0]) return false;
00096 if (c[1] != sp.c[1]) return false;
00097 if (c[2] != sp.c[2]) return false;
00098 return true;
00099 }
00100 bool operator!=(const Color &sp) const {
00101 return !(*this == sp);
00102 }
00103 bool Black() const {
00104 if (c[0] != 0.) return false;
00105 if (c[1] != 0.) return false;
00106 if (c[2] != 0.) return false;
00107 return true;
00108 }
00109 Color Sqrt() const {
00110 Color ret;
00111 ret.c[0] = sqrtf(c[0]);
00112 ret.c[1] = sqrtf(c[1]);
00113 ret.c[2] = sqrtf(c[2]);
00114 return ret;
00115 }
00116 Color Pow(const Color &e) const {
00117 Color ret;
00118 ret.c[0] = c[0] > 0 ? powf(c[0], e.c[0]) : 0.f;
00119 ret.c[1] = c[1] > 0 ? powf(c[1], e.c[1]) : 0.f;
00120 ret.c[2] = c[2] > 0 ? powf(c[2], e.c[2]) : 0.f;
00121 return ret;
00122 }
00123 Color operator-() const {
00124 Color ret;
00125 ret.c[0] = -c[0];
00126 ret.c[1] = -c[1];
00127 ret.c[2] = -c[2];
00128 return ret;
00129 }
00130 friend Color Exp(const Color &s) {
00131 Color ret;
00132 ret.c[0] = expf(s.c[0]);
00133 ret.c[1] = expf(s.c[1]);
00134 ret.c[2] = expf(s.c[2]);
00135 return ret;
00136 }
00137 Color Clamp(float low = 0.f,
00138 float high = INFINITY) const {
00139 Color ret;
00140 ret.c[0] = ::Clamp(c[0], low, high);
00141 ret.c[1] = ::Clamp(c[1], low, high);
00142 ret.c[2] = ::Clamp(c[2], low, high);
00143 return ret;
00144 }
00145 bool IsNaN() const {
00146 if (isnan(c[0])) return true;
00147 if (isnan(c[1])) return true;
00148 if (isnan(c[2])) return true;
00149 return false;
00150 }
00151 void Print(FILE *f) const {
00152 for (int i = 0; i < 3; ++i)
00153 fprintf(f, "%f ", c[i]);
00154 }
00155
00156 float y() const {
00157 return 0.;
00158 }
00159
00160 bool operator<(const Color &s2) const {
00161 return y() < s2.y();
00162 }
00163 friend class lux::ParamSet;
00164
00165
00166 float c[3];
00167
00168 private:
00169 template<class Archive>
00170 void serialize(Archive & ar, const unsigned int version)
00171 {
00172 for (int i = 0; i < 3; ++i)
00173 ar & c[i];
00174 }
00175 };
00176
00177
00178 class RGBColor : public Color {
00179 public:
00180
00181 RGBColor(float v = 0.f) {
00182 c[0] = v; c[1] = v; c[2] = v;
00183 }
00184 RGBColor(float cs[3]) {
00185 c[0] = cs[0]; c[1] = cs[1]; c[2] = cs[2];
00186 }
00187 RGBColor(XYZColor xyz);
00188 RGBColor(const Color &color) {
00189 c[0] = color.c[0]; c[1] = color.c[1]; c[2] = color.c[2];
00190 }
00191
00192
00193 void ToXYZ(float &x, float &y, float &z) const {
00194 x = 0.412453f * c[0] + 0.357580f * c[1] + 0.180423f * c[2];
00195 y = 0.212671f * c[0] + 0.715160f * c[1] + 0.072169f * c[2];
00196 z = 0.019334f * c[0] + 0.119193f * c[1] + 0.950227f * c[2];
00197 }
00198 void ToXYZ(float xyz[3]) const {
00199 ToXYZ(xyz[0], xyz[1], xyz[2]);
00200 }
00201 void ToXYZ(XYZColor xyz) const;
00202 XYZColor ToXYZ() const;
00203
00204
00205 void FromXYZ(float x, float y, float z) {
00206 c[0] = 3.240479f * x + -1.537150f * y + -0.498535f * z;
00207 c[1] = -0.969256f * x + 1.875991f * y + 0.041556f * z;
00208 c[2] = 0.055648f * x + -0.204043f * y + 1.057311f * z;
00209 }
00210 void FromXYZ(float xyz[3]) {
00211 FromXYZ(xyz[0], xyz[1], xyz[2]);
00212 }
00213 void FromXYZ(XYZColor xyz);
00214
00215 float y() const {
00216 return 0.212671f * c[0] + 0.715160f * c[1] + 0.072169f * c[2];
00217 }
00218 };
00219
00220
00221 class XYZColor : public Color {
00222
00223 friend class boost::serialization::access;
00224
00225 public:
00226
00227 XYZColor(float v = 0.f) {
00228 c[0] = v; c[1] = v; c[2] = v;
00229 }
00230 XYZColor(float cs[3]) {
00231 c[0] = cs[0]; c[1] = cs[1]; c[2] = cs[2];
00232 }
00233 XYZColor(RGBColor rgb);
00234
00235
00236 void ToRGB(float &r, float &g, float &b) const {
00237 r = 3.240479f * c[0] + -1.537150f * c[1] + -0.498535f * c[2];
00238 g = -0.969256f * c[0] + 1.875991f * c[1] + 0.041556f * c[2];
00239 b = 0.055648f * c[0] + -0.204043f * c[1] + 1.057311f * c[2];
00240 }
00241 void ToRGB(float rgb[3]) const {
00242 ToRGB(rgb[0], rgb[1], rgb[2]);
00243 }
00244 void ToRGB(RGBColor rgb) const;
00245 RGBColor ToRGB() const;
00246
00247
00248 void FromRGB(float r, float g, float b) {
00249 c[0] = 0.412453f * r + 0.357580f * g + 0.180423f * b;
00250 c[1] = 0.212671f * r + 0.715160f * g + 0.072169f * b;
00251 c[2] = 0.019334f * r + 0.119193f * g + 0.950227f * b;
00252 }
00253 void FromRGB(float rgb[3]) {
00254 FromRGB(rgb[0], rgb[1], rgb[2]);
00255 }
00256 void FromRGB(RGBColor rgb);
00257
00258 float y() const {
00259 return c[1];
00260 }
00261 };
00262
00270 class ColorSystem
00271 {
00272 public:
00273 ColorSystem(float xR, float yR, float xG, float yG, float xB, float yB,
00274 float xW, float yW, float lum = 1.);
00287 RGBColor Convert(XYZColor &color) const {
00288 float c[3];
00289 c[0] = conversion[0][0] * color.c[0] + conversion[0][1] * color.c[1] + conversion[0][2] * color.c[2];
00290 c[1] = conversion[1][0] * color.c[0] + conversion[1][1] * color.c[1] + conversion[1][2] * color.c[2];
00291 c[2] = conversion[2][0] * color.c[0] + conversion[2][1] * color.c[1] + conversion[2][2] * color.c[2];
00292 return RGBColor(c);
00293 }
00294 bool Constrain(const XYZColor &xyz, RGBColor &rgb) const;
00295 protected:
00296 float xRed, yRed;
00297 float xGreen, yGreen;
00298 float xBlue, yBlue;
00299 float xWhite, yWhite;
00300 float luminance;
00301 float conversion[3][3];
00302 };
00303
00304
00305 inline ostream &operator<<(ostream &os, const RGBColor &s) {
00306 for (int i = 0; i < 3; ++i) {
00307 os << s.c[i];
00308 if (i != 3-1)
00309 os << ", ";
00310 }
00311 return os;
00312 }
00313
00314 inline RGBColor::RGBColor(XYZColor xyz) {
00315 ToXYZ(xyz.c[0], xyz.c[1], xyz.c[2]);
00316 }
00317
00318 inline void RGBColor::ToXYZ(XYZColor xyz) const {
00319 ToXYZ(xyz.c[0], xyz.c[1], xyz.c[2]);
00320 }
00321 inline XYZColor RGBColor::ToXYZ() const {
00322 XYZColor xyz;
00323 ToXYZ(xyz.c[0], xyz.c[1], xyz.c[2]);
00324 return xyz;
00325 }
00326
00327 inline void RGBColor::FromXYZ(XYZColor xyz) {
00328 FromXYZ(xyz.c[0], xyz.c[1], xyz.c[2]);
00329 }
00330
00331
00332
00333 inline ostream &operator<<(ostream &os, const XYZColor &s) {
00334 for (int i = 0; i < 3; ++i) {
00335 os << s.c[i];
00336 if (i != 3-1)
00337 os << ", ";
00338 }
00339 return os;
00340 }
00341
00342 inline XYZColor::XYZColor(RGBColor rgb) {
00343 ToRGB(rgb.c[0], rgb.c[1], rgb.c[2]);
00344 }
00345
00346 inline void XYZColor::ToRGB(RGBColor rgb) const {
00347 ToRGB(rgb.c[0], rgb.c[1], rgb.c[2]);
00348 }
00349 inline RGBColor XYZColor::ToRGB() const {
00350 RGBColor rgb;
00351 ToRGB(rgb.c[0], rgb.c[1], rgb.c[2]);
00352 return rgb;
00353 }
00354
00355 inline void XYZColor::FromRGB(RGBColor rgb) {
00356 FromRGB(rgb.c[0], rgb.c[1], rgb.c[2]);
00357 }
00358
00359 }
00360
00361
00362
00363
00364 #endif // LUX_COLOR_H