8 #ifndef BOOST_GIL_GIL_CHANNEL_ALGORITHM_HPP     9 #define BOOST_GIL_GIL_CHANNEL_ALGORITHM_HPP    11 #include <boost/gil/channel.hpp>    12 #include <boost/gil/promote_integral.hpp>    13 #include <boost/gil/typedefs.hpp>    14 #include <boost/gil/detail/is_channel_integral.hpp>    15 #include <boost/gil/detail/mp11.hpp>    18 #include <type_traits>    20 namespace boost { 
namespace gil {
    25 template <
typename SrcChannelV, 
typename DstChannelV, 
bool SrcIsIntegral, 
bool DstIsIntegral>
    28 template <
typename SrcChannelV, 
typename DstChannelV, 
bool SrcIsGreater>
    29 struct channel_converter_unsigned_integral;
    31 template <
typename SrcChannelV, 
typename DstChannelV, 
bool SrcLessThanDst, 
bool SrcDivisible>
    32 struct channel_converter_unsigned_integral_impl;
    34 template <
typename SrcChannelV, 
typename DstChannelV, 
bool SrcLessThanDst, 
bool CannotFitInInteger>
    35 struct channel_converter_unsigned_integral_nondivisible;
    42 template <
typename Un
signedIntegralChannel>
    43 struct unsigned_integral_max_value
    44     : std::integral_constant
    46         UnsignedIntegralChannel,
    47         (std::numeric_limits<UnsignedIntegralChannel>::max)()
    52 struct unsigned_integral_max_value<uint8_t>
    53     : std::integral_constant<uint32_t, 0xFF>
    57 struct unsigned_integral_max_value<uint16_t>
    58     : std::integral_constant<uint32_t, 0xFFFF>
    62 struct unsigned_integral_max_value<uint32_t>
    63     : std::integral_constant<uintmax_t, 0xFFFFFFFF>
    67 struct unsigned_integral_max_value<packed_channel_value<K>>
    68     : std::integral_constant
    70         typename packed_channel_value<K>::integer_t,
    80 template <typename UnsignedIntegralChannel>
    81 struct unsigned_integral_num_bits
    82     : std::integral_constant<int, sizeof(UnsignedIntegralChannel) * 8>
    86 struct unsigned_integral_num_bits<packed_channel_value<K>>
    87     : std::integral_constant<int, K>
   126 template <typename SrcChannelV, typename DstChannelV>     
   127 struct channel_converter_unsigned
   128     : detail::channel_converter_unsigned_impl
   132         detail::is_channel_integral<SrcChannelV>::value,
   133         detail::is_channel_integral<DstChannelV>::value
   138 template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {};
   147 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral>
   148 struct channel_converter_unsigned_impl {
   149     using argument_type = SrcChannelV;
   150     using result_type = DstChannelV;
   151     DstChannelV operator()(SrcChannelV src) const {
   152         return DstChannelV(channel_traits<DstChannelV>::min_value() +
   153             (src - channel_traits<SrcChannelV>::min_value()) / channel_range<SrcChannelV>() * channel_range<DstChannelV>());
   156     template <typename C>
   157     static double channel_range() {
   158         return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value());
   163 template <typename SrcChannelV, typename DstChannelV>
   164 struct channel_converter_unsigned_impl<SrcChannelV, DstChannelV, true, true>
   165     : channel_converter_unsigned_integral
   171             unsigned_integral_max_value<SrcChannelV>,
   172             unsigned_integral_max_value<DstChannelV>
   181 template <typename SrcChannelV, typename DstChannelV>
   182 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,true>
   183     : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,
   184     !(unsigned_integral_max_value<DstChannelV>::value % unsigned_integral_max_value<SrcChannelV>::value) > {};
   186 template <typename SrcChannelV, typename DstChannelV>
   187 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,false>
   188     : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,
   189     !(unsigned_integral_max_value<SrcChannelV>::value % unsigned_integral_max_value<DstChannelV>::value) > {};
   199 template <typename SrcChannelV, typename DstChannelV>
   200 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,true> {
   201     DstChannelV operator()(SrcChannelV src) const {
   202         using integer_t = typename unsigned_integral_max_value<DstChannelV>::value_type;
   203         static const integer_t mul = unsigned_integral_max_value<DstChannelV>::value / unsigned_integral_max_value<SrcChannelV>::value;
   204         return DstChannelV(src * mul);
   211 template <typename SrcChannelV, typename DstChannelV>
   212 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,true> {
   213     DstChannelV operator()(SrcChannelV src) const {
   214         using integer_t = typename unsigned_integral_max_value<SrcChannelV>::value_type;
   215         static const integer_t div = unsigned_integral_max_value<SrcChannelV>::value / unsigned_integral_max_value<DstChannelV>::value;
   216         static const integer_t div2 = div/2;
   217         return DstChannelV((src + div2) / div);
   222 template <typename DstChannelV>
   223 struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true> {
   224     DstChannelV operator()(uintmax_t src) const {
   225         static const uintmax_t div = unsigned_integral_max_value<uint32_t>::value / unsigned_integral_max_value<DstChannelV>::value;
   226         static const uintmax_t div2 = div/2;
   227         if (src > unsigned_integral_max_value<uintmax_t>::value - div2)
   228             return unsigned_integral_max_value<DstChannelV>::value;
   229         return DstChannelV((src + div2) / div);
   236 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst>
   237 struct channel_converter_unsigned_integral_impl<SrcChannelV, DstChannelV, SrcLessThanDst, false>
   238     : channel_converter_unsigned_integral_nondivisible
   245             unsigned_integral_num_bits<uintmax_t>,
   248                 unsigned_integral_num_bits<SrcChannelV>,
   249                 unsigned_integral_num_bits<DstChannelV>
   259 template <typename SrcChannelV, typename DstChannelV>
   260 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV, DstChannelV, true, false>
   262     DstChannelV operator()(SrcChannelV src) const
   264         using dest_t = typename base_channel_type<DstChannelV>::type;
   266             static_cast<dest_t>(src * unsigned_integral_max_value<DstChannelV>::value)
   267             / unsigned_integral_max_value<SrcChannelV>::value);
   275 template <typename SrcChannelV, typename DstChannelV>
   276 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV, DstChannelV, true, true>
   278     DstChannelV operator()(SrcChannelV src) const
   280         static const double mul
   281             = unsigned_integral_max_value<DstChannelV>::value
   282             / double(unsigned_integral_max_value<SrcChannelV>::value);
   283         return DstChannelV(src * mul);
   290 template <typename SrcChannelV, typename DstChannelV, bool CannotFit>
   291 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> {
   292     DstChannelV operator()(SrcChannelV src) const {
   294         using src_integer_t = typename detail::unsigned_integral_max_value<SrcChannelV>::value_type;
   295         using dst_integer_t = typename detail::unsigned_integral_max_value<DstChannelV>::value_type;
   297         static const double div = unsigned_integral_max_value<SrcChannelV>::value
   298                                 / static_cast< double >( unsigned_integral_max_value<DstChannelV>::value );
   300         static const src_integer_t div2 = static_cast< src_integer_t >( div / 2.0 );
   302         return DstChannelV( static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div )));
   312 template <typename DstChannelV> struct channel_converter_unsigned<float32_t,DstChannelV> {
   313     using argument_type = float32_t;
   314     using result_type = DstChannelV;
   315     DstChannelV operator()(float32_t x) const
   317         using dst_integer_t = typename detail::unsigned_integral_max_value<DstChannelV>::value_type;
   318         return DstChannelV( static_cast< dst_integer_t >(x*channel_traits<DstChannelV>::max_value()+0.5f ));
   322 template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,float32_t> {
   323     using argument_type = float32_t;
   324     using result_type = SrcChannelV;
   325     float32_t operator()(SrcChannelV   x) const { return float32_t(x/float(channel_traits<SrcChannelV>::max_value())); }
   328 template <> struct channel_converter_unsigned<float32_t,float32_t> {
   329     using argument_type = float32_t;
   330     using result_type = float32_t;
   331     float32_t operator()(float32_t   x) const { return x; }
   336 template <> struct channel_converter_unsigned<uint32_t,float32_t> {
   337     using argument_type = uint32_t;
   338     using result_type = float32_t;
   339     float32_t operator()(uint32_t x) const {
   341         if (x>=channel_traits<uint32_t>::max_value()) return channel_traits<float32_t>::max_value();
   342         return float(x) / float(channel_traits<uint32_t>::max_value());
   346 template <> struct channel_converter_unsigned<float32_t,uint32_t> {
   348     using result_type = uint32_t;
   351         if (x>=channel_traits<float32_t>::max_value())
   352             return channel_traits<uint32_t>::max_value();
   354         auto const max_value = channel_traits<uint32_t>::max_value();
   355         auto const result = x * static_cast<float32_t::base_channel_t>(max_value) + 0.5f;
   356         return static_cast<uint32_t>(result);
   365 template <
typename ChannelValue>     
   366 struct channel_convert_to_unsigned : 
public detail::identity<ChannelValue> {
   367     using type = ChannelValue;
   370 template <> 
struct channel_convert_to_unsigned<int8_t> {
   371     using argument_type = int8_t;
   372     using result_type = uint8_t;
   373     using type = uint8_t;
   374     type operator()(int8_t val)
 const {
   375         return static_cast<uint8_t>(static_cast<uint32_t>(val) + 128u);
   379 template <> 
struct channel_convert_to_unsigned<int16_t> {
   380     using argument_type = int16_t;
   381     using result_type = uint16_t;
   382     using type = uint16_t;
   383     type operator()(int16_t val)
 const {
   384         return static_cast<uint16_t>(static_cast<uint32_t>(val) + 32768u);
   388 template <> 
struct channel_convert_to_unsigned<int32_t> {
   389     using argument_type = int32_t;
   390     using result_type = uint32_t;
   391     using type = uint32_t;
   392     type operator()(int32_t val)
 const {
   393         return static_cast<uint32_t>(val)+(1u<<31);
   400 template <
typename ChannelValue>     
   401 struct channel_convert_from_unsigned : 
public detail::identity<ChannelValue> {
   402     using type = ChannelValue;
   405 template <> 
struct channel_convert_from_unsigned<int8_t> {
   406     using argument_type = uint8_t;
   407     using result_type = int8_t;
   409     type  operator()(uint8_t val)
 const {
   410         return static_cast<int8_t>(static_cast<int32_t>(val) - 128);
   414 template <> 
struct channel_convert_from_unsigned<int16_t> {
   415     using argument_type = uint16_t;
   416     using result_type = int16_t;
   417     using type = int16_t;
   418     type operator()(uint16_t val)
 const {
   419         return static_cast<int16_t>(static_cast<int32_t>(val) - 32768);
   423 template <> 
struct channel_convert_from_unsigned<int32_t> {
   424     using argument_type = uint32_t;
   425     using result_type = int32_t;
   426     using type = int32_t;
   427     type operator()(uint32_t val)
 const {
   428         return static_cast<int32_t>(val - (1u<<31));
   436 template <
typename SrcChannelV, 
typename DstChannelV> 
   438     using argument_type = SrcChannelV;
   439     using result_type = DstChannelV;
   440     DstChannelV operator()(
const SrcChannelV& src)
 const {
   441         using to_unsigned = detail::channel_convert_to_unsigned<SrcChannelV>;
   442         using from_unsigned = detail::channel_convert_from_unsigned<DstChannelV>;
   443         using converter_unsigned = channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type>;
   444         return from_unsigned()(converter_unsigned()(to_unsigned()(src)));
   450 template <
typename DstChannel, 
typename SrcChannel> 
   451 inline typename channel_traits<DstChannel>::value_type 
channel_convert(
const SrcChannel& src) {
   453                              typename channel_traits<DstChannel>::value_type>()(src);
   461     template <
typename Ch1, 
typename Ch2>
   462     void operator()(
const Ch1& src, Ch2& dst)
 const {
   463         dst=channel_convert<Ch2>(src);
   469     inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128; 
return (tmp + (tmp>>8))>>8; }
   472     inline uint32_t div32768(uint32_t in) { 
return (in+16384)>>15; }
   489 template <
typename ChannelValue>
   491     using first_argument_type = ChannelValue;
   492     using second_argument_type = ChannelValue;
   493     using result_type = ChannelValue;
   494     ChannelValue operator()(ChannelValue a, ChannelValue b)
 const {
   495         return ChannelValue(
static_cast<typename base_channel_type<ChannelValue>::type
>(a / 
double(channel_traits<ChannelValue>::max_value()) * b));
   501     using first_argument_type = uint8_t;
   502     using second_argument_type = uint8_t;
   503     using result_type = uint8_t;
   504     uint8_t operator()(uint8_t a, uint8_t b)
 const { 
return uint8_t(detail::div255(uint32_t(a) * uint32_t(b))); }
   509     using first_argument_type = uint16_t;
   510     using second_argument_type = uint16_t;
   511     using result_type = uint16_t;
   512     uint16_t operator()(uint16_t a, uint16_t b)
 const { 
return uint16_t((uint32_t(a) * uint32_t(b))/65535); }
   524 template <
typename ChannelValue>
   526     using first_argument_type = ChannelValue;
   527     using second_argument_type = ChannelValue;
   528     using result_type = ChannelValue;
   529     ChannelValue operator()(ChannelValue a, ChannelValue b)
 const {
   530         using to_unsigned = detail::channel_convert_to_unsigned<ChannelValue>;
   531         using from_unsigned = detail::channel_convert_from_unsigned<ChannelValue>;
   533         return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b)));
   538 template <
typename Channel> 
   539 inline typename channel_traits<Channel>::value_type 
channel_multiply(Channel a, Channel b) {
   558 template <
typename Channel> 
   561     using base_t = 
typename base_channel_type<Channel>::type;
   562     using promoted_t = 
typename promote_integral<base_t>::type;
   563     promoted_t 
const promoted_x = x;
   564     promoted_t 
const promoted_max = channel_traits<Channel>::max_value();
   565     promoted_t 
const promoted_min = channel_traits<Channel>::min_value();
   566     promoted_t 
const promoted_inverted_x = promoted_max - promoted_x + promoted_min;
   567     auto const inverted_x = static_cast<base_t>(promoted_inverted_x);
 channel_traits< Channel >::value_type channel_invert(Channel x)
Default implementation. Provide overloads for performance.
Definition: channel_algorithm.hpp:559
scoped_channel_value< float, float_point_zero< float >, float_point_one< float > > float32_t
32-bit floating point channel type with range [0.0f ... 1.0f]. Models ChannelValueConcept
Definition: typedefs.hpp:124
channel_traits< DstChannel >::value_type channel_convert(const SrcChannel &src)
Converting from one channel type to another.
Definition: channel_algorithm.hpp:451
channel_traits< Channel >::value_type channel_multiply(Channel a, Channel b)
A function multiplying two channels. result = a * b / max_value.
Definition: channel_algorithm.hpp:539
identity taken from SGI STL.
Definition: utilities.hpp:209
Same as channel_converter, except it takes the destination channel by reference, which allows us to m...
Definition: channel_algorithm.hpp:460
A function object to multiply two channels. result = a * b / max_value.
Definition: channel_algorithm.hpp:525
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:490
This is the default implementation. Performance specializatons are provided.
Definition: channel_algorithm.hpp:26
A unary function object converting between channel types.
Definition: channel_algorithm.hpp:437