- Main Page
- Related Pages
- Namespaces
- Classes
- Files

# color.h

Go to the documentation of this file.

    00001 /* === S Y N F I G ========================================================= */
    00022 /* ========================================================================= */
    00023
    00024 /* === S T A R T =========================================================== */
    00025
    00026 #ifndef __SYNFIG_COLOR_H
    00027 #define __SYNFIG_COLOR_H
    00028
    00029 /* === H E A D E R S ======================================================= */
    00030
    00031
    00032 //#include <cmath>
    00033 #include <math.h>
    00034 #include <cassert>
    00035 #include "gamma.h"
    00036 #include <synfig/string.h>
    00037
    00038 #ifdef USE_HALF_TYPE
    00039 #include <OpenEXR/half.h>
    00040 #endif
    00041
    00042 #ifndef SYNFIG_NO_ANGLE
    00043 # include "angle.h"
    00044 #endif
    00045
    00046 /* === M A C R O S ========================================================= */
    00047
    00048 #define use_colorspace_gamma()  App::use_colorspace_gamma
    00049 #define colorspace_gamma()      (2.2f)
    00050 #define gamma_in(x)             ((x>=0) ? pow((float)x,1.0f/colorspace_gamma()) : -pow((float)-x,1.0f/colorspace_gamma()))
    00051 #define gamma_out(x)            ((x>=0) ? pow((float)x,     colorspace_gamma()) : -pow((float)-x,     colorspace_gamma()))
    00052
    00053 #ifdef WIN32
    00054 #include <float.h>
    00055 #ifndef isnan
    00056 extern "C" { int _isnan(double x); }
    00057 #define isnan _isnan
    00058 #endif
    00059 #endif
    00060
    00061 // For some reason isnan() isn't working on macosx any more.
    00062 // This is a quick fix.
    00063 #if defined(__APPLE__) && !defined(SYNFIG_ISNAN_FIX)
    00064 #ifdef isnan
    00065 #undef isnan
    00066 #endif
    00067 inline bool isnan(double x) { return x != x; }
    00068 inline bool isnan(float x) { return x != x; }
    00069 #define SYNFIG_ISNAN_FIX 1
    00070 #endif
    00071
    00072 namespace synfig {
    00073
    00074 #ifdef USE_HALF_TYPE
    00075 typedef half ColorReal;
    00076 #else
    00077 typedef float ColorReal;
    00078 #endif
    00079
    00080 static const float EncodeYUV[3][3]=
    00081 {
    00082     { 0.299f, 0.587f, 0.114f },
    00083     { -0.168736f, -0.331264f, 0.5f },
    00084     { 0.5f, -0.418688f, -0.081312f }
    00085 };
    00086
    00087 static const float DecodeYUV[3][3]=
    00088 {
    00089     { 1.0f, 0.0f, 1.402f },
    00090     { 1.0f, -0.344136f, -0.714136f },
    00091     { 1.0f, 1.772f, 0.0f }
    00092 };
    00093
    00094 /* === T Y P E D E F S ===================================================== */
    00095
    00096 /* === C L A S S E S & S T R U C T S ======================================= */
    00097
    00098 #ifdef USE_HALF_TYPE
    00099 class ColorAccumulator;
    00100 #endif
    00101
    00102
    00103
    00104
    00109 class Color
    00110 {
    00111 public:
    00112     typedef ColorReal value_type;
    00113
    00114 private:
    00115     value_type a_, r_, g_, b_;
    00116
    00117 public:
    00118
    00119     const String get_string(void)const;
    00120
    00121     Color &
    00122     operator+=(const Color &rhs)
    00123     {
    00124         r_+=rhs.r_;
    00125         g_+=rhs.g_;
    00126         b_+=rhs.b_;
    00127         a_+=rhs.a_;
    00128         return *this;
    00129     }
    00130
    00131     Color &
    00132     operator-=(const Color &rhs)
    00133     {
    00134         r_-=rhs.r_;
    00135         g_-=rhs.g_;
    00136         b_-=rhs.b_;
    00137         a_-=rhs.a_;
    00138         return *this;
    00139     }
    00140
    00141     Color &
    00142     operator*=(const float &rhs)
    00143     {
    00144         r_*=rhs;
    00145         g_*=rhs;
    00146         b_*=rhs;
    00147         a_*=rhs;
    00148         return *this;
    00149     }
    00150
    00151     Color &
    00152     operator/=(const float &rhs)
    00153     {
    00154         const float temp(value_type(1)/rhs);
    00155         r_*=temp;
    00156         g_*=temp;
    00157         b_*=temp;
    00158         a_*=temp;
    00159         return *this;
    00160     }
    00161
    00162     Color
    00163     operator+(const Color &rhs)const
    00164     { return Color(*this)+=rhs; }
    00165
    00166     Color
    00167     operator-(const Color &rhs)const
    00168     { return Color(*this)-=rhs; }
    00169
    00170     Color
    00171     operator*(const float &rhs)const
    00172     { return Color(*this)*=rhs; }
    00173
    00174     Color
    00175     operator/(const float &rhs)const
    00176     { return Color(*this)/=rhs; }
    00177
    00178     bool
    00179     operator==(const Color &rhs)const
    00180     { return r_==rhs.r_ && g_==rhs.g_ && b_==rhs.b_ && a_==rhs.a_; }
    00181
    00182     bool
    00183     operator!=(const Color &rhs)const
    00184     { return r_!=rhs.r_ || g_!=rhs.g_ || b_!=rhs.b_ || a_!=rhs.a_; }
    00185
    00186     Color
    00187     operator-()const
    00188     { return Color(-r_,-g_,-b_,-a_); }
    00189
    00191     Color
    00192     operator~()const
    00193     { return Color(1.0f-r_,1.0f-g_,1.0f-b_,a_); }
    00194
    00195     bool is_valid()const
    00196     { return !isnan(r_) && !isnan(g_) && !isnan(b_) && !isnan(a_); }
    00197
    00198     Color premult_alpha() const
    00199     {
    00200         return Color (r_*a_, g_*a_, b_*a_, a_);
    00201     }
    00202
    00203     Color demult_alpha() const
    00204     {
    00205         if(a_)
    00206         {
    00207             const value_type inva = 1/a_;
    00208             return Color (r_*inva, g_*inva, b_*inva, a_);
    00209         }else return alpha();
    00210     }
    00211
    00212 public:
    00213     // ETL/trunk/ETL/_gaussian.h does:
    00214     //   SR1=SR2=SR3=typename T::value_type();
    00215     // and expects that to give it initialized colors
    00216     // Otherwise the 'gaussian' blur type is random.
    00217     Color() :a_(0), r_(0), g_(0), b_(0) { }
    00218     Color(const value_type &f) :a_(f),r_(f), g_(f), b_(f) { }
    00219     Color(int f) :a_(f),r_(f), g_(f), b_(f) { }
    00220
    00225     Color(const value_type& R, const value_type& G, const value_type& B, const value_type& A=1):
    00226         a_(A),
    00227         r_(R),
    00228         g_(G),
    00229         b_(B) { }
    00230
    00233     Color(const Color& c, const value_type& A):
    00234         a_(A),
    00235         r_(c.r_),
    00236         g_(c.g_),
    00237         b_(c.b_) { }
    00238
    00239
    00241     Color(const Color& c):
    00242         a_(c.a_),
    00243         r_(c.r_),
    00244         g_(c.g_),
    00245         b_(c.b_) { }
    00246
    00247 #ifdef USE_HALF_TYPE
    00248     friend class ColorAccumulator;
    00250     Color(const ColorAccumulator& c);
    00251 #endif
    00252
    00254     //Color(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); }
    00255
    00256     /*const Color &operator=(const value_type &i)
    00257     {
    00258         r_ = g_ = b_ = a_ = i;
    00259         return *this;
    00260     }*/
    00261     //Color& operator=(const Color &c) { memcpy((void*)this, (const void*)&c, sizeof(Color)); return *this; }
    00262
    00264     const value_type& get_r()const { return r_; }
    00265
    00267     const value_type& get_g()const { return g_; }
    00268
    00270     const value_type& get_b()const { return b_; }
    00271
    00273     const value_type& get_a()const { return a_; }
    00274
    00276     const value_type& get_alpha()const { return get_a(); }
    00277
    00279     static ColorReal hex2real(String s);
    00280
    00282     static const String real2hex(ColorReal c);
    00283
    00285     const String get_hex()const { return String(real2hex(r_)+real2hex(g_)+real2hex(b_)); }
    00286
    00288     void set_hex(String& hex);
    00289
    00291     Color& set_r(const value_type& x) { r_ = x; return *this; }
    00292
    00294     Color& set_g(const value_type& x) { g_ = x; return *this; }
    00295
    00297     Color& set_b(const value_type& x) { b_ = x; return *this; }
    00298
    00300     Color& set_a(const value_type& x) { a_ = x; return *this; }
    00301
    00303     Color& set_alpha(const value_type& x) { return set_a(x); }
    00304
    00306     float
    00307     get_y() const
    00308     {
    00309         return
    00310             (float)get_r()*EncodeYUV[0][0]+
    00311             (float)get_g()*EncodeYUV[0][1]+
    00312             (float)get_b()*EncodeYUV[0][2];
    00313     }
    00314
    00315
    00317     float
    00318     get_u() const
    00319     {
    00320         return
    00321             (float)get_r()*EncodeYUV[1][0]+
    00322             (float)get_g()*EncodeYUV[1][1]+
    00323             (float)get_b()*EncodeYUV[1][2];
    00324     }
    00325
    00326
    00328     float
    00329     get_v() const
    00330     {
    00331         return
    00332             (float)get_r()*EncodeYUV[2][0]+
    00333             (float)get_g()*EncodeYUV[2][1]+
    00334             (float)get_b()*EncodeYUV[2][2];
    00335     }
    00336
    00338
    00340     float
    00341     get_s() const
    00342     {
    00343         const float u(get_u()), v(get_v());
    00344         return sqrt(u*u+v*v);
    00345     }
    00346
    00348     Color&
    00349     set_yuv(const float &y, const float &u, const float &v)
    00350     {
    00351         set_r(y*DecodeYUV[0][0]+u*DecodeYUV[0][1]+v*DecodeYUV[0][2]);
    00352         set_g(y*DecodeYUV[1][0]+u*DecodeYUV[1][1]+v*DecodeYUV[1][2]);
    00353         set_b(y*DecodeYUV[2][0]+u*DecodeYUV[2][1]+v*DecodeYUV[2][2]);
    00354         return *this;
    00355     }
    00356
    00358     Color& set_y(const float &y) { return set_yuv(y,get_u(),get_v()); }
    00359
    00361     Color& set_u(const float &u) { return set_yuv(get_y(),u,get_v()); }
    00362
    00364     Color& set_v(const float &v) { return set_yuv(get_y(),get_u(),v); }
    00365
    00367     Color& set_uv(const float& u, const float& v) { return set_yuv(get_y(),u,v); }
    00368
    00370
    00371     Color&
    00372     set_s(const float &x)
    00373     {
    00374         float u(get_u()), v(get_v());
    00375         const float s(sqrt(u*u+v*v));
    00376         if(s)
    00377         {
    00378             u=(u/s)*x;
    00379             v=(v/s)*x;
    00380             return set_uv(u,v);
    00381         }
    00382         return *this;
    00383     }
    00384
    00386     static Color YUV(const float& y, const float& u, const float& v, const value_type& a=1)
    00387         { return Color().set_yuv(y,u,v).set_a(a); }
    00388
    00389 #ifndef SYNFIG_NO_ANGLE
    00391
    00393     Angle
    00394     get_hue() const
    00395         { return Angle::tan(get_u(),get_v()); }
    00396
    00398     Angle get_uv_angle() const { return get_hue(); }
    00399
    00401
    00402     Color&
    00403     set_hue(const Angle& theta)
    00404     {
    00405         const float s(get_s());
    00406         const float
    00407             u(s*(float)Angle::sin(theta).get()),
    00408             v(s*(float)Angle::cos(theta).get());
    00409         return set_uv(u,v);
    00410     }
    00411
    00413     Color& set_uv_angle(const Angle& theta) { return set_hue(theta); }
    00414
    00416     Color& rotate_uv(const Angle& theta)
    00417     {
    00418         const float a(Angle::sin(theta).get()), b(Angle::cos(theta).get());
    00419         const float u(get_u()), v(get_v());
    00420
    00421         return set_uv(b*u-a*v,a*u+b*v);
    00422     }
    00423
    00425
    00428     Color& set_yuv(const float& y, const float& s, const Angle& theta)
    00429     {
    00430         return
    00431             set_yuv(
    00432                 y,
    00433                 s*(float)Angle::sin(theta).get(),
    00434                 s*(float)Angle::cos(theta).get()
    00435             );
    00436     }
    00437
    00439
    00443     static Color YUV(const float& y, const float& s, const Angle& theta, const value_type& a=1)
    00444         { return Color().set_yuv(y,s,theta).set_a(a); }
    00445
    00446 #endif
    00447
    00449     Color clamped()const;
    00450
    00452     Color clamped_negative()const;
    00453
    00454     /* Preset Colors */
    00455
    00457
    00458 #ifdef HAS_VIMAGE
    00459     static inline Color alpha() { return Color(0,0,0,0.0000001f); }
    00460 #else
    00461     static inline Color alpha() { return Color(0,0,0,0); }
    00462 #endif
    00463     static inline Color black() { return Color(0,0,0); }
    00464     static inline Color white() { return Color(1,1,1); }
    00465     static inline Color gray() { return Color(0.5f,0.5f,0.5f); }
    00466     static inline Color magenta() { return Color(1,0,1); }
    00467     static inline Color red() { return Color(1,0,0); }
    00468     static inline Color green() { return Color(0,1,0); }
    00469     static inline Color blue() { return Color(0,0,1); }
    00470     static inline Color cyan() { return Color(0,1,1); }
    00471     static inline Color yellow() { return Color(1,1,0); }
    00473
    00475     enum BlendMethod
    00476     {
    00477         BLEND_COMPOSITE=0,
    00478         BLEND_STRAIGHT=1,
    00479         BLEND_ONTO=13,
    00480         BLEND_STRAIGHT_ONTO=21,
    00481         BLEND_BEHIND=12,
    00482         BLEND_SCREEN=16,
    00483         BLEND_OVERLAY=20,
    00484         BLEND_HARD_LIGHT=17,
    00485         BLEND_MULTIPLY=6,
    00486         BLEND_DIVIDE=7,
    00487         BLEND_ADD=4,
    00488         BLEND_SUBTRACT=5,
    00489         BLEND_DIFFERENCE=18,
    00490         BLEND_BRIGHTEN=2,
    00491         BLEND_DARKEN=3,
    00492         BLEND_COLOR=8,
    00493         BLEND_HUE=9,
    00494         BLEND_SATURATION=10,
    00495         BLEND_LUMINANCE=11,
    00496
    00497         BLEND_ALPHA_BRIGHTEN=14,
    00498         BLEND_ALPHA_DARKEN=15,
    00499         BLEND_ALPHA_OVER=19,
    00500
    00501         BLEND_END=22
    00502     };
    00503
    00504     /* Other */
    00505     static Color blend(Color a, Color b,float amount,BlendMethod type=BLEND_COMPOSITE);
    00506
    00507     static bool is_onto(BlendMethod x)
    00508     {
    00509         return x==BLEND_BRIGHTEN
    00510             || x==BLEND_DARKEN
    00511             || x==BLEND_ADD
    00512             || x==BLEND_SUBTRACT
    00513             || x==BLEND_MULTIPLY
    00514             || x==BLEND_DIVIDE
    00515             || x==BLEND_COLOR
    00516             || x==BLEND_HUE
    00517             || x==BLEND_SATURATION
    00518             || x==BLEND_LUMINANCE
    00519             || x==BLEND_ONTO
    00520             || x==BLEND_STRAIGHT_ONTO
    00521             || x==BLEND_SCREEN
    00522             || x==BLEND_OVERLAY
    00523             || x==BLEND_DIFFERENCE
    00524             || x==BLEND_HARD_LIGHT
    00525         ;
    00526     }
    00527
    00529     static bool is_straight(BlendMethod x)
    00530     {
    00531         return x==BLEND_STRAIGHT
    00532             || x==BLEND_STRAIGHT_ONTO
    00533             || x==BLEND_ALPHA_BRIGHTEN
    00534         ;
    00535     }
    00536 /*protected:
    00537
    00538     value_type& operator[](const int i)
    00539     {
    00540         assert(i>=0);
    00541         assert(i<(signed)(sizeof(Color)/sizeof(value_type)));
    00542         return (&r_)[i];
    00543     }
    00544
    00545     const value_type& operator[](const int i)const
    00546     {
    00547         assert(i>=0);
    00548         assert(i<(signed)(sizeof(Color)/sizeof(value_type)));
    00549         return (&r_)[i];
    00550     }
    00551 */
    00552 }; // END of class Color
    00553
    00554 #ifndef USE_HALF_TYPE
    00555 typedef Color ColorAccumulator;
    00556 #else
    00557 class ColorAccumulator
    00558 {
    00559     friend class Color;
    00560 public:
    00561     typedef float value_type;
    00562
    00563 private:
    00564     value_type a_, r_, g_, b_;
    00565
    00566 public:
    00567
    00568     ColorAccumulator &
    00569     operator+=(const ColorAccumulator &rhs)
    00570     {
    00571         r_+=rhs.r_;
    00572         g_+=rhs.g_;
    00573         b_+=rhs.b_;
    00574         a_+=rhs.a_;
    00575         return *this;
    00576     }
    00577
    00578     ColorAccumulator &
    00579     operator-=(const ColorAccumulator &rhs)
    00580     {
    00581         r_-=rhs.r_;
    00582         g_-=rhs.g_;
    00583         b_-=rhs.b_;
    00584         a_-=rhs.a_;
    00585         return *this;
    00586     }
    00587
    00588     ColorAccumulator &
    00589     operator*=(const float &rhs)
    00590     {
    00591         r_*=rhs;
    00592         g_*=rhs;
    00593         b_*=rhs;
    00594         a_*=rhs;
    00595         return *this;
    00596     }
    00597
    00598     ColorAccumulator &
    00599     operator/=(const float &rhs)
    00600     {
    00601         const float temp(value_type(1)/rhs);
    00602         r_*=temp;
    00603         g_*=temp;
    00604         b_*=temp;
    00605         a_*=temp;
    00606         return *this;
    00607     }
    00608
    00609     ColorAccumulator
    00610     operator+(const ColorAccumulator &rhs)const
    00611     { return Color(*this)+=rhs; }
    00612
    00613     ColorAccumulator
    00614     operator-(const ColorAccumulator &rhs)const
    00615     { return Color(*this)-=rhs; }
    00616
    00617     ColorAccumulator
    00618     operator*(const float &rhs)const
    00619     { return Color(*this)*=rhs; }
    00620
    00621     ColorAccumulator
    00622     operator/(const float &rhs)const
    00623     { return Color(*this)/=rhs; }
    00624
    00625     bool
    00626     operator==(const ColorAccumulator &rhs)const
    00627     { return r_==rhs.r_ && g_==rhs.g_ && b_==rhs.b_ && a_!=rhs.a_; }
    00628
    00629     bool
    00630     operator!=(const ColorAccumulator &rhs)const
    00631     { return r_!=rhs.r_ || g_!=rhs.g_ || b_!=rhs.b_ || a_!=rhs.a_; }
    00632
    00633     Color
    00634     operator-()const
    00635     { return ColorAccumulator(-r_,-g_,-b_,-a_); }
    00636
    00637     bool is_valid()const
    00638     { return !isnan(r_) && !isnan(g_) && !isnan(b_) && !isnan(a_); }
    00639
    00640 public:
    00641     ColorAccumulator() { }
    00642
    00647     ColorAccumulator(const value_type& R, const value_type& G, const value_type& B, const value_type& A=1):
    00648         a_(A),
    00649         r_(R),
    00650         g_(G),
    00651         b_(B) { }
    00652
    00654     ColorAccumulator(const ColorAccumulator& c):
    00655         a_(c.a_),
    00656         r_(c.r_),
    00657         g_(c.g_),
    00658         b_(c.b_) { }
    00659
    00661     ColorAccumulator(const Color& c):
    00662         a_(c.a_),
    00663         r_(c.r_),
    00664         g_(c.g_),
    00665         b_(c.b_) { }
    00666
    00668     ColorAccumulator(int c): a_(c),r_(c), g_(c), b_(c) { }
    00669
    00671     const value_type& get_r()const { return r_; }
    00672
    00674     const value_type& get_g()const { return g_; }
    00675
    00677     const value_type& get_b()const { return b_; }
    00678
    00680     const value_type& get_a()const { return a_; }
    00681
    00683     const value_type& get_alpha()const { return get_a(); }
    00684
    00686     ColorAccumulator& set_r(const value_type& x) { r_ = x; return *this; }
    00687
    00689     ColorAccumulator& set_g(const value_type& x) { g_ = x; return *this; }
    00690
    00692     ColorAccumulator& set_b(const value_type& x) { b_ = x; return *this; }
    00693
    00695     ColorAccumulator& set_a(const value_type& x) { a_ = x; return *this; }
    00696
    00698     ColorAccumulator& set_alpha(const value_type& x) { return set_a(x); }
    00699 };
    00700
    00701 inline
    00702 Color::Color(const ColorAccumulator& c):
    00703     a_(c.a_),
    00704     r_(c.r_),
    00705     g_(c.g_),
    00706     b_(c.b_) { }
    00707
    00708 #endif
    00709
    00710
    00711
    00712
    00713
    00714 enum PixelFormat
    00715 {
    00716 /* Bit  Descriptions (ON/OFF)
    00717 ** ----+-------------
    00718 ** 0    Color Channels (Gray/RGB)
    00719 ** 1    Alpha Channel (WITH/WITHOUT)
    00720 ** 2    ZDepth  (WITH/WITHOUT)
    00721 ** 3    Endian (BGR/RGB)
    00722 ** 4    Alpha Location (Start/End)
    00723 ** 5    ZDepth Location (Start/End)
    00724 ** 6    Alpha/ZDepth Arrangement (ZA,AZ)
    00725 ** 7    Alpha Range (Inverted,Normal)
    00726 ** 8    Z Range (Inverted,Normal)
    00727 */
    00728     PF_RGB=0,
    00729     PF_GRAY=(1<<0),
    00730     PF_A=(1<<1),
    00731     PF_Z=(1<<2),
    00732     PF_BGR=(1<<3),
    00733     PF_A_START=(1<<4),
    00734     PF_Z_START=(1<<5),
    00735     PF_ZA=(1<<6),
    00736
    00737     PF_A_INV=(1<<7),
    00738     PF_Z_INV=(1<<8),
    00739     PF_RAW_COLOR=(1<<9)+(1<<1)
    00740 };
    00741
    00742 inline PixelFormat operator|(PixelFormat lhs, PixelFormat rhs)
    00743     { return static_cast<PixelFormat>((int)lhs|(int)rhs); }
    00744
    00745 inline PixelFormat operator&(PixelFormat lhs, PixelFormat rhs)
    00746     { return static_cast<PixelFormat>((int)lhs&(int)rhs); }
    00747 #define FLAGS(x,y)      (((x)&(y))==(y))
    00748
    00750 inline int
    00751 channels(PixelFormat x)
    00752 {
    00753     int chan=0;
    00754     if(FLAGS(x,PF_GRAY))
    00755         ++chan;
    00756     else
    00757         chan+=3;
    00758     if(FLAGS(x,PF_A))
    00759         ++chan;
    00760     if(FLAGS(x,PF_Z))
    00761         ++chan;
    00762     if(FLAGS(x,PF_RAW_COLOR))
    00763         chan=sizeof(Color);
    00764
    00765     return chan;
    00766 }
    00767
    00768 inline unsigned char *
    00769 Color2PixelFormat(const Color &color, const PixelFormat &pf, unsigned char *out, const Gamma &gamma)
    00770 {
    00771     if(FLAGS(pf,PF_RAW_COLOR))
    00772     {
    00773         Color *outcol=reinterpret_cast<Color *>(out);
    00774         *outcol=color;
    00775         out+=sizeof(color);
    00776         return out;
    00777     }
    00778
    00779     int alpha=(int)((FLAGS(pf,PF_A_INV)?(-(float)color.get_a()+1):(float)color.get_a())*255);
    00780     if(alpha<0)alpha=0;
    00781     if(alpha>255)alpha=255;
    00782
    00783     if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
    00784     {
    00785         if(FLAGS(pf,PF_Z_START))
    00786             *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
    00787         if(FLAGS(pf,PF_A_START))
    00788             *out++=static_cast<unsigned char>(alpha);
    00789     }
    00790     else
    00791     {
    00792         if(FLAGS(pf,PF_A_START))
    00793             *out++=static_cast<unsigned char>(alpha);
    00794         if(FLAGS(pf,PF_Z_START))
    00795             *out++/*=(unsigned char)(color.GetZ()*255.0f)*/;
    00796
    00797     }
    00798
    00799     if(FLAGS(pf,PF_GRAY))
    00800         *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_y()));
    00801     else
    00802     {
    00803         if(FLAGS(pf,PF_BGR))
    00804         {
    00805             *out++=static_cast<unsigned char>(gamma.r_F32_to_U8(color.get_b()));
    00806             *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_g()));
    00807             *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_r()));
    00808         }
    00809         else
    00810         {
    00811             *out++=static_cast<unsigned char>(gamma.r_F32_to_U8(color.get_r()));
    00812             *out++=static_cast<unsigned char>(gamma.g_F32_to_U8(color.get_g()));
    00813             *out++=static_cast<unsigned char>(gamma.b_F32_to_U8(color.get_b()));
    00814         }
    00815     }
    00816
    00817     if(FLAGS(pf,PF_ZA))
    00818     {
    00819         if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
    00820             out++;//*out++=(unsigned char)(color.GetZ()*255.0f);
    00821         if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
    00822             *out++=static_cast<unsigned char>(alpha);
    00823     }
    00824     else
    00825     {
    00826         if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
    00827             out++;//*out++=(unsigned char)(color.GetZ()*255.0f);
    00828         if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
    00829             *out++=static_cast<unsigned char>(alpha);
    00830     }
    00831     return out;
    00832 }
    00833
    00834 inline void
    00835 convert_color_format(unsigned char *dest, const Color *src, int w, PixelFormat pf,const Gamma &gamma)
    00836 {
    00837     assert(w>=0);
    00838     while(w--)
    00839         dest=Color2PixelFormat((*(src++)).clamped(),pf,dest,gamma);
    00840 }
    00841
    00842 inline const unsigned char *
    00843 PixelFormat2Color(Color &color, const PixelFormat &pf,const unsigned char *out)
    00844 {
    00845     if(FLAGS(pf,PF_ZA|PF_A_START|PF_Z_START))
    00846     {
    00847         if(FLAGS(pf,PF_Z_START))
    00848             out++;//color.SetZ((Color::value_type)*out++/255.0f);
    00849         if(FLAGS(pf,PF_A_START))
    00850             color.set_a((float)*out++/255);
    00851     }
    00852     else
    00853     {
    00854         if(FLAGS(pf,PF_A_START))
    00855             color.set_a((float)*out++/255);
    00856         if(FLAGS(pf,PF_Z_START))
    00857             out++;//color.SetZ((Color::value_type)*out++/255.0f);
    00858     }
    00859
    00860     if(FLAGS(pf,PF_GRAY))
    00861         color.set_yuv((float)*out++/255,0,0);
    00862     else
    00863     {
    00864         if(FLAGS(pf,PF_BGR))
    00865         {
    00866             color.set_b((float)*out++/255);
    00867             color.set_g((float)*out++/255);
    00868             color.set_r((float)*out++/255);
    00869         }
    00870         else
    00871         {
    00872             color.set_r((float)*out++/255);
    00873             color.set_g((float)*out++/255);
    00874             color.set_b((float)*out++/255);
    00875         }
    00876     }
    00877
    00878     if(FLAGS(pf,PF_ZA))
    00879     {
    00880         if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
    00881             out++;//color.SetZ((Color::value_type)*out++/255.0f);
    00882         if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
    00883             color.set_a((float)*out++/255);
    00884     }
    00885     else
    00886     {
    00887         if(!FLAGS(pf,PF_A_START) && FLAGS(pf,PF_A))
    00888             color.set_a((float)*out++/255);
    00889         if(!FLAGS(pf,PF_Z_START) && FLAGS(pf,PF_Z))
    00890             out++;//color.SetZ((Color::value_type)*out++/255.0f);
    00891     }
    00892     return out;
    00893 }
    00894
    00895
    00896
    00897 }; // END of namespace synfig
    00898
    00899 /* === E N D =============================================================== */
    00900
    00901 #endif