Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / gil / extension / numeric / channel_numeric_operations.hpp
1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
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_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
9 #define BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
10
11 #include <boost/gil/channel.hpp>
12
13 namespace boost { namespace gil {
14
15 // Function objects and utilities for channel-wise numeric operations.
16 //
17 // List of currently defined functors:
18 //    channel_plus_t (+)
19 //    channel_minus_t (-)
20 //    channel_multiplies_t (*)
21 //    channel_divides_t (/),
22 //    channel_plus_scalar_t (+s)
23 //    channel_minus_scalar_t (-s),
24 //    channel_multiplies_scalar_t (*s)
25 //    channel_divides_scalar_t (/s),
26 //    channel_halves_t (/=2)
27 //    channel_zeros_t (=0)
28 //    channel_assigns_t (=)
29
30 /// \ingroup ChannelNumericOperations
31 /// \brief Arithmetic operation of addition of two channel values.
32 /// \note This is a generic implementation; user should specialize it for better performance.
33 template <typename Channel1, typename Channel2, typename ChannelResult>
34 struct channel_plus_t
35 {
36     using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
37     using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
38     static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
39         "ChannelRef1 not convertible to ChannelResult");
40     static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
41         "ChannelRef2 not convertible to ChannelResult");
42
43     /// \param ch1 - first of the two addends (augend).
44     /// \param ch2 - second of the two addends.
45     auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
46     {
47         return ChannelResult(ch1) + ChannelResult(ch2);
48     }
49 };
50
51 /// \ingroup ChannelNumericOperations
52 /// \brief Arithmetic operation of subtraction of two channel values.
53 /// \note This is a generic implementation; user should specialize it for better performance.
54 template <typename Channel1, typename Channel2, typename ChannelResult>
55 struct channel_minus_t
56 {
57     using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
58     using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
59     static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
60         "ChannelRef1 not convertible to ChannelResult");
61     static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
62         "ChannelRef2 not convertible to ChannelResult");
63
64     /// \param ch1 - minuend operand of the subtraction.
65     /// \param ch2 - subtrahend operand of the subtraction.
66     auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
67     {
68         return ChannelResult(ch1) - ChannelResult(ch2);
69     }
70 };
71
72 /// \ingroup ChannelNumericOperations
73 /// \brief Arithmetic operation of multiplication of two channel values.
74 /// \note This is a generic implementation; user should specialize it for better performance.
75 template <typename Channel1, typename Channel2, typename ChannelResult>
76 struct channel_multiplies_t
77 {
78     using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
79     using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
80     static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
81         "ChannelRef1 not convertible to ChannelResult");
82     static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
83         "ChannelRef2 not convertible to ChannelResult");
84
85     /// \param ch1 - first of the two factors (multiplicand).
86     /// \param ch2 - second of the two factors (multiplier).
87     auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
88     {
89         return ChannelResult(ch1) * ChannelResult(ch2);
90     }
91 };
92
93 /// \ingroup ChannelNumericOperations
94 /// \brief Arithmetic operation of division of two channel values.
95 /// \note This is a generic implementation; user should specialize it for better performance.
96 template <typename Channel1, typename Channel2, typename ChannelResult>
97 struct channel_divides_t
98 {
99     using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
100     using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
101     static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
102         "ChannelRef1 not convertible to ChannelResult");
103     static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
104         "ChannelRef2 not convertible to ChannelResult");
105
106     /// \param ch1 - dividend operand of the two division operation.
107     /// \param ch2 - divisor operand of the two division operation.
108     auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
109     {
110         return ChannelResult(ch1) / ChannelResult(ch2);
111     }
112 };
113
114 /// \ingroup ChannelNumericOperations
115 /// \brief Arithmetic operation of adding scalar to channel value.
116 /// \note This is a generic implementation; user should specialize it for better performance.
117 template <typename Channel, typename Scalar, typename ChannelResult>
118 struct channel_plus_scalar_t
119 {
120     using ChannelRef = typename channel_traits<Channel>::const_reference;
121     static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
122         "ChannelRef not convertible to ChannelResult");
123     static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
124     static_assert(std::is_convertible<Scalar, ChannelResult>::value,
125         "Scalar not convertible to ChannelResult");
126
127     auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
128     {
129         return ChannelResult(channel) + ChannelResult(scalar);
130     }
131 };
132
133 /// \ingroup ChannelNumericOperations
134 /// \brief Arithmetic operation of subtracting scalar from channel value.
135 /// \note This is a generic implementation; user should specialize it for better performance.
136 template <typename Channel, typename Scalar, typename ChannelResult>
137 struct channel_minus_scalar_t
138 {
139     using ChannelRef = typename channel_traits<Channel>::const_reference;
140     static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
141         "ChannelRef not convertible to ChannelResult");
142     static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
143     static_assert(std::is_convertible<Scalar, ChannelResult>::value,
144         "Scalar not convertible to ChannelResult");
145
146     /// \param channel - minuend operand of the subtraction.
147     /// \param scalar - subtrahend operand of the subtraction.
148     auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
149     {
150         // TODO: Convertion after subtraction vs conversion of operands in channel_minus_t?
151         return ChannelResult(channel - scalar);
152     }
153 };
154
155 /// \ingroup ChannelNumericOperations
156 /// \brief Arithmetic operation of channel value by a scalar.
157 /// \note This is a generic implementation; user should specialize it for better performance.
158 template <typename Channel, typename Scalar, typename ChannelResult>
159 struct channel_multiplies_scalar_t
160 {
161     using ChannelRef = typename channel_traits<Channel>::const_reference;
162     static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
163         "ChannelRef not convertible to ChannelResult");
164     static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
165     static_assert(std::is_convertible<Scalar, ChannelResult>::value,
166         "Scalar not convertible to ChannelResult");
167
168     /// \param channel - first of the two factors (multiplicand).
169     /// \param scalar - second of the two factors (multiplier).
170     auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
171     {
172         return ChannelResult(channel) * ChannelResult(scalar);
173     }
174 };
175
176 /// \ingroup ChannelNumericOperations
177 /// \brief Arithmetic operation of dividing channel value by scalar.
178 /// \note This is a generic implementation; user should specialize it for better performance.
179 template <typename Channel, typename Scalar, typename ChannelResult>
180 struct channel_divides_scalar_t
181 {
182     using ChannelRef = typename channel_traits<Channel>::const_reference;
183     static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
184         "ChannelRef not convertible to ChannelResult");
185     static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
186     static_assert(std::is_convertible<Scalar, ChannelResult>::value,
187         "Scalar not convertible to ChannelResult");
188
189     /// \param channel - dividend operand of the two division operation.
190     /// \param scalar - divisor operand of the two division operation.
191     auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
192     {
193         return ChannelResult(channel) / ChannelResult(scalar);
194     }
195 };
196
197 /// \ingroup ChannelNumericOperations
198 /// \brief Arithmetic operation of dividing channel value by 2
199 /// \note This is a generic implementation; user should specialize it for better performance.
200 template <typename Channel>
201 struct channel_halves_t
202 {
203     using ChannelRef = typename channel_traits<Channel>::reference;
204
205     auto operator()(ChannelRef channel) const -> ChannelRef
206     {
207         // TODO: Split into steps: extract with explicit conversion to double, divide and assign?
208         //double const v = ch;
209         //ch = static_cast<Channel>(v / 2.0);
210         channel /= 2.0;
211         return channel;
212     }
213 };
214
215 /// \ingroup ChannelNumericOperations
216 /// \brief Operation of setting channel value to zero
217 /// \note This is a generic implementation; user should specialize it for better performance.
218 template <typename Channel>
219 struct channel_zeros_t
220 {
221     using ChannelRef = typename channel_traits<Channel>::reference;
222
223     auto operator()(ChannelRef channel) const -> ChannelRef
224     {
225         channel = Channel(0);
226         return channel;
227     }
228 };
229
230 /// \ingroup ChannelNumericOperations
231 /// structure for assigning one channel to another
232 /// \note This is a generic implementation; user should specialize it for better performance.
233 template <typename Channel1, typename Channel2>
234 struct channel_assigns_t
235 {
236     using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
237     using ChannelRef2 = typename channel_traits<Channel2>::reference;
238     static_assert(std::is_convertible<ChannelRef1, Channel2>::value,
239         "ChannelRef1 not convertible to Channel2");
240
241     /// \param ch1 - assignor side (input) of the assignment operation
242     /// \param ch2 - assignee side (output) of the assignment operation
243     auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelRef2
244     {
245         ch2 = Channel2(ch1);
246         return ch2;
247     }
248 };
249
250 }}  // namespace boost::gil
251
252 #endif