premultiply.hpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. //
  2. // Copyright 2014 Bill Gallafent
  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_PREMULTIPLY_HPP
  9. #define BOOST_GIL_PREMULTIPLY_HPP
  10. #include <boost/gil/rgba.hpp>
  11. #include <boost/gil/detail/mp11.hpp>
  12. #include <boost/core/ignore_unused.hpp>
  13. #include <type_traits>
  14. namespace boost { namespace gil {
  15. template <typename SrcP, typename DstP>
  16. struct channel_premultiply
  17. {
  18. channel_premultiply(SrcP const & src, DstP & dst)
  19. : src_(src), dst_(dst)
  20. {}
  21. template <typename Channel>
  22. void operator()(Channel /* channel */) const
  23. {
  24. // TODO: Explain why 'channel' input paramater is not used, or used as tag only.
  25. // @todo: need to do a "channel_convert" too, in case the channel types aren't the same?
  26. get_color(dst_, Channel()) = channel_multiply(get_color(src_,Channel()), alpha_or_max(src_));
  27. }
  28. SrcP const & src_;
  29. DstP & dst_;
  30. };
  31. namespace detail
  32. {
  33. template <typename SrcP, typename DstP>
  34. void assign_alpha_if(std::true_type, SrcP const &src, DstP &dst)
  35. {
  36. get_color(dst,alpha_t()) = alpha_or_max(src);
  37. }
  38. template <typename SrcP, typename DstP>
  39. void assign_alpha_if(std::false_type, SrcP const& src, DstP& dst)
  40. {
  41. // nothing to do
  42. boost::ignore_unused(src);
  43. boost::ignore_unused(dst);
  44. }
  45. }
  46. struct premultiply
  47. {
  48. template <typename SrcP, typename DstP>
  49. void operator()(const SrcP& src, DstP& dst) const
  50. {
  51. using src_colour_space_t = typename color_space_type<SrcP>::type;
  52. using dst_colour_space_t = typename color_space_type<DstP>::type;
  53. using src_colour_channels = mp11::mp_remove<src_colour_space_t, alpha_t>;
  54. using has_alpha_t = std::integral_constant<bool, mp11::mp_contains<dst_colour_space_t, alpha_t>::value>;
  55. mp11::mp_for_each<src_colour_channels>(channel_premultiply<SrcP, DstP>(src, dst));
  56. detail::assign_alpha_if(has_alpha_t(), src, dst);
  57. }
  58. };
  59. template <typename SrcConstRefP, // const reference to the source pixel
  60. typename DstP> // Destination pixel value (models PixelValueConcept)
  61. class premultiply_deref_fn
  62. {
  63. public:
  64. using const_t = premultiply_deref_fn<SrcConstRefP, DstP>;
  65. using value_type = DstP;
  66. using reference = value_type; // read-only dereferencing
  67. using const_reference = const value_type &;
  68. using argument_type = SrcConstRefP;
  69. using result_type = reference;
  70. static constexpr bool is_mutable = false;
  71. result_type operator()(argument_type srcP) const
  72. {
  73. result_type dstP;
  74. premultiply()(srcP,dstP);
  75. return dstP;
  76. }
  77. };
  78. template <typename SrcView, typename DstP>
  79. struct premultiplied_view_type
  80. {
  81. private:
  82. using src_pix_ref = typename SrcView::const_t::reference; // const reference to pixel in SrcView
  83. using deref_t = premultiply_deref_fn<src_pix_ref, DstP>; // the dereference adaptor that performs color conversion
  84. using add_ref_t = typename SrcView::template add_deref<deref_t>;
  85. public:
  86. using type = typename add_ref_t::type; // the color converted view type
  87. static type make(const SrcView& sv) { return add_ref_t::make(sv, deref_t()); }
  88. };
  89. template <typename DstP, typename View> inline
  90. typename premultiplied_view_type<View,DstP>::type premultiply_view(const View& src)
  91. {
  92. return premultiplied_view_type<View,DstP>::make(src);
  93. }
  94. }} // namespace boost::gil
  95. #endif