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