1 /* === S Y N F I G ========================================================= */
3 ** \brief Color Class Implementation
5 ** $Id: color.h,v 1.1.1.1 2005/01/04 01:23:14 darco Exp $
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 /* ========================================================================= */
23 /* === S T A R T =========================================================== */
25 #ifndef __SYNFIG_COLOR_H
26 #define __SYNFIG_COLOR_H
28 /* === H E A D E R S ======================================================= */
38 #include <OpenEXR/half.h>
41 #ifndef SYNFIG_NO_ANGLE
45 /* === M A C R O S ========================================================= */
50 extern "C" { int _isnan(double x); }
55 // For some reason isnan() isn't working on macosx any more.
56 // This is a quick fix.
57 #if defined(__APPLE__) && !defined(SYNFIG_ISNAN_FIX)
61 inline bool isnan(double x) { return x != x; }
62 inline bool isnan(float x) { return x != x; }
63 #define SYNFIG_ISNAN_FIX 1
69 typedef half ColorReal;
71 typedef float ColorReal;
74 static const float EncodeYUV[3][3]=
76 { 0.299f, 0.587f, 0.114f },
77 { -0.168736f, -0.331264f, 0.5f },
78 { 0.5f, -0.418688f, -0.081312f }
81 static const float DecodeYUV[3][3]=
83 { 1.0f, 0.0f, 1.402f },
84 { 1.0f, -0.344136f, -0.714136f },
85 { 1.0f, 1.772f, 0.0f }
88 /* === T Y P E D E F S ===================================================== */
90 /* === C L A S S E S & S T R U C T S ======================================= */
93 class ColorAccumulator;
101 ** Future optimizations: lookup table for sqrt()?
106 typedef ColorReal value_type;
109 value_type a_, r_, g_, b_;
114 operator+=(const Color &rhs)
124 operator-=(const Color &rhs)
134 operator*=(const float &rhs)
144 operator/=(const float &rhs)
146 const float temp(value_type(1)/rhs);
155 operator+(const Color &rhs)const
156 { return Color(*this)+=rhs; }
159 operator-(const Color &rhs)const
160 { return Color(*this)-=rhs; }
163 operator*(const float &rhs)const
164 { return Color(*this)*=rhs; }
167 operator/(const float &rhs)const
168 { return Color(*this)/=rhs; }
171 operator==(const Color &rhs)const
172 { return r_==rhs.r_ && g_==rhs.g_ && b_==rhs.b_ && a_==rhs.a_; }
175 operator!=(const Color &rhs)const
176 { return r_!=rhs.r_ || g_!=rhs.g_ || b_!=rhs.b_ || a_!=rhs.a_; }
180 { return Color(-r_,-g_,-b_,-a_); }
182 //! Effectively 1.0-color
185 { return Color(1.0f-r_,1.0f-g_,1.0f-b_,a_); }
188 { return !isnan(r_) && !isnan(g_) && !isnan(b_) && !isnan(a_); }
190 Color premult_alpha() const
192 return Color (r_*a_, g_*a_, b_*a_, a_);
195 Color demult_alpha() const
199 const value_type inva = 1/a_;
200 return Color (r_*inva, g_*inva, b_*inva, a_);
201 }else return alpha();
205 Color() /*:r_(0), g_(0), b_(0), a_(0)*/ { }
206 Color(const value_type &f) :a_(f),r_(f), g_(f), b_(f) { }
207 Color(int f) :a_(f),r_(f), g_(f), b_(f) { }
212 ** \param A Opacity(alpha) */
213 Color(const value_type& R, const value_type& G, const value_type& B, const value_type& A=1):
219 /*! \param C Source for color components
220 ** \param A Opacity(alpha) */
221 Color(const Color& c, const value_type& A):
229 Color(const Color& c):
236 friend class ColorAccumulator;
237 //! Convert constructor
238 Color(const ColorAccumulator& c);
242 //Color(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); }
244 /*const Color &operator=(const value_type &i)
246 r_ = g_ = b_ = a_ = i;
249 //Color& operator=(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); return *this; }
251 //! Returns the RED component
252 const value_type& get_r()const { return r_; }
254 //! Returns the GREEN component
255 const value_type& get_g()const { return g_; }
257 //! Returns the BLUE component
258 const value_type& get_b()const { return b_; }
260 //! Returns the amount of opacity (alpha)
261 const value_type& get_a()const { return a_; }
263 //! Synonym for get_a(). \see get_a()
264 const value_type& get_alpha()const { return get_a(); }
266 //! Sets the RED component to \a x
267 Color& set_r(const value_type& x) { r_ = x; return *this; }
269 //! Sets the GREEN component to \a x
270 Color& set_g(const value_type& x) { g_ = x; return *this; }
272 //! Sets the BLUE component to \a x
273 Color& set_b(const value_type& x) { b_ = x; return *this; }
275 //! Sets the opacity (alpha) to \a x
276 Color& set_a(const value_type& x) { a_ = x; return *this; }
278 //! Synonym for set_a(). \see set_a()
279 Color& set_alpha(const value_type& x) { return set_a(x); }
281 //! Returns color's luminance
286 (float)get_r()*EncodeYUV[0][0]+
287 (float)get_g()*EncodeYUV[0][1]+
288 (float)get_b()*EncodeYUV[0][2];
292 //! Returns U component of chromanance
297 (float)get_r()*EncodeYUV[1][0]+
298 (float)get_g()*EncodeYUV[1][1]+
299 (float)get_b()*EncodeYUV[1][2];
303 //! Returns V component of chromanance
308 (float)get_r()*EncodeYUV[2][0]+
309 (float)get_g()*EncodeYUV[2][1]+
310 (float)get_b()*EncodeYUV[2][2];
313 //! Returns the color's saturation
314 /*! This is is the magnitude of the U and V components.
319 const float u(get_u()), v(get_v());
320 return sqrt(u*u+v*v);
323 //! Sets the luminance (\a y) and chromanance (\a u and \a v)
325 set_yuv(const float &y, const float &u, const float &v)
327 set_r(y*DecodeYUV[0][0]+u*DecodeYUV[0][1]+v*DecodeYUV[0][2]);
328 set_g(y*DecodeYUV[1][0]+u*DecodeYUV[1][1]+v*DecodeYUV[1][2]);
329 set_b(y*DecodeYUV[2][0]+u*DecodeYUV[2][1]+v*DecodeYUV[2][2]);
333 //! Sets color luminance
334 Color& set_y(const float &y) { return set_yuv(y,get_u(),get_v()); }
336 //! Set U component of chromanance
337 Color& set_u(const float &u) { return set_yuv(get_y(),u,get_v()); }
339 //! Set V component of chromanance
340 Color& set_v(const float &v) { return set_yuv(get_y(),get_u(),v); }
342 //! Set the U and V components of chromanance
343 Color& set_uv(const float& u, const float& v) { return set_yuv(get_y(),u,v); }
345 //! Sets the color's saturation
348 set_s(const float &x)
350 float u(get_u()), v(get_v());
351 const float s(sqrt(u*u+v*v));
361 //! YUV Color constructor
362 static Color YUV(const float& y, const float& u, const float& v, const value_type& a=1)
363 { return Color().set_yuv(y,u,v).set_a(a); }
365 #ifndef SYNFIG_NO_ANGLE
366 //! Returns the hue of the chromanance
367 /*! This is the angle of the U and V components.
371 { return Angle::tan(get_u(),get_v()); }
373 //! Synonym for get_hue(). \see get_hue()
374 Angle get_uv_angle() const { return get_hue(); }
376 //! Sets the color's hue
377 /*! \see get_hue() */
379 set_hue(const Angle& theta)
381 const float s(get_s());
383 u(s*(float)Angle::sin(theta).get()),
384 v(s*(float)Angle::cos(theta).get());
388 //! Synonym for set_hue(). \see set_hue()
389 Color& set_uv_angle(const Angle& theta) { return set_hue(theta); }
391 //! Rotates the chromanance vector by amount specified by \a theta
392 Color& rotate_uv(const Angle& theta)
394 const float a(Angle::sin(theta).get()), b(Angle::cos(theta).get());
395 const float u(get_u()), v(get_v());
397 return set_uv(b*u-a*v,a*u+b*v);
400 //! Sets the luminance (\a y) and chromanance (\a s and \a theta).
401 /*! \param y Luminance
402 ** \param s Saturation
403 ** \param theta Hue */
404 Color& set_yuv(const float& y, const float& s, const Angle& theta)
409 s*(float)Angle::sin(theta).get(),
410 s*(float)Angle::cos(theta).get()
414 //! YUV color constructor where the chroma is in the saturation/hue form.
415 /*! \param y Luminance
416 ** \param s Saturation
418 ** \param a Opacity (alpha) */
419 static Color YUV(const float& y, const float& s, const Angle& theta, const value_type& a=1)
420 { return Color().set_yuv(y,s,theta).set_a(a); }
424 //! Clamps a color so that its values are in range. Ignores attempting to visualize negative colors.
425 Color clamped()const;
427 //! Clamps a color so that its values are in range.
428 Color clamped_negative()const;
432 //! Preset Color Constructors
435 static inline Color alpha() { return Color(0,0,0,0.0000001f); }
437 static inline Color alpha() { return Color(0,0,0,0); }
439 static inline Color black() { return Color(0,0,0); }
440 static inline Color white() { return Color(1,1,1); }
441 static inline Color gray() { return Color(0.5f,0.5f,0.5f); }
442 static inline Color magenta() { return Color(1,0,1); }
443 static inline Color red() { return Color(1,0,0); }
444 static inline Color green() { return Color(0,1,0); }
445 static inline Color blue() { return Color(0,0,1); }
446 static inline Color cyan() { return Color(0,1,1); }
447 static inline Color yellow() { return Color(1,1,0); }
453 BLEND_COMPOSITE=0, //!< Color A is composited onto B (Taking into about A's alpha)
454 BLEND_STRAIGHT=1, //!< Straight linear interpolation from A->B (Alpha ignored)
455 BLEND_BRIGHTEN=2, //!< If composite is brighter than B, use composite. B otherwise.
456 BLEND_DARKEN=3, //!< If composite is brighter than B, use composite. B otherwise.
457 BLEND_ADD=4, //!< Simple A+B.
458 BLEND_SUBTRACT=5, //!< Simple A-B.
459 BLEND_MULTIPLY=6, //!< Simple A*B.
460 BLEND_DIVIDE=7, //!< Simple B/A
461 BLEND_COLOR=8, //!< Preserves the U and V channels of color A
462 BLEND_HUE=9, //!< Preserves the angle of the UV vector of color A
463 BLEND_SATURATION=10,//!< Preserves the magnitude of the UV Vector of color A
464 BLEND_LUMINANCE=11, //!< Preserves the Y channel of color A
465 BLEND_BEHIND=12, //!< Similar to BLEND_COMPOSITE, except that B is composited onto A.
466 BLEND_ONTO=13, //!< Similar to BLEND_COMPOSITE, except that B's alpha is maintained
467 BLEND_SCREEN=16, //!< \writeme
468 BLEND_OVERLAY=20, //!< \writeme
469 BLEND_DIFFERENCE=18, //!< \writeme
470 BLEND_HARD_LIGHT=17, //!< \writeme
473 BLEND_ALPHA_BRIGHTEN=14, //!< If A is less opaque than B, use A
474 BLEND_ALPHA_DARKEN=15, //!< If A is more opaque than B, use B
475 BLEND_ALPHA_OVER=19,//!< multiply alphas and then straight blends that using the amount
476 BLEND_STRAIGHT_ONTO=21,//!< \writeme
478 BLEND_END=22 //!< \internal
482 static Color blend(Color a, Color b,float amount,BlendMethod type=BLEND_COMPOSITE);
484 static bool is_onto(BlendMethod x)
486 return x==BLEND_BRIGHTEN
494 || x==BLEND_SATURATION
495 || x==BLEND_LUMINANCE
497 || x==BLEND_STRAIGHT_ONTO
500 || x==BLEND_DIFFERENCE
501 || x==BLEND_HARD_LIGHT
506 value_type& operator[](const int i)
509 assert(i<(signed)(sizeof(Color)/sizeof(value_type)));
513 const value_type& operator[](const int i)const
516 assert(i<(signed)(sizeof(Color)/sizeof(value_type)));
520 }; // END of class Color
522 #ifndef USE_HALF_TYPE
523 typedef Color ColorAccumulator;
525 class ColorAccumulator
529 typedef float value_type;
532 value_type a_, r_, g_, b_;
537 operator+=(const ColorAccumulator &rhs)
547 operator-=(const ColorAccumulator &rhs)
557 operator*=(const float &rhs)
567 operator/=(const float &rhs)
569 const float temp(value_type(1)/rhs);
578 operator+(const ColorAccumulator &rhs)const
579 { return Color(*this)+=rhs; }
582 operator-(const ColorAccumulator &rhs)const
583 { return Color(*this)-=rhs; }
586 operator*(const float &rhs)const
587 { return Color(*this)*=rhs; }
590 operator/(const float &rhs)const
591 { return Color(*this)/=rhs; }
594 operator==(const ColorAccumulator &rhs)const
595 { return r_==rhs.r_ && g_==rhs.g_ && b_==rhs.b_ && a_!=rhs.a_; }
598 operator!=(const ColorAccumulator &rhs)const
599 { return r_!=rhs.r_ || g_!=rhs.g_ || b_!=rhs.b_ || a_!=rhs.a_; }
603 { return ColorAccumulator(-r_,-g_,-b_,-a_); }
606 { return !isnan(r_) && !isnan(g_) && !isnan(b_) && !isnan(a_); }
609 ColorAccumulator() { }
614 ** \param A Opacity(alpha) */
615 ColorAccumulator(const value_type& R, const value_type& G, const value_type& B, const value_type& A=1):
622 ColorAccumulator(const ColorAccumulator& c):
629 ColorAccumulator(const Color& c):
635 //! Returns the RED component
636 const value_type& get_r()const { return r_; }
638 //! Returns the GREEN component
639 const value_type& get_g()const { return g_; }
641 //! Returns the BLUE component
642 const value_type& get_b()const { return b_; }
644 //! Returns the amount of opacity (alpha)
645 const value_type& get_a()const { return a_; }
647 //! Synonym for get_a(). \see get_a()
648 const value_type& get_alpha()const { return get_a(); }
650 //! Sets the RED component to \a x
651 ColorAccumulator& set_r(const value_type& x) { r_ = x; return *this; }
653 //! Sets the GREEN component to \a x
654 ColorAccumulator& set_g(const value_type& x) { g_ = x; return *this; }
656 //! Sets the BLUE component to \a x
657 ColorAccumulator& set_b(const value_type& x) { b_ = x; return *this; }
659 //! Sets the opacity (alpha) to \a x
660 ColorAccumulator& set_a(const value_type& x) { a_ = x; return *this; }
662 //! Synonym for set_a(). \see set_a()
663 ColorAccumulator& set_alpha(const value_type& x) { return set_a(x); }
667 Color::Color(const ColorAccumulator& c):
681 /* Bit Descriptions (ON/OFF)
682 ** ----+-------------
683 ** 0 Color Channels (Gray/RGB)
684 ** 1 Alpha Channel (WITH/WITHOUT)
685 ** 2 ZDepth (WITH/WITHOUT)
686 ** 3 Endian (BGR/RGB)
687 ** 4 Alpha Location (Start/End)
688 ** 5 ZDepth Location (Start/End)
689 ** 6 Alpha/ZDepth Arangement (ZA,AZ)
690 ** 7 Alpha Range (Inverted,Normal)
691 ** 8 Z Range (Inverted,Normal)
694 PF_GRAY=(1<<0), //!< If set, use one grayscale channel. If clear, use three channels for RGB
695 PF_A=(1<<1), //!< If set, include alpha channel
696 PF_Z=(1<<2), //!< If set, include ZDepth channel
697 PF_BGR=(1<<3), //!< If set, reverse the order of the RGB channels
698 PF_A_START=(1<<4), //!< If set, alpha channel is before the color data. If clear, it is after.
699 PF_Z_START=(1<<5), //!< If set, ZDepth channel is before the color data. If clear, it is after.
700 PF_ZA=(1<<6), //!< If set, the ZDepth channel will be infront of the alpha channel. If clear, they are reversed.
702 PF_A_INV=(1<<7), //!< If set, the alpha channel is stored as 1.0-a
703 PF_Z_INV=(1<<8), //!< If set, the ZDepth channel is stored as 1.0-z
704 PF_RAW_COLOR=(1<<9)+(1<<1) //!< If set, the data represents a raw Color datastructure, and all other bits are ignored.
707 inline PixelFormat operator|(PixelFormat lhs, PixelFormat rhs)
708 { return static_cast<PixelFormat>((int)lhs|(int)rhs); }
710 inline PixelFormat operator&(PixelFormat lhs, PixelFormat rhs)
711 { return static_cast<PixelFormat>((int)lhs&(int)rhs); }
712 #define FLAGS(x,y) (((x)&(y))==(y))
714 //! Returns the number of channels that the given PixelFormat calls for
716 channels(PixelFormat x)
727 if(FLAGS(x,PF_RAW_COLOR))
733 inline unsigned char *
734 Color2PixelFormat(const Color &color, const PixelFormat &pf, unsigned char *out, const Gamma &gamma)
736 if(FLAGS(pf,PF_RAW_COLOR))
738 Color *outcol=reinterpret_cast<Color *>(out);
744 int alpha=(int)((FLAGS(pf,PF_A_INV)?(-(float)color.get_a()+1):(float)color.get_a())*255);
746 if(alpha>255)alpha=255;
748 if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
750 if(FLAGS(pf,PF_Z_START))
751 *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
752 if(FLAGS(pf,PF_A_START))
753 *out++=static_cast<unsigned char>(alpha);
757 if(FLAGS(pf,PF_A_START))
758 *out++=static_cast<unsigned char>(alpha);
759 if(FLAGS(pf,PF_Z_START))
760 *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
764 if(FLAGS(pf,PF_GRAY))
765 *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_y()));
770 *out++=static_cast<unsigned char>(gamma.r_F32_to_U8(color.get_b()));
771 *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_g()));
772 *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_r()));
776 *out++=static_cast<unsigned char>(gamma.r_F32_to_U8(color.get_r()));
777 *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_g()));
778 *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_b()));
784 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
785 out++;//*out++=(unsigned char)(color.GetZ()*255.0f);
786 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
787 *out++=static_cast<unsigned char>(alpha);
791 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
792 out++;//*out++=(unsigned char)(color.GetZ()*255.0f);
793 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
794 *out++=static_cast<unsigned char>(alpha);
800 convert_color_format(unsigned char *dest, const Color *src, int w, PixelFormat pf,const Gamma &gamma)
804 dest=Color2PixelFormat((*(src++)).clamped(),pf,dest,gamma);
807 inline const unsigned char *
808 PixelFormat2Color(Color &color, const PixelFormat &pf,const unsigned char *out)
810 if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
812 if(FLAGS(pf,PF_Z_START))
813 out++;//color.SetZ((Color::value_type)*out++/255.0f);
814 if(FLAGS(pf,PF_A_START))
815 color.set_a((float)*out++/255);
819 if(FLAGS(pf,PF_A_START))
820 color.set_a((float)*out++/255);
821 if(FLAGS(pf,PF_Z_START))
822 out++;//color.SetZ((Color::value_type)*out++/255.0f);
825 if(FLAGS(pf,PF_GRAY))
826 color.set_yuv((float)*out++/255,0,0);
831 color.set_b((float)*out++/255);
832 color.set_g((float)*out++/255);
833 color.set_r((float)*out++/255);
837 color.set_r((float)*out++/255);
838 color.set_g((float)*out++/255);
839 color.set_b((float)*out++/255);
845 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
846 out++;//color.SetZ((Color::value_type)*out++/255.0f);
847 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
848 color.set_a((float)*out++/255);
852 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
853 color.set_a((float)*out++/255);
854 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
855 out++;//color.SetZ((Color::value_type)*out++/255.0f);
862 }; // END of namespace synfig
864 /* === E N D =============================================================== */