Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

color.h

Go to the documentation of this file.
00001 
00059 #ifndef __COLOR__
00060 #define __COLOR__
00061 
00062 #include <math.h>
00063 
00064 #include <iterator>
00065 #include <list>
00066 #include <vector>
00067 
00068 #ifndef WITHOUT_LIMITS
00069 #include <limits>
00070 #endif
00071 
00072 #include "io_tools.h"
00073 #include "msg_stream.h"
00074 
00075 #ifndef WITHOUT_STATIC_CONST  // in case of trouble with gcc 2.96
00076 #define CONST_STATIC const
00077 #else
00078 #define CONST_STATIC
00079 #endif
00080 
00081 /*
00082 
00083   ###############
00084   # typedef ... #
00085   ###############
00086   
00087  */
00088 
00089 template<typename RGB_converter> class Basic_color;
00090 
00091 template<typename Real> class RGB_color;
00092 template<typename Real> class HSV_color;
00093 template<typename Real> class XYZ_color;
00094 template<typename Real> class Luv_color;
00095 template<typename Real> class Grey_level_color;
00096 
00097 template<typename Real> class RGB_converter_to_RGB;
00098 template<typename Real> class RGB_converter_to_HSV;
00099 template<typename Real> class RGB_converter_to_XYZ;
00100 template<typename Real> class RGB_converter_to_Luv;
00101 template<typename Real> class RGB_converter_to_grey_level;
00102 
00103 typedef RGB_color<float>         RGB_f_color;
00104 typedef RGB_color<double>        RGB_d_color;
00105 
00106 typedef HSV_color<float>         HSV_f_color;
00107 typedef HSV_color<double>        HSV_d_color;
00108 
00109 typedef XYZ_color<float>         XYZ_f_color;
00110 typedef XYZ_color<double>        XYZ_d_color;
00111 
00112 typedef Luv_color<float>         Luv_f_color;
00113 typedef Luv_color<double>        Luv_d_color;
00114 
00115 typedef Grey_level_color<float>  Grey_level_f_color;
00116 typedef Grey_level_color<double> Grey_level_d_color;
00117 
00118 
00119 template<typename RGB_converter>
00120 std::ostream& operator<<(std::ostream& s,
00121                          const Basic_color<RGB_converter>& c);
00122 
00123 /*
00124 
00125   #####################
00126   # class Basic_color #
00127   #####################
00128 
00129 */
00130 
00133 
00140 template<typename RGB_converter>
00141 class Basic_color{
00142 
00143 public:
00144 
00145   typedef typename RGB_converter::component_type component_type;
00146   typedef component_type                         distance_type;
00147 
00148   typedef RGB_converter  converter_type;
00149   
00150   Basic_color();
00151   
00152   Basic_color(const char r,  const char g,  const char b);
00153   Basic_color(const float r, const float g, const float b);
00154   Basic_color(const double r,const double g,const double b);
00155   
00156   Basic_color(const Basic_color<RGB_converter>& c);
00157   
00158   inline Basic_color<RGB_converter>&
00159   operator=(const Basic_color<RGB_converter>& c);
00160 
00161   inline bool operator==(const Basic_color<RGB_converter>& c) const;
00162   inline bool operator!=(const Basic_color<RGB_converter>& c) const;
00163   
00165 
00166   
00167   inline void get_RGB(char* const r,  char* const g,  char* const b) const;
00168   inline void get_RGB(float* const r, float* const g, float* const b) const;
00169   inline void get_RGB(double* const r,double* const g,double* const b) const;  
00171 
00173 
00174   
00175   inline void get_space_position(component_type* const x_space,
00176                                  component_type* const y_space,
00177                                  component_type* const z_space) const;
00178 
00179   template<typename Space_vector>
00180   inline void get_space_position(Space_vector* const space_vector) const;
00182 
00183   
00185 
00186   
00187   inline void set_space_position(const component_type x_space,
00188                                  const component_type y_space,
00189                                  const component_type z_space);
00190 
00191   template<typename Space_vector>
00192   inline void set_space_position(const Space_vector& space_vector);
00194 
00196   inline bool is_not_a_color() const;
00197 
00199   inline void write_to_bytes(std::ostream& out) const;
00200 
00202   inline void read_from_bytes(std::istream& in);
00203 
00205   inline static distance_type
00206   square_distance(const Basic_color<RGB_converter>& c1,
00207                   const Basic_color<RGB_converter>& c2);
00208 
00210   inline static distance_type
00211   distance(const Basic_color<RGB_converter>& c1,
00212            const Basic_color<RGB_converter>& c2);
00213   
00215 
00216   
00217   template<typename Basic_color_iterator>
00218   static void mean(Basic_color_iterator first,
00219                    Basic_color_iterator last,
00220                    Basic_color<RGB_converter>* const result);
00221 
00222   template<typename Basic_color_iterator,typename Weight_iterator>
00223   static void mean(Basic_color_iterator first_clr,
00224                    Basic_color_iterator last_clr,
00225                    Weight_iterator first_w,
00226                    Weight_iterator last_w,
00227                    Basic_color<RGB_converter>* const result);
00229 
00231 
00232 
00233   template<typename Basic_color_iterator>
00234   static void robust_mean(Basic_color_iterator first,
00235                           Basic_color_iterator last,
00236                           Basic_color<RGB_converter>* const result,
00237                           const unsigned int n_iter = 1);
00238 
00239   template<typename Basic_color_iterator,typename Weight_iterator>
00240   static void robust_mean(Basic_color_iterator first_clr,
00241                           Basic_color_iterator last_clr,
00242                           Weight_iterator first_w,
00243                           Weight_iterator last_w,
00244                           Basic_color<RGB_converter>* const result,
00245                           const unsigned int n_iter = 1);
00247 
00250   static void main_conversion_output(std::ostream& out = std::cout) ;
00251 
00253 
00254   
00255   template<typename Basic_color_iterator>
00256   inline static distance_type
00257   square_deviation(const Basic_color_iterator first,
00258                    const Basic_color_iterator last);
00259 
00260   template<typename Basic_color_iterator>
00261   static distance_type
00262   square_deviation(const Basic_color_iterator first,
00263                    const Basic_color_iterator last,
00264                    Basic_color<RGB_converter>* const mean_color);
00266 
00268 
00269 
00270   static const Basic_color<RGB_converter> black;
00271   static const Basic_color<RGB_converter> grey;
00272   static const Basic_color<RGB_converter> white;
00273   
00274   static const Basic_color<RGB_converter> red;
00275   static const Basic_color<RGB_converter> green;
00276   static const Basic_color<RGB_converter> blue;
00277 
00278   static const Basic_color<RGB_converter> cyan;
00279   static const Basic_color<RGB_converter> magenta;
00280   static const Basic_color<RGB_converter> yellow;
00282 
00283   static void cycle(const double alpha,
00284                     Basic_color<RGB_converter>* const result,
00285                     const Basic_color<RGB_converter>& clr_0 = red,
00286                     const Basic_color<RGB_converter>& clr_1 = blue,
00287                     const Basic_color<RGB_converter>& clr_2 = yellow,
00288                     const Basic_color<RGB_converter>& clr_3 = magenta);
00289   
00291   friend std::ostream&
00292   operator<<<RGB_converter>(std::ostream& s,
00293                             const Basic_color<RGB_converter>& c);
00294 
00295 private:
00297 
00298   
00299   component_type x,y,z;
00301 };
00302 
00303 
00304 /*
00305 
00306   ###################
00307   # class RGB_color #
00308   ###################
00309 
00310  */
00311 
00312 
00313 template<typename Real>
00314 class RGB_color
00315   :public Basic_color<RGB_converter_to_RGB<Real> >{
00316 
00317 public:
00318   
00319   RGB_color()
00320     :Basic_color<RGB_converter_to_RGB<Real> >(){}
00321   
00322   RGB_color(const char r,  const char g,  const char b)
00323     :Basic_color<RGB_converter_to_RGB<Real> >(r,g,b){}
00324 
00325   RGB_color(const float r, const float g, const float b)
00326     :Basic_color<RGB_converter_to_RGB<Real> >(r,g,b){}
00327 
00328   RGB_color(const double r,const double g,const double b)
00329     :Basic_color<RGB_converter_to_RGB<Real> >(r,g,b){}
00330   
00331   RGB_color(const Basic_color<RGB_converter_to_RGB<Real> >& c)
00332     :Basic_color<RGB_converter_to_RGB<Real> >(c){}
00333 
00334 };
00335 
00336 
00337 
00338 
00339 
00340 
00341 /*
00342 
00343   ###################
00344   # class HSV_color #
00345   ###################
00346 
00347  */
00348 
00349 
00350 template<typename Real>
00351 class HSV_color
00352   :public Basic_color<RGB_converter_to_HSV<Real> >{
00353 
00354 public:
00355   
00356   HSV_color()
00357     :Basic_color<RGB_converter_to_HSV<Real> >(){}
00358   
00359   HSV_color(const char r,  const char g,  const char b)
00360     :Basic_color<RGB_converter_to_HSV<Real> >(r,g,b){}
00361   
00362   HSV_color(const float r, const float g, const float b)
00363     :Basic_color<RGB_converter_to_HSV<Real> >(r,g,b){}
00364   
00365   HSV_color(const double r,const double g,const double b)
00366     :Basic_color<RGB_converter_to_HSV<Real> >(r,g,b){}
00367   
00368   HSV_color(const Basic_color<RGB_converter_to_HSV<Real> >& c)
00369     :Basic_color<RGB_converter_to_HSV<Real> >(c){}
00370 
00371 };
00372 
00373 
00374 
00375 /*
00376 
00377   ###################
00378   # class XYZ_color #
00379   ###################
00380 
00381  */
00382 
00383 
00384 template<typename Real>
00385 class XYZ_color
00386   :public Basic_color<RGB_converter_to_XYZ<Real> >{
00387 
00388 public:
00389   
00390   XYZ_color()
00391     :Basic_color<RGB_converter_to_XYZ<Real> >(){}
00392   
00393   XYZ_color(const char r,  const char g,  const char b)
00394     :Basic_color<RGB_converter_to_XYZ<Real> >(r,g,b){}
00395   
00396   XYZ_color(const float r, const float g, const float b)
00397     :Basic_color<RGB_converter_to_XYZ<Real> >(r,g,b){}
00398   
00399   XYZ_color(const double r,const double g,const double b)
00400     :Basic_color<RGB_converter_to_XYZ<Real> >(r,g,b){}
00401   
00402   XYZ_color(const Basic_color<RGB_converter_to_XYZ<Real> >& c)
00403     :Basic_color<RGB_converter_to_XYZ<Real> >(c){}
00404 
00405 };
00406 
00407 
00408 
00409 
00410 
00411 /*
00412 
00413   ###################
00414   # class Luv_color #
00415   ###################
00416 
00417  */
00418 
00419 
00420 template<typename Real>
00421 class Luv_color
00422   :public Basic_color<RGB_converter_to_Luv<Real> >{
00423 
00424 public:
00425   
00426   Luv_color()
00427     :Basic_color<RGB_converter_to_Luv<Real> >(){}
00428   
00429   Luv_color(const char r,  const char g,  const char b)
00430     :Basic_color<RGB_converter_to_Luv<Real> >(r,g,b){}
00431   
00432   Luv_color(const float r, const float g, const float b)
00433     :Basic_color<RGB_converter_to_Luv<Real> >(r,g,b){}
00434   
00435   Luv_color(const double r,const double g,const double b)
00436     :Basic_color<RGB_converter_to_Luv<Real> >(r,g,b){}
00437   
00438   Luv_color(const Basic_color<RGB_converter_to_Luv<Real> >& c)
00439     :Basic_color<RGB_converter_to_Luv<Real> >(c){}
00440 
00441 };
00442 
00443 
00444 
00445 
00446 
00447 /*
00448 
00449   ##########################
00450   # class Grey_level_color #
00451   ##########################
00452 
00453  */
00454 
00455 
00456 template<typename Real>
00457 class Grey_level_color
00458   :public Basic_color<RGB_converter_to_grey_level<Real> >{
00459 
00460 public:
00461   
00462   Grey_level_color()
00463     :Basic_color<RGB_converter_to_grey_level<Real> >(){}
00464 
00465   Grey_level_color(const char c)
00466     :Basic_color<RGB_converter_to_grey_level<Real> >(c,c,c){}
00467 
00468   Grey_level_color(const float f)
00469     :Basic_color<RGB_converter_to_grey_level<Real> >(f,f,f){}
00470 
00471   Grey_level_color(const double d)
00472     :Basic_color<RGB_converter_to_grey_level<Real> >(d,d,d){}
00473   
00474   Grey_level_color(const char r,  const char g,  const char b)
00475     :Basic_color<RGB_converter_to_grey_level<Real> >(r,g,b){}
00476   
00477   Grey_level_color(const float r, const float g, const float b)
00478     :Basic_color<RGB_converter_to_grey_level<Real> >(r,g,b){}
00479   
00480   Grey_level_color(const double r,const double g,const double b)
00481     :Basic_color<RGB_converter_to_grey_level<Real> >(r,g,b){}
00482   
00483   Grey_level_color(const Basic_color<RGB_converter_to_grey_level<Real> >& c)
00484     :Basic_color<RGB_converter_to_grey_level<Real> >(c){}
00485 
00486 };
00487 
00488 
00489 /*
00490 
00491   ##############################
00492   # class RGB_converter_to_HSV #
00493   ##############################
00494 
00495 */
00496 
00497 
00499 
00502 template<typename Real>
00503 class RGB_converter_to_HSV{
00504   
00505 public:
00506 
00507   typedef Real component_type;
00508   
00509   inline static void from_RGB_to_cartesian(const double r,
00510                                            const double g,
00511                                            const double b,
00512                                            component_type* const x,
00513                                            component_type* const y,
00514                                            component_type* const z);
00515 
00516   inline static void from_cartesian_to_RGB(const component_type x,
00517                                            const component_type y,
00518                                            const component_type z,
00519                                            double* const r,
00520                                            double* const g,
00521                                            double* const b);
00522 
00523 private:
00524   inline static void RGB_to_HSV(const double r,const double g,const double b,
00525                                 double* const h,double* const s,double* const v);
00526   
00527   inline static void HSV_to_RGB(const double h,const double s,const double v,
00528                                 double* const r,double* const g,double* const b);
00529 };
00530 
00531 
00532 
00533 
00534 /*
00535 
00536   ##############################
00537   # class RGB_converter_to_RGB #
00538   ##############################
00539 
00540 */
00541 
00542 
00544 
00547 template<typename Real>
00548 class RGB_converter_to_RGB{
00549   
00550 public:
00551 
00553   typedef Real component_type;
00554   
00555   inline static void from_RGB_to_cartesian(const double r,
00556                                            const double g,
00557                                            const double b,
00558                                            component_type* const x,
00559                                            component_type* const y,
00560                                            component_type* const z);
00561 
00562   inline static void from_cartesian_to_RGB(const component_type x,
00563                                            const component_type y,
00564                                            const component_type z,
00565                                            double* const r,
00566                                            double* const g,
00567                                            double* const b);
00568 };
00569 
00570 
00571 
00573 
00576 template<typename Real>
00577 class RGB_converter_to_XYZ{
00578   
00579 public:
00580 
00581   typedef Real component_type;
00582   
00583   inline static void from_RGB_to_cartesian(const double r,
00584                                            const double g,
00585                                            const double b,
00586                                            component_type* const x,
00587                                            component_type* const y,
00588                                            component_type* const z);
00589 
00590   inline static void from_cartesian_to_RGB(const component_type x,
00591                                            const component_type y,
00592                                            const component_type z,
00593                                            double* const r,
00594                                            double* const g,
00595                                            double* const b);
00596 };
00597 
00598 
00599 
00601 
00604 template<typename Real>
00605 class RGB_converter_to_Luv{
00606   
00607 public:
00608 
00609   typedef Real component_type;
00610   
00611   inline static void from_RGB_to_cartesian(const double r,
00612                                            const double g,
00613                                            const double b,
00614                                            component_type* const x,
00615                                            component_type* const y,
00616                                            component_type* const z);
00617 
00618   inline static void from_cartesian_to_RGB(const component_type x,
00619                                            const component_type y,
00620                                            const component_type z,
00621                                            double* const r,
00622                                            double* const g,
00623                                            double* const b);
00624 private:
00626 
00627   
00628   static const double Xn;
00629   static const double Yn;
00630   static const double Zn;
00632 
00634 
00635   
00636   static double L2Y(const double l);
00637   static double Y2L(const double y);
00639 };
00640 
00641 
00642 
00643 
00645 
00648 template<typename Real>
00649 class RGB_converter_to_grey_level{
00650   
00651 public:
00652 
00653   typedef Real component_type;
00654   
00655   inline static void from_RGB_to_cartesian(const double r,
00656                                            const double g,
00657                                            const double b,
00658                                            component_type* const x,
00659                                            component_type* const y,
00660                                            component_type* const z);
00661 
00662   inline static void from_cartesian_to_RGB(const component_type x,
00663                                            const component_type y,
00664                                            const component_type z,
00665                                            double* const r,
00666                                            double* const g,
00667                                            double* const b);
00668 
00669   inline static void set_min_value(const double value);
00670   inline static void set_max_value(const double value);
00671 };
00672 
00673 
00674 
00675 
00676 /*
00677 
00678   #######################
00679   # class Color_to_grey #
00680   #######################
00681 
00682  */
00683 
00685 
00687 template<typename Color,typename Grey>
00688 class Color_to_grey{
00689 public:
00690   Color_to_grey(){}
00691 
00692   Grey operator()(const Color& c){
00693     Grey r,g,b;
00694     c.get_RGB(&r,&g,&b);
00695     return (r+g+b)/3;
00696   }
00697 };
00698 
00699 
00700 
00701 
00702 
00703 /*
00704 
00705   #######################
00706   # class Grey_to_color #
00707   #######################
00708 
00709 */
00710 
00712 template<typename Grey,typename Color>
00713 class Grey_to_color{
00714 public:
00715   Grey_to_color(){}
00716 
00717   inline Color operator()(const Grey g){ return Color(g,g,g); }
00718 };
00719 
00720 
00721 
00722 
00723 /*
00724 
00725   ########################
00726   # class Black_or_white #
00727   ########################
00728   
00729 */
00730 
00732 template<typename Color>
00733 class Black_or_white{
00734 public:
00735   Black_or_white(){}
00736 
00737   inline Color operator()(const bool b){ return (b?(Color(1.0,1.0,1.0)):
00738                                                  (Color(0.0,0.0,0.0))); }
00739 };
00740 
00741 
00742 
00743 
00744 
00745 
00746 
00747 
00748 
00749 /*
00750   
00751   #############################################
00752   #############################################
00753   #############################################
00754   ######                                 ######
00755   ######   I M P L E M E N T A T I O N   ######
00756   ######                                 ######
00757   #############################################
00758   #############################################
00759   #############################################
00760   
00761 */
00762 
00763 
00764 
00765 
00766 
00767 
00768 
00769 /*
00770 
00771   #####################
00772   # class Basic_color #
00773   #####################
00774 
00775 */
00776 
00777 #ifndef WITHOUT_LIMITS
00778 
00779 template<typename RGB_converter>
00780 Basic_color<RGB_converter>::
00781 Basic_color()
00782   :x(std::numeric_limits<component_type>::signaling_NaN()),
00783    y(std::numeric_limits<component_type>::signaling_NaN()),
00784    z(std::numeric_limits<component_type>::signaling_NaN()){}
00785 
00786 #else
00787 
00788 template<typename RGB_converter>
00789 Basic_color<RGB_converter>::
00790 Basic_color()
00791   :x(),y(),z(){
00792 
00793 }
00794 
00795 #endif
00796 
00797 template<typename RGB_converter>
00798 Basic_color<RGB_converter>::
00799 Basic_color(const char r,const char g,const char b){
00800 
00801   RGB_converter::from_RGB_to_cartesian(static_cast<double>(r)/255,
00802                                        static_cast<double>(g)/255,
00803                                        static_cast<double>(b)/255,
00804                                        &x,&y,&z);
00805 }
00806 
00807 
00808 template<typename RGB_converter>
00809 Basic_color<RGB_converter>::
00810 Basic_color(const float r,const float g,const float b){
00811 
00812   RGB_converter::from_RGB_to_cartesian(static_cast<double>(r),
00813                                        static_cast<double>(g),
00814                                        static_cast<double>(b),
00815                                        &x,&y,&z);
00816 }
00817 
00818 
00819 template<typename RGB_converter>
00820 Basic_color<RGB_converter>::
00821 Basic_color(const double r,const double g,const double b){
00822 
00823   RGB_converter::from_RGB_to_cartesian(r,g,b,&x,&y,&z);
00824 }
00825 
00826 
00827 template<typename RGB_converter>
00828 Basic_color<RGB_converter>::
00829 Basic_color(const Basic_color<RGB_converter>& c)
00830   :x(c.x),y(c.y),z(c.z){
00831 }
00832 
00833 
00834 template<typename RGB_converter>
00835 Basic_color<RGB_converter>&
00836 Basic_color<RGB_converter>::
00837 operator=(const Basic_color<RGB_converter>& c){
00838 
00839   if (this!=&c){
00840     x = c.x;
00841     y = c.y;
00842     z = c.z;
00843   }
00844   
00845   return *this;
00846 }
00847 
00848 
00849 template<typename RGB_converter>
00850 bool
00851 Basic_color<RGB_converter>::
00852 operator==(const Basic_color<RGB_converter>& c) const{
00853   
00854   return ((x==c.x)&&(y==c.y)&&(z==c.z));
00855 }
00856 
00857 
00858 template<typename RGB_converter>
00859 bool
00860 Basic_color<RGB_converter>::
00861 operator!=(const Basic_color<RGB_converter>& c) const{
00862   
00863   return ((x!=c.x)||(y!=c.y)||(z!=c.z));
00864 }
00865 
00866 
00867 template<typename RGB_converter>
00868 void
00869 Basic_color<RGB_converter>::
00870 get_RGB(char* const r,char* const g,char* const b) const{
00871 
00872   double R,G,B;
00873   
00874   RGB_converter::from_cartesian_to_RGB(x,y,z,&R,&G,&B);
00875 
00876   *r = static_cast<char>(rint(R*255));
00877   *g = static_cast<char>(rint(G*255));
00878   *b = static_cast<char>(rint(B*255));  
00879 }
00880 
00881 
00882 template<typename RGB_converter>
00883 void
00884 Basic_color<RGB_converter>::
00885 get_RGB(float* const r,float* const g,float* const b) const{
00886 
00887   double R,G,B;
00888   
00889   RGB_converter::from_cartesian_to_RGB(x,y,z,&R,&G,&B);
00890 
00891   *r = static_cast<float>(R);
00892   *g = static_cast<float>(G);
00893   *b = static_cast<float>(B);  
00894 }
00895 
00896 
00897 template<typename RGB_converter>
00898 void
00899 Basic_color<RGB_converter>::
00900 get_RGB(double* const r,double* const g,double* const b) const{
00901   RGB_converter::from_cartesian_to_RGB(x,y,z,r,g,b);
00902 }
00903 
00904 
00908 template<typename RGB_converter>
00909 void
00910 Basic_color<RGB_converter>::
00911 get_space_position(component_type* const x_space,
00912                    component_type* const y_space,
00913                    component_type* const z_space) const{
00914   *x_space = x;
00915   *y_space = y;
00916   *z_space = z;
00917 }
00918 
00919 
00926 template<typename RGB_converter>
00927 template<typename Space_vector>
00928 void
00929 Basic_color<RGB_converter>::
00930 get_space_position(Space_vector* const space_vector) const{
00931   
00932   typedef typename Space_vector::value_type type;
00933   
00934   (*space_vector)[0] = static_cast<type>(x);
00935   (*space_vector)[1] = static_cast<type>(y);
00936   (*space_vector)[2] = static_cast<type>(z);
00937 }
00938 
00939 
00940 template<typename RGB_converter>
00941 void
00942 Basic_color<RGB_converter>::
00943 set_space_position(const component_type x_space,
00944                    const component_type y_space,
00945                    const component_type z_space){
00946   x = x_space;
00947   y = y_space;
00948   z = z_space;
00949 }
00950 
00951 
00955 template<typename RGB_converter>
00956 template<typename Space_vector>
00957 void
00958 Basic_color<RGB_converter>::
00959 set_space_position(const Space_vector& space_vector){
00960   x = static_cast<component_type>(space_vector[0]);
00961   y = static_cast<component_type>(space_vector[1]);
00962   z = static_cast<component_type>(space_vector[2]);
00963 }
00964 
00965 
00966 template<typename RGB_converter>
00967 bool
00968 Basic_color<RGB_converter>::
00969 is_not_a_color() const{
00970   return (is_signaling_NaN(x)||is_signaling_NaN(y)||is_signaling_NaN(z));  
00971 }
00972 
00973 
00974 template<typename RGB_converter>
00975 void
00976 Basic_color<RGB_converter>::
00977 write_to_bytes(std::ostream& out) const{
00978 
00979   using namespace IO_tools;
00980   
00981   int size = sizeof(component_type);
00982 
00983   switch (size){
00984     
00985   case 2:
00986     write_2_bytes(x,out); 
00987     write_2_bytes(y,out);
00988     write_2_bytes(z,out);
00989     return;
00990 
00991   case 4:
00992     write_4_bytes(x,out); 
00993     write_4_bytes(y,out);
00994     write_4_bytes(z,out);
00995     return;
00996 
00997   default:
00998     Message::error<<"Basic_color::write_to_bytes : sizeof(component_type) = "<<size
00999                   <<" non implemented"<<Message::done;
01000   }
01001   
01002   return;
01003 }
01004 
01005 
01006 template<typename RGB_converter>
01007 void
01008 Basic_color<RGB_converter>::
01009 read_from_bytes(std::istream& in){
01010 
01011   using namespace IO_tools;
01012 
01013   int size = sizeof(component_type);
01014 
01015   switch (size){
01016     
01017   case 2:
01018     read_2_bytes(&x,in); 
01019     read_2_bytes(&y,in);
01020     read_2_bytes(&z,in);
01021     return;
01022 
01023   case 4:
01024     read_4_bytes(&x,in); 
01025     read_4_bytes(&y,in);
01026     read_4_bytes(&z,in);
01027     return;
01028 
01029   default:
01030     Message::error<<"Basic_color::read_to_bytes : sizeof(component_type) = "<<size
01031                   <<" non implemenrted"<<Message::done;
01032   }
01033 }
01034 
01035 
01036 template<typename RGB_converter>
01037 typename Basic_color<RGB_converter>::distance_type
01038 Basic_color<RGB_converter>::
01039 square_distance(const Basic_color<RGB_converter>& c1,
01040                 const Basic_color<RGB_converter>& c2){
01041 
01042   const distance_type dx = c1.x - c2.x;
01043   const distance_type dy = c1.y - c2.y;
01044   const distance_type dz = c1.z - c2.z;
01045 
01046   return (dx*dx + dy*dy + dz*dz);
01047 }
01048 
01049 
01053 template<typename RGB_converter>
01054 typename Basic_color<RGB_converter>::distance_type
01055 Basic_color<RGB_converter>::
01056 distance(const Basic_color<RGB_converter>& c1,
01057          const Basic_color<RGB_converter>& c2){
01058   return sqrtf(square_distance(c1,c2));
01059 }
01060 
01061 
01062 template<typename RGB_converter>
01063 template<typename Basic_color_iterator>
01064 void
01065 Basic_color<RGB_converter>::
01066 mean(Basic_color_iterator first,
01067      Basic_color_iterator last,
01068      Basic_color<RGB_converter>* const result){
01069 
01070   unsigned int n     = 0;
01071   result->x = 0;
01072   result->y = 0;
01073   result->z = 0;  
01074   
01075   for(Basic_color_iterator c=first;c!=last;c++){
01076     result->x += c->x;
01077     result->y += c->y;
01078     result->z += c->z;
01079     n++;
01080   }
01081 
01082   result->x /= n;
01083   result->y /= n;
01084   result->z /= n;
01085 }
01086 
01087 
01088 template<typename RGB_converter>
01089 template<typename Basic_color_iterator,typename Weight_iterator>
01090 void
01091 Basic_color<RGB_converter>::
01092 mean(Basic_color_iterator first_clr,
01093      Basic_color_iterator last_clr,
01094      Weight_iterator      first_w,
01095      Weight_iterator      last_w,
01096      Basic_color<RGB_converter>* const result){
01097 
01098   component_type n = 0;
01099   result->x        = 0;
01100   result->y        = 0;
01101   result->z        = 0;
01102   
01103   Basic_color_iterator c;
01104   Weight_iterator w;
01105   for(c=first_clr,w=first_w;
01106       (c!=last_clr)&&(w!=last_w);
01107       c++,w++){
01108     result->x += c->x * (*w);
01109     result->y += c->y * (*w);
01110     result->z += c->z * (*w);
01111     n         += (*w);
01112   }
01113 
01114   if (n==0){
01115     Message::warning<<"Basic_color::mean : the weight sum is null\n"<<Message::done;
01116     *result = Basic_color<RGB_converter>();
01117   }
01118   else{
01119     result->x /= n;
01120     result->y /= n;
01121     result->z /= n;
01122   }
01123 }
01124 
01125 
01126 template<typename RGB_converter>
01127 template<typename Basic_color_iterator>
01128 void
01129 Basic_color<RGB_converter>::
01130 robust_mean(Basic_color_iterator first,
01131             Basic_color_iterator last,
01132             Basic_color<RGB_converter>* const result,
01133             const unsigned int n_iter){
01134   
01135   mean(first,last,result);
01136 
01137   if (n_iter==0){
01138     return;
01139   }
01140   
01141   int n             = 0;
01142   distance_type sum = 0;
01143 
01144   std::list<distance_type> dist;
01145 
01146   // Compute the variamce.
01147   
01148   for(Basic_color_iterator c=first;c!=last;c++){
01149     distance_type sq = square_distance(*c,*result);
01150     dist.push_back(sq);
01151     sum += sq;
01152     n++;
01153   }
01154 
01155   distance_type sq_dev;
01156 
01157   if (n>0) {
01158     sq_dev = (sum/n);
01159   }
01160 
01161 #ifndef WITHOUT_LIMITS
01162   else{
01163     sq_dev = std::numeric_limits<distance_type>::signaling_NaN();
01164     Message::warning<<"no color to compute the variance"<<Message::done;
01165   }
01166 #endif
01167 
01168   // Keep only the nearest ones.
01169   typedef typename std::iterator_traits<Basic_color_iterator>::value_type
01170     color_type;
01171   
01172   std::list<color_type> near_one;
01173 
01174   n = 0;
01175   Basic_color_iterator               c;
01176   typename std::list<distance_type>::iterator d;
01177   for(c=first,d=dist.begin();c!=last;c++,d++){
01178     if ((*d)<=sq_dev){
01179       near_one.push_back(*c);
01180       n++;
01181     }
01182   }
01183 
01184   
01185   robust_mean(near_one.begin(),near_one.end(),result,n_iter-1);
01186 }
01187 
01188 
01189 template<typename RGB_converter>
01190 template<typename Basic_color_iterator,typename Weight_iterator>
01191 void
01192 Basic_color<RGB_converter>::
01193 robust_mean(Basic_color_iterator first_clr,
01194                  Basic_color_iterator last_clr,
01195                  Weight_iterator first_w,
01196                  Weight_iterator last_w,
01197                  Basic_color<RGB_converter>* const result,
01198                  const unsigned int n_iter){
01199 
01200   mean(first_clr,last_clr,first_w,last_w,result);
01201 
01202   if (n_iter==0){
01203     return;
01204   }
01205   
01206   component_type n   = 0;
01207   distance_type  sum = 0;
01208 
01209   std::list<distance_type> dist;
01210 
01211   // Compute the variance.
01212   Basic_color_iterator c;
01213   Weight_iterator w;
01214   for(c=first_clr,w=first_w;
01215       (c!=last_clr)&&(w!=last_w);
01216       c++,w++){
01217 
01218     distance_type sq = square_distance(*c,*result);
01219     dist.push_back(sq);
01220     sum += (*w) * sq;
01221     n += *w;
01222   }
01223 
01224   distance_type sq_dev;
01225 
01226   if (n>0) {
01227     sq_dev = (sum/n);
01228   }
01229 
01230 #ifndef WITHOUT_LIMITS
01231   else{
01232     sq_dev = std::numeric_limits<distance_type>::signaling_NaN();
01233     Message::warning<<"no color to compute the variance"<<Message::done;
01234   }
01235 #endif
01236 
01237   // Keep only the nearest one.
01238   typedef typename std::iterator_traits<Basic_color_iterator>::value_type
01239     color_type;
01240   typedef typename std::iterator_traits<Weight_iterator>::value_type
01241     weight_type;
01242   
01243   std::list<color_type> near_clr;
01244   std::list<weight_type> near_w;
01245 
01246   n = 0;
01247   typename std::list<distance_type>::iterator d;
01248   for(c=first_clr, w=first_w, d=dist.begin();
01249       (c != last_clr) && (w != last_w);
01250       c++, w++, d++){
01251     
01252     if ((*d)<=sq_dev){
01253       near_clr.push_back(*c);
01254       near_w.push_back(*w);
01255       n++;
01256     }
01257   }
01258 
01259   
01260   robust_mean(near_clr.begin(),near_clr.end(),
01261               near_w.begin(),near_w.end(),
01262               result,n_iter-1);
01263 
01264 }
01265 
01266 
01267 template<typename RGB_converter>
01268 template<typename Basic_color_iterator>
01269 typename Basic_color<RGB_converter>::distance_type
01270 Basic_color<RGB_converter>::
01271 square_deviation(Basic_color_iterator first,
01272                  Basic_color_iterator last){
01273 
01274   Basic_color<RGB_converter> mean_color;
01275 
01276   return square_deviation(first,last,&mean_color);
01277 }
01278 
01279 
01280 template<typename RGB_converter>
01281 template<typename Basic_color_iterator>
01282 typename Basic_color<RGB_converter>::distance_type
01283 Basic_color<RGB_converter>::
01284 square_deviation(Basic_color_iterator first,
01285                  Basic_color_iterator last,
01286                  Basic_color<RGB_converter>* const mean_color){
01287 
01288   mean(first,last,mean_color);
01289 
01290   int n             = 0;
01291   distance_type sum = 0;
01292   
01293   for(Basic_color_iterator c=first;c!=last;c++){
01294     sum += square_distance(*c,*mean_color);
01295     n++;
01296   }
01297 
01298 #ifndef WITHOUT_LIMITS
01299   return ((n>0)?(sum/n):(std::numeric_limits<distance_type>::signaling_NaN()));
01300 #else
01301   return (sum/n);
01302 #endif
01303 }
01304 
01305 
01306 template<typename RGB_converter>
01307 void
01308 Basic_color<RGB_converter>::
01309 main_conversion_output(std::ostream& out){
01310 
01311   Basic_color<RGB_converter> clr;
01312   component_type r,g,b;
01313 
01314   clr = white;
01315   clr.get_RGB(&r,&g,&b);
01316   out<<"r: "<<r<<"\tg: "<<g<<"\tb: "<<b<<"\n"
01317      <<"->\tx: "<<clr.x<<"\ty: "<<clr.y<<"\tz: "<<clr.z<<"\n"<<std::endl;
01318 
01319   clr = grey;
01320   clr.get_RGB(&r,&g,&b);
01321   out<<"r: "<<r<<"\tg: "<<g<<"\tb: "<<b<<"\n"
01322      <<"->\tx: "<<clr.x<<"\ty: "<<clr.y<<"\tz: "<<clr.z<<"\n"<<std::endl;
01323 
01324   clr = black;
01325   clr.get_RGB(&r,&g,&b);
01326   out<<"r: "<<r<<"\tg: "<<g<<"\tb: "<<b<<"\n"
01327      <<"->\tx: "<<clr.x<<"\ty: "<<clr.y<<"\tz: "<<clr.z<<"\n"<<std::endl;
01328 
01329   clr = red;
01330   clr.get_RGB(&r,&g,&b);
01331   out<<"r: "<<r<<"\tg: "<<g<<"\tb: "<<b<<"\n"
01332      <<"->\tx: "<<clr.x<<"\ty: "<<clr.y<<"\tz: "<<clr.z<<"\n"<<std::endl;
01333 
01334   clr = green;
01335   clr.get_RGB(&r,&g,&b);
01336   out<<"r: "<<r<<"\tg: "<<g<<"\tb: "<<b<<"\n"
01337      <<"->\tx: "<<clr.x<<"\ty: "<<clr.y<<"\tz: "<<clr.z<<"\n"<<std::endl;
01338   
01339   clr = blue;
01340   clr.get_RGB(&r,&g,&b);
01341   out<<"r: "<<r<<"\tg: "<<g<<"\tb: "<<b<<"\n"
01342      <<"->\tx: "<<clr.x<<"\ty: "<<clr.y<<"\tz: "<<clr.z<<"\n"<<std::endl;
01343   
01344   clr = cyan;
01345   clr.get_RGB(&r,&g,&b);
01346   out<<"r: "<<r<<"\tg: "<<g<<"\tb: "<<b<<"\n"
01347      <<"->\tx: "<<clr.x<<"\ty: "<<clr.y<<"\tz: "<<clr.z<<"\n"<<std::endl;
01348 
01349   clr = magenta;
01350   clr.get_RGB(&r,&g,&b);
01351   out<<"r: "<<r<<"\tg: "<<g<<"\tb: "<<b<<"\n"
01352      <<"->\tx: "<<clr.x<<"\ty: "<<clr.y<<"\tz: "<<clr.z<<"\n"<<std::endl;
01353   
01354   clr = yellow;
01355   clr.get_RGB(&r,&g,&b);
01356   out<<"r: "<<r<<"\tg: "<<g<<"\tb: "<<b<<"\n"
01357      <<"->\tx: "<<clr.x<<"\ty: "<<clr.y<<"\tz: "<<clr.z<<"\n"<<std::endl;
01358 }
01359 
01360 
01361 template<typename RGB_converter>
01362 const Basic_color<RGB_converter>
01363 Basic_color<RGB_converter>::white(1.0f, 1.0f, 1.0f);
01364 
01365 template<typename RGB_converter>
01366 const Basic_color<RGB_converter>
01367 Basic_color<RGB_converter>::grey(0.5f, 0.5f, 0.5f);
01368 
01369 template<typename RGB_converter>
01370 const Basic_color<RGB_converter>
01371 Basic_color<RGB_converter>::black(0.0f, 0.0f, 0.0f);
01372 
01373 template<typename RGB_converter>
01374 const Basic_color<RGB_converter>
01375 Basic_color<RGB_converter>::red(1.0f, 0.0f, 0.0f);
01376 
01377 template<typename RGB_converter>
01378 const Basic_color<RGB_converter>
01379 Basic_color<RGB_converter>::green(0.0f, 1.0f, 0.0f);
01380 
01381 template<typename RGB_converter>
01382 const Basic_color<RGB_converter>
01383 Basic_color<RGB_converter>::blue(0.0f, 0.0f, 1.0f);
01384 
01385 template<typename RGB_converter>
01386 const Basic_color<RGB_converter>
01387 Basic_color<RGB_converter>::cyan(0.0f, 1.0f, 1.0f);
01388 
01389 template<typename RGB_converter>
01390 const Basic_color<RGB_converter>
01391 Basic_color<RGB_converter>::magenta(1.0f, 0.0f, 1.0f);
01392 
01393 template<typename RGB_converter>
01394 const Basic_color<RGB_converter>
01395 Basic_color<RGB_converter>::yellow(1.0f, 1.0f, 0.0f);
01396 
01397 
01398 template<typename RGB_converter>
01399 void
01400 Basic_color<RGB_converter>::
01401 cycle(const double alpha,
01402       Basic_color<RGB_converter>* const result,
01403       const Basic_color<RGB_converter>& clr_0,
01404       const Basic_color<RGB_converter>& clr_1,
01405       const Basic_color<RGB_converter>& clr_2,
01406       const Basic_color<RGB_converter>& clr_3){
01407 
01408   const double a = alpha - floor(alpha/(2.0*M_PI))*2.0*M_PI;
01409   
01410   std::vector<Basic_color<RGB_converter> > color(2);
01411   std::vector<double>                      weight(2);
01412 
01413 
01414   if ((a<0) || (a>2.0*M_PI)){
01415     Message::error<<"Basic_color<RGB_converter>::cycle : valeur de a"
01416                   <<" non valable : "<<a<<Message::done;
01417   }
01418   
01419   if ((a>=0) && (a<=M_PI_2)){
01420     color[0]  = clr_0;
01421     weight[0] = M_PI_2 - a;
01422     
01423     color[1]  = clr_1;
01424     weight[1] = M_PI_2 - weight[0]; 
01425   }
01426 
01427   if ((a>M_PI_2) && (a<=M_PI)){
01428     color[0]  = clr_1;
01429     weight[0] = M_PI - a;
01430     color[1]  = clr_2;
01431     weight[1] = M_PI_2 - weight[0]; 
01432   }
01433 
01434   if ((a>M_PI) && (a<=1.5*M_PI)){
01435     color[0]  = clr_2;
01436     weight[0] = 1.5*M_PI - a;
01437     color[1]  = clr_3;
01438     weight[1] = M_PI_2 - weight[0]; 
01439   }
01440 
01441   if ((a>1.5*M_PI) && (a<=2.0*M_PI)){
01442     color[0]  = clr_3;
01443     weight[0] = 2*M_PI - a;
01444     color[1]  = clr_0;
01445     weight[1] = M_PI_2 - weight[0]; 
01446   }
01447 
01448   mean(color.begin(),color.end(),weight.begin(),weight.end(),result);
01449 }
01450 
01451 
01452 /*
01453 
01454   ##############################
01455   # class RGB_converter_to_HSV #
01456   ##############################
01457 
01458 */
01459 
01460 template<typename Real>
01461 void
01462 RGB_converter_to_HSV<Real>::
01463 from_RGB_to_cartesian(const double r,
01464                       const double g,
01465                       const double b,
01466                       component_type* const x,
01467                       component_type* const y,
01468                       component_type* const z){
01469   
01470   double h,s,v;
01471   RGB_to_HSV(r,g,b,&h,&s,&v);
01472 
01473 #ifndef M_PI
01474   const double theta = 2 * 3.14159265358979323846 * h;
01475 #else
01476   const double theta = 2 * M_PI * h;
01477 #endif
01478 
01479   const float f = s*v;
01480 
01481   *x = static_cast<component_type>(f * cos(theta));
01482   *y = static_cast<component_type>(f * sin(theta));
01483   *z = static_cast<component_type>(v);
01484 }
01485 
01486 
01487 template<typename Real>
01488 void
01489 RGB_converter_to_HSV<Real>::
01490 from_cartesian_to_RGB(const component_type x,
01491                       const component_type y,
01492                       const component_type z,
01493                       double* const r,
01494                       double* const g,
01495                       double* const b){
01496 
01497   const double X = static_cast<double>(x);
01498   const double Y = static_cast<double>(y);
01499   const double f = sqrt(X*X + Y*Y);
01500   const double v = static_cast<double>(z);
01501   const double s = (v>0.0)?(f/v):(0.0);
01502 
01503 #ifndef M_PI
01504   double theta = atan2(Y,X) / (2 * 3.14159265358979323846);
01505 #else
01506   double theta = atan2(Y,X) / (2 * M_PI);
01507 #endif
01508 
01509   const double h = (theta>0) ? theta : (theta + 1);
01510   
01511   HSV_to_RGB(h,s,v,r,g,b);
01512 }
01513 
01514 
01515 template<typename Real>
01516 void
01517 RGB_converter_to_HSV<Real>::
01518 RGB_to_HSV(const double r,  const double g,  const double b,
01519            double* const h, double* const s, double* const v){
01520 
01521   const double min   = std::min(r,std::min(g,b));
01522   const double max   = std::max(r,std::max(g,b));
01523   const double delta = max - min;
01524   
01525   *v = max; 
01526     
01527   if (max!=0)
01528     *s = delta / max;    
01529   else {
01530     *s = 0;
01531     *h = 0;
01532     return;
01533   }
01534     
01535   if (delta==0) { 
01536     *s = 0;
01537     *h = 0;
01538     return;
01539   }
01540 
01541   if(r==max) {
01542       *h = ( g - b ) / delta;        // between yellow & magenta
01543   }
01544   else if( g == max ) {
01545     *h = 2 + ( b - r ) / delta;    // between cyan & yellow
01546   }
01547   else {
01548     *h = 4 + ( r - g ) / delta;    // between magenta & cyan
01549   }
01550     
01551   *h /= 6;    
01552   if(*h<0){
01553     *h += 1;
01554   }
01555 
01556 }
01557   
01558 template<typename Real>
01559 void
01560 RGB_converter_to_HSV<Real>::
01561 HSV_to_RGB(const double h,const double s,const double v,
01562            double* const r,double* const g,double* const b){
01563   
01564   if(s==0) { // achromatic (grey)
01565     *r = v;
01566     *g = v;
01567     *b = v;
01568     return;
01569   }
01570   
01571   const int i    = static_cast<int>(floor(6*h));
01572   const double f = 6*h - i;     
01573   const double p = v * ( 1 - s );
01574   const double q = v * ( 1 - s * f );
01575   const double t = v * ( 1 - s * ( 1 - f ) );
01576  
01577   switch(i) {
01578   case 6:
01579   case 0:
01580     *r = v;
01581     *g = t;
01582     *b = p;
01583     break;
01584     
01585   case 1:
01586     *r = q;
01587     *g = v;
01588     *b = p;
01589     break;
01590     
01591   case 2:
01592     *r = p;
01593     *g = v;
01594     *b = t;
01595     break;
01596     
01597   case 3:
01598     *r = p;
01599     *g = q;
01600     *b = v;
01601     break;
01602     
01603   case 4:
01604     *r = t;
01605     *g = p;
01606     *b = v;
01607     break;
01608     
01609   default:  
01610     *r = v;
01611     *g = p;
01612     *b = q;
01613     break;
01614   }   
01615 }
01616 
01618 
01619 
01620 /*
01621 
01622   ##############################
01623   # class RGB_converter_to_RGB #
01624   ##############################
01625 
01626 */
01627 
01628 
01629 template<typename Real>
01630 void
01631 RGB_converter_to_RGB<Real>::
01632 from_RGB_to_cartesian(const double r,
01633                       const double g,
01634                       const double b,
01635                       component_type* const x,
01636                       component_type* const y,
01637                       component_type* const z){
01638   
01639   *x = static_cast<component_type>(r);
01640   *y = static_cast<component_type>(g);
01641   *z = static_cast<component_type>(b);
01642 }
01643 
01644 template<typename Real>
01645 void
01646 RGB_converter_to_RGB<Real>::
01647 from_cartesian_to_RGB(const component_type x,
01648                       const component_type y,
01649                       const component_type z,
01650                       double* const r,
01651                       double* const g,
01652                       double* const b){
01653   
01654   *r = static_cast<double>(x);
01655   *g = static_cast<double>(y);
01656   *b = static_cast<double>(z);
01657 }
01658 
01659 
01660 
01661 /*
01662 
01663   ##############################
01664   # class RGB_converter_to_XYZ #
01665   ##############################
01666 
01667 */
01668 
01669 template<typename Real>
01670 void
01671 RGB_converter_to_XYZ<Real>::
01672 from_RGB_to_cartesian(const double r,
01673                       const double g,
01674                       const double b,
01675                       component_type* const x,
01676                       component_type* const y,
01677                       component_type* const z){
01678   
01679   *x = static_cast<component_type>(r*0.412453 + g*0.357580 + b*0.180423);
01680   *y = static_cast<component_type>(r*0.212671 + g*0.715160 + b*0.072169);
01681   *z = static_cast<component_type>(r*0.019334 + g*0.119193 + b*0.950227);
01682 
01683 
01684 }
01685 
01686 
01687 template<typename Real>
01688 void
01689 RGB_converter_to_XYZ<Real>::
01690 from_cartesian_to_RGB(const component_type x,
01691                       const component_type y,
01692                       const component_type z,
01693                       double* const r,
01694                       double* const g,
01695                       double* const b){
01696 
01697   
01698 
01699   const double R =
01700     static_cast<double>(x*3.240479 + y*-1.537150 + z*-0.498535);
01701   const double G =
01702     static_cast<double>(x*-0.969256 + y*1.875992 + z*0.041556);
01703   const double B =
01704     static_cast<double>(x*0.055648 + y*-0.204043 + z*1.057311);
01705 
01706   if (R<0.0)      { *r = 0.0; }
01707   else if (R>1.0) { *r = 1.0; }
01708   else            { *r = R; }
01709 
01710   if (G<0.0)      { *g = 0.0; }
01711   else if (G>1.0) { *g = 1.0; }
01712   else            { *g = G; }
01713 
01714   if (B<0.0)      { *b = 0.0; }
01715   else if (B>1.0) { *b = 1.0; }
01716   else            { *b = B; }
01717 }
01718 
01719 
01720 
01721 /*
01722 
01723   ##############################
01724   # class RGB_converter_to_Luv #
01725   ##############################
01726 */
01727 
01728 template<typename Real>
01729 const double RGB_converter_to_Luv<Real>::Xn = 0.95045592705;
01730 template<typename Real>
01731 const double RGB_converter_to_Luv<Real>::Yn = 1.0;
01732 template<typename Real>
01733 const double RGB_converter_to_Luv<Real>::Zn = 1.0890577508;
01734 
01735 template<typename Real>
01736 double
01737 RGB_converter_to_Luv<Real>::L2Y(const double l){
01738 
01739   return (l>7.99625) ?
01740     Yn*pow((l+16)/116,3.0) :
01741     Yn*l/903.3;
01742 }
01743 
01744 template<typename Real>
01745 double
01746 RGB_converter_to_Luv<Real>::Y2L(const double y){
01747 
01748   const double ratio = y/Yn;
01749 
01750   return (ratio>0.008856) ?
01751     116 * pow(ratio,1.0/3.0) - 16 :
01752     903.3 * ratio;
01753 }
01754 
01755 
01756 template<typename Real>
01757 void
01758 RGB_converter_to_Luv<Real>::
01759 from_RGB_to_cartesian(const double r,
01760                       const double g,
01761                       const double b,
01762                       component_type* const x,
01763                       component_type* const y,
01764                       component_type* const z){
01765   
01766   const double X = r*0.412453 + g*0.357580 + b*0.180423;
01767   const double Y = r*0.212671 + g*0.715160 + b*0.072169;
01768   const double Z = r*0.019334 + g*0.119193 + b*0.950227;
01769 
01770 
01771   *x = static_cast<component_type>(Y2L(Y / Yn));
01772   const double tmp = Xn + 15 * Yn + 3 * Zn;
01773   const double unp = 4 * Xn / tmp;
01774   const double vnp = 9 * Yn / tmp;
01775   const double tmp2 = X + 15 * Y + 3 * Z;
01776   const double up = (X==0)? 0 : 4 * X / tmp2;
01777   const double vp = (Y==0)? 0 : 9 * Y / tmp2;
01778   *y = static_cast<component_type>(13 * (*x) * (up - unp));
01779   *z = static_cast<component_type>(13 * (*x) * (vp - vnp));
01780 }
01781 
01782 
01783 template<typename Real>
01784 void
01785 RGB_converter_to_Luv<Real>::
01786 from_cartesian_to_RGB(const component_type x,
01787                       const component_type y,
01788                       const component_type z,
01789                       double* const r,
01790                       double* const g,
01791                       double* const b){
01792 
01793   const double Y = L2Y(static_cast<double>(x));
01794   const double tmp = Xn + 15 * Yn + 3 * Zn;
01795   const double unp = 4 * Xn / tmp;
01796   const double vnp = 9 * Yn / tmp;
01797   const double Q = ((y==0) ? 0
01798     : static_cast<double>(y) / (13 * static_cast<double>(x))) + unp;
01799   const double R = ((z==0) ? 0
01800     : static_cast<double>(z) / (13 * static_cast<double>(x))) + vnp;
01801   const double A = 3 * Y * (5 * R - 3);
01802   const double Z = ((Q - 4) * A - 15 * Q * R * Y) / (12 * R);
01803   const double X = -(A / R + 3 * Z);
01804 
01805 
01806   const double red   = X*3.240479  + Y*-1.537150 + Z*-0.498535;
01807   const double green = X*-0.969256 + Y*1.875992  + Z*0.041556;
01808   const double blue  = X*0.055648  + Y*-0.204043 + Z*1.057311;
01809 
01810   if (red<0.0)      { *r = 0.0; }
01811   else if (red>1.0) { *r = 1.0; }
01812   else              { *r = red; }
01813 
01814   if (green<0.0)      { *g = 0.0; }
01815   else if (green>1.0) { *g = 1.0; }
01816   else                { *g = green; }
01817 
01818   if (blue<0.0)      { *b = 0.0; }
01819   else if (blue>1.0) { *b = 1.0; }
01820   else               { *b = blue; }
01821 }
01822 
01823 
01824 /*
01825 
01826   #####################################
01827   # class RGB_converter_to_grey_level #
01828   #####################################
01829   
01830 */
01831 
01832 
01833 
01834 template<typename Real>
01835 void
01836 RGB_converter_to_grey_level<Real>::
01837 from_RGB_to_cartesian(const double r,
01838                       const double g,
01839                       const double b,
01840                       component_type* const x,
01841                       component_type* const y,
01842                       component_type* const z){
01843 
01844   *x = static_cast<component_type>((r+g+b)/3.0);
01845   *y = static_cast<component_type>(0);
01846   *z = static_cast<component_type>(0);
01847 }
01848 
01849 
01850 template<typename Real>
01851 void
01852 RGB_converter_to_grey_level<Real>::
01853 from_cartesian_to_RGB(const component_type x,
01854                       const component_type y,
01855                       const component_type z,
01856                       double* const r,
01857                       double* const g,
01858                       double* const b){
01859   
01860   *r = static_cast<double>(x);
01861   *g = static_cast<double>(x);
01862   *b = static_cast<double>(x);
01863 }
01864 
01865 
01866 
01867 /*
01868 
01869   #########################
01870   # Fonctions hors classe #
01871   #########################
01872 
01873  */
01874 
01875 template<typename RGB_converter>
01876 std::ostream& operator<<(std::ostream& s,
01877                          const Basic_color<RGB_converter>& c){
01878 
01879   s<<c.x<<"\t"<<c.y<<"\t"<<c.z<<"\t";
01880   
01881   return s;
01882 }
01883 
01884 #undef CONST_STATIC
01885 
01886 #endif
01887 

Generated on Fri Aug 20 15:03:52 2004 by doxygen1.2.18