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_HSV_HPP
9 #define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSV_HPP
11 #include <boost/numeric/conversion/cast.hpp>
13 #include <boost/gil/color_convert.hpp>
14 #include <boost/gil/typedefs.hpp>
15 #include <boost/gil/detail/mp11.hpp>
20 namespace boost{ namespace gil {
22 /// \addtogroup ColorNameModel
24 namespace hsv_color_space
29 struct saturation_t{};
35 /// \ingroup ColorSpaceModel
36 using hsv_t = mp11::mp_list
38 hsv_color_space::hue_t,
39 hsv_color_space::saturation_t,
40 hsv_color_space::value_t
43 /// \ingroup LayoutModel
44 using hsv_layout_t = layout<hsv_t>;
46 GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, hsv)
48 /// \ingroup ColorConvert
51 struct default_color_converter_impl< rgb_t, hsv_t >
53 template <typename P1, typename P2>
54 void operator()( const P1& src, P2& dst ) const
56 using namespace hsv_color_space;
58 // only float32_t for hsv is supported
59 float32_t temp_red = channel_convert<float32_t>( get_color( src, red_t() ));
60 float32_t temp_green = channel_convert<float32_t>( get_color( src, green_t() ));
61 float32_t temp_blue = channel_convert<float32_t>( get_color( src, blue_t() ));
63 float32_t hue, saturation, value;
65 float32_t min_color = (std::min)( temp_red, (std::min)( temp_green, temp_blue ));
66 float32_t max_color = (std::max)( temp_red, (std::max)( temp_green, temp_blue ));
70 float32_t diff = max_color - min_color;
72 if( max_color < 0.0001f )
78 saturation = diff / max_color;
82 if( saturation < 0.0001f )
84 //it doesn't matter what value it has
89 if( (std::abs)( boost::numeric_cast<float32_t>(temp_red - max_color) ) < 0.0001f )
91 hue = ( temp_green - temp_blue )
94 else if( temp_green >= max_color ) // means == but >= avoids compiler warning; color is never greater than max
96 hue = 2.f + ( temp_blue - temp_red )
101 hue = 4.f + ( temp_red - temp_green )
105 //to bring it to a number between 0 and 1
114 get_color( dst, hue_t() ) = hue;
115 get_color( dst, saturation_t() ) = saturation;
116 get_color( dst, value_t() ) = value;
120 /// \ingroup ColorConvert
121 /// \brief HSV to RGB
123 struct default_color_converter_impl<hsv_t,rgb_t>
125 template <typename P1, typename P2>
126 void operator()( const P1& src, P2& dst) const
128 using namespace hsv_color_space;
130 float32_t red, green, blue;
132 //If saturation is 0, the color is a shade of gray
133 if( abs( get_color( src, saturation_t() )) < 0.0001f )
135 // If saturation is 0, the color is a shade of gray
136 red = get_color( src, value_t() );
137 green = get_color( src, value_t() );
138 blue = get_color( src, value_t() );
142 float32_t frac, p, q, t, h;
145 //to bring hue to a number between 0 and 6, better for the calculations
146 h = get_color( src, hue_t() );
149 i = static_cast<uint32_t>(floor(h));
153 p = get_color( src, value_t() )
154 * ( 1.f - get_color( src, saturation_t() ));
156 q = get_color( src, value_t() )
157 * ( 1.f - ( get_color( src, saturation_t() ) * frac ));
159 t = get_color( src, value_t() )
160 * ( 1.f - ( get_color( src, saturation_t() ) * ( 1.f - frac )));
166 red = get_color( src, value_t() );
176 green = get_color( src, value_t() );
185 green = get_color( src, value_t() );
195 blue = get_color( src, value_t() );
204 blue = get_color( src, value_t() );
211 red = get_color( src, value_t() );
221 get_color(dst,red_t()) =
222 channel_convert<typename color_element_type< P2, red_t >::type>( red );
223 get_color(dst,green_t())=
224 channel_convert<typename color_element_type< P2, green_t >::type>( green );
225 get_color(dst,blue_t()) =
226 channel_convert<typename color_element_type< P2, blue_t >::type>( blue );