]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
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 |