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
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
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
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
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
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
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
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
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
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
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
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
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
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
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
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
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
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
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
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;
01543 }
01544 else if( g == max ) {
01545 *h = 2 + ( b - r ) / delta;
01546 }
01547 else {
01548 *h = 4 + ( r - g ) / delta;
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) {
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
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
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
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
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
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