123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- //
- // Copyright 2005-2007 Adobe Systems Incorporated
- // Copyright 2021 Pranam Lashkari <[email protected]>
- //
- // Distributed under the Boost Software License, Version 1.0
- // See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt
- //
- #ifndef BOOST_GIL_CHANNEL_NUMERIC_OPERATIONS_HPP
- #define BOOST_GIL_CHANNEL_NUMERIC_OPERATIONS_HPP
- #include <boost/gil/channel.hpp>
- namespace boost { namespace gil {
- // Function objects and utilities for channel-wise numeric operations.
- //
- // List of currently defined functors:
- // channel_plus_t (+)
- // channel_minus_t (-)
- // channel_multiplies_t (*)
- // channel_divides_t (/),
- // channel_plus_scalar_t (+s)
- // channel_minus_scalar_t (-s),
- // channel_multiplies_scalar_t (*s)
- // channel_divides_scalar_t (/s),
- // channel_halves_t (/=2)
- // channel_zeros_t (=0)
- // channel_assigns_t (=)
- /// \ingroup ChannelNumericOperations
- /// \brief Arithmetic operation of addition of two channel values.
- /// \note This is a generic implementation; user should specialize it for better performance.
- template <typename Channel1, typename Channel2, typename ChannelResult>
- struct channel_plus_t
- {
- using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
- using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
- static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
- "ChannelRef1 not convertible to ChannelResult");
- static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
- "ChannelRef2 not convertible to ChannelResult");
- /// \param ch1 - first of the two addends (augend).
- /// \param ch2 - second of the two addends.
- auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
- {
- return ChannelResult(ch1) + ChannelResult(ch2);
- }
- };
- /// \ingroup ChannelNumericOperations
- /// \brief Arithmetic operation of subtraction of two channel values.
- /// \note This is a generic implementation; user should specialize it for better performance.
- template <typename Channel1, typename Channel2, typename ChannelResult>
- struct channel_minus_t
- {
- using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
- using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
- static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
- "ChannelRef1 not convertible to ChannelResult");
- static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
- "ChannelRef2 not convertible to ChannelResult");
- /// \param ch1 - minuend operand of the subtraction.
- /// \param ch2 - subtrahend operand of the subtraction.
- auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
- {
- return ChannelResult(ch1) - ChannelResult(ch2);
- }
- };
- /// \ingroup ChannelNumericOperations
- /// \brief Arithmetic operation of multiplication of two channel values.
- /// \note This is a generic implementation; user should specialize it for better performance.
- template <typename Channel1, typename Channel2, typename ChannelResult>
- struct channel_multiplies_t
- {
- using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
- using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
- static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
- "ChannelRef1 not convertible to ChannelResult");
- static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
- "ChannelRef2 not convertible to ChannelResult");
- /// \param ch1 - first of the two factors (multiplicand).
- /// \param ch2 - second of the two factors (multiplier).
- auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
- {
- return ChannelResult(ch1) * ChannelResult(ch2);
- }
- };
- /// \ingroup ChannelNumericOperations
- /// \brief Arithmetic operation of division of two channel values.
- /// \note This is a generic implementation; user should specialize it for better performance.
- template <typename Channel1, typename Channel2, typename ChannelResult>
- struct channel_divides_t
- {
- using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
- using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
- static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
- "ChannelRef1 not convertible to ChannelResult");
- static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
- "ChannelRef2 not convertible to ChannelResult");
- /// \param ch1 - dividend operand of the two division operation.
- /// \param ch2 - divisor operand of the two division operation.
- auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
- {
- return ChannelResult(ch1) / ChannelResult(ch2);
- }
- };
- /// \ingroup ChannelNumericOperations
- /// \brief Arithmetic operation of adding scalar to channel value.
- /// \note This is a generic implementation; user should specialize it for better performance.
- template <typename Channel, typename Scalar, typename ChannelResult>
- struct channel_plus_scalar_t
- {
- using ChannelRef = typename channel_traits<Channel>::const_reference;
- static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
- "ChannelRef not convertible to ChannelResult");
- static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
- static_assert(std::is_convertible<Scalar, ChannelResult>::value,
- "Scalar not convertible to ChannelResult");
- auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
- {
- return ChannelResult(channel) + ChannelResult(scalar);
- }
- };
- /// \ingroup ChannelNumericOperations
- /// \brief Arithmetic operation of subtracting scalar from channel value.
- /// \note This is a generic implementation; user should specialize it for better performance.
- template <typename Channel, typename Scalar, typename ChannelResult>
- struct channel_minus_scalar_t
- {
- using ChannelRef = typename channel_traits<Channel>::const_reference;
- static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
- "ChannelRef not convertible to ChannelResult");
- static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
- static_assert(std::is_convertible<Scalar, ChannelResult>::value,
- "Scalar not convertible to ChannelResult");
- /// \param channel - minuend operand of the subtraction.
- /// \param scalar - subtrahend operand of the subtraction.
- auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
- {
- // TODO: Convertion after subtraction vs conversion of operands in channel_minus_t?
- return ChannelResult(channel - scalar);
- }
- };
- /// \ingroup ChannelNumericOperations
- /// \brief Arithmetic operation of channel value by a scalar.
- /// \note This is a generic implementation; user should specialize it for better performance.
- template <typename Channel, typename Scalar, typename ChannelResult>
- struct channel_multiplies_scalar_t
- {
- using ChannelRef = typename channel_traits<Channel>::const_reference;
- static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
- "ChannelRef not convertible to ChannelResult");
- static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
- static_assert(std::is_convertible<Scalar, ChannelResult>::value,
- "Scalar not convertible to ChannelResult");
- /// \param channel - first of the two factors (multiplicand).
- /// \param scalar - second of the two factors (multiplier).
- auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
- {
- return ChannelResult(channel) * ChannelResult(scalar);
- }
- };
- /// \ingroup ChannelNumericOperations
- /// \brief Arithmetic operation of dividing channel value by scalar.
- /// \note This is a generic implementation; user should specialize it for better performance.
- template <typename Channel, typename Scalar, typename ChannelResult>
- struct channel_divides_scalar_t
- {
- using ChannelRef = typename channel_traits<Channel>::const_reference;
- static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
- "ChannelRef not convertible to ChannelResult");
- static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
- static_assert(std::is_convertible<Scalar, ChannelResult>::value,
- "Scalar not convertible to ChannelResult");
- /// \param channel - dividend operand of the two division operation.
- /// \param scalar - divisor operand of the two division operation.
- auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
- {
- return ChannelResult(channel) / ChannelResult(scalar);
- }
- };
- /// \ingroup ChannelNumericOperations
- /// \brief Arithmetic operation of dividing channel value by 2
- /// \note This is a generic implementation; user should specialize it for better performance.
- template <typename Channel>
- struct channel_halves_t
- {
- using ChannelRef = typename channel_traits<Channel>::reference;
- auto operator()(ChannelRef channel) const -> ChannelRef
- {
- // TODO: Split into steps: extract with explicit conversion to double, divide and assign?
- //double const v = ch;
- //ch = static_cast<Channel>(v / 2.0);
- channel /= 2.0;
- return channel;
- }
- };
- /// \ingroup ChannelNumericOperations
- /// \brief Operation of setting channel value to zero
- /// \note This is a generic implementation; user should specialize it for better performance.
- template <typename Channel>
- struct channel_zeros_t
- {
- using ChannelRef = typename channel_traits<Channel>::reference;
- auto operator()(ChannelRef channel) const -> ChannelRef
- {
- channel = Channel(0);
- return channel;
- }
- };
- /// \ingroup ChannelNumericOperations
- /// structure for assigning one channel to another
- /// \note This is a generic implementation; user should specialize it for better performance.
- template <typename Channel1, typename Channel2>
- struct channel_assigns_t
- {
- using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
- using ChannelRef2 = typename channel_traits<Channel2>::reference;
- static_assert(std::is_convertible<ChannelRef1, Channel2>::value,
- "ChannelRef1 not convertible to Channel2");
- /// \param ch1 - assignor side (input) of the assignment operation
- /// \param ch2 - assignee side (output) of the assignment operation
- auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelRef2
- {
- ch2 = Channel2(ch1);
- return ch2;
- }
- };
- }} // namespace boost::gil
- #endif
|