channel_numeric_operations.hpp 10 KB

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