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