// // Copyright 2012 Chung-Lin Wen // // Distributed under the Boost Software License, Version 1.0 // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt // #ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_LAB_HPP #define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_LAB_HPP #include #include #include // FIXME: Include what you use, not everything, even in extensions! #include namespace boost{ namespace gil { /// \addtogroup ColorNameModel /// \{ namespace lab_color_space { /// \brief Luminance struct luminance_t {}; /// \brief a Color Component struct a_color_opponent_t {}; /// \brief b Color Component struct b_color_opponent_t {}; } /// \} /// \ingroup ColorSpaceModel using lab_t = mp11::mp_list < lab_color_space::luminance_t, lab_color_space::a_color_opponent_t, lab_color_space::b_color_opponent_t >; /// \ingroup LayoutModel using lab_layout_t = layout; GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, lab) /// \ingroup ColorConvert /// \brief LAB to XYZ template <> struct default_color_converter_impl< lab_t, xyz_t > { template void operator()( const P1& src, P2& dst ) const { using namespace lab_color_space; using namespace xyz_color_space; float32_t p = ((get_color(src, luminance_t()) + 16.f)/116.f); get_color(dst, y_t()) = 1.f * powf(p, 3.f); get_color(dst, x_t()) = 0.95047f * powf((p + (get_color(src, a_color_opponent_t())/500.f) ), 3.f); get_color(dst, z_t()) = 1.08883f * powf((p - (get_color(src, b_color_opponent_t())/200.f) ), 3.f); } }; /// \ingroup ColorConvert /// \brief XYZ to LAB /// \note I assume \c xyz_t template <> struct default_color_converter_impl< xyz_t, lab_t > { private: /// \ref http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html BOOST_FORCEINLINE float32_t forward_companding(float32_t value) const { if (value > 216.f/24389.f) { return powf(value, 1.f/3.f); } else { return ((24389.f/27.f * value + 16.f)/116.f); } } public: template void operator()( const P1& src, P2& dst ) const { using namespace lab_color_space; float32_t f_y = forward_companding( channel_convert( get_color(src, xyz_color_space::y_t()) ) // / 1.f ); float32_t f_x = forward_companding( channel_convert( get_color(src, xyz_color_space::x_t()) ) * (1.f / 0.95047f) // if the compiler is smart, it should // precalculate this, no? ); float32_t f_z = forward_companding( channel_convert( get_color(src, xyz_color_space::z_t()) ) * (1.f / 1.08883f) // if the compiler is smart, it should // precalculate this, no? ); get_color(dst, luminance_t()) = 116.f * f_y - 16.f; get_color(dst, a_color_opponent_t()) = 500.f * (f_x - f_y); get_color(dst, b_color_opponent_t()) = 200.f * (f_y - f_z); } }; /// \ingroup ColorConvert /// \brief RGB to LAB template <> struct default_color_converter_impl< rgb_t, lab_t > { template void operator()( const P1& src, P2& dst ) const { using namespace lab_color_space; xyz32f_pixel_t xyz32f_temp_pixel; default_color_converter_impl()(src, xyz32f_temp_pixel); default_color_converter_impl()(xyz32f_temp_pixel, dst); } }; /// \ingroup ColorConvert /// \brief LAB to RGB template <> struct default_color_converter_impl { template void operator()( const P1& src, P2& dst) const { using namespace lab_color_space; xyz32f_pixel_t xyz32f_temp_pixel; default_color_converter_impl()(src, xyz32f_temp_pixel); default_color_converter_impl()(xyz32f_temp_pixel, dst); } }; } // namespace gil } // namespace boost #endif