Fix bugs in previous commit that caused FTBFS in synfig and ETL FTBFS with older...
[synfig.git] / synfig-core / tags / synfig_0_61_07_rc2 / src / synfig / color.h
1 /* === S Y N F I G ========================================================= */
2 /*!     \file color.h
3 **      \brief Color Class Implementation
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007 Chris Moore
10 **
11 **      This package is free software; you can redistribute it and/or
12 **      modify it under the terms of the GNU General Public License as
13 **      published by the Free Software Foundation; either version 2 of
14 **      the License, or (at your option) any later version.
15 **
16 **      This package is distributed in the hope that it will be useful,
17 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **      General Public License for more details.
20 **      \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === S T A R T =========================================================== */
25
26 #ifndef __SYNFIG_COLOR_H
27 #define __SYNFIG_COLOR_H
28
29 /* === H E A D E R S ======================================================= */
30
31
32 //#include <cmath>
33 #include <math.h>
34 #include <cassert>
35 #include "gamma.h"
36 #include <synfig/string.h>
37
38 #ifdef USE_HALF_TYPE
39 #include <OpenEXR/half.h>
40 #endif
41
42 #ifndef SYNFIG_NO_ANGLE
43 # include "angle.h"
44 #endif
45
46 /* === M A C R O S ========================================================= */
47
48 #define use_colorspace_gamma()  App::use_colorspace_gamma
49 #define colorspace_gamma()              (2.2f)
50 #define gamma_in(x)                             ((x>=0) ? pow((float)x,1.0f/colorspace_gamma()) : -pow((float)-x,1.0f/colorspace_gamma()))
51 #define gamma_out(x)                    ((x>=0) ? pow((float)x,     colorspace_gamma()) : -pow((float)-x,     colorspace_gamma()))
52
53 #ifdef WIN32
54 #include <float.h>
55 #ifndef isnan
56 extern "C" { int _isnan(double x); }
57 #define isnan _isnan
58 #endif
59 #endif
60
61 // For some reason isnan() isn't working on macosx any more.
62 // This is a quick fix.
63 #if defined(__APPLE__) && !defined(SYNFIG_ISNAN_FIX)
64 #ifdef isnan
65 #undef isnan
66 #endif
67 inline bool isnan(double x) { return x != x; }
68 inline bool isnan(float x) { return x != x; }
69 #define SYNFIG_ISNAN_FIX 1
70 #endif
71
72 namespace synfig {
73
74 #ifdef USE_HALF_TYPE
75 typedef half ColorReal;
76 #else
77 typedef float ColorReal;
78 #endif
79
80 static const float EncodeYUV[3][3]=
81 {
82         { 0.299f, 0.587f, 0.114f },
83         { -0.168736f, -0.331264f, 0.5f },
84         { 0.5f, -0.418688f, -0.081312f }
85 };
86
87 static const float DecodeYUV[3][3]=
88 {
89         { 1.0f, 0.0f, 1.402f },
90         { 1.0f, -0.344136f, -0.714136f },
91         { 1.0f, 1.772f, 0.0f }
92 };
93
94 /* === T Y P E D E F S ===================================================== */
95
96 /* === C L A S S E S & S T R U C T S ======================================= */
97
98 #ifdef USE_HALF_TYPE
99 class ColorAccumulator;
100 #endif
101
102
103
104
105 /*!     \class Color
106 **      \todo Writeme
107 **      Future optimizations: lookup table for sqrt()?
108 */
109 class Color
110 {
111 public:
112         typedef ColorReal value_type;
113
114 private:
115         value_type a_, r_, g_, b_;
116
117 public:
118
119         const String get_string(void)const;
120
121         Color &
122         operator+=(const Color &rhs)
123         {
124                 r_+=rhs.r_;
125                 g_+=rhs.g_;
126                 b_+=rhs.b_;
127                 a_+=rhs.a_;
128                 return *this;
129         }
130
131         Color &
132         operator-=(const Color &rhs)
133         {
134                 r_-=rhs.r_;
135                 g_-=rhs.g_;
136                 b_-=rhs.b_;
137                 a_-=rhs.a_;
138                 return *this;
139         }
140
141         Color &
142         operator*=(const float &rhs)
143         {
144                 r_*=rhs;
145                 g_*=rhs;
146                 b_*=rhs;
147                 a_*=rhs;
148                 return *this;
149         }
150
151         Color &
152         operator/=(const float &rhs)
153         {
154                 const float temp(value_type(1)/rhs);
155                 r_*=temp;
156                 g_*=temp;
157                 b_*=temp;
158                 a_*=temp;
159                 return *this;
160         }
161
162         Color
163         operator+(const Color &rhs)const
164         { return Color(*this)+=rhs; }
165
166         Color
167         operator-(const Color &rhs)const
168         { return Color(*this)-=rhs; }
169
170         Color
171         operator*(const float &rhs)const
172         { return Color(*this)*=rhs; }
173
174         Color
175         operator/(const float &rhs)const
176         { return Color(*this)/=rhs; }
177
178         bool
179         operator==(const Color &rhs)const
180         { return r_==rhs.r_ && g_==rhs.g_ && b_==rhs.b_ && a_==rhs.a_; }
181
182         bool
183         operator!=(const Color &rhs)const
184         { return r_!=rhs.r_ || g_!=rhs.g_ || b_!=rhs.b_ || a_!=rhs.a_; }
185
186         Color
187         operator-()const
188         { return Color(-r_,-g_,-b_,-a_); }
189
190         //! Effectively 1.0-color
191         Color
192         operator~()const
193         { return Color(1.0f-r_,1.0f-g_,1.0f-b_,a_); }
194
195         bool is_valid()const
196         { return !isnan(r_) && !isnan(g_) && !isnan(b_) && !isnan(a_); }
197
198         Color premult_alpha() const
199         {
200                 return Color (r_*a_, g_*a_, b_*a_, a_);
201         }
202
203         Color demult_alpha() const
204         {
205                 if(a_)
206                 {
207                         const value_type inva = 1/a_;
208                         return Color (r_*inva, g_*inva, b_*inva, a_);
209                 }else return alpha();
210         }
211
212 public:
213         // ETL/trunk/ETL/_gaussian.h does:
214         //   SR1=SR2=SR3=typename T::value_type();
215         // and expects that to give it initialised colors
216         // Otherwise the 'gaussian' blur type is random.
217         Color() :a_(0), r_(0), g_(0), b_(0) { }
218         Color(const value_type &f) :a_(f),r_(f), g_(f), b_(f) { }
219         Color(int f) :a_(f),r_(f), g_(f), b_(f) { }
220
221         /*!     \param R Red
222         **      \param G Green
223         **      \param B Blue
224         **      \param A Opacity(alpha) */
225         Color(const value_type& R, const value_type& G, const value_type& B, const value_type& A=1):
226                 a_(A),
227                 r_(R),
228                 g_(G),
229                 b_(B) { }
230
231         /*!     \param c Source for color components
232         **      \param A Opacity(alpha) */
233         Color(const Color& c, const value_type& A):
234                 a_(A),
235                 r_(c.r_),
236                 g_(c.g_),
237                 b_(c.b_) { }
238
239
240         //!     Copy constructor
241         Color(const Color& c):
242                 a_(c.a_),
243                 r_(c.r_),
244                 g_(c.g_),
245                 b_(c.b_) { }
246
247 #ifdef USE_HALF_TYPE
248         friend class ColorAccumulator;
249         //!     Convert constructor
250         Color(const ColorAccumulator& c);
251 #endif
252
253         //!     Copy constructor
254         //Color(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); }
255
256         /*const Color &operator=(const value_type &i)
257         {
258                 r_ = g_ = b_ = a_ = i;
259                 return *this;
260         }*/
261         //Color& operator=(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); return *this; }
262
263         //! Returns the RED component
264         const value_type& get_r()const { return r_; }
265
266         //! Returns the GREEN component
267         const value_type& get_g()const { return g_; }
268
269         //! Returns the BLUE component
270         const value_type& get_b()const { return b_; }
271
272         //! Returns the amount of opacity (alpha)
273         const value_type& get_a()const { return a_; }
274
275         //! Synonym for get_a(). \see get_a()
276         const value_type& get_alpha()const { return get_a(); }
277
278         //! Converts a 2 character hex string \a s (00-ff) into a ColorReal (0.0-1.0)
279         static ColorReal hex2real(String s);
280
281         //! Converts a ColorReal \a c (0.0-1.0) into a 2 character hex string (00-ff)
282         static const String real2hex(ColorReal c);
283
284         //! Returns the color as a 6 character hex sting
285         const String get_hex()const { return String(real2hex(r_)+real2hex(g_)+real2hex(b_)); }
286
287         //! Sets the color's R, G, and B from a 3 or 6 character hex string
288         void set_hex(String& hex);
289
290         //! Sets the RED component to \a x
291         Color& set_r(const value_type& x) { r_ = x; return *this; }
292
293         //! Sets the GREEN component to \a x
294         Color& set_g(const value_type& x) { g_ = x; return *this; }
295
296         //! Sets the BLUE component to \a x
297         Color& set_b(const value_type& x) { b_ = x; return *this; }
298
299         //! Sets the opacity (alpha) to \a x
300         Color& set_a(const value_type& x) { a_ = x; return *this; }
301
302         //! Synonym for set_a(). \see set_a()
303         Color& set_alpha(const value_type& x) { return set_a(x); }
304
305         //! Returns color's luminance
306         float
307         get_y() const
308         {
309                 return
310                         (float)get_r()*EncodeYUV[0][0]+
311                         (float)get_g()*EncodeYUV[0][1]+
312                         (float)get_b()*EncodeYUV[0][2];
313         }
314
315
316         //! Returns U component of chromanance
317         float
318         get_u() const
319         {
320                 return
321                         (float)get_r()*EncodeYUV[1][0]+
322                         (float)get_g()*EncodeYUV[1][1]+
323                         (float)get_b()*EncodeYUV[1][2];
324         }
325
326
327         //! Returns V component of chromanance
328         float
329         get_v() const
330         {
331                 return
332                         (float)get_r()*EncodeYUV[2][0]+
333                         (float)get_g()*EncodeYUV[2][1]+
334                         (float)get_b()*EncodeYUV[2][2];
335         }
336
337         //! Returns the color's saturation
338         /*!     This is is the magnitude of the U and V components.
339         **      \see set_s() */
340         float
341         get_s() const
342         {
343                 const float u(get_u()), v(get_v());
344                 return sqrt(u*u+v*v);
345         }
346
347         //! Sets the luminance (\a y) and chromanance (\a u and \a v)
348         Color&
349         set_yuv(const float &y, const float &u, const float &v)
350         {
351                 set_r(y*DecodeYUV[0][0]+u*DecodeYUV[0][1]+v*DecodeYUV[0][2]);
352                 set_g(y*DecodeYUV[1][0]+u*DecodeYUV[1][1]+v*DecodeYUV[1][2]);
353                 set_b(y*DecodeYUV[2][0]+u*DecodeYUV[2][1]+v*DecodeYUV[2][2]);
354                 return *this;
355         }
356
357         //! Sets color luminance
358         Color& set_y(const float &y) { return set_yuv(y,get_u(),get_v()); }
359
360         //! Set U component of chromanance
361         Color& set_u(const float &u) { return set_yuv(get_y(),u,get_v()); }
362
363         //! Set V component of chromanance
364         Color& set_v(const float &v) { return set_yuv(get_y(),get_u(),v); }
365
366         //! Set the U and V components of chromanance
367         Color& set_uv(const float& u, const float& v) { return set_yuv(get_y(),u,v); }
368
369         //! Sets the color's saturation
370         /*!     \see get_s() */
371         Color&
372         set_s(const float &x)
373         {
374                 float u(get_u()), v(get_v());
375                 const float s(sqrt(u*u+v*v));
376                 if(s)
377                 {
378                         u=(u/s)*x;
379                         v=(v/s)*x;
380                         return set_uv(u,v);
381                 }
382                 return *this;
383         }
384
385         //! YUV Color constructor
386         static Color YUV(const float& y, const float& u, const float& v, const value_type& a=1)
387                 { return Color().set_yuv(y,u,v).set_a(a); }
388
389 #ifndef SYNFIG_NO_ANGLE
390         //! Returns the hue of the chromanance
391         /*!     This is the angle of the U and V components.
392         **      \see set_hue() */
393         Angle
394         get_hue() const
395                 { return Angle::tan(get_u(),get_v()); }
396
397         //! Synonym for get_hue(). \see get_hue()
398         Angle get_uv_angle() const { return get_hue(); }
399
400         //! Sets the color's hue
401         /*!     \see get_hue() */
402         Color&
403         set_hue(const Angle& theta)
404         {
405                 const float s(get_s());
406                 const float
407                         u(s*(float)Angle::sin(theta).get()),
408                         v(s*(float)Angle::cos(theta).get());
409                 return set_uv(u,v);
410         }
411
412         //! Synonym for set_hue(). \see set_hue()
413         Color& set_uv_angle(const Angle& theta) { return set_hue(theta); }
414
415         //! Rotates the chromanance vector by amount specified by \a theta
416         Color& rotate_uv(const Angle& theta)
417         {
418                 const float     a(Angle::sin(theta).get()),     b(Angle::cos(theta).get());
419                 const float     u(get_u()),     v(get_v());
420
421                 return set_uv(b*u-a*v,a*u+b*v);
422         }
423
424         //! Sets the luminance (\a y) and chromanance (\a s and \a theta).
425         /*!     \param y Luminance
426         **      \param s Saturation
427         **      \param theta Hue */
428         Color& set_yuv(const float& y, const float& s, const Angle& theta)
429         {
430                 return
431                         set_yuv(
432                                 y,
433                                 s*(float)Angle::sin(theta).get(),
434                                 s*(float)Angle::cos(theta).get()
435                         );
436         }
437
438         //! YUV color constructor where the chroma is in the saturation/hue form.
439         /*!     \param y Luminance
440         **      \param s Saturation
441         **      \param theta Hue
442         **      \param a Opacity (alpha) */
443         static Color YUV(const float& y, const float& s, const Angle& theta, const value_type& a=1)
444                 { return Color().set_yuv(y,s,theta).set_a(a); }
445
446 #endif
447
448         //! Clamps a color so that its values are in range. Ignores attempting to visualize negative colors.
449         Color clamped()const;
450
451         //! Clamps a color so that its values are in range.
452         Color clamped_negative()const;
453
454         /* Preset Colors */
455
456         //! Preset Color Constructors
457         //@{
458 #ifdef HAS_VIMAGE
459         static inline Color alpha() { return Color(0,0,0,0.0000001f); }
460 #else
461         static inline Color alpha() { return Color(0,0,0,0); }
462 #endif
463         static inline Color black() { return Color(0,0,0); }
464         static inline Color white() { return Color(1,1,1); }
465         static inline Color gray() { return Color(0.5f,0.5f,0.5f); }
466         static inline Color magenta() { return Color(1,0,1); }
467         static inline Color red() { return Color(1,0,0); }
468         static inline Color green() { return Color(0,1,0); }
469         static inline Color blue() { return Color(0,0,1); }
470         static inline Color cyan() { return Color(0,1,1); }
471         static inline Color yellow() { return Color(1,1,0); }
472         //@}
473
474         //! \writeme
475         enum BlendMethod
476         {
477                 BLEND_COMPOSITE=0,                      //!< Color A is composited onto B (Taking A's alpha into account)
478                 BLEND_STRAIGHT=1,                       //!< Straight linear interpolation from A->B (Alpha ignored)
479                 BLEND_ONTO=13,                          //!< Similar to BLEND_COMPOSITE, except that B's alpha is maintained
480                 BLEND_STRAIGHT_ONTO=21,         //!< <deprecated> \writeme
481                 BLEND_BEHIND=12,                        //!< Similar to BLEND_COMPOSITE, except that B is composited onto A.
482                 BLEND_SCREEN=16,                        //!< \writeme
483                 BLEND_OVERLAY=20,                       //!< \writeme
484                 BLEND_HARD_LIGHT=17,            //!< \writeme
485                 BLEND_MULTIPLY=6,                       //!< Simple A*B.
486                 BLEND_DIVIDE=7,                         //!< Simple B/A
487                 BLEND_ADD=4,                            //!< Simple A+B.
488                 BLEND_SUBTRACT=5,                       //!< Simple A-B.
489                 BLEND_DIFFERENCE=18,            //!< Simple |A-B|.
490                 BLEND_BRIGHTEN=2,                       //!< If composite is brighter than B, use composite. B otherwise.
491                 BLEND_DARKEN=3,                         //!< If composite is darker than B, use composite. B otherwise.
492                 BLEND_COLOR=8,                          //!< Preserves the U and V channels of color A
493                 BLEND_HUE=9,                            //!< Preserves the angle of the UV vector of color A
494                 BLEND_SATURATION=10,            //!< Preserves the magnitude of the UV Vector of color A
495                 BLEND_LUMINANCE=11,                     //!< Preserves the Y channel of color A
496
497                 BLEND_ALPHA_BRIGHTEN=14,        //!< <deprecated> If A is less opaque than B, use A
498                 BLEND_ALPHA_DARKEN=15,          //!< <deprecated> If A is more opaque than B, use B
499                 BLEND_ALPHA_OVER=19,            //!< <deprecated> multiply alphas and then straight blends using the amount
500
501                 BLEND_END=22                            //!< \internal
502         };
503
504         /* Other */
505         static Color blend(Color a, Color b,float amount,BlendMethod type=BLEND_COMPOSITE);
506
507         static bool is_onto(BlendMethod x)
508         {
509                 return x==BLEND_BRIGHTEN
510                         || x==BLEND_DARKEN
511                         || x==BLEND_ADD
512                         || x==BLEND_SUBTRACT
513                         || x==BLEND_MULTIPLY
514                         || x==BLEND_DIVIDE
515                         || x==BLEND_COLOR
516                         || x==BLEND_HUE
517                         || x==BLEND_SATURATION
518                         || x==BLEND_LUMINANCE
519                         || x==BLEND_ONTO
520                         || x==BLEND_STRAIGHT_ONTO
521                         || x==BLEND_SCREEN
522                         || x==BLEND_OVERLAY
523                         || x==BLEND_DIFFERENCE
524                         || x==BLEND_HARD_LIGHT
525                 ;
526         }
527 /*protected:
528
529         value_type& operator[](const int i)
530         {
531                 assert(i>=0);
532                 assert(i<(signed)(sizeof(Color)/sizeof(value_type)));
533                 return (&r_)[i];
534         }
535
536         const value_type& operator[](const int i)const
537         {
538                 assert(i>=0);
539                 assert(i<(signed)(sizeof(Color)/sizeof(value_type)));
540                 return (&r_)[i];
541         }
542 */
543 }; // END of class Color
544
545 #ifndef USE_HALF_TYPE
546 typedef Color ColorAccumulator;
547 #else
548 class ColorAccumulator
549 {
550         friend class Color;
551 public:
552         typedef float value_type;
553
554 private:
555         value_type a_, r_, g_, b_;
556
557 public:
558
559         ColorAccumulator &
560         operator+=(const ColorAccumulator &rhs)
561         {
562                 r_+=rhs.r_;
563                 g_+=rhs.g_;
564                 b_+=rhs.b_;
565                 a_+=rhs.a_;
566                 return *this;
567         }
568
569         ColorAccumulator &
570         operator-=(const ColorAccumulator &rhs)
571         {
572                 r_-=rhs.r_;
573                 g_-=rhs.g_;
574                 b_-=rhs.b_;
575                 a_-=rhs.a_;
576                 return *this;
577         }
578
579         ColorAccumulator &
580         operator*=(const float &rhs)
581         {
582                 r_*=rhs;
583                 g_*=rhs;
584                 b_*=rhs;
585                 a_*=rhs;
586                 return *this;
587         }
588
589         ColorAccumulator &
590         operator/=(const float &rhs)
591         {
592                 const float temp(value_type(1)/rhs);
593                 r_*=temp;
594                 g_*=temp;
595                 b_*=temp;
596                 a_*=temp;
597                 return *this;
598         }
599
600         ColorAccumulator
601         operator+(const ColorAccumulator &rhs)const
602         { return Color(*this)+=rhs; }
603
604         ColorAccumulator
605         operator-(const ColorAccumulator &rhs)const
606         { return Color(*this)-=rhs; }
607
608         ColorAccumulator
609         operator*(const float &rhs)const
610         { return Color(*this)*=rhs; }
611
612         ColorAccumulator
613         operator/(const float &rhs)const
614         { return Color(*this)/=rhs; }
615
616         bool
617         operator==(const ColorAccumulator &rhs)const
618         { return r_==rhs.r_ && g_==rhs.g_ && b_==rhs.b_ && a_!=rhs.a_; }
619
620         bool
621         operator!=(const ColorAccumulator &rhs)const
622         { return r_!=rhs.r_ || g_!=rhs.g_ || b_!=rhs.b_ || a_!=rhs.a_; }
623
624         Color
625         operator-()const
626         { return ColorAccumulator(-r_,-g_,-b_,-a_); }
627
628         bool is_valid()const
629         { return !isnan(r_) && !isnan(g_) && !isnan(b_) && !isnan(a_); }
630
631 public:
632         ColorAccumulator() { }
633
634         /*!     \param R Red
635         **      \param G Green
636         **      \param B Blue
637         **      \param A Opacity(alpha) */
638         ColorAccumulator(const value_type& R, const value_type& G, const value_type& B, const value_type& A=1):
639                 a_(A),
640                 r_(R),
641                 g_(G),
642                 b_(B) { }
643
644         //!     Copy constructor
645         ColorAccumulator(const ColorAccumulator& c):
646                 a_(c.a_),
647                 r_(c.r_),
648                 g_(c.g_),
649                 b_(c.b_) { }
650
651         //!     Converter
652         ColorAccumulator(const Color& c):
653                 a_(c.a_),
654                 r_(c.r_),
655                 g_(c.g_),
656                 b_(c.b_) { }
657
658         //! Converter
659         ColorAccumulator(int c): a_(c),r_(c), g_(c), b_(c) { }
660
661         //! Returns the RED component
662         const value_type& get_r()const { return r_; }
663
664         //! Returns the GREEN component
665         const value_type& get_g()const { return g_; }
666
667         //! Returns the BLUE component
668         const value_type& get_b()const { return b_; }
669
670         //! Returns the amount of opacity (alpha)
671         const value_type& get_a()const { return a_; }
672
673         //! Synonym for get_a(). \see get_a()
674         const value_type& get_alpha()const { return get_a(); }
675
676         //! Sets the RED component to \a x
677         ColorAccumulator& set_r(const value_type& x) { r_ = x; return *this; }
678
679         //! Sets the GREEN component to \a x
680         ColorAccumulator& set_g(const value_type& x) { g_ = x; return *this; }
681
682         //! Sets the BLUE component to \a x
683         ColorAccumulator& set_b(const value_type& x) { b_ = x; return *this; }
684
685         //! Sets the opacity (alpha) to \a x
686         ColorAccumulator& set_a(const value_type& x) { a_ = x; return *this; }
687
688         //! Synonym for set_a(). \see set_a()
689         ColorAccumulator& set_alpha(const value_type& x) { return set_a(x); }
690 };
691
692 inline
693 Color::Color(const ColorAccumulator& c):
694         a_(c.a_),
695         r_(c.r_),
696         g_(c.g_),
697         b_(c.b_) { }
698
699 #endif
700
701
702
703
704
705 enum PixelFormat
706 {
707 /* Bit  Descriptions (ON/OFF)
708 ** ----+-------------
709 ** 0    Color Channels (Gray/RGB)
710 ** 1    Alpha Channel (WITH/WITHOUT)
711 ** 2    ZDepth  (WITH/WITHOUT)
712 ** 3    Endian (BGR/RGB)
713 ** 4    Alpha Location (Start/End)
714 ** 5    ZDepth Location (Start/End)
715 ** 6    Alpha/ZDepth Arangement (ZA,AZ)
716 ** 7    Alpha Range (Inverted,Normal)
717 ** 8    Z Range (Inverted,Normal)
718 */
719         PF_RGB=0,
720         PF_GRAY=(1<<0),                 //!< If set, use one grayscale channel. If clear, use three channels for RGB
721         PF_A=(1<<1),                    //!< If set, include alpha channel
722         PF_Z=(1<<2),                    //!< If set, include ZDepth channel
723         PF_BGR=(1<<3),                  //!< If set, reverse the order of the RGB channels
724         PF_A_START=(1<<4),              //!< If set, alpha channel is before the color data. If clear, it is after.
725         PF_Z_START=(1<<5),              //!< If set, ZDepth channel is before the color data. If clear, it is after.
726         PF_ZA=(1<<6),                   //!< If set, the ZDepth channel will be infront of the alpha channel. If clear, they are reversed.
727
728         PF_A_INV=(1<<7),                //!< If set, the alpha channel is stored as 1.0-a
729         PF_Z_INV=(1<<8),                //!< If set, the ZDepth channel is stored as 1.0-z
730         PF_RAW_COLOR=(1<<9)+(1<<1)      //!< If set, the data represents a raw Color datastructure, and all other bits are ignored.
731 };
732
733 inline PixelFormat operator|(PixelFormat lhs, PixelFormat rhs)
734         { return static_cast<PixelFormat>((int)lhs|(int)rhs); }
735
736 inline PixelFormat operator&(PixelFormat lhs, PixelFormat rhs)
737         { return static_cast<PixelFormat>((int)lhs&(int)rhs); }
738 #define FLAGS(x,y)              (((x)&(y))==(y))
739
740 //! Returns the number of channels that the given PixelFormat calls for
741 inline int
742 channels(PixelFormat x)
743 {
744         int chan=0;
745         if(FLAGS(x,PF_GRAY))
746                 ++chan;
747         else
748                 chan+=3;
749         if(FLAGS(x,PF_A))
750                 ++chan;
751         if(FLAGS(x,PF_Z))
752                 ++chan;
753         if(FLAGS(x,PF_RAW_COLOR))
754                 chan=sizeof(Color);
755
756         return chan;
757 }
758
759 inline unsigned char *
760 Color2PixelFormat(const Color &color, const PixelFormat &pf, unsigned char *out, const Gamma &gamma)
761 {
762         if(FLAGS(pf,PF_RAW_COLOR))
763         {
764                 Color *outcol=reinterpret_cast<Color *>(out);
765                 *outcol=color;
766                 out+=sizeof(color);
767                 return out;
768         }
769
770         int alpha=(int)((FLAGS(pf,PF_A_INV)?(-(float)color.get_a()+1):(float)color.get_a())*255);
771         if(alpha<0)alpha=0;
772         if(alpha>255)alpha=255;
773
774         if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
775         {
776                 if(FLAGS(pf,PF_Z_START))
777                         *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
778                 if(FLAGS(pf,PF_A_START))
779                         *out++=static_cast<unsigned char>(alpha);
780         }
781         else
782         {
783                 if(FLAGS(pf,PF_A_START))
784                         *out++=static_cast<unsigned char>(alpha);
785                 if(FLAGS(pf,PF_Z_START))
786                         *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
787
788         }
789
790         if(FLAGS(pf,PF_GRAY))
791                 *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_y()));
792         else
793         {
794                 if(FLAGS(pf,PF_BGR))
795                 {
796                         *out++=static_cast<unsigned char>(gamma.r_F32_to_U8(color.get_b()));
797                         *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_g()));
798                         *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_r()));
799                 }
800                 else
801                 {
802                         *out++=static_cast<unsigned char>(gamma.r_F32_to_U8(color.get_r()));
803                         *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_g()));
804                         *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_b()));
805                 }
806         }
807
808         if(FLAGS(pf,PF_ZA))
809         {
810                 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
811                         out++;//*out++=(unsigned char)(color.GetZ()*255.0f);
812                 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
813                         *out++=static_cast<unsigned char>(alpha);
814         }
815         else
816         {
817                 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
818                         out++;//*out++=(unsigned char)(color.GetZ()*255.0f);
819                 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
820                         *out++=static_cast<unsigned char>(alpha);
821         }
822         return out;
823 }
824
825 inline void
826 convert_color_format(unsigned char *dest, const Color *src, int w, PixelFormat pf,const Gamma &gamma)
827 {
828         assert(w>=0);
829         while(w--)
830                 dest=Color2PixelFormat((*(src++)).clamped(),pf,dest,gamma);
831 }
832
833 inline const unsigned char *
834 PixelFormat2Color(Color &color, const PixelFormat &pf,const unsigned char *out)
835 {
836         if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
837         {
838                 if(FLAGS(pf,PF_Z_START))
839                         out++;//color.SetZ((Color::value_type)*out++/255.0f);
840                 if(FLAGS(pf,PF_A_START))
841                         color.set_a((float)*out++/255);
842         }
843         else
844         {
845                 if(FLAGS(pf,PF_A_START))
846                         color.set_a((float)*out++/255);
847                 if(FLAGS(pf,PF_Z_START))
848                         out++;//color.SetZ((Color::value_type)*out++/255.0f);
849         }
850
851         if(FLAGS(pf,PF_GRAY))
852                 color.set_yuv((float)*out++/255,0,0);
853         else
854         {
855                 if(FLAGS(pf,PF_BGR))
856                 {
857                         color.set_b((float)*out++/255);
858                         color.set_g((float)*out++/255);
859                         color.set_r((float)*out++/255);
860                 }
861                 else
862                 {
863                         color.set_r((float)*out++/255);
864                         color.set_g((float)*out++/255);
865                         color.set_b((float)*out++/255);
866                 }
867         }
868
869         if(FLAGS(pf,PF_ZA))
870         {
871                 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
872                         out++;//color.SetZ((Color::value_type)*out++/255.0f);
873                 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
874                         color.set_a((float)*out++/255);
875         }
876         else
877         {
878                 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
879                         color.set_a((float)*out++/255);
880                 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
881                         out++;//color.SetZ((Color::value_type)*out++/255.0f);
882         }
883         return out;
884 }
885
886
887
888 }; // END of namespace synfig
889
890 /* === E N D =============================================================== */
891
892 #endif