channel_numeric_operations.hpp 10 KB

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