1 #ifndef color_hsl_convert_rgb
2 #define color_hsl_convert_rgb
3 
4 #include "../category.hpp"
5 #include "../place/place.hpp"
6 
7 #include "../../_internal/convert.hpp"
8 
9 #include "../../rgb/trait/container.hpp"
10 #include "../../rgb/trait/component.hpp"
11 #include "../../rgb/trait/index.hpp"
12 #include "../../rgb/trait/bound.hpp"
13 #include "../../rgb/category.hpp"
14 
15 
16 #include "../../_internal/normalize.hpp"
17 #include "../../_internal/diverse.hpp"
18 
19 
20 namespace color
21  {
22   namespace _internal
23    {
24 
25     template
26      <
27        typename hsl_tag_name
28       ,typename rgb_tag_name
29      >
30      struct convert
31       <
32         ::color::category::hsl< hsl_tag_name >
33        ,::color::category::rgb< rgb_tag_name >
34       >
35       {
36        public:
37          typedef ::color::category::hsl< hsl_tag_name > category_left_type;
38          typedef ::color::category::rgb< rgb_tag_name > category_right_type;
39 
40          typedef typename ::color::trait::scalar<category_left_type>::instance_type scalar_type;
41 
42          typedef ::color::trait::scalar<category_left_type> scalar_trait_type;
43 
44          typedef ::color::trait::container<category_left_type>     container_left_trait_type;
45          typedef ::color::trait::container<category_right_type>    container_right_trait_type;
46 
47          typedef typename container_left_trait_type::input_type         container_left_input_type;
48          typedef typename container_right_trait_type::model_type  container_right_const_input_type;
49 
50          typedef ::color::_internal::diverse< category_left_type >    diverse_type;
51          typedef ::color::_internal::normalize< category_right_type > normalize_type;
52 
53          enum
54           {
55                    hue_p = ::color::place::_internal::hue<category_left_type>::position_enum
56            ,saturation_p = ::color::place::_internal::saturation<category_left_type>::position_enum
57            , lightness_p = ::color::place::_internal::lightness<category_left_type>::position_enum
58           };
59 
60          enum
61           {
62             red_p   = ::color::place::_internal::red<category_right_type>::position_enum
63            ,green_p = ::color::place::_internal::green<category_right_type>::position_enum
64            ,blue_p  = ::color::place::_internal::blue<category_right_type>::position_enum
65           };
66 
processcolor::_internal::convert67          static void process
68           (
69             container_left_input_type         left
70            ,container_right_const_input_type  right
71           )
72           {
73            scalar_type r = normalize_type::template process<red_p  >( container_right_trait_type::template get<red_p  >( right ) );
74            scalar_type g = normalize_type::template process<green_p>( container_right_trait_type::template get<green_p>( right ) );
75            scalar_type b = normalize_type::template process<blue_p >( container_right_trait_type::template get<blue_p >( right ) );
76 
77            const scalar_type hi = std::max<scalar_type>( { r, g, b } );
78            const scalar_type lo = std::min<scalar_type>( { r, g, b } );
79            scalar_type delta = hi - lo;
80 
81            scalar_type h = 0;
82            scalar_type s = 0;
83            scalar_type l = (hi + lo) / scalar_type(2);
84 
85            if( false == scalar_trait_type::is_small( delta ) )
86             {
87              s = delta / ( 1 - fabs( 2*l - 1 ) );
88              if( hi == r )
89               {
90                h = (scalar_type(60)/scalar_type(360)) * (g - b) / delta + (g < b ? scalar_type(1) : scalar_type(0));
91               }
92              if( hi == g )
93               {
94                h = (scalar_type(60)/scalar_type(360)) * (b - r) / delta + (scalar_type(120)/scalar_type(360));
95               }
96              if( hi == b )
97               {
98                h = (scalar_type(60)/scalar_type(360)) * (r - g) / delta + (scalar_type(240)/scalar_type(360));
99               }
100             }
101 
102            container_left_trait_type::template set<       hue_p>( left, diverse_type::template process<       hue_p>( h ) );
103            container_left_trait_type::template set<saturation_p>( left, diverse_type::template process<saturation_p>( s ) );
104            container_left_trait_type::template set< lightness_p>( left, diverse_type::template process< lightness_p>( l ) );
105           }
106       };
107 
108    }
109  }
110 
111 #endif
112