1 /* === S I N F 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 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
14 ** You may not copy, print, publish, or in any
15 ** other way distribute this software without
16 ** a prior written agreement with
17 ** the copyright holder.
20 /* ========================================================================= */
22 /* === S T A R T =========================================================== */
24 #ifndef __SINFG_COLOR_H
25 #define __SINFG_COLOR_H
27 /* === H E A D E R S ======================================================= */
29 #ifndef SINFG_NO_ANGLE
40 #include <OpenEXR/half.h>
43 /* === M A C R O S ========================================================= */
50 extern "C" { int _isnan(double x); }
56 #define isnan __isnanf
64 typedef half ColorReal;
66 typedef float ColorReal;
69 static const float EncodeYUV[3][3]=
71 { 0.299f, 0.587f, 0.114f },
72 { -0.168736f, -0.331264f, 0.5f },
73 { 0.5f, -0.418688f, -0.081312f }
76 static const float DecodeYUV[3][3]=
78 { 1.0f, 0.0f, 1.402f },
79 { 1.0f, -0.344136f, -0.714136f },
80 { 1.0f, 1.772f, 0.0f }
83 /* === T Y P E D E F S ===================================================== */
85 /* === C L A S S E S & S T R U C T S ======================================= */
88 class ColorAccumulator;
96 ** Future optimizations: lookup table for sqrt()?
101 typedef ColorReal value_type;
104 value_type a_, r_, g_, b_;
109 operator+=(const Color &rhs)
119 operator-=(const Color &rhs)
129 operator*=(const float &rhs)
139 operator/=(const float &rhs)
141 const float temp(value_type(1)/rhs);
150 operator+(const Color &rhs)const
151 { return Color(*this)+=rhs; }
154 operator-(const Color &rhs)const
155 { return Color(*this)-=rhs; }
158 operator*(const float &rhs)const
159 { return Color(*this)*=rhs; }
162 operator/(const float &rhs)const
163 { return Color(*this)/=rhs; }
166 operator==(const Color &rhs)const
167 { return r_==rhs.r_ && g_==rhs.g_ && b_==rhs.b_ && a_==rhs.a_; }
170 operator!=(const Color &rhs)const
171 { return r_!=rhs.r_ || g_!=rhs.g_ || b_!=rhs.b_ || a_!=rhs.a_; }
175 { return Color(-r_,-g_,-b_,-a_); }
177 //! Effectively 1.0-color
180 { return Color(1.0f-r_,1.0f-g_,1.0f-b_,a_); }
183 { return !isnan(r_) && !isnan(g_) && !isnan(b_) && !isnan(a_); }
185 Color premult_alpha() const
187 return Color (r_*a_, g_*a_, b_*a_, a_);
190 Color demult_alpha() const
194 const value_type inva = 1/a_;
195 return Color (r_*inva, g_*inva, b_*inva, a_);
196 }else return alpha();
200 Color() /*:r_(0), g_(0), b_(0), a_(0)*/ { }
201 Color(const value_type &f) :a_(f),r_(f), g_(f), b_(f) { }
202 Color(int f) :a_(f),r_(f), g_(f), b_(f) { }
207 ** \param A Opacity(alpha) */
208 Color(const value_type& R, const value_type& G, const value_type& B, const value_type& A=1):
214 /*! \param C Source for color components
215 ** \param A Opacity(alpha) */
216 Color(const Color& c, const value_type& A):
224 Color(const Color& c):
231 friend class ColorAccumulator;
232 //! Convert constructor
233 Color(const ColorAccumulator& c);
237 //Color(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); }
239 /*const Color &operator=(const value_type &i)
241 r_ = g_ = b_ = a_ = i;
244 //Color& operator=(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); return *this; }
246 //! Returns the RED component
247 const value_type& get_r()const { return r_; }
249 //! Returns the GREEN component
250 const value_type& get_g()const { return g_; }
252 //! Returns the BLUE component
253 const value_type& get_b()const { return b_; }
255 //! Returns the amount of opacity (alpha)
256 const value_type& get_a()const { return a_; }
258 //! Synonym for get_a(). \see get_a()
259 const value_type& get_alpha()const { return get_a(); }
261 //! Sets the RED component to \a x
262 Color& set_r(const value_type& x) { r_ = x; return *this; }
264 //! Sets the GREEN component to \a x
265 Color& set_g(const value_type& x) { g_ = x; return *this; }
267 //! Sets the BLUE component to \a x
268 Color& set_b(const value_type& x) { b_ = x; return *this; }
270 //! Sets the opacity (alpha) to \a x
271 Color& set_a(const value_type& x) { a_ = x; return *this; }
273 //! Synonym for set_a(). \see set_a()
274 Color& set_alpha(const value_type& x) { return set_a(x); }
276 //! Returns color's luminance
281 (float)get_r()*EncodeYUV[0][0]+
282 (float)get_g()*EncodeYUV[0][1]+
283 (float)get_b()*EncodeYUV[0][2];
287 //! Returns U component of chromanance
292 (float)get_r()*EncodeYUV[1][0]+
293 (float)get_g()*EncodeYUV[1][1]+
294 (float)get_b()*EncodeYUV[1][2];
298 //! Returns V component of chromanance
303 (float)get_r()*EncodeYUV[2][0]+
304 (float)get_g()*EncodeYUV[2][1]+
305 (float)get_b()*EncodeYUV[2][2];
308 //! Returns the color's saturation
309 /*! This is is the magnitude of the U and V components.
314 const float u(get_u()), v(get_v());
315 return sqrt(u*u+v*v);
318 //! Sets the luminance (\a y) and chromanance (\a u and \a v)
320 set_yuv(const float &y, const float &u, const float &v)
322 set_r(y*DecodeYUV[0][0]+u*DecodeYUV[0][1]+v*DecodeYUV[0][2]);
323 set_g(y*DecodeYUV[1][0]+u*DecodeYUV[1][1]+v*DecodeYUV[1][2]);
324 set_b(y*DecodeYUV[2][0]+u*DecodeYUV[2][1]+v*DecodeYUV[2][2]);
328 //! Sets color luminance
329 Color& set_y(const float &y) { return set_yuv(y,get_u(),get_v()); }
331 //! Set U component of chromanance
332 Color& set_u(const float &u) { return set_yuv(get_y(),u,get_v()); }
334 //! Set V component of chromanance
335 Color& set_v(const float &v) { return set_yuv(get_y(),get_u(),v); }
337 //! Set the U and V components of chromanance
338 Color& set_uv(const float& u, const float& v) { return set_yuv(get_y(),u,v); }
340 //! Sets the color's saturation
343 set_s(const float &x)
345 float u(get_u()), v(get_v());
346 const float s(sqrt(u*u+v*v));
356 //! YUV Color constructor
357 static Color YUV(const float& y, const float& u, const float& v, const value_type& a=1)
358 { return Color().set_yuv(y,u,v).set_a(a); }
360 #ifndef SINFG_NO_ANGLE
361 //! Returns the hue of the chromanance
362 /*! This is the angle of the U and V components.
366 { return Angle::tan(get_u(),get_v()); }
368 //! Synonym for get_hue(). \see get_hue()
369 Angle get_uv_angle() const { return get_hue(); }
371 //! Sets the color's hue
372 /*! \see get_hue() */
374 set_hue(const Angle& theta)
376 const float s(get_s());
378 u(s*(float)Angle::sin(theta).get()),
379 v(s*(float)Angle::cos(theta).get());
383 //! Synonym for set_hue(). \see set_hue()
384 Color& set_uv_angle(const Angle& theta) { return set_hue(theta); }
386 //! Rotates the chromanance vector by amount specified by \a theta
387 Color& rotate_uv(const Angle& theta)
389 const float a(Angle::sin(theta).get()), b(Angle::cos(theta).get());
390 const float u(get_u()), v(get_v());
392 return set_uv(b*u-a*v,a*u+b*v);
395 //! Sets the luminance (\a y) and chromanance (\a s and \a theta).
396 /*! \param y Luminance
397 ** \param s Saturation
398 ** \param theta Hue */
399 Color& set_yuv(const float& y, const float& s, const Angle& theta)
404 s*(float)Angle::sin(theta).get(),
405 s*(float)Angle::cos(theta).get()
409 //! YUV color constructor where the chroma is in the saturation/hue form.
410 /*! \param y Luminance
411 ** \param s Saturation
413 ** \param a Opacity (alpha) */
414 static Color YUV(const float& y, const float& s, const Angle& theta, const value_type& a=1)
415 { return Color().set_yuv(y,s,theta).set_a(a); }
419 //! Clamps a color so that its values are in range. Ignores attempting to visualize negative colors.
420 Color clamped()const;
422 //! Clamps a color so that its values are in range.
423 Color clamped_negative()const;
427 //! Preset Color Constructors
430 static inline Color alpha() { return Color(0,0,0,0.0000001f); }
432 static inline Color alpha() { return Color(0,0,0,0); }
434 static inline Color black() { return Color(0,0,0); }
435 static inline Color white() { return Color(1,1,1); }
436 static inline Color gray() { return Color(0.5f,0.5f,0.5f); }
437 static inline Color magenta() { return Color(1,0,1); }
438 static inline Color red() { return Color(1,0,0); }
439 static inline Color green() { return Color(0,1,0); }
440 static inline Color blue() { return Color(0,0,1); }
441 static inline Color cyan() { return Color(0,1,1); }
442 static inline Color yellow() { return Color(1,1,0); }
448 BLEND_COMPOSITE=0, //!< Color A is composited onto B (Taking into about A's alpha)
449 BLEND_STRAIGHT=1, //!< Straight linear interpolation from A->B (Alpha ignored)
450 BLEND_BRIGHTEN=2, //!< If composite is brighter than B, use composite. B otherwise.
451 BLEND_DARKEN=3, //!< If composite is brighter than B, use composite. B otherwise.
452 BLEND_ADD=4, //!< Simple A+B.
453 BLEND_SUBTRACT=5, //!< Simple A-B.
454 BLEND_MULTIPLY=6, //!< Simple A*B.
455 BLEND_DIVIDE=7, //!< Simple B/A
456 BLEND_COLOR=8, //!< Preserves the U and V channels of color A
457 BLEND_HUE=9, //!< Preserves the angle of the UV vector of color A
458 BLEND_SATURATION=10,//!< Preserves the magnitude of the UV Vector of color A
459 BLEND_LUMINANCE=11, //!< Preserves the Y channel of color A
460 BLEND_BEHIND=12, //!< Similar to BLEND_COMPOSITE, except that B is composited onto A.
461 BLEND_ONTO=13, //!< Similar to BLEND_COMPOSITE, except that B's alpha is maintained
462 BLEND_SCREEN=16, //!< \writeme
463 BLEND_OVERLAY=20, //!< \writeme
464 BLEND_DIFFERENCE=18, //!< \writeme
465 BLEND_HARD_LIGHT=17, //!< \writeme
468 BLEND_ALPHA_BRIGHTEN=14, //!< If A is less opaque than B, use A
469 BLEND_ALPHA_DARKEN=15, //!< If A is more opaque than B, use B
470 BLEND_ALPHA_OVER=19,//!< multiply alphas and then straight blends that using the amount
471 BLEND_STRAIGHT_ONTO=21,//!< \writeme
473 BLEND_END=22 //!< \internal
477 static Color blend(Color a, Color b,float amount,BlendMethod type=BLEND_COMPOSITE);
479 static bool is_onto(BlendMethod x)
481 return x==BLEND_BRIGHTEN
489 || x==BLEND_SATURATION
490 || x==BLEND_LUMINANCE
492 || x==BLEND_STRAIGHT_ONTO
495 || x==BLEND_DIFFERENCE
496 || x==BLEND_HARD_LIGHT
501 value_type& operator[](const int i)
504 assert(i<(signed)(sizeof(Color)/sizeof(value_type)));
508 const value_type& operator[](const int i)const
511 assert(i<(signed)(sizeof(Color)/sizeof(value_type)));
515 }; // END of class Color
517 #ifndef USE_HALF_TYPE
518 typedef Color ColorAccumulator;
520 class ColorAccumulator
524 typedef float value_type;
527 value_type a_, r_, g_, b_;
532 operator+=(const ColorAccumulator &rhs)
542 operator-=(const ColorAccumulator &rhs)
552 operator*=(const float &rhs)
562 operator/=(const float &rhs)
564 const float temp(value_type(1)/rhs);
573 operator+(const ColorAccumulator &rhs)const
574 { return Color(*this)+=rhs; }
577 operator-(const ColorAccumulator &rhs)const
578 { return Color(*this)-=rhs; }
581 operator*(const float &rhs)const
582 { return Color(*this)*=rhs; }
585 operator/(const float &rhs)const
586 { return Color(*this)/=rhs; }
589 operator==(const ColorAccumulator &rhs)const
590 { return r_==rhs.r_ && g_==rhs.g_ && b_==rhs.b_ && a_!=rhs.a_; }
593 operator!=(const ColorAccumulator &rhs)const
594 { return r_!=rhs.r_ || g_!=rhs.g_ || b_!=rhs.b_ || a_!=rhs.a_; }
598 { return ColorAccumulator(-r_,-g_,-b_,-a_); }
601 { return !isnan(r_) && !isnan(g_) && !isnan(b_) && !isnan(a_); }
604 ColorAccumulator() { }
609 ** \param A Opacity(alpha) */
610 ColorAccumulator(const value_type& R, const value_type& G, const value_type& B, const value_type& A=1):
617 ColorAccumulator(const ColorAccumulator& c):
624 ColorAccumulator(const Color& c):
630 //! Returns the RED component
631 const value_type& get_r()const { return r_; }
633 //! Returns the GREEN component
634 const value_type& get_g()const { return g_; }
636 //! Returns the BLUE component
637 const value_type& get_b()const { return b_; }
639 //! Returns the amount of opacity (alpha)
640 const value_type& get_a()const { return a_; }
642 //! Synonym for get_a(). \see get_a()
643 const value_type& get_alpha()const { return get_a(); }
645 //! Sets the RED component to \a x
646 ColorAccumulator& set_r(const value_type& x) { r_ = x; return *this; }
648 //! Sets the GREEN component to \a x
649 ColorAccumulator& set_g(const value_type& x) { g_ = x; return *this; }
651 //! Sets the BLUE component to \a x
652 ColorAccumulator& set_b(const value_type& x) { b_ = x; return *this; }
654 //! Sets the opacity (alpha) to \a x
655 ColorAccumulator& set_a(const value_type& x) { a_ = x; return *this; }
657 //! Synonym for set_a(). \see set_a()
658 ColorAccumulator& set_alpha(const value_type& x) { return set_a(x); }
662 Color::Color(const ColorAccumulator& c):
676 /* Bit Descriptions (ON/OFF)
677 ** ----+-------------
678 ** 0 Color Channels (Gray/RGB)
679 ** 1 Alpha Channel (WITH/WITHOUT)
680 ** 2 ZDepth (WITH/WITHOUT)
681 ** 3 Endian (BGR/RGB)
682 ** 4 Alpha Location (Start/End)
683 ** 5 ZDepth Location (Start/End)
684 ** 6 Alpha/ZDepth Arangement (ZA,AZ)
685 ** 7 Alpha Range (Inverted,Normal)
686 ** 8 Z Range (Inverted,Normal)
689 PF_GRAY=(1<<0), //!< If set, use one grayscale channel. If clear, use three channels for RGB
690 PF_A=(1<<1), //!< If set, include alpha channel
691 PF_Z=(1<<2), //!< If set, include ZDepth channel
692 PF_BGR=(1<<3), //!< If set, reverse the order of the RGB channels
693 PF_A_START=(1<<4), //!< If set, alpha channel is before the color data. If clear, it is after.
694 PF_Z_START=(1<<5), //!< If set, ZDepth channel is before the color data. If clear, it is after.
695 PF_ZA=(1<<6), //!< If set, the ZDepth channel will be infront of the alpha channel. If clear, they are reversed.
697 PF_A_INV=(1<<7), //!< If set, the alpha channel is stored as 1.0-a
698 PF_Z_INV=(1<<8), //!< If set, the ZDepth channel is stored as 1.0-z
699 PF_RAW_COLOR=(1<<9)+(1<<1) //!< If set, the data represents a raw Color datastructure, and all other bits are ignored.
702 inline PixelFormat operator|(PixelFormat lhs, PixelFormat rhs)
703 { return static_cast<PixelFormat>((int)lhs|(int)rhs); }
705 inline PixelFormat operator&(PixelFormat lhs, PixelFormat rhs)
706 { return static_cast<PixelFormat>((int)lhs&(int)rhs); }
707 #define FLAGS(x,y) (((x)&(y))==(y))
709 //! Returns the number of channels that the given PixelFormat calls for
711 channels(PixelFormat x)
722 if(FLAGS(x,PF_RAW_COLOR))
728 inline unsigned char *
729 Color2PixelFormat(const Color &color, const PixelFormat &pf, unsigned char *out, const Gamma &gamma)
731 if(FLAGS(pf,PF_RAW_COLOR))
733 Color *outcol=reinterpret_cast<Color *>(out);
739 int alpha=(int)((FLAGS(pf,PF_A_INV)?(-(float)color.get_a()+1):(float)color.get_a())*255);
741 if(alpha>255)alpha=255;
743 if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
745 if(FLAGS(pf,PF_Z_START))
746 *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
747 if(FLAGS(pf,PF_A_START))
748 *out++=static_cast<unsigned char>(alpha);
752 if(FLAGS(pf,PF_A_START))
753 *out++=static_cast<unsigned char>(alpha);
754 if(FLAGS(pf,PF_Z_START))
755 *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
759 if(FLAGS(pf,PF_GRAY))
760 *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_y()));
765 *out++=static_cast<unsigned char>(gamma.r_F32_to_U8(color.get_b()));
766 *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_g()));
767 *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_r()));
771 *out++=static_cast<unsigned char>(gamma.r_F32_to_U8(color.get_r()));
772 *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_g()));
773 *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_b()));
779 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
780 out++;//*out++=(unsigned char)(color.GetZ()*255.0f);
781 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
782 *out++=static_cast<unsigned char>(alpha);
786 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
787 out++;//*out++=(unsigned char)(color.GetZ()*255.0f);
788 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
789 *out++=static_cast<unsigned char>(alpha);
795 convert_color_format(unsigned char *dest, const Color *src, int w, PixelFormat pf,const Gamma &gamma)
799 dest=Color2PixelFormat((*(src++)).clamped(),pf,dest,gamma);
802 inline const unsigned char *
803 PixelFormat2Color(Color &color, const PixelFormat &pf,const unsigned char *out)
805 if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
807 if(FLAGS(pf,PF_Z_START))
808 out++;//color.SetZ((Color::value_type)*out++/255.0f);
809 if(FLAGS(pf,PF_A_START))
810 color.set_a((float)*out++/255);
814 if(FLAGS(pf,PF_A_START))
815 color.set_a((float)*out++/255);
816 if(FLAGS(pf,PF_Z_START))
817 out++;//color.SetZ((Color::value_type)*out++/255.0f);
820 if(FLAGS(pf,PF_GRAY))
821 color.set_yuv((float)*out++/255,0,0);
826 color.set_b((float)*out++/255);
827 color.set_g((float)*out++/255);
828 color.set_r((float)*out++/255);
832 color.set_r((float)*out++/255);
833 color.set_g((float)*out++/255);
834 color.set_b((float)*out++/255);
840 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
841 out++;//color.SetZ((Color::value_type)*out++/255.0f);
842 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
843 color.set_a((float)*out++/255);
847 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
848 color.set_a((float)*out++/255);
849 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
850 out++;//color.SetZ((Color::value_type)*out++/255.0f);
857 }; // END of namespace sinfg
859 /* === E N D =============================================================== */