sources:


website:
more info here


screenshot:
studies/grafik2/Computergrafik-Code3/Aufgabe8/color.cpp
download file

  1 //
  2 // Computergraphik II
  3 // Prof. Dr. Juergen Doellner
  4 // Wintersemester 2001/2002
  5 //
  6 // Rahmenprogramm fuer Aufgabenzettel 3
  7 //
  8 // Autoren: Florian Kirsch (kirsch@hpi.uni-potsdam.de)
  9 // Marc Nienhaus (nienhaus@hpi.uni-potsdam.de)
 10 // Juergen Doellner (doellner@hpi.uni-potsdam.de)
 11 //
 12
 13 #include "color.h"
 14 #include <assert.h>
 15 #include <iostream.h>
 16
 17 template<class T>
 18 static inline const T& Min(const T& a, const T& b) {
 19     return((a < b) ? a : b);
 20 }
 21
 22 template<class T>
 23 static inline const T& Max(const T& a, const T& b) {
 24     return((a > b) ? a : b);
 25 }
 26
 27 inline double clamp(double v) {
 28     return v>1 ? 1.0 : (v<0 ? 0 : v);
 29 }
 30
 31 Color::Color(double grey) {
 32     rgba_[0] = rgba_[1] = rgba_[2] = grey;
 33     rgba_[3] = 1.0;
 34 }
 35
 36 Color::Color(double r, double g, double b, double a) {
 37     rgba_[0] = r;
 38     rgba_[1] = g;
 39     rgba_[2] = b;
 40     rgba_[3] = a;
 41 }
 42
 43 double Color::operator[](int i) const {
 44     assert(i>=0 && i<=3);
 45     return rgba_[i];
 46 }
 47
 48 double& Color::operator[](int i) {
 49     assert(i>=0 && i<=3);
 50     return rgba_[i];
 51 }
 52
 53 bool Color::operator==(const Color& mc) const {
 54     return rgba_[0]==mc.rgba_[0] &&
 55            rgba_[1]==mc.rgba_[1] &&
 56            rgba_[2]==mc.rgba_[2] &&
 57            rgba_[3]==mc.rgba_[3];
 58 }
 59
 60 bool Color::operator!=(const Color& mc) const {
 61     return rgba_[0]!=mc.rgba_[0] ||
 62            rgba_[1]!=mc.rgba_[1] ||
 63            rgba_[2]!=mc.rgba_[2] ||
 64            rgba_[3]!=mc.rgba_[3];
 65 }
 66
 67 Color Color::operator+(const Color& mc) const {
 68     double r = clamp(rgba_[0]+mc.rgba_[0]);
 69     double g = clamp(rgba_[1]+mc.rgba_[1]);
 70     double b = clamp(rgba_[2]+mc.rgba_[2]);
 71     double a = rgba_[3];
 72     return Color(r,g,b,a);
 73 }
 74
 75 Color Color::operator-(const Color& mc) const {
 76     double r = clamp(rgba_[0]-mc.rgba_[0]);
 77     double g = clamp(rgba_[1]-mc.rgba_[1]);
 78     double b = clamp(rgba_[2]-mc.rgba_[2]);
 79     double a = rgba_[3];
 80     return Color(r,g,b,a);
 81 }
 82
 83 Color Color::operator*(double d) const {
 84     double r = clamp(rgba_[0]*d);
 85     double g = clamp(rgba_[1]*d);
 86     double b = clamp(rgba_[2]*d);
 87     double a = rgba_[3];
 88     return Color(r,g,b,a);
 89 }
 90
 91 //
 92 // RGB - HSV
 93 //
 94
 95 Color Color::hsv(double h, double s, double v, double alpha) {
 96     // normalize hue angle
 97     while (h<   0.0) h += 360.0;
 98     while (h>=360.0) h -= 360.0;
 99
100     assert(h>=-360.0 && h<=360.0);
101     assert(v>=0.0 && v<=1.0);
102     assert(s>=0.0 && s<=1.0);
103
104     double R, G, B;
105     if (s==0.0) {
106         // color on black-white center line
107         // achromatic color!
108         R = v;
109         G = v;
110         B = v;
111     }  else {
112         // chromatic color
113         if (h==360.0) h = 0.0;
114         if (h<0.0) h+=360.0;
115         h = h/60.0;
116         int i = (int)h;
117         double f = h - i;
118         double p = v*(1.0-s);
119         double q = v*(1.0-(s*f));
120         double t = v*(1.0-(s*(1.0-f)));
121         switch(i) {
122         case 0: R = v; G = t; B = p; break;
123         case 1: R = q; G = v; B = p; break;
124         case 2: R = p; G = v; B = t; break;
125         case 3: R = p; G = q; B = v; break;
126         case 4: R = t; G = p; B = v; break;
127         case 5: R = v; G = p; B = q; break;
128         default: ;
129         }
130     }
131     return Color(R,G,B,alpha);
132 }
133
134 double Color::value() const {
135     return Max(rgba_[0], Max(rgba_[1], rgba_[2]));
136 }
137
138 double Color::saturation() const {
139     double v = Max(rgba_[0], Max(rgba_[1], rgba_[2]));
140     if(v!=0.0) {
141         double m = Min(rgba_[0], Min(rgba_[1], rgba_[2]));
142         return (v-m)/v;
143     } else {
144         return 0.0;
145     }
146 }
147
148 double Color::hue() const {
149     double s = saturation();
150     if(s==0.0) return 0.0; // hue is undefined
151
152     double mmax = Max(rgba_[0], Max(rgba_[1], rgba_[2]));
153     double mmin = Min(rgba_[0], Min(rgba_[1], rgba_[2]));
154     double delta = mmax - mmin;
155
156     double h;
157     if(rgba_[0]==mmax)
158         h = 0.0 + (rgba_[1]-rgba_[2])/delta;
159     else if(rgba_[1]==mmax)
160         h = 2.0 + (rgba_[2]-rgba_[0])/delta;
161     else         h = 4.0 + (rgba_[0]-rgba_[1])/delta;
162
163     h = h * 60.0;
164     if(h<0.0) h += 360.0;
165
166     return h;
167 }
168
169
170 // interpolate two colors in RGBA space
171 Color Color::InterpolateRGB(const Color& from, const Color& to, double dPercentage)
172 {
173     return Color(from[0]*(1-dPercentage) + to[0]*dPercentage,    // red
174                  from[1]*(1-dPercentage) + to[1]*dPercentage,    // green
175                  from[2]*(1-dPercentage) + to[2]*dPercentage,    // blue
176                  from[3]*(1-dPercentage) + to[3]*dPercentage)
;    // alpha
177 }
178
179
180 // interpolate two colors in RGBA space
181 Color Color::InterpolateHSV(const Color& from, const Color& to, double dPercentage, bool bClockwise)
182 {
183     double interpolate_hue;
184     if (bClockwise)
185     {
186         // positive hue
187         double delta_hue = to.hue() - from.hue();
188         // MUST be positive
189         if (delta_hue < 0.0)   
190             delta_hue += 360.0;
191         // interpolate
192         interpolate_hue = delta_hue*dPercentage + from.hue();
193     }
194     else     {
195         // negative hue
196         double delta_hue = to.hue() - from.hue();
197         // MUST be negative
198         if (delta_hue >= 0.0)
199             delta_hue -= 360.0;
200         // interpolate
201         interpolate_hue = delta_hue*dPercentage + from.hue();
202     }
203
204     // interpolate
205     double interpolate_sat = (to.saturation() - from.saturation())*dPercentage + from.saturation();
206     double interpolate_val = (to.value()      - from.value())     *dPercentage + from.value();
207
208     // get RGB from HSV
209     Color result = hsv(interpolate_hue, interpolate_sat, interpolate_val);
210     // interpolate alpha channel
211     return Color(result[0], result[1], result[2], from[3]*(1-dPercentage) + to[3]*dPercentage);
212 }
213
214
215 ostream& operator<<(ostream& ostr, const Color& mc) {
216     ostr << mc[0] << " " << mc[1] << " " << mc[2] << " " << mc[3] << " ";
217     return ostr;
218 }
219
220 istream& operator>>(istream& s, Color& mc) {
221       char ch;
222
223     s >> ch;
224     if(ch =='{')// format "{ r g b a }"
225         s >> mc[0] >> mc[1] >> mc[2] >> mc[3] >> ch;
226         if (ch != '}') {
227             s.clear(ios::badbit);
228         }
229     } else { // format "r g b a"
230         s.putback(ch);
231         s >> mc[0] >> mc[1] >> mc[2] >> mc[3];
232     }
233
234     return s;
235 }
236
237
238
239