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