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 BOOST_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 inverse_compandingboost::gil::default_color_converter_impl52 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> operator ()boost::gil::default_color_converter_impl66 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 compandingboost::gil::default_color_converter_impl102 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> operator ()boost::gil::default_color_converter_impl116 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 151