hsl.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. //
  2. // Copyright 2012 Christian Henning
  3. //
  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
  7. //
  8. #ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSL_HPP
  9. #define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSL_HPP
  10. #include <boost/gil/color_convert.hpp>
  11. #include <boost/gil/typedefs.hpp>
  12. #include <boost/gil/detail/mp11.hpp>
  13. namespace boost{ namespace gil {
  14. /// \addtogroup ColorNameModel
  15. /// \{
  16. namespace hsl_color_space
  17. {
  18. /// \brief Hue
  19. struct hue_t {};
  20. /// \brief Saturation
  21. struct saturation_t {};
  22. /// \brief Lightness
  23. struct lightness_t {};
  24. }
  25. /// \}
  26. /// \ingroup ColorSpaceModel
  27. using hsl_t = mp11::mp_list
  28. <
  29. hsl_color_space::hue_t,
  30. hsl_color_space::saturation_t,
  31. hsl_color_space::lightness_t
  32. >;
  33. /// \ingroup LayoutModel
  34. using hsl_layout_t = layout<hsl_t>;
  35. GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, hsl)
  36. /// \ingroup ColorConvert
  37. /// \brief RGB to HSL
  38. template <>
  39. struct default_color_converter_impl< rgb_t, hsl_t >
  40. {
  41. template <typename P1, typename P2>
  42. void operator()( const P1& src, P2& dst ) const
  43. {
  44. using namespace hsl_color_space;
  45. // only float32_t for hsl is supported
  46. float32_t temp_red = channel_convert<float32_t>( get_color( src, red_t() ));
  47. float32_t temp_green = channel_convert<float32_t>( get_color( src, green_t() ));
  48. float32_t temp_blue = channel_convert<float32_t>( get_color( src, blue_t() ));
  49. float32_t hue, saturation, lightness;
  50. float32_t min_color = (std::min)( temp_red, (std::min)( temp_green, temp_blue ));
  51. float32_t max_color = (std::max)( temp_red, (std::max)( temp_green, temp_blue ));
  52. if( std::abs( min_color - max_color ) < 0.001 )
  53. {
  54. // rgb color is gray
  55. hue = 0.f;
  56. saturation = 0.f;
  57. // doesn't matter which rgb channel we use.
  58. lightness = temp_red;
  59. }
  60. else
  61. {
  62. float32_t diff = max_color - min_color;
  63. // lightness calculation
  64. lightness = ( min_color + max_color ) / 2.f;
  65. // saturation calculation
  66. if( lightness < 0.5f )
  67. {
  68. saturation = diff
  69. / ( min_color + max_color );
  70. }
  71. else
  72. {
  73. saturation = ( max_color - min_color )
  74. / ( 2.f - diff );
  75. }
  76. // hue calculation
  77. if( std::abs( max_color - temp_red ) < 0.0001f )
  78. {
  79. // max_color is red
  80. hue = ( temp_green - temp_blue )
  81. / diff;
  82. }
  83. else if( std::abs( max_color - temp_green) < 0.0001f )
  84. {
  85. // max_color is green
  86. // 2.0 + (b - r) / (maxColor - minColor);
  87. hue = 2.f
  88. + ( temp_blue - temp_red )
  89. / diff;
  90. }
  91. else
  92. {
  93. // max_color is blue
  94. hue = 4.f
  95. + ( temp_red - temp_blue )
  96. / diff;
  97. }
  98. hue /= 6.f;
  99. if( hue < 0.f )
  100. {
  101. hue += 1.f;
  102. }
  103. }
  104. get_color( dst,hue_t() ) = hue;
  105. get_color( dst,saturation_t() ) = saturation;
  106. get_color( dst,lightness_t() ) = lightness;
  107. }
  108. };
  109. /// \ingroup ColorConvert
  110. /// \brief HSL to RGB
  111. template <>
  112. struct default_color_converter_impl<hsl_t,rgb_t>
  113. {
  114. template <typename P1, typename P2>
  115. void operator()( const P1& src, P2& dst) const
  116. {
  117. using namespace hsl_color_space;
  118. float32_t red, green, blue;
  119. if( std::abs( get_color( src, saturation_t() )) < 0.0001 )
  120. {
  121. // If saturation is 0, the color is a shade of gray
  122. red = get_color( src, lightness_t() );
  123. green = get_color( src, lightness_t() );
  124. blue = get_color( src, lightness_t() );
  125. }
  126. else
  127. {
  128. float temp1, temp2;
  129. float tempr, tempg, tempb;
  130. //Set the temporary values
  131. if( get_color( src, lightness_t() ) < 0.5 )
  132. {
  133. temp2 = get_color( src, lightness_t() )
  134. * ( 1.f + get_color( src, saturation_t() ) );
  135. }
  136. else
  137. {
  138. temp2 = ( get_color( src, lightness_t() ) + get_color( src, saturation_t() ))
  139. - ( get_color( src, lightness_t() ) * get_color( src, saturation_t() ));
  140. }
  141. temp1 = 2.f
  142. * get_color( src, lightness_t() )
  143. - temp2;
  144. tempr = get_color( src, hue_t() ) + 1.f / 3.f;
  145. if( tempr > 1.f )
  146. {
  147. tempr--;
  148. }
  149. tempg = get_color( src, hue_t() );
  150. tempb = get_color( src, hue_t() ) - 1.f / 3.f;
  151. if( tempb < 0.f )
  152. {
  153. tempb++;
  154. }
  155. //Red
  156. if( tempr < 1.f / 6.f )
  157. {
  158. red = temp1 + ( temp2 - temp1 ) * 6.f * tempr;
  159. }
  160. else if( tempr < 0.5f )
  161. {
  162. red = temp2;
  163. }
  164. else if( tempr < 2.f / 3.f )
  165. {
  166. red = temp1 + (temp2 - temp1)
  167. * (( 2.f / 3.f ) - tempr) * 6.f;
  168. }
  169. else
  170. {
  171. red = temp1;
  172. }
  173. //Green
  174. if( tempg < 1.f / 6.f )
  175. {
  176. green = temp1 + ( temp2 - temp1 ) * 6.f * tempg;
  177. }
  178. else if( tempg < 0.5f )
  179. {
  180. green = temp2;
  181. }
  182. else if( tempg < 2.f / 3.f )
  183. {
  184. green = temp1 + ( temp2 - temp1 )
  185. * (( 2.f / 3.f ) - tempg) * 6.f;
  186. }
  187. else
  188. {
  189. green = temp1;
  190. }
  191. //Blue
  192. if( tempb < 1.f / 6.f )
  193. {
  194. blue = temp1 + (temp2 - temp1) * 6.f * tempb;
  195. }
  196. else if( tempb < 0.5f )
  197. {
  198. blue = temp2;
  199. }
  200. else if( tempb < 2.f / 3.f )
  201. {
  202. blue = temp1 + (temp2 - temp1)
  203. * (( 2.f / 3.f ) - tempb) * 6.f;
  204. }
  205. else
  206. {
  207. blue = temp1;
  208. }
  209. }
  210. get_color(dst,red_t()) =
  211. channel_convert<typename color_element_type< P2, red_t >::type>( red );
  212. get_color(dst,green_t())=
  213. channel_convert<typename color_element_type< P2, green_t >::type>( green );
  214. get_color(dst,blue_t()) =
  215. channel_convert<typename color_element_type< P2, blue_t >::type>( blue );
  216. }
  217. };
  218. } // namespace gil
  219. } // namespace boost
  220. #endif