studies/grafik2/Computergrafik-Code3/Aufgabe8/color.cpp
⇒
download file
1
2
3
4
5
6
7
8
9
10
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
93
94
95 Color Color::hsv(double h, double s, double v, double alpha) {
96
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
107
108 R = v;
109 G = v;
110 B = v;
111 } else {
112
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;
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
171 Color Color::InterpolateRGB(const Color& from, const Color& to, double dPercentage)
172 {
173 return Color(from[0]*(1-dPercentage) + to[0]*dPercentage,
174 from[1]*(1-dPercentage) + to[1]*dPercentage,
175 from[2]*(1-dPercentage) + to[2]*dPercentage,
176 from[3]*(1-dPercentage) + to[3]*dPercentage);
177 }
178
179
180
181 Color Color::InterpolateHSV(const Color& from, const Color& to, double dPercentage, bool bClockwise)
182 {
183 double interpolate_hue;
184 if (bClockwise)
185 {
186
187 double delta_hue = to.hue() - from.hue();
188
189 if (delta_hue < 0.0)
190 delta_hue += 360.0;
191
192 interpolate_hue = delta_hue*dPercentage + from.hue();
193 }
194 else
{
195
196 double delta_hue = to.hue() - from.hue();
197
198 if (delta_hue >= 0.0)
199 delta_hue -= 360.0;
200
201 interpolate_hue = delta_hue*dPercentage + from.hue();
202 }
203
204
205 double interpolate_sat = (to.saturation() - from.saturation())*dPercentage + from.saturation();
206 double interpolate_val = (to.value() - from.value()) *dPercentage + from.value();
207
208
209 Color result = hsv(interpolate_hue, interpolate_sat, interpolate_val);
210
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 =='{') {
225 s >> mc[0] >> mc[1] >> mc[2] >> mc[3] >> ch;
226 if (ch != '}') {
227 s.clear(ios::badbit);
228 }
229 } else {
230 s.putback(ch);
231 s >> mc[0] >> mc[1] >> mc[2] >> mc[3];
232 }
233
234 return s;
235 }
236
237
238
239