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):
636 ColorAccumulator(int c): a_(c),r_(c), g_(c), b_(c) { }
638 //! Returns the RED component
639 const value_type& get_r()const { return r_; }
641 //! Returns the GREEN component
642 const value_type& get_g()const { return g_; }
644 //! Returns the BLUE component
645 const value_type& get_b()const { return b_; }
647 //! Returns the amount of opacity (alpha)
648 const value_type& get_a()const { return a_; }
650 //! Synonym for get_a(). \see get_a()
651 const value_type& get_alpha()const { return get_a(); }
653 //! Sets the RED component to \a x
654 ColorAccumulator& set_r(const value_type& x) { r_ = x; return *this; }
656 //! Sets the GREEN component to \a x
657 ColorAccumulator& set_g(const value_type& x) { g_ = x; return *this; }
659 //! Sets the BLUE component to \a x
660 ColorAccumulator& set_b(const value_type& x) { b_ = x; return *this; }
662 //! Sets the opacity (alpha) to \a x
663 ColorAccumulator& set_a(const value_type& x) { a_ = x; return *this; }
665 //! Synonym for set_a(). \see set_a()
666 ColorAccumulator& set_alpha(const value_type& x) { return set_a(x); }
670 Color::Color(const ColorAccumulator& c):
684 /* Bit Descriptions (ON/OFF)
685 ** ----+-------------
686 ** 0 Color Channels (Gray/RGB)
687 ** 1 Alpha Channel (WITH/WITHOUT)
688 ** 2 ZDepth (WITH/WITHOUT)
689 ** 3 Endian (BGR/RGB)
690 ** 4 Alpha Location (Start/End)
691 ** 5 ZDepth Location (Start/End)
692 ** 6 Alpha/ZDepth Arangement (ZA,AZ)
693 ** 7 Alpha Range (Inverted,Normal)
694 ** 8 Z Range (Inverted,Normal)
697 PF_GRAY=(1<<0), //!< If set, use one grayscale channel. If clear, use three channels for RGB
698 PF_A=(1<<1), //!< If set, include alpha channel
699 PF_Z=(1<<2), //!< If set, include ZDepth channel
700 PF_BGR=(1<<3), //!< If set, reverse the order of the RGB channels
701 PF_A_START=(1<<4), //!< If set, alpha channel is before the color data. If clear, it is after.
702 PF_Z_START=(1<<5), //!< If set, ZDepth channel is before the color data. If clear, it is after.
703 PF_ZA=(1<<6), //!< If set, the ZDepth channel will be infront of the alpha channel. If clear, they are reversed.
705 PF_A_INV=(1<<7), //!< If set, the alpha channel is stored as 1.0-a
706 PF_Z_INV=(1<<8), //!< If set, the ZDepth channel is stored as 1.0-z
707 PF_RAW_COLOR=(1<<9)+(1<<1) //!< If set, the data represents a raw Color datastructure, and all other bits are ignored.
710 inline PixelFormat operator|(PixelFormat lhs, PixelFormat rhs)
711 { return static_cast<PixelFormat>((int)lhs|(int)rhs); }
713 inline PixelFormat operator&(PixelFormat lhs, PixelFormat rhs)
714 { return static_cast<PixelFormat>((int)lhs&(int)rhs); }
715 #define FLAGS(x,y) (((x)&(y))==(y))
717 //! Returns the number of channels that the given PixelFormat calls for
719 channels(PixelFormat x)
730 if(FLAGS(x,PF_RAW_COLOR))
736 inline unsigned char *
737 Color2PixelFormat(const Color &color, const PixelFormat &pf, unsigned char *out, const Gamma &gamma)
739 if(FLAGS(pf,PF_RAW_COLOR))
741 Color *outcol=reinterpret_cast<Color *>(out);
747 int alpha=(int)((FLAGS(pf,PF_A_INV)?(-(float)color.get_a()+1):(float)color.get_a())*255);
749 if(alpha>255)alpha=255;
751 if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
753 if(FLAGS(pf,PF_Z_START))
754 *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
755 if(FLAGS(pf,PF_A_START))
756 *out++=static_cast<unsigned char>(alpha);
760 if(FLAGS(pf,PF_A_START))
761 *out++=static_cast<unsigned char>(alpha);
762 if(FLAGS(pf,PF_Z_START))
763 *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
767 if(FLAGS(pf,PF_GRAY))
768 *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_y()));
773 *out++=static_cast<unsigned char>(gamma.r_F32_to_U8(color.get_b()));
774 *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_g()));
775 *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_r()));
779 *out++=static_cast<unsigned char>(gamma.r_F32_to_U8(color.get_r()));
780 *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_g()));
781 *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_b()));
787 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
788 out++;//*out++=(unsigned char)(color.GetZ()*255.0f);
789 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
790 *out++=static_cast<unsigned char>(alpha);
794 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
795 out++;//*out++=(unsigned char)(color.GetZ()*255.0f);
796 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
797 *out++=static_cast<unsigned char>(alpha);
803 convert_color_format(unsigned char *dest, const Color *src, int w, PixelFormat pf,const Gamma &gamma)
807 dest=Color2PixelFormat((*(src++)).clamped(),pf,dest,gamma);
810 inline const unsigned char *
811 PixelFormat2Color(Color &color, const PixelFormat &pf,const unsigned char *out)
813 if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
815 if(FLAGS(pf,PF_Z_START))
816 out++;//color.SetZ((Color::value_type)*out++/255.0f);
817 if(FLAGS(pf,PF_A_START))
818 color.set_a((float)*out++/255);
822 if(FLAGS(pf,PF_A_START))
823 color.set_a((float)*out++/255);
824 if(FLAGS(pf,PF_Z_START))
825 out++;//color.SetZ((Color::value_type)*out++/255.0f);
828 if(FLAGS(pf,PF_GRAY))
829 color.set_yuv((float)*out++/255,0,0);
834 color.set_b((float)*out++/255);
835 color.set_g((float)*out++/255);
836 color.set_r((float)*out++/255);
840 color.set_r((float)*out++/255);
841 color.set_g((float)*out++/255);
842 color.set_b((float)*out++/255);
848 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
849 out++;//color.SetZ((Color::value_type)*out++/255.0f);
850 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
851 color.set_a((float)*out++/255);
855 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
856 color.set_a((float)*out++/255);
857 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
858 out++;//color.SetZ((Color::value_type)*out++/255.0f);
865 }; // END of namespace synfig
867 /* === E N D =============================================================== */