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