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