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