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