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. operator ()boost::gil::channel_plus_t45 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. operator ()boost::gil::channel_minus_t66 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). operator ()boost::gil::channel_multiplies_t87 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. operator ()boost::gil::channel_divides_t108 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 operator ()boost::gil::channel_plus_scalar_t127 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. operator ()boost::gil::channel_minus_scalar_t148 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). operator ()boost::gil::channel_multiplies_scalar_t170 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. operator ()boost::gil::channel_divides_scalar_t191 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 operator ()boost::gil::channel_halves_t205 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 operator ()boost::gil::channel_zeros_t223 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 operator ()boost::gil::channel_assigns_t243 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 253