xyz.hpp 4.2 KB

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