1 /* === S Y N F I G ========================================================= */
2 /*!	\file
3 **	\brief Color class function implementation
4 **
5 **	$Id$
6 **
7 **	\legal
8 **	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **	Copyright (c) 2007, 2008 Chris Moore
10 **	Copyright (c) 2012-2013 Carlos López
11 **	Copyright (c) 2015 Diego Barrios Romero
12 **
13 **	This package is free software; you can redistribute it and/or
14 **	modify it under the terms of the GNU General Public License as
15 **	published by the Free Software Foundation; either version 2 of
16 **	the License, or (at your option) any later version.
17 **
18 **	This package is distributed in the hope that it will be useful,
19 **	but WITHOUT ANY WARRANTY; without even the implied warranty of
20 **	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 **	General Public License for more details.
22 **	\endlegal
23 */
24 /* ========================================================================= */
25 
26 #ifndef __SYNFIG_COLOR_COLOR_HPP
27 #define __SYNFIG_COLOR_COLOR_HPP
28 
29 #include <cmath>
30 #include <cassert>
31 #include <stdint.h>
32 
33 #include <synfig/gamma.h>
34 #include <synfig/string.h>
35 #include <synfig/angle.h>
36 
37 
38 #ifdef USE_HALF_TYPE
39 #include <OpenEXR/half.h>
40 #endif
41 #ifdef USING_PCH
42 #	include "pch.h"
43 #else
44 #ifdef HAVE_CONFIG_H
45 #	include <config.h>
46 #endif
47 
48 #include <ETL/angle>
49 #include <cstdio>
50 
51 #endif
52 
53 namespace synfig {
54 
operator +=(const Color & rhs)55 Color&	Color::operator+=(const Color &rhs)
56 {
57 	r_+=rhs.r_;
58 	g_+=rhs.g_;
59 	b_+=rhs.b_;
60 	a_+=rhs.a_;
61 	return *this;
62 }
63 
operator -=(const Color & rhs)64 Color& Color::operator-=(const Color &rhs)
65 {
66 	r_-=rhs.r_;
67 	g_-=rhs.g_;
68 	b_-=rhs.b_;
69 	a_-=rhs.a_;
70 	return *this;
71 }
72 
operator *=(const float & rhs)73 Color& Color::operator*=(const float &rhs)
74 {
75 	r_*=rhs;
76 	g_*=rhs;
77 	b_*=rhs;
78 	a_*=rhs;
79 	return *this;
80 }
81 
operator /=(const float & rhs)82 Color& Color::operator/=(const float &rhs)
83 {
84 	const float temp(value_type(1)/rhs);
85 	r_*=temp;
86 	g_*=temp;
87 	b_*=temp;
88 	a_*=temp;
89 	return *this;
90 }
91 
operator +(const Color & rhs) const92 Color Color::operator+(const Color &rhs) const
93 {
94     return Color(*this)+=rhs;
95 }
96 
operator -(const Color & rhs) const97 Color Color::operator-(const Color &rhs) const
98 { return Color(*this)-=rhs; }
99 
operator *(const float & rhs) const100 Color Color::operator*(const float &rhs)const
101 { return Color(*this)*=rhs; }
102 
operator /(const float & rhs) const103 Color Color::operator/(const float &rhs)const
104 { return Color(*this)/=rhs; }
105 
operator <(const Color & rhs) const106 bool Color::operator<(const Color &rhs)const
107 {
108 	return r_<rhs.r_ ? true  : rhs.r_<r_ ? false
109 		 : g_<rhs.g_ ? true  : rhs.g_<g_ ? false
110 		 : b_<rhs.b_ ? true  : rhs.b_<b_ ? false
111 		 : a_<rhs.a_;
112 }
113 
operator ==(const Color & rhs) const114 bool Color::operator==(const Color &rhs)const
115 { return r_==rhs.r_ && g_==rhs.g_ && b_==rhs.b_ && a_==rhs.a_; }
116 
operator !=(const Color & rhs) const117 bool Color::operator!=(const Color &rhs)const
118 { return r_!=rhs.r_ || g_!=rhs.g_ || b_!=rhs.b_ || a_!=rhs.a_; }
119 
operator -() const120 Color Color::operator-()const
121 { return Color(-r_,-g_,-b_,-a_); }
122 
123 //! Effectively 1.0-color
operator ~() const124 Color Color::operator~()const
125 { return Color(1.0f-r_,1.0f-g_,1.0f-b_,a_); }
126 
is_valid() const127 bool Color::is_valid()const
128 { return !std::isnan(r_) && !std::isnan(g_) && !std::isnan(b_) && !std::isnan(a_); }
129 
premult_alpha() const130 Color Color::premult_alpha() const
131 {
132 	return Color (r_*a_, g_*a_, b_*a_, a_);
133 }
134 
demult_alpha() const135 Color Color::demult_alpha() const
136 {
137 	if(a_)
138 	{
139 		const value_type inva = 1/a_;
140 		return Color (r_*inva, g_*inva, b_*inva, a_);
141 	}else return alpha();
142 }
143 
Color()144 Color::Color() :r_(0), g_(0), b_(0),a_(0) { }
Color(const value_type & f)145 Color::Color(const value_type &f) :r_(f), g_(f), b_(f),a_(f) { }
Color(int f)146 Color::Color(int f) :r_(f), g_(f), b_(f),a_(f) { }
147 
Color(const value_type & R,const value_type & G,const value_type & B,const value_type & A)148 Color::Color(const value_type& R,
149              const value_type& G,
150              const value_type& B,
151              const value_type& A):
152 	r_(R),
153 	g_(G),
154 	b_(B),
155 	a_(A) { }
156 
Color(const Color & c,const value_type & A)157 Color::Color(const Color& c, const value_type& A):
158 	r_(c.r_),
159 	g_(c.g_),
160 	b_(c.b_),
161 	a_(A) { }
162 
Color(const Color & c)163 Color::Color(const Color& c):
164 	r_(c.r_),
165 	g_(c.g_),
166 	b_(c.b_),
167 	a_(c.a_) { }
168 
169 #ifdef USE_HALF_TYPE
170 	friend class ColorAccumulator;
171 	//!	Convert constructor
172 	Color(const ColorAccumulator& c);
173 #endif
174 
175 	//!	Copy constructor
176 	//Color(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); }
177 
178 	/*const Color &operator=(const value_type &i)
179 	{
180 		r_ = g_ = b_ = a_ = i;
181 		return *this;
182 	}*/
183 	//Color& operator=(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); return *this; }
184 
185 
get_hex() const186 const String Color::get_hex()const
187 {
188     return String(real2hex(r_) + real2hex(g_) + real2hex(b_));
189 }
190 
191 
192 //! Returns color's luminance
get_y() const193 float Color::get_y() const
194 {
195 	return
196 		(float)get_r()*EncodeYUV[0][0]+
197 		(float)get_g()*EncodeYUV[0][1]+
198 		(float)get_b()*EncodeYUV[0][2];
199 }
200 
201 
202 //! Returns U component of chromanance
get_u() const203 float Color::get_u() const
204 {
205 	return
206 		(float)get_r()*EncodeYUV[1][0]+
207 		(float)get_g()*EncodeYUV[1][1]+
208 		(float)get_b()*EncodeYUV[1][2];
209 }
210 
211 
212 	//! Returns V component of chromanance
get_v() const213 float Color::get_v() const
214 {
215 	return
216 		(float)get_r()*EncodeYUV[2][0]+
217 		(float)get_g()*EncodeYUV[2][1]+
218 		(float)get_b()*EncodeYUV[2][2];
219 }
220 
221 //! Returns the color's saturation
222 /*!	This is is the magnitude of the U and V components.
223 **	\see set_s() */
get_s() const224 float Color::get_s() const
225 {
226 	const float u(get_u()), v(get_v());
227 	return sqrt(u*u+v*v);
228 }
229 
230 //! Sets the luminance (\a y) and chromanance (\a u and \a v)
set_yuv(const float & y,const float & u,const float & v)231 Color& Color::set_yuv(const float &y, const float &u, const float &v)
232 {
233 	set_r(y*DecodeYUV[0][0]+u*DecodeYUV[0][1]+v*DecodeYUV[0][2]);
234 	set_g(y*DecodeYUV[1][0]+u*DecodeYUV[1][1]+v*DecodeYUV[1][2]);
235 	set_b(y*DecodeYUV[2][0]+u*DecodeYUV[2][1]+v*DecodeYUV[2][2]);
236 	return *this;
237 }
238 
239 //! Sets color luminance
set_y(const float & y)240 Color& Color::set_y(const float &y) { return set_yuv(y,get_u(),get_v()); }
241 
242 //! Set U component of chromanance
set_u(const float & u)243 Color& Color::set_u(const float &u) { return set_yuv(get_y(),u,get_v()); }
244 
245 //! Set V component of chromanance
set_v(const float & v)246 Color& Color::set_v(const float &v) { return set_yuv(get_y(),get_u(),v); }
247 
248 //! Set the U and V components of chromanance
set_uv(const float & u,const float & v)249 Color& Color::set_uv(const float& u, const float& v) { return set_yuv(get_y(),u,v); }
250 
251 //! Sets the color's saturation
252 /*!	\see get_s() */
set_s(const float & x)253 Color& Color::set_s(const float &x)
254 {
255 	float u(get_u()), v(get_v());
256 	const float s(sqrt(u*u+v*v));
257 	if(s)
258 	{
259 		u=(u/s)*x;
260 		v=(v/s)*x;
261 		return set_uv(u,v);
262 	}
263 	return *this;
264 }
265 
266 //! YUV Color constructor
YUV(const float & y,const float & u,const float & v,const value_type & a)267 Color Color::YUV(const float& y, const float& u, const float& v, const value_type& a)
268 	{ return Color().set_yuv(y,u,v).set_a(a); }
269 
270 //! Returns the hue of the chromanance
271 /*!	This is the angle of the U and V components.
272 **	\see set_hue() */
get_hue() const273 Angle Color::get_hue() const
274 	{ return Angle::tan(get_u(),get_v()); }
275 
276 //! Synonym for get_hue(). \see get_hue()
get_uv_angle() const277 Angle Color::get_uv_angle() const { return get_hue(); }
278 
279 //! Sets the color's hue
280 /*!	\see get_hue() */
set_hue(const Angle & theta)281 Color& Color::set_hue(const Angle& theta)
282 {
283 	const float s(get_s());
284 	const float
285 		u(s*(float)Angle::sin(theta).get()),
286 		v(s*(float)Angle::cos(theta).get());
287 	return set_uv(u,v);
288 }
289 
290 //! Synonym for set_hue(). \see set_hue()
set_uv_angle(const Angle & theta)291 Color& Color::set_uv_angle(const Angle& theta) { return set_hue(theta); }
292 
293 //! Rotates the chromanance vector by amount specified by \a theta
rotate_uv(const Angle & theta)294 Color& Color::rotate_uv(const Angle& theta)
295 {
296 	const float	a(Angle::sin(theta).get()),	b(Angle::cos(theta).get());
297 	const float	u(get_u()),	v(get_v());
298 
299 	return set_uv(b*u-a*v,a*u+b*v);
300 }
301 
set_yuv(const float & y,const float & s,const Angle & theta)302 Color& Color::set_yuv(const float& y, const float& s, const Angle& theta)
303 {
304 	return
305 		set_yuv(
306 			y,
307 			s*(float)Angle::sin(theta).get(),
308 			s*(float)Angle::cos(theta).get()
309 		);
310 }
311 
YUV(const float & y,const float & s,const Angle & theta,const value_type & a)312 Color Color::YUV(const float& y, const float& s, const Angle& theta, const value_type& a)
313 	{ return Color().set_yuv(y,s,theta).set_a(a); }
314 
315 
316 
317 /*protected:
318 
319 	value_type& operator[](const int i)
320 	{
321 		assert(i>=0);
322 		assert(i<(signed)(sizeof(Color)/sizeof(value_type)));
323 		return (&r_)[i];
324 	}
325 
326 	const value_type& operator[](const int i)const
327 	{
328 		assert(i>=0);
329 		assert(i<(signed)(sizeof(Color)/sizeof(value_type)));
330 		return (&r_)[i];
331 	}
332 */
333 
334 } // synfig namespace
335 
336 #endif // __SYNFIG_COLOR_COLOR_HPP
337 
338