2 // Copyright 2012 Christian Henning
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
8 #ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSL_HPP
9 #define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSL_HPP
11 #include <boost/gil/color_convert.hpp>
12 #include <boost/gil/typedefs.hpp>
13 #include <boost/gil/detail/mp11.hpp>
15 namespace boost{ namespace gil {
17 /// \addtogroup ColorNameModel
19 namespace hsl_color_space
24 struct saturation_t {};
26 struct lightness_t {};
30 /// \ingroup ColorSpaceModel
31 using hsl_t = mp11::mp_list
33 hsl_color_space::hue_t,
34 hsl_color_space::saturation_t,
35 hsl_color_space::lightness_t
38 /// \ingroup LayoutModel
39 using hsl_layout_t = layout<hsl_t>;
42 GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, hsl)
44 /// \ingroup ColorConvert
47 struct default_color_converter_impl< rgb_t, hsl_t >
49 template <typename P1, typename P2>
50 void operator()( const P1& src, P2& dst ) const
52 using namespace hsl_color_space;
54 // only float32_t for hsl is supported
55 float32_t temp_red = channel_convert<float32_t>( get_color( src, red_t() ));
56 float32_t temp_green = channel_convert<float32_t>( get_color( src, green_t() ));
57 float32_t temp_blue = channel_convert<float32_t>( get_color( src, blue_t() ));
59 float32_t hue, saturation, lightness;
61 float32_t min_color = (std::min)( temp_red, (std::min)( temp_green, temp_blue ));
62 float32_t max_color = (std::max)( temp_red, (std::max)( temp_green, temp_blue ));
64 if( std::abs( min_color - max_color ) < 0.001 )
71 // doesn't matter which rgb channel we use.
77 float32_t diff = max_color - min_color;
79 // lightness calculation
81 lightness = ( min_color + max_color ) / 2.f;
83 // saturation calculation
85 if( lightness < 0.5f )
88 / ( min_color + max_color );
92 saturation = ( max_color - min_color )
98 if( std::abs( max_color - temp_red ) < 0.0001f )
101 hue = ( temp_green - temp_blue )
105 else if( std::abs( max_color - temp_green) < 0.0001f )
107 // max_color is green
108 // 2.0 + (b - r) / (maxColor - minColor);
110 + ( temp_blue - temp_red )
118 + ( temp_red - temp_blue )
130 get_color( dst,hue_t() ) = hue;
131 get_color( dst,saturation_t() ) = saturation;
132 get_color( dst,lightness_t() ) = lightness;
136 /// \ingroup ColorConvert
137 /// \brief HSL to RGB
139 struct default_color_converter_impl<hsl_t,rgb_t>
141 template <typename P1, typename P2>
142 void operator()( const P1& src, P2& dst) const
144 using namespace hsl_color_space;
146 float32_t red, green, blue;
148 if( std::abs( get_color( src, saturation_t() )) < 0.0001 )
150 // If saturation is 0, the color is a shade of gray
151 red = get_color( src, lightness_t() );
152 green = get_color( src, lightness_t() );
153 blue = get_color( src, lightness_t() );
158 float tempr, tempg, tempb;
160 //Set the temporary values
161 if( get_color( src, lightness_t() ) < 0.5 )
163 temp2 = get_color( src, lightness_t() )
164 * ( 1.f + get_color( src, saturation_t() ) );
168 temp2 = ( get_color( src, lightness_t() ) + get_color( src, saturation_t() ))
169 - ( get_color( src, lightness_t() ) * get_color( src, saturation_t() ));
173 * get_color( src, lightness_t() )
176 tempr = get_color( src, hue_t() ) + 1.f / 3.f;
183 tempg = get_color( src, hue_t() );
184 tempb = get_color( src, hue_t() ) - 1.f / 3.f;
192 if( tempr < 1.f / 6.f )
194 red = temp1 + ( temp2 - temp1 ) * 6.f * tempr;
196 else if( tempr < 0.5f )
200 else if( tempr < 2.f / 3.f )
202 red = temp1 + (temp2 - temp1)
203 * (( 2.f / 3.f ) - tempr) * 6.f;
211 if( tempg < 1.f / 6.f )
213 green = temp1 + ( temp2 - temp1 ) * 6.f * tempg;
215 else if( tempg < 0.5f )
219 else if( tempg < 2.f / 3.f )
221 green = temp1 + ( temp2 - temp1 )
222 * (( 2.f / 3.f ) - tempg) * 6.f;
230 if( tempb < 1.f / 6.f )
232 blue = temp1 + (temp2 - temp1) * 6.f * tempb;
234 else if( tempb < 0.5f )
238 else if( tempb < 2.f / 3.f )
240 blue = temp1 + (temp2 - temp1)
241 * (( 2.f / 3.f ) - tempb) * 6.f;
249 get_color(dst,red_t()) =
250 channel_convert<typename color_element_type< P2, red_t >::type>( red );
251 get_color(dst,green_t())=
252 channel_convert<typename color_element_type< P2, green_t >::type>( green );
253 get_color(dst,blue_t()) =
254 channel_convert<typename color_element_type< P2, blue_t >::type>( blue );