Move the gamma_in and gamma_out macros into "color.h".
[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         Color() /*:r_(0), g_(0), b_(0), a_(0)*/ { }
213         Color(const value_type &f) :a_(f),r_(f), g_(f), b_(f) { }
214         Color(int f) :a_(f),r_(f), g_(f), b_(f) { }
215
216         /*!     \param R Red
217         **      \param G Green
218         **      \param B Blue
219         **      \param A Opacity(alpha) */
220         Color(const value_type& R, const value_type& G, const value_type& B, const value_type& A=1):
221                 a_(A),
222                 r_(R),
223                 g_(G),
224                 b_(B) { }
225
226         /*!     \param c Source for color components
227         **      \param A Opacity(alpha) */
228         Color(const Color& c, const value_type& A):
229                 a_(A),
230                 r_(c.r_),
231                 g_(c.g_),
232                 b_(c.b_) { }
233
234
235         //!     Copy constructor
236         Color(const Color& c):
237                 a_(c.a_),
238                 r_(c.r_),
239                 g_(c.g_),
240                 b_(c.b_) { }
241
242 #ifdef USE_HALF_TYPE
243         friend class ColorAccumulator;
244         //!     Convert constructor
245         Color(const ColorAccumulator& c);
246 #endif
247
248         //!     Copy constructor
249         //Color(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); }
250
251         /*const Color &operator=(const value_type &i)
252         {
253                 r_ = g_ = b_ = a_ = i;
254                 return *this;
255         }*/
256         //Color& operator=(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); return *this; }
257
258         //! Returns the RED component
259         const value_type& get_r()const { return r_; }
260
261         //! Returns the GREEN component
262         const value_type& get_g()const { return g_; }
263
264         //! Returns the BLUE component
265         const value_type& get_b()const { return b_; }
266
267         //! Returns the amount of opacity (alpha)
268         const value_type& get_a()const { return a_; }
269
270         //! Synonym for get_a(). \see get_a()
271         const value_type& get_alpha()const { return get_a(); }
272
273         //! Converts a 2 character hex string \a s (00-ff) into a ColorReal (0.0-1.0)
274         static ColorReal hex2real(String s);
275
276         //! Converts a ColorReal \a c (0.0-1.0) into a 2 character hex string (00-ff)
277         static const String real2hex(ColorReal c);
278
279         //! Returns the color as a 6 character hex sting
280         const String get_hex()const { return String(real2hex(r_)+real2hex(g_)+real2hex(b_)); }
281
282         //! Sets the color's R, G, and B from a 3 or 6 character hex string
283         void set_hex(String& hex);
284
285         //! Sets the RED component to \a x
286         Color& set_r(const value_type& x) { r_ = x; return *this; }
287
288         //! Sets the GREEN component to \a x
289         Color& set_g(const value_type& x) { g_ = x; return *this; }
290
291         //! Sets the BLUE component to \a x
292         Color& set_b(const value_type& x) { b_ = x; return *this; }
293
294         //! Sets the opacity (alpha) to \a x
295         Color& set_a(const value_type& x) { a_ = x; return *this; }
296
297         //! Synonym for set_a(). \see set_a()
298         Color& set_alpha(const value_type& x) { return set_a(x); }
299
300         //! Returns color's luminance
301         float
302         get_y() const
303         {
304                 return
305                         (float)get_r()*EncodeYUV[0][0]+
306                         (float)get_g()*EncodeYUV[0][1]+
307                         (float)get_b()*EncodeYUV[0][2];
308         }
309
310
311         //! Returns U component of chromanance
312         float
313         get_u() const
314         {
315                 return
316                         (float)get_r()*EncodeYUV[1][0]+
317                         (float)get_g()*EncodeYUV[1][1]+
318                         (float)get_b()*EncodeYUV[1][2];
319         }
320
321
322         //! Returns V component of chromanance
323         float
324         get_v() const
325         {
326                 return
327                         (float)get_r()*EncodeYUV[2][0]+
328                         (float)get_g()*EncodeYUV[2][1]+
329                         (float)get_b()*EncodeYUV[2][2];
330         }
331
332         //! Returns the color's saturation
333         /*!     This is is the magnitude of the U and V components.
334         **      \see set_s() */
335         float
336         get_s() const
337         {
338                 const float u(get_u()), v(get_v());
339                 return sqrt(u*u+v*v);
340         }
341
342         //! Sets the luminance (\a y) and chromanance (\a u and \a v)
343         Color&
344         set_yuv(const float &y, const float &u, const float &v)
345         {
346                 set_r(y*DecodeYUV[0][0]+u*DecodeYUV[0][1]+v*DecodeYUV[0][2]);
347                 set_g(y*DecodeYUV[1][0]+u*DecodeYUV[1][1]+v*DecodeYUV[1][2]);
348                 set_b(y*DecodeYUV[2][0]+u*DecodeYUV[2][1]+v*DecodeYUV[2][2]);
349                 return *this;
350         }
351
352         //! Sets color luminance
353         Color& set_y(const float &y) { return set_yuv(y,get_u(),get_v()); }
354
355         //! Set U component of chromanance
356         Color& set_u(const float &u) { return set_yuv(get_y(),u,get_v()); }
357
358         //! Set V component of chromanance
359         Color& set_v(const float &v) { return set_yuv(get_y(),get_u(),v); }
360
361         //! Set the U and V components of chromanance
362         Color& set_uv(const float& u, const float& v) { return set_yuv(get_y(),u,v); }
363
364         //! Sets the color's saturation
365         /*!     \see get_s() */
366         Color&
367         set_s(const float &x)
368         {
369                 float u(get_u()), v(get_v());
370                 const float s(sqrt(u*u+v*v));
371                 if(s)
372                 {
373                         u=(u/s)*x;
374                         v=(v/s)*x;
375                         return set_uv(u,v);
376                 }
377                 return *this;
378         }
379
380         //! YUV Color constructor
381         static Color YUV(const float& y, const float& u, const float& v, const value_type& a=1)
382                 { return Color().set_yuv(y,u,v).set_a(a); }
383
384 #ifndef SYNFIG_NO_ANGLE
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 #endif
442
443         //! Clamps a color so that its values are in range. Ignores attempting to visualize negative colors.
444         Color clamped()const;
445
446         //! Clamps a color so that its values are in range.
447         Color clamped_negative()const;
448
449         /* Preset Colors */
450
451         //! Preset Color Constructors
452         //@{
453 #ifdef HAS_VIMAGE
454         static inline Color alpha() { return Color(0,0,0,0.0000001f); }
455 #else
456         static inline Color alpha() { return Color(0,0,0,0); }
457 #endif
458         static inline Color black() { return Color(0,0,0); }
459         static inline Color white() { return Color(1,1,1); }
460         static inline Color gray() { return Color(0.5f,0.5f,0.5f); }
461         static inline Color magenta() { return Color(1,0,1); }
462         static inline Color red() { return Color(1,0,0); }
463         static inline Color green() { return Color(0,1,0); }
464         static inline Color blue() { return Color(0,0,1); }
465         static inline Color cyan() { return Color(0,1,1); }
466         static inline Color yellow() { return Color(1,1,0); }
467         //@}
468
469         //! \writeme
470         enum BlendMethod
471         {
472                 BLEND_COMPOSITE=0,                      //!< Color A is composited onto B (Taking A's alpha into account)
473                 BLEND_STRAIGHT=1,                       //!< Straight linear interpolation from A->B (Alpha ignored)
474                 BLEND_ONTO=13,                          //!< Similar to BLEND_COMPOSITE, except that B's alpha is maintained
475                 BLEND_STRAIGHT_ONTO=21,         //!< <deprecated> \writeme
476                 BLEND_BEHIND=12,                        //!< Similar to BLEND_COMPOSITE, except that B is composited onto A.
477                 BLEND_SCREEN=16,                        //!< \writeme
478                 BLEND_OVERLAY=20,                       //!< \writeme
479                 BLEND_HARD_LIGHT=17,            //!< \writeme
480                 BLEND_MULTIPLY=6,                       //!< Simple A*B.
481                 BLEND_DIVIDE=7,                         //!< Simple B/A
482                 BLEND_ADD=4,                            //!< Simple A+B.
483                 BLEND_SUBTRACT=5,                       //!< Simple A-B.
484                 BLEND_DIFFERENCE=18,            //!< Simple |A-B|.
485                 BLEND_BRIGHTEN=2,                       //!< If composite is brighter than B, use composite. B otherwise.
486                 BLEND_DARKEN=3,                         //!< If composite is darker than B, use composite. B otherwise.
487                 BLEND_COLOR=8,                          //!< Preserves the U and V channels of color A
488                 BLEND_HUE=9,                            //!< Preserves the angle of the UV vector of color A
489                 BLEND_SATURATION=10,            //!< Preserves the magnitude of the UV Vector of color A
490                 BLEND_LUMINANCE=11,                     //!< Preserves the Y channel of color A
491
492                 BLEND_ALPHA_BRIGHTEN=14,        //!< <deprecated> If A is less opaque than B, use A
493                 BLEND_ALPHA_DARKEN=15,          //!< <deprecated> If A is more opaque than B, use B
494                 BLEND_ALPHA_OVER=19,            //!< <deprecated> multiply alphas and then straight blends using the amount
495
496                 BLEND_END=22                            //!< \internal
497         };
498
499         /* Other */
500         static Color blend(Color a, Color b,float amount,BlendMethod type=BLEND_COMPOSITE);
501
502         static bool is_onto(BlendMethod x)
503         {
504                 return x==BLEND_BRIGHTEN
505                         || x==BLEND_DARKEN
506                         || x==BLEND_ADD
507                         || x==BLEND_SUBTRACT
508                         || x==BLEND_MULTIPLY
509                         || x==BLEND_DIVIDE
510                         || x==BLEND_COLOR
511                         || x==BLEND_HUE
512                         || x==BLEND_SATURATION
513                         || x==BLEND_LUMINANCE
514                         || x==BLEND_ONTO
515                         || x==BLEND_STRAIGHT_ONTO
516                         || x==BLEND_SCREEN
517                         || x==BLEND_OVERLAY
518                         || x==BLEND_DIFFERENCE
519                         || x==BLEND_HARD_LIGHT
520                 ;
521         }
522 /*protected:
523
524         value_type& operator[](const int i)
525         {
526                 assert(i>=0);
527                 assert(i<(signed)(sizeof(Color)/sizeof(value_type)));
528                 return (&r_)[i];
529         }
530
531         const value_type& operator[](const int i)const
532         {
533                 assert(i>=0);
534                 assert(i<(signed)(sizeof(Color)/sizeof(value_type)));
535                 return (&r_)[i];
536         }
537 */
538 }; // END of class Color
539
540 #ifndef USE_HALF_TYPE
541 typedef Color ColorAccumulator;
542 #else
543 class ColorAccumulator
544 {
545         friend class Color;
546 public:
547         typedef float value_type;
548
549 private:
550         value_type a_, r_, g_, b_;
551
552 public:
553
554         ColorAccumulator &
555         operator+=(const ColorAccumulator &rhs)
556         {
557                 r_+=rhs.r_;
558                 g_+=rhs.g_;
559                 b_+=rhs.b_;
560                 a_+=rhs.a_;
561                 return *this;
562         }
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 float &rhs)
576         {
577                 r_*=rhs;
578                 g_*=rhs;
579                 b_*=rhs;
580                 a_*=rhs;
581                 return *this;
582         }
583
584         ColorAccumulator &
585         operator/=(const float &rhs)
586         {
587                 const float temp(value_type(1)/rhs);
588                 r_*=temp;
589                 g_*=temp;
590                 b_*=temp;
591                 a_*=temp;
592                 return *this;
593         }
594
595         ColorAccumulator
596         operator+(const ColorAccumulator &rhs)const
597         { return Color(*this)+=rhs; }
598
599         ColorAccumulator
600         operator-(const ColorAccumulator &rhs)const
601         { return Color(*this)-=rhs; }
602
603         ColorAccumulator
604         operator*(const float &rhs)const
605         { return Color(*this)*=rhs; }
606
607         ColorAccumulator
608         operator/(const float &rhs)const
609         { return Color(*this)/=rhs; }
610
611         bool
612         operator==(const ColorAccumulator &rhs)const
613         { return r_==rhs.r_ && g_==rhs.g_ && b_==rhs.b_ && a_!=rhs.a_; }
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         Color
620         operator-()const
621         { return ColorAccumulator(-r_,-g_,-b_,-a_); }
622
623         bool is_valid()const
624         { return !isnan(r_) && !isnan(g_) && !isnan(b_) && !isnan(a_); }
625
626 public:
627         ColorAccumulator() { }
628
629         /*!     \param R Red
630         **      \param G Green
631         **      \param B Blue
632         **      \param A Opacity(alpha) */
633         ColorAccumulator(const value_type& R, const value_type& G, const value_type& B, const value_type& A=1):
634                 a_(A),
635                 r_(R),
636                 g_(G),
637                 b_(B) { }
638
639         //!     Copy constructor
640         ColorAccumulator(const ColorAccumulator& c):
641                 a_(c.a_),
642                 r_(c.r_),
643                 g_(c.g_),
644                 b_(c.b_) { }
645
646         //!     Converter
647         ColorAccumulator(const Color& c):
648                 a_(c.a_),
649                 r_(c.r_),
650                 g_(c.g_),
651                 b_(c.b_) { }
652
653         //! Converter
654         ColorAccumulator(int c): a_(c),r_(c), g_(c), b_(c) { }
655
656         //! Returns the RED component
657         const value_type& get_r()const { return r_; }
658
659         //! Returns the GREEN component
660         const value_type& get_g()const { return g_; }
661
662         //! Returns the BLUE component
663         const value_type& get_b()const { return b_; }
664
665         //! Returns the amount of opacity (alpha)
666         const value_type& get_a()const { return a_; }
667
668         //! Synonym for get_a(). \see get_a()
669         const value_type& get_alpha()const { return get_a(); }
670
671         //! Sets the RED component to \a x
672         ColorAccumulator& set_r(const value_type& x) { r_ = x; return *this; }
673
674         //! Sets the GREEN component to \a x
675         ColorAccumulator& set_g(const value_type& x) { g_ = x; return *this; }
676
677         //! Sets the BLUE component to \a x
678         ColorAccumulator& set_b(const value_type& x) { b_ = x; return *this; }
679
680         //! Sets the opacity (alpha) to \a x
681         ColorAccumulator& set_a(const value_type& x) { a_ = x; return *this; }
682
683         //! Synonym for set_a(). \see set_a()
684         ColorAccumulator& set_alpha(const value_type& x) { return set_a(x); }
685 };
686
687 inline
688 Color::Color(const ColorAccumulator& c):
689         a_(c.a_),
690         r_(c.r_),
691         g_(c.g_),
692         b_(c.b_) { }
693
694 #endif
695
696
697
698
699
700 enum PixelFormat
701 {
702 /* Bit  Descriptions (ON/OFF)
703 ** ----+-------------
704 ** 0    Color Channels (Gray/RGB)
705 ** 1    Alpha Channel (WITH/WITHOUT)
706 ** 2    ZDepth  (WITH/WITHOUT)
707 ** 3    Endian (BGR/RGB)
708 ** 4    Alpha Location (Start/End)
709 ** 5    ZDepth Location (Start/End)
710 ** 6    Alpha/ZDepth Arangement (ZA,AZ)
711 ** 7    Alpha Range (Inverted,Normal)
712 ** 8    Z Range (Inverted,Normal)
713 */
714         PF_RGB=0,
715         PF_GRAY=(1<<0),                 //!< If set, use one grayscale channel. If clear, use three channels for RGB
716         PF_A=(1<<1),                    //!< If set, include alpha channel
717         PF_Z=(1<<2),                    //!< If set, include ZDepth channel
718         PF_BGR=(1<<3),                  //!< If set, reverse the order of the RGB channels
719         PF_A_START=(1<<4),              //!< If set, alpha channel is before the color data. If clear, it is after.
720         PF_Z_START=(1<<5),              //!< If set, ZDepth channel is before the color data. If clear, it is after.
721         PF_ZA=(1<<6),                   //!< If set, the ZDepth channel will be infront of the alpha channel. If clear, they are reversed.
722
723         PF_A_INV=(1<<7),                //!< If set, the alpha channel is stored as 1.0-a
724         PF_Z_INV=(1<<8),                //!< If set, the ZDepth channel is stored as 1.0-z
725         PF_RAW_COLOR=(1<<9)+(1<<1)      //!< If set, the data represents a raw Color datastructure, and all other bits are ignored.
726 };
727
728 inline PixelFormat operator|(PixelFormat lhs, PixelFormat rhs)
729         { return static_cast<PixelFormat>((int)lhs|(int)rhs); }
730
731 inline PixelFormat operator&(PixelFormat lhs, PixelFormat rhs)
732         { return static_cast<PixelFormat>((int)lhs&(int)rhs); }
733 #define FLAGS(x,y)              (((x)&(y))==(y))
734
735 //! Returns the number of channels that the given PixelFormat calls for
736 inline int
737 channels(PixelFormat x)
738 {
739         int chan=0;
740         if(FLAGS(x,PF_GRAY))
741                 ++chan;
742         else
743                 chan+=3;
744         if(FLAGS(x,PF_A))
745                 ++chan;
746         if(FLAGS(x,PF_Z))
747                 ++chan;
748         if(FLAGS(x,PF_RAW_COLOR))
749                 chan=sizeof(Color);
750
751         return chan;
752 }
753
754 inline unsigned char *
755 Color2PixelFormat(const Color &color, const PixelFormat &pf, unsigned char *out, const Gamma &gamma)
756 {
757         if(FLAGS(pf,PF_RAW_COLOR))
758         {
759                 Color *outcol=reinterpret_cast<Color *>(out);
760                 *outcol=color;
761                 out+=sizeof(color);
762                 return out;
763         }
764
765         int alpha=(int)((FLAGS(pf,PF_A_INV)?(-(float)color.get_a()+1):(float)color.get_a())*255);
766         if(alpha<0)alpha=0;
767         if(alpha>255)alpha=255;
768
769         if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
770         {
771                 if(FLAGS(pf,PF_Z_START))
772                         *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
773                 if(FLAGS(pf,PF_A_START))
774                         *out++=static_cast<unsigned char>(alpha);
775         }
776         else
777         {
778                 if(FLAGS(pf,PF_A_START))
779                         *out++=static_cast<unsigned char>(alpha);
780                 if(FLAGS(pf,PF_Z_START))
781                         *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
782
783         }
784
785         if(FLAGS(pf,PF_GRAY))
786                 *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_y()));
787         else
788         {
789                 if(FLAGS(pf,PF_BGR))
790                 {
791                         *out++=static_cast<unsigned char>(gamma.r_F32_to_U8(color.get_b()));
792                         *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_g()));
793                         *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_r()));
794                 }
795                 else
796                 {
797                         *out++=static_cast<unsigned char>(gamma.r_F32_to_U8(color.get_r()));
798                         *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_g()));
799                         *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_b()));
800                 }
801         }
802
803         if(FLAGS(pf,PF_ZA))
804         {
805                 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
806                         out++;//*out++=(unsigned char)(color.GetZ()*255.0f);
807                 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
808                         *out++=static_cast<unsigned char>(alpha);
809         }
810         else
811         {
812                 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
813                         out++;//*out++=(unsigned char)(color.GetZ()*255.0f);
814                 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
815                         *out++=static_cast<unsigned char>(alpha);
816         }
817         return out;
818 }
819
820 inline void
821 convert_color_format(unsigned char *dest, const Color *src, int w, PixelFormat pf,const Gamma &gamma)
822 {
823         assert(w>=0);
824         while(w--)
825                 dest=Color2PixelFormat((*(src++)).clamped(),pf,dest,gamma);
826 }
827
828 inline const unsigned char *
829 PixelFormat2Color(Color &color, const PixelFormat &pf,const unsigned char *out)
830 {
831         if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
832         {
833                 if(FLAGS(pf,PF_Z_START))
834                         out++;//color.SetZ((Color::value_type)*out++/255.0f);
835                 if(FLAGS(pf,PF_A_START))
836                         color.set_a((float)*out++/255);
837         }
838         else
839         {
840                 if(FLAGS(pf,PF_A_START))
841                         color.set_a((float)*out++/255);
842                 if(FLAGS(pf,PF_Z_START))
843                         out++;//color.SetZ((Color::value_type)*out++/255.0f);
844         }
845
846         if(FLAGS(pf,PF_GRAY))
847                 color.set_yuv((float)*out++/255,0,0);
848         else
849         {
850                 if(FLAGS(pf,PF_BGR))
851                 {
852                         color.set_b((float)*out++/255);
853                         color.set_g((float)*out++/255);
854                         color.set_r((float)*out++/255);
855                 }
856                 else
857                 {
858                         color.set_r((float)*out++/255);
859                         color.set_g((float)*out++/255);
860                         color.set_b((float)*out++/255);
861                 }
862         }
863
864         if(FLAGS(pf,PF_ZA))
865         {
866                 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
867                         out++;//color.SetZ((Color::value_type)*out++/255.0f);
868                 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
869                         color.set_a((float)*out++/255);
870         }
871         else
872         {
873                 if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
874                         color.set_a((float)*out++/255);
875                 if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
876                         out++;//color.SetZ((Color::value_type)*out++/255.0f);
877         }
878         return out;
879 }
880
881
882
883 }; // END of namespace synfig
884
885 /* === E N D =============================================================== */
886
887 #endif