2 // Copyright 2005-2007 Adobe Systems Incorporated
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
8 #ifndef BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
9 #define BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
11 #include <boost/gil/channel.hpp>
13 namespace boost { namespace gil {
15 // Function objects and utilities for channel-wise numeric operations.
17 // List of currently defined functors:
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 (=)
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>
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");
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
47 return ChannelResult(ch1) + ChannelResult(ch2);
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
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");
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
68 return ChannelResult(ch1) - ChannelResult(ch2);
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
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");
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
89 return ChannelResult(ch1) * ChannelResult(ch2);
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
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");
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
110 return ChannelResult(ch1) / ChannelResult(ch2);
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
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");
127 auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
129 return ChannelResult(channel) + ChannelResult(scalar);
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
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");
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
150 // TODO: Convertion after subtraction vs conversion of operands in channel_minus_t?
151 return ChannelResult(channel - scalar);
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
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");
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
172 return ChannelResult(channel) * ChannelResult(scalar);
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
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");
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
193 return ChannelResult(channel) / ChannelResult(scalar);
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
203 using ChannelRef = typename channel_traits<Channel>::reference;
205 auto operator()(ChannelRef channel) const -> ChannelRef
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);
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
221 using ChannelRef = typename channel_traits<Channel>::reference;
223 auto operator()(ChannelRef channel) const -> ChannelRef
225 channel = Channel(0);
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
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");
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
250 }} // namespace boost::gil