• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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