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