Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:05

0001 //
0002 // Copyright 2005-2007 Adobe Systems Incorporated
0003 // Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
0004 //
0005 // Distributed under the Boost Software License, Version 1.0
0006 // See accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt
0008 //
0009 #ifndef BOOST_GIL_CHANNEL_NUMERIC_OPERATIONS_HPP
0010 #define BOOST_GIL_CHANNEL_NUMERIC_OPERATIONS_HPP
0011 
0012 #include <boost/gil/channel.hpp>
0013 
0014 namespace boost { namespace gil {
0015 
0016 // Function objects and utilities for channel-wise numeric operations.
0017 //
0018 // List of currently defined functors:
0019 //    channel_plus_t (+)
0020 //    channel_minus_t (-)
0021 //    channel_multiplies_t (*)
0022 //    channel_divides_t (/),
0023 //    channel_plus_scalar_t (+s)
0024 //    channel_minus_scalar_t (-s),
0025 //    channel_multiplies_scalar_t (*s)
0026 //    channel_divides_scalar_t (/s),
0027 //    channel_halves_t (/=2)
0028 //    channel_zeros_t (=0)
0029 //    channel_assigns_t (=)
0030 
0031 /// \ingroup ChannelNumericOperations
0032 /// \brief Arithmetic operation of addition of two channel values.
0033 /// \note This is a generic implementation; user should specialize it for better performance.
0034 template <typename Channel1, typename Channel2, typename ChannelResult>
0035 struct channel_plus_t
0036 {
0037     using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
0038     using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
0039     static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
0040         "ChannelRef1 not convertible to ChannelResult");
0041     static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
0042         "ChannelRef2 not convertible to ChannelResult");
0043 
0044     /// \param ch1 - first of the two addends (augend).
0045     /// \param ch2 - second of the two addends.
0046     auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
0047     {
0048         return ChannelResult(ch1) + ChannelResult(ch2);
0049     }
0050 };
0051 
0052 /// \ingroup ChannelNumericOperations
0053 /// \brief Arithmetic operation of subtraction of two channel values.
0054 /// \note This is a generic implementation; user should specialize it for better performance.
0055 template <typename Channel1, typename Channel2, typename ChannelResult>
0056 struct channel_minus_t
0057 {
0058     using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
0059     using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
0060     static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
0061         "ChannelRef1 not convertible to ChannelResult");
0062     static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
0063         "ChannelRef2 not convertible to ChannelResult");
0064 
0065     /// \param ch1 - minuend operand of the subtraction.
0066     /// \param ch2 - subtrahend operand of the subtraction.
0067     auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
0068     {
0069         return ChannelResult(ch1) - ChannelResult(ch2);
0070     }
0071 };
0072 
0073 /// \ingroup ChannelNumericOperations
0074 /// \brief Arithmetic operation of multiplication of two channel values.
0075 /// \note This is a generic implementation; user should specialize it for better performance.
0076 template <typename Channel1, typename Channel2, typename ChannelResult>
0077 struct channel_multiplies_t
0078 {
0079     using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
0080     using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
0081     static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
0082         "ChannelRef1 not convertible to ChannelResult");
0083     static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
0084         "ChannelRef2 not convertible to ChannelResult");
0085 
0086     /// \param ch1 - first of the two factors (multiplicand).
0087     /// \param ch2 - second of the two factors (multiplier).
0088     auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
0089     {
0090         return ChannelResult(ch1) * ChannelResult(ch2);
0091     }
0092 };
0093 
0094 /// \ingroup ChannelNumericOperations
0095 /// \brief Arithmetic operation of division of two channel values.
0096 /// \note This is a generic implementation; user should specialize it for better performance.
0097 template <typename Channel1, typename Channel2, typename ChannelResult>
0098 struct channel_divides_t
0099 {
0100     using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
0101     using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
0102     static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
0103         "ChannelRef1 not convertible to ChannelResult");
0104     static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
0105         "ChannelRef2 not convertible to ChannelResult");
0106 
0107     /// \param ch1 - dividend operand of the two division operation.
0108     /// \param ch2 - divisor operand of the two division operation.
0109     auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
0110     {
0111         return ChannelResult(ch1) / ChannelResult(ch2);
0112     }
0113 };
0114 
0115 /// \ingroup ChannelNumericOperations
0116 /// \brief Arithmetic operation of adding scalar to channel value.
0117 /// \note This is a generic implementation; user should specialize it for better performance.
0118 template <typename Channel, typename Scalar, typename ChannelResult>
0119 struct channel_plus_scalar_t
0120 {
0121     using ChannelRef = typename channel_traits<Channel>::const_reference;
0122     static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
0123         "ChannelRef not convertible to ChannelResult");
0124     static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
0125     static_assert(std::is_convertible<Scalar, ChannelResult>::value,
0126         "Scalar not convertible to ChannelResult");
0127 
0128     auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
0129     {
0130         return ChannelResult(channel) + ChannelResult(scalar);
0131     }
0132 };
0133 
0134 /// \ingroup ChannelNumericOperations
0135 /// \brief Arithmetic operation of subtracting scalar from channel value.
0136 /// \note This is a generic implementation; user should specialize it for better performance.
0137 template <typename Channel, typename Scalar, typename ChannelResult>
0138 struct channel_minus_scalar_t
0139 {
0140     using ChannelRef = typename channel_traits<Channel>::const_reference;
0141     static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
0142         "ChannelRef not convertible to ChannelResult");
0143     static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
0144     static_assert(std::is_convertible<Scalar, ChannelResult>::value,
0145         "Scalar not convertible to ChannelResult");
0146 
0147     /// \param channel - minuend operand of the subtraction.
0148     /// \param scalar - subtrahend operand of the subtraction.
0149     auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
0150     {
0151         // TODO: Convertion after subtraction vs conversion of operands in channel_minus_t?
0152         return ChannelResult(channel - scalar);
0153     }
0154 };
0155 
0156 /// \ingroup ChannelNumericOperations
0157 /// \brief Arithmetic operation of channel value by a scalar.
0158 /// \note This is a generic implementation; user should specialize it for better performance.
0159 template <typename Channel, typename Scalar, typename ChannelResult>
0160 struct channel_multiplies_scalar_t
0161 {
0162     using ChannelRef = typename channel_traits<Channel>::const_reference;
0163     static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
0164         "ChannelRef not convertible to ChannelResult");
0165     static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
0166     static_assert(std::is_convertible<Scalar, ChannelResult>::value,
0167         "Scalar not convertible to ChannelResult");
0168 
0169     /// \param channel - first of the two factors (multiplicand).
0170     /// \param scalar - second of the two factors (multiplier).
0171     auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
0172     {
0173         return ChannelResult(channel) * ChannelResult(scalar);
0174     }
0175 };
0176 
0177 /// \ingroup ChannelNumericOperations
0178 /// \brief Arithmetic operation of dividing channel value by scalar.
0179 /// \note This is a generic implementation; user should specialize it for better performance.
0180 template <typename Channel, typename Scalar, typename ChannelResult>
0181 struct channel_divides_scalar_t
0182 {
0183     using ChannelRef = typename channel_traits<Channel>::const_reference;
0184     static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
0185         "ChannelRef not convertible to ChannelResult");
0186     static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
0187     static_assert(std::is_convertible<Scalar, ChannelResult>::value,
0188         "Scalar not convertible to ChannelResult");
0189 
0190     /// \param channel - dividend operand of the two division operation.
0191     /// \param scalar - divisor operand of the two division operation.
0192     auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
0193     {
0194         return ChannelResult(channel) / ChannelResult(scalar);
0195     }
0196 };
0197 
0198 /// \ingroup ChannelNumericOperations
0199 /// \brief Arithmetic operation of dividing channel value by 2
0200 /// \note This is a generic implementation; user should specialize it for better performance.
0201 template <typename Channel>
0202 struct channel_halves_t
0203 {
0204     using ChannelRef = typename channel_traits<Channel>::reference;
0205 
0206     auto operator()(ChannelRef channel) const -> ChannelRef
0207     {
0208         // TODO: Split into steps: extract with explicit conversion to double, divide and assign?
0209         //double const v = ch;
0210         //ch = static_cast<Channel>(v / 2.0);
0211         channel /= 2.0;
0212         return channel;
0213     }
0214 };
0215 
0216 /// \ingroup ChannelNumericOperations
0217 /// \brief Operation of setting channel value to zero
0218 /// \note This is a generic implementation; user should specialize it for better performance.
0219 template <typename Channel>
0220 struct channel_zeros_t
0221 {
0222     using ChannelRef = typename channel_traits<Channel>::reference;
0223 
0224     auto operator()(ChannelRef channel) const -> ChannelRef
0225     {
0226         channel = Channel(0);
0227         return channel;
0228     }
0229 };
0230 
0231 /// \ingroup ChannelNumericOperations
0232 /// structure for assigning one channel to another
0233 /// \note This is a generic implementation; user should specialize it for better performance.
0234 template <typename Channel1, typename Channel2>
0235 struct channel_assigns_t
0236 {
0237     using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
0238     using ChannelRef2 = typename channel_traits<Channel2>::reference;
0239     static_assert(std::is_convertible<ChannelRef1, Channel2>::value,
0240         "ChannelRef1 not convertible to Channel2");
0241 
0242     /// \param ch1 - assignor side (input) of the assignment operation
0243     /// \param ch2 - assignee side (output) of the assignment operation
0244     auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelRef2
0245     {
0246         ch2 = Channel2(ch1);
0247         return ch2;
0248     }
0249 };
0250 
0251 }}  // namespace boost::gil
0252 
0253 #endif