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