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