lab.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. //
  2. // Copyright 2012 Chung-Lin Wen
  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_LAB_HPP
  9. #define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_LAB_HPP
  10. #include <boost/gil/extension/toolbox/color_spaces/xyz.hpp>
  11. #include <boost/gil/color_convert.hpp>
  12. #include <boost/gil.hpp> // FIXME: Include what you use, not everything, even in extensions!
  13. #include <boost/gil/detail/mp11.hpp>
  14. namespace boost{ namespace gil {
  15. /// \addtogroup ColorNameModel
  16. /// \{
  17. namespace lab_color_space
  18. {
  19. /// \brief Luminance
  20. struct luminance_t {};
  21. /// \brief a Color Component
  22. struct a_color_opponent_t {};
  23. /// \brief b Color Component
  24. struct b_color_opponent_t {};
  25. }
  26. /// \}
  27. /// \ingroup ColorSpaceModel
  28. using lab_t = mp11::mp_list
  29. <
  30. lab_color_space::luminance_t,
  31. lab_color_space::a_color_opponent_t,
  32. lab_color_space::b_color_opponent_t
  33. >;
  34. /// \ingroup LayoutModel
  35. using lab_layout_t = layout<lab_t>;
  36. GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, lab)
  37. /// \ingroup ColorConvert
  38. /// \brief LAB to XYZ
  39. template <>
  40. struct default_color_converter_impl< lab_t, xyz_t >
  41. {
  42. template <typename P1, typename P2>
  43. void operator()( const P1& src, P2& dst ) const
  44. {
  45. using namespace lab_color_space;
  46. using namespace xyz_color_space;
  47. float32_t p = ((get_color(src, luminance_t()) + 16.f)/116.f);
  48. get_color(dst, y_t()) =
  49. 1.f * powf(p, 3.f);
  50. get_color(dst, x_t()) =
  51. 0.95047f * powf((p +
  52. (get_color(src, a_color_opponent_t())/500.f)
  53. ), 3.f);
  54. get_color(dst, z_t()) =
  55. 1.08883f * powf((p -
  56. (get_color(src, b_color_opponent_t())/200.f)
  57. ), 3.f);
  58. }
  59. };
  60. /// \ingroup ColorConvert
  61. /// \brief XYZ to LAB
  62. /// \note I assume \c xyz_t
  63. template <>
  64. struct default_color_converter_impl< xyz_t, lab_t >
  65. {
  66. private:
  67. /// \ref http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html
  68. BOOST_FORCEINLINE
  69. float32_t forward_companding(float32_t value) const
  70. {
  71. if (value > 216.f/24389.f)
  72. {
  73. return powf(value, 1.f/3.f);
  74. }
  75. else
  76. {
  77. return ((24389.f/27.f * value + 16.f)/116.f);
  78. }
  79. }
  80. public:
  81. template <typename P1, typename P2>
  82. void operator()( const P1& src, P2& dst ) const
  83. {
  84. using namespace lab_color_space;
  85. float32_t f_y =
  86. forward_companding(
  87. channel_convert<float32_t>(
  88. get_color(src, xyz_color_space::y_t())
  89. )
  90. // / 1.f
  91. );
  92. float32_t f_x =
  93. forward_companding(
  94. channel_convert<float32_t>(
  95. get_color(src, xyz_color_space::x_t())
  96. )
  97. * (1.f / 0.95047f) // if the compiler is smart, it should
  98. // precalculate this, no?
  99. );
  100. float32_t f_z =
  101. forward_companding(
  102. channel_convert<float32_t>(
  103. get_color(src, xyz_color_space::z_t())
  104. )
  105. * (1.f / 1.08883f) // if the compiler is smart, it should
  106. // precalculate this, no?
  107. );
  108. get_color(dst, luminance_t()) =
  109. 116.f * f_y - 16.f;
  110. get_color(dst, a_color_opponent_t()) =
  111. 500.f * (f_x - f_y);
  112. get_color(dst, b_color_opponent_t()) =
  113. 200.f * (f_y - f_z);
  114. }
  115. };
  116. /// \ingroup ColorConvert
  117. /// \brief RGB to LAB
  118. template <>
  119. struct default_color_converter_impl< rgb_t, lab_t >
  120. {
  121. template <typename P1, typename P2>
  122. void operator()( const P1& src, P2& dst ) const
  123. {
  124. using namespace lab_color_space;
  125. xyz32f_pixel_t xyz32f_temp_pixel;
  126. default_color_converter_impl<rgb_t, xyz_t>()(src, xyz32f_temp_pixel);
  127. default_color_converter_impl<xyz_t, lab_t>()(xyz32f_temp_pixel, dst);
  128. }
  129. };
  130. /// \ingroup ColorConvert
  131. /// \brief LAB to RGB
  132. template <>
  133. struct default_color_converter_impl<lab_t,rgb_t>
  134. {
  135. template <typename P1, typename P2>
  136. void operator()( const P1& src, P2& dst) const
  137. {
  138. using namespace lab_color_space;
  139. xyz32f_pixel_t xyz32f_temp_pixel;
  140. default_color_converter_impl<lab_t, xyz_t>()(src, xyz32f_temp_pixel);
  141. default_color_converter_impl<xyz_t, rgb_t>()(xyz32f_temp_pixel, dst);
  142. }
  143. };
  144. } // namespace gil
  145. } // namespace boost
  146. #endif