1
2 /******************************************************************************
3 * MODULE : true_color.hpp
4 * DESCRIPTION: RGBA colors represented by floating point numbers
5 * COPYRIGHT : (C) 2013 Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11
12 #ifndef TRUE_COLOR_H
13 #define TRUE_COLOR_H
14 #include "tree.hpp"
15 #include "unary_function.hpp"
16
17 /******************************************************************************
18 * Main true_color class
19 ******************************************************************************/
20
21 class true_color {
22 public:
23 typedef double scalar_type;
24
25 public:
26 double b;
27 double g;
28 double r;
29 double a;
30
31 public:
true_color()32 inline true_color () {}
true_color(const true_color & c)33 inline true_color (const true_color& c):
34 b (c.b), g (c.g), r (c.r), a (c.a) {}
operator =(const true_color & c)35 inline true_color& operator = (const true_color& c) {
36 b= c.b; g= c.g; r= c.r; a= c.a; return *this; }
true_color(double r2,double g2,double b2,double a2)37 inline true_color (double r2, double g2, double b2, double a2):
38 b (b2), g (g2), r (r2), a (a2) {}
true_color(color c)39 inline true_color (color c):
40 b (((double) (c & 0xff)) / 255.0),
41 g (((double) ((c >> 8) & 0xff)) / 255.0),
42 r (((double) ((c >> 16) & 0xff)) / 255.0),
43 a (((double) ((c >> 24) & 0xff)) / 255.0) {}
operator color() const44 inline operator color () const {
45 return
46 ((int) (b * 255 + 0.5)) +
47 (((int) (g * 255 + 0.5)) << 8) +
48 (((int) (r * 255 + 0.5)) << 16) +
49 (((int) (a * 255 + 0.5)) << 24); }
50 };
51
52 inline tm_ostream&
operator <<(tm_ostream & out,const true_color & c)53 operator << (tm_ostream& out, const true_color& c) {
54 return out << "[ " << c.r << ", " << c.g << ", " << c.b
55 << "; " << c.a << "]";
56 }
57
58 /******************************************************************************
59 * Basic arithmetic
60 ******************************************************************************/
61
62 inline true_color
operator +(const true_color & c1,const true_color & c2)63 operator + (const true_color& c1, const true_color& c2) {
64 return true_color (c1.r + c2.r, c1.g + c2.g, c1.b + c2.b, c1.a + c2.a);
65 }
66
67 inline true_color
operator -(const true_color & c1,const true_color & c2)68 operator - (const true_color& c1, const true_color& c2) {
69 return true_color (c1.r - c2.r, c1.g - c2.g, c1.b - c2.b, c1.a - c2.a);
70 }
71
72 inline true_color
operator *(const true_color & c1,const true_color & c2)73 operator * (const true_color& c1, const true_color& c2) {
74 return true_color (c1.r * c2.r, c1.g * c2.g, c1.b * c2.b, c1.a * c2.a);
75 }
76
77 inline true_color
operator /(const true_color & c1,const true_color & c2)78 operator / (const true_color& c1, const true_color& c2) {
79 return true_color (c1.r / c2.r, c1.g / c2.g, c1.b / c2.b, c1.a / c2.a);
80 }
81
82 inline true_color&
operator +=(true_color & c1,const true_color & c2)83 operator += (true_color& c1, const true_color& c2) {
84 c1.r += c2.r; c1.g += c2.g; c1.b += c2.b; c1.a += c2.a;
85 return c1;
86 }
87
88 inline true_color&
operator -=(true_color & c1,const true_color & c2)89 operator -= (true_color& c1, const true_color& c2) {
90 c1.r -= c2.r; c1.g -= c2.g; c1.b -= c2.b; c1.a -= c2.a;
91 return c1;
92 }
93
94 inline true_color&
operator *=(true_color & c1,const true_color & c2)95 operator *= (true_color& c1, const true_color& c2) {
96 cout << c1 << ", " << c2 << "\n";
97 c1.r *= c2.r; c1.g *= c2.g; c1.b *= c2.b; c1.a *= c2.a;
98 return c1;
99 }
100
101 inline true_color&
operator /=(true_color & c1,const true_color & c2)102 operator /= (true_color& c1, const true_color& c2) {
103 c1.r /= c2.r; c1.g /= c2.g; c1.b /= c2.b; c1.a /= c2.a;
104 return c1;
105 }
106
107 inline true_color
operator *(double x,const true_color & c)108 operator * (double x, const true_color& c) {
109 return true_color (c.r * x, c.g * x, c.b * x, c.a * x);
110 }
111
112 inline true_color
operator *(const true_color & c,double x)113 operator * (const true_color& c, double x) {
114 return true_color (c.r * x, c.g * x, c.b * x, c.a * x);
115 }
116
117 inline true_color
operator /(const true_color & c,double x)118 operator / (const true_color& c, double x) {
119 return true_color (c.r / x, c.g / x, c.b / x, c.a / x);
120 }
121
122 inline true_color
min(const true_color & c1,const true_color & c2)123 min (const true_color& c1, const true_color& c2) {
124 return true_color (min (c1.r, c2.r), min (c1.g, c2.g),
125 min (c1.b, c2.b), min (c1.a, c2.a));
126 }
127
128 inline true_color
max(const true_color & c1,const true_color & c2)129 max (const true_color& c1, const true_color& c2) {
130 return true_color (max (c1.r, c2.r), min (c1.g, c2.g),
131 max (c1.b, c2.b), min (c1.a, c2.a));
132 }
133
134 /******************************************************************************
135 * Composition operators
136 ******************************************************************************/
137
138 inline true_color
source_over(const true_color & c1,const true_color & c2)139 source_over (const true_color& c1, const true_color& c2) {
140 double a1= c1.a, a2= c2.a, a= a2 + a1 * (1 - a2);
141 double u= 1.0 / (a + 1.0e-6);
142 double f1= a1 * (1 - a2) * u, f2= a2 * u;
143 return true_color (c1.r * f1 + c2.r * f2,
144 c1.g * f1 + c2.g * f2,
145 c1.b * f1 + c2.b * f2,
146 a);
147 }
148
149 inline true_color
towards_source(const true_color & c1,const true_color & c2)150 towards_source (const true_color& c1, const true_color& c2) {
151 double a2= c2.a, a1= 1.0 - a2;
152 return true_color (c1.r * a1 + c2.r * a2,
153 c1.g * a1 + c2.g * a2,
154 c1.b * a1 + c2.b * a2,
155 c1.a);
156 }
157
158 inline true_color
alpha_distance(const true_color & c1,const true_color & c2)159 alpha_distance (const true_color& c1, const true_color& c2) {
160 double a1= c1.a, a2= c2.a, s= a1 + a2 + 1.0e-6, a= fabs (a1 - a2);
161 double f1= a1 / s, f2= a2 / s;
162 return true_color (c1.r * f1 + c2.r * f2,
163 c1.g * f1 + c2.g * f2,
164 c1.b * f1 + c2.b * f2,
165 a);
166 }
167
168 /******************************************************************************
169 * Transparency
170 ******************************************************************************/
171
172 inline void
clear(true_color & c)173 clear (true_color& c) {
174 c.r= c.g= c.b= c.a= 0.0;
175 }
176
177 inline void
clear_alpha(true_color & c)178 clear_alpha (true_color& c) {
179 c.a= 0.0;
180 }
181
182 inline double
get_alpha(const true_color & c)183 get_alpha (const true_color& c) {
184 return c.a;
185 }
186
187 inline double&
get_alpha(true_color & c)188 get_alpha (true_color& c) {
189 return c.a;
190 }
191
192 inline true_color
mul_alpha(const true_color & c)193 mul_alpha (const true_color& c) {
194 return true_color (c.r * c.a, c.g * c.a, c.b * c.a, c.a);
195 }
196
197 inline true_color
div_alpha(const true_color & c)198 div_alpha (const true_color& c) {
199 if (c.a < 0.00390625 && c.a > -0.00390625) return c;
200 else return true_color (c.r / c.a, c.g / c.a, c.b / c.a, c.a);
201 }
202
203 inline true_color
apply_alpha(const true_color & c,double a)204 apply_alpha (const true_color& c, double a) {
205 return true_color (c.r, c.g, c.b, c.a * a);
206 }
207
208 /******************************************************************************
209 * Other operators
210 ******************************************************************************/
211
212 inline true_color
normalize(const true_color & c)213 normalize (const true_color& c) {
214 return true_color (max (min (c.r, 1.0), 0.0),
215 max (min (c.g, 1.0), 0.0),
216 max (min (c.b, 1.0), 0.0),
217 max (min (c.a, 1.0), 0.0));
218 }
219
220 inline true_color
hypot(const true_color & c1,const true_color & c2)221 hypot (const true_color& c1, const true_color& c2) {
222 return true_color (sqrt (c1.r * c1.r + c2.r * c2.r),
223 sqrt (c1.g * c1.g + c2.g * c2.g),
224 sqrt (c1.b * c1.b + c2.b * c2.b),
225 sqrt (c1.a * c1.a + c2.a * c2.a));
226 }
227
228 inline double
max(const true_color & c)229 max (const true_color& c) {
230 return max (c.r, max (c.g, max (c.b, c.a)));
231 }
232
233 inline double
inner_max(const true_color & c1,const true_color & c2)234 inner_max (const true_color& c1, const true_color& c2) {
235 return max (max (c1.r * c2.r, c1.g * c2.g),
236 max (c1.b * c2.b, c1.a * c2.a));
237 }
238
239 true_color mix (const true_color& c1, double a1,
240 const true_color& c2, double a2);
241 true_color mix (const true_color& c1, double a1,
242 const true_color& c2, double a2,
243 const true_color& c3, double a3,
244 const true_color& c4, double a4);
245
246 /******************************************************************************
247 * Color transformations
248 ******************************************************************************/
249
250 unary_function<true_color,true_color>
251 color_matrix_function (const array<double>& a);
252 unary_function<true_color,true_color>
253 make_transparent_function (const true_color& bgc);
254 unary_function<true_color,true_color>
255 make_opaque_function (const true_color& bgc);
256
257 #endif // defined TRUE_COLOR_H
258