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