Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / gil / extension / toolbox / color_spaces / xyz.hpp
1 //
2 // Copyright 2012 Chung-Lin Wen, Davide Anastasia
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_XYZ_HPP
9 #define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_XYZ_HPP
10
11 #include <boost/gil/color_convert.hpp>
12 #include <boost/gil/typedefs.hpp>
13 #include <boost/gil/detail/mp11.hpp>
14
15 namespace boost{ namespace gil {
16
17 /// \addtogroup ColorNameModel
18 /// \{
19 namespace xyz_color_space
20 {
21 /// \brief x Color Component
22 struct x_t {};
23 /// \brief y Color Component
24 struct y_t {};
25 /// \brief z Color Component
26 struct z_t {};
27 }
28 /// \}
29
30 /// \ingroup ColorSpaceModel
31 using xyz_t = mp11::mp_list
32 <
33     xyz_color_space::x_t,
34     xyz_color_space::y_t,
35     xyz_color_space::z_t
36 >;
37
38 /// \ingroup LayoutModel
39 using xyz_layout_t = layout<xyz_t>;
40
41 GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, xyz)
42
43 /// \ingroup ColorConvert
44 /// \brief RGB to XYZ
45 /// <a href="http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html">Link</a>
46 /// \note rgb_t is assumed to be sRGB D65
47 template <>
48 struct default_color_converter_impl< rgb_t, xyz_t >
49 {
50 private:
51     BOOST_FORCEINLINE
52     float32_t inverse_companding(float32_t sample) const
53     {
54         if ( sample > 0.04045f )
55         {
56             return powf((( sample + 0.055f ) / 1.055f ), 2.4f);
57         }
58         else
59         {
60             return ( sample / 12.92f );
61         }
62     }
63
64 public:
65     template <typename P1, typename P2>
66     void operator()( const P1& src, P2& dst ) const
67     {
68         using namespace xyz_color_space;
69
70         float32_t red(
71             inverse_companding(
72                 channel_convert<float32_t>(get_color(src, red_t()))));
73         float32_t green(
74             inverse_companding(
75                 channel_convert<float32_t>(get_color(src, green_t()))));
76         float32_t blue(
77             inverse_companding(
78                 channel_convert<float32_t>(get_color(src, blue_t()))));
79
80         get_color( dst, x_t() ) =
81                 red * 0.4124564f +
82                 green * 0.3575761f +
83                 blue * 0.1804375f;
84         get_color( dst, y_t() ) =
85                 red * 0.2126729f +
86                 green * 0.7151522f +
87                 blue * 0.0721750f;
88         get_color( dst, z_t() ) =
89                 red * 0.0193339f +
90                 green * 0.1191920f +
91                 blue * 0.9503041f;
92     }
93 };
94
95 /// \ingroup ColorConvert
96 /// \brief XYZ to RGB
97 template <>
98 struct default_color_converter_impl<xyz_t,rgb_t>
99 {
100 private:
101     BOOST_FORCEINLINE
102     float32_t companding(float32_t sample) const
103     {
104         if ( sample > 0.0031308f )
105         {
106             return ( 1.055f * powf( sample, 1.f/2.4f ) - 0.055f );
107         }
108         else
109         {
110             return ( 12.92f * sample );
111         }
112     }
113
114 public:
115     template <typename P1, typename P2>
116     void operator()( const P1& src, P2& dst) const
117     {
118         using namespace xyz_color_space;
119
120         // Note: ideally channel_convert should be compiled out, because xyz_t
121         // is float32_t natively only
122         float32_t x( channel_convert<float32_t>( get_color( src, x_t() ) ) );
123         float32_t y( channel_convert<float32_t>( get_color( src, y_t() ) ) );
124         float32_t z( channel_convert<float32_t>( get_color( src, z_t() ) ) );
125
126         get_color(dst,red_t())  =
127                 channel_convert<typename color_element_type<P2, red_t>::type>(
128                     companding( x *  3.2404542f +
129                                 y * -1.5371385f +
130                                 z * -0.4985314f )
131                     );
132         get_color(dst,green_t()) =
133                 channel_convert<typename color_element_type<P2, green_t>::type>(
134                     companding( x * -0.9692660f +
135                                 y *  1.8760108f +
136                                 z *  0.0415560f )
137                     );
138         get_color(dst,blue_t()) =
139                 channel_convert<typename color_element_type<P2, blue_t>::type>(
140                     companding( x *  0.0556434f +
141                                 y * -0.2040259f +
142                                 z *  1.0572252f )
143                     );
144     }
145 };
146
147 } // namespace gil
148 } // namespace boost
149
150 #endif // BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_XYZ_HPP