File indexing completed on 2024-11-15 09:12:38
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_GIL_GIL_CHANNEL_ALGORITHM_HPP
0009 #define BOOST_GIL_GIL_CHANNEL_ALGORITHM_HPP
0010
0011 #include <boost/gil/channel.hpp>
0012 #include <boost/gil/promote_integral.hpp>
0013 #include <boost/gil/typedefs.hpp>
0014 #include <boost/gil/detail/is_channel_integral.hpp>
0015 #include <boost/gil/detail/mp11.hpp>
0016
0017 #include <limits>
0018 #include <type_traits>
0019
0020 namespace boost { namespace gil {
0021
0022 namespace detail {
0023
0024
0025 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral>
0026 struct channel_converter_unsigned_impl;
0027
0028 template <typename SrcChannelV, typename DstChannelV, bool SrcIsGreater>
0029 struct channel_converter_unsigned_integral;
0030
0031 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool SrcDivisible>
0032 struct channel_converter_unsigned_integral_impl;
0033
0034 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool CannotFitInInteger>
0035 struct channel_converter_unsigned_integral_nondivisible;
0036
0037
0038
0039
0040
0041
0042 template <typename UnsignedIntegralChannel>
0043 struct unsigned_integral_max_value
0044 : std::integral_constant
0045 <
0046 UnsignedIntegralChannel,
0047 (std::numeric_limits<UnsignedIntegralChannel>::max)()
0048 >
0049 {};
0050
0051 template <>
0052 struct unsigned_integral_max_value<uint8_t>
0053 : std::integral_constant<uint32_t, 0xFF>
0054 {};
0055
0056 template <>
0057 struct unsigned_integral_max_value<uint16_t>
0058 : std::integral_constant<uint32_t, 0xFFFF>
0059 {};
0060
0061 template <>
0062 struct unsigned_integral_max_value<uint32_t>
0063 : std::integral_constant<uintmax_t, 0xFFFFFFFF>
0064 {};
0065
0066 template <int K>
0067 struct unsigned_integral_max_value<packed_channel_value<K>>
0068 : std::integral_constant
0069 <
0070 typename packed_channel_value<K>::integer_t,
0071 (uint64_t(1)<<K)-1
0072 >
0073 {};
0074
0075
0076
0077
0078
0079
0080 template <typename UnsignedIntegralChannel>
0081 struct unsigned_integral_num_bits
0082 : std::integral_constant<int, static_cast<int>(sizeof(UnsignedIntegralChannel) * 8)>
0083 {};
0084
0085 template <int K>
0086 struct unsigned_integral_num_bits<packed_channel_value<K>>
0087 : std::integral_constant<int, K>
0088 {};
0089
0090 }
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 template <typename SrcChannelV, typename DstChannelV>
0127 struct channel_converter_unsigned
0128 : detail::channel_converter_unsigned_impl
0129 <
0130 SrcChannelV,
0131 DstChannelV,
0132 detail::is_channel_integral<SrcChannelV>::value,
0133 detail::is_channel_integral<DstChannelV>::value
0134 >
0135 {};
0136
0137
0138 template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {};
0139
0140 namespace detail {
0141
0142
0143
0144
0145
0146
0147 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral>
0148 struct channel_converter_unsigned_impl {
0149 using argument_type = SrcChannelV;
0150 using result_type = DstChannelV;
0151 auto operator()(SrcChannelV src) const -> DstChannelV
0152 {
0153 return DstChannelV(channel_traits<DstChannelV>::min_value() +
0154 (src - channel_traits<SrcChannelV>::min_value()) / channel_range<SrcChannelV>() * channel_range<DstChannelV>());
0155 }
0156
0157 private:
0158 template <typename C>
0159 static auto channel_range() -> double
0160 {
0161 return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value());
0162 }
0163 };
0164
0165
0166 template <typename SrcChannelV, typename DstChannelV>
0167 struct channel_converter_unsigned_impl<SrcChannelV, DstChannelV, true, true>
0168 : channel_converter_unsigned_integral
0169 <
0170 SrcChannelV,
0171 DstChannelV,
0172 mp11::mp_less
0173 <
0174 unsigned_integral_max_value<SrcChannelV>,
0175 unsigned_integral_max_value<DstChannelV>
0176 >::value
0177 >
0178 {};
0179
0180
0181
0182
0183
0184 template <typename SrcChannelV, typename DstChannelV>
0185 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,true>
0186 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,
0187 !(unsigned_integral_max_value<DstChannelV>::value % unsigned_integral_max_value<SrcChannelV>::value) > {};
0188
0189 template <typename SrcChannelV, typename DstChannelV>
0190 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,false>
0191 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,
0192 !(unsigned_integral_max_value<SrcChannelV>::value % unsigned_integral_max_value<DstChannelV>::value) > {};
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 template <typename SrcChannelV, typename DstChannelV>
0203 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,true> {
0204 auto operator()(SrcChannelV src) const -> DstChannelV
0205 {
0206 using integer_t = typename unsigned_integral_max_value<DstChannelV>::value_type;
0207 static const integer_t mul = unsigned_integral_max_value<DstChannelV>::value / unsigned_integral_max_value<SrcChannelV>::value;
0208 return DstChannelV(src * mul);
0209 }
0210 };
0211
0212
0213
0214
0215 template <typename SrcChannelV, typename DstChannelV>
0216 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,true> {
0217 auto operator()(SrcChannelV src) const -> DstChannelV
0218 {
0219 using integer_t = typename unsigned_integral_max_value<SrcChannelV>::value_type;
0220 static const integer_t div = unsigned_integral_max_value<SrcChannelV>::value / unsigned_integral_max_value<DstChannelV>::value;
0221 static const integer_t div2 = div/2;
0222 return DstChannelV((src + div2) / div);
0223 }
0224 };
0225
0226
0227 template <typename DstChannelV>
0228 struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true> {
0229 auto operator()(uintmax_t src) const -> DstChannelV
0230 {
0231 static const uintmax_t div = unsigned_integral_max_value<uint32_t>::value / unsigned_integral_max_value<DstChannelV>::value;
0232 static const uintmax_t div2 = div/2;
0233 if (src > unsigned_integral_max_value<uintmax_t>::value - div2)
0234 return unsigned_integral_max_value<DstChannelV>::value;
0235 return DstChannelV((src + div2) / div);
0236 }
0237 };
0238
0239
0240
0241
0242 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst>
0243 struct channel_converter_unsigned_integral_impl<SrcChannelV, DstChannelV, SrcLessThanDst, false>
0244 : channel_converter_unsigned_integral_nondivisible
0245 <
0246 SrcChannelV,
0247 DstChannelV,
0248 SrcLessThanDst,
0249 mp11::mp_less
0250 <
0251 unsigned_integral_num_bits<uintmax_t>,
0252 mp11::mp_plus
0253 <
0254 unsigned_integral_num_bits<SrcChannelV>,
0255 unsigned_integral_num_bits<DstChannelV>
0256 >
0257 >::value
0258 >
0259 {};
0260
0261
0262
0263
0264
0265 template <typename SrcChannelV, typename DstChannelV>
0266 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV, DstChannelV, true, false>
0267 {
0268 auto operator()(SrcChannelV src) const -> DstChannelV
0269 {
0270 using dest_t = typename base_channel_type<DstChannelV>::type;
0271 return DstChannelV(
0272 static_cast<dest_t>(src * unsigned_integral_max_value<DstChannelV>::value)
0273 / unsigned_integral_max_value<SrcChannelV>::value);
0274 }
0275 };
0276
0277
0278
0279
0280
0281 template <typename SrcChannelV, typename DstChannelV>
0282 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV, DstChannelV, true, true>
0283 {
0284 auto operator()(SrcChannelV src) const -> DstChannelV
0285 {
0286 static const double mul
0287 = unsigned_integral_max_value<DstChannelV>::value
0288 / double(unsigned_integral_max_value<SrcChannelV>::value);
0289 return DstChannelV(src * mul);
0290 }
0291 };
0292
0293
0294
0295
0296 template <typename SrcChannelV, typename DstChannelV, bool CannotFit>
0297 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit>
0298 {
0299 auto operator()(SrcChannelV src) const -> DstChannelV
0300 {
0301 using src_integer_t = typename detail::unsigned_integral_max_value<SrcChannelV>::value_type;
0302 using dst_integer_t = typename detail::unsigned_integral_max_value<DstChannelV>::value_type;
0303
0304 static const double div = unsigned_integral_max_value<SrcChannelV>::value
0305 / static_cast< double >( unsigned_integral_max_value<DstChannelV>::value );
0306
0307 static const src_integer_t div2 = static_cast< src_integer_t >( div / 2.0 );
0308
0309 return DstChannelV( static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div )));
0310 }
0311 };
0312
0313 }
0314
0315
0316
0317
0318
0319 template <typename DstChannelV> struct channel_converter_unsigned<float32_t,DstChannelV> {
0320 using argument_type = float32_t;
0321 using result_type = DstChannelV;
0322 auto operator()(float32_t x) const -> DstChannelV
0323 {
0324 using dst_integer_t = typename detail::unsigned_integral_max_value<DstChannelV>::value_type;
0325 return DstChannelV( static_cast< dst_integer_t >(x*channel_traits<DstChannelV>::max_value()+0.5f ));
0326 }
0327 };
0328
0329 template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,float32_t> {
0330 using argument_type = float32_t;
0331 using result_type = SrcChannelV;
0332 auto operator()(SrcChannelV x) const -> float32_t { return float32_t(x/float(channel_traits<SrcChannelV>::max_value())); }
0333 };
0334
0335 template <> struct channel_converter_unsigned<float32_t,float32_t> {
0336 using argument_type = float32_t;
0337 using result_type = float32_t;
0338 auto operator()(float32_t x) const -> float32_t { return x; }
0339 };
0340
0341
0342
0343 template <> struct channel_converter_unsigned<uint32_t,float32_t> {
0344 using argument_type = uint32_t;
0345 using result_type = float32_t;
0346 auto operator()(uint32_t x) const -> float32_t
0347 {
0348
0349 if (x>=channel_traits<uint32_t>::max_value()) return channel_traits<float32_t>::max_value();
0350 return float(x) / float(channel_traits<uint32_t>::max_value());
0351 }
0352 };
0353
0354 template <> struct channel_converter_unsigned<float32_t,uint32_t> {
0355 using argument_type = float32_t;
0356 using result_type = uint32_t;
0357 auto operator()(float32_t x) const -> uint32_t
0358 {
0359
0360 if (x>=channel_traits<float32_t>::max_value())
0361 return channel_traits<uint32_t>::max_value();
0362
0363 auto const max_value = channel_traits<uint32_t>::max_value();
0364 auto const result = x * static_cast<float32_t::base_channel_t>(max_value) + 0.5f;
0365 return static_cast<uint32_t>(result);
0366 }
0367 };
0368
0369
0370
0371 namespace detail {
0372
0373
0374 template <typename ChannelValue>
0375 struct channel_convert_to_unsigned : public detail::identity<ChannelValue> {
0376 using type = ChannelValue;
0377 };
0378
0379 template <> struct channel_convert_to_unsigned<int8_t> {
0380 using argument_type = int8_t;
0381 using result_type = uint8_t;
0382 using type = uint8_t;
0383 type operator()(int8_t val) const {
0384 return static_cast<uint8_t>(static_cast<uint32_t>(val) + 128u);
0385 }
0386 };
0387
0388 template <> struct channel_convert_to_unsigned<int16_t> {
0389 using argument_type = int16_t;
0390 using result_type = uint16_t;
0391 using type = uint16_t;
0392 type operator()(int16_t val) const {
0393 return static_cast<uint16_t>(static_cast<uint32_t>(val) + 32768u);
0394 }
0395 };
0396
0397 template <> struct channel_convert_to_unsigned<int32_t> {
0398 using argument_type = int32_t;
0399 using result_type = uint32_t;
0400 using type = uint32_t;
0401 type operator()(int32_t val) const {
0402 return static_cast<uint32_t>(val)+(1u<<31);
0403 }
0404 };
0405
0406
0407
0408
0409 template <typename ChannelValue>
0410 struct channel_convert_from_unsigned : public detail::identity<ChannelValue> {
0411 using type = ChannelValue;
0412 };
0413
0414 template <> struct channel_convert_from_unsigned<int8_t> {
0415 using argument_type = uint8_t;
0416 using result_type = int8_t;
0417 using type = int8_t;
0418 type operator()(uint8_t val) const {
0419 return static_cast<int8_t>(static_cast<int32_t>(val) - 128);
0420 }
0421 };
0422
0423 template <> struct channel_convert_from_unsigned<int16_t> {
0424 using argument_type = uint16_t;
0425 using result_type = int16_t;
0426 using type = int16_t;
0427 type operator()(uint16_t val) const {
0428 return static_cast<int16_t>(static_cast<int32_t>(val) - 32768);
0429 }
0430 };
0431
0432 template <> struct channel_convert_from_unsigned<int32_t> {
0433 using argument_type = uint32_t;
0434 using result_type = int32_t;
0435 using type = int32_t;
0436 type operator()(uint32_t val) const {
0437 return static_cast<int32_t>(val - (1u<<31));
0438 }
0439 };
0440
0441 }
0442
0443
0444
0445 template <typename SrcChannelV, typename DstChannelV>
0446 struct channel_converter {
0447 using argument_type = SrcChannelV;
0448 using result_type = DstChannelV;
0449 auto operator()(SrcChannelV const& src) const -> DstChannelV
0450 {
0451 using to_unsigned = detail::channel_convert_to_unsigned<SrcChannelV>;
0452 using from_unsigned = detail::channel_convert_from_unsigned<DstChannelV>;
0453 using converter_unsigned = channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type>;
0454 return from_unsigned()(converter_unsigned()(to_unsigned()(src)));
0455 }
0456 };
0457
0458
0459
0460 template <typename DstChannel, typename SrcChannel>
0461 inline auto channel_convert(SrcChannel const& src) -> typename channel_traits<DstChannel>::value_type
0462 {
0463 return channel_converter<typename channel_traits<SrcChannel>::value_type,
0464 typename channel_traits<DstChannel>::value_type>()(src);
0465 }
0466
0467
0468
0469
0470
0471 struct default_channel_converter {
0472 template <typename Ch1, typename Ch2>
0473 void operator()(Ch1 const& src, Ch2& dst) const
0474 {
0475 dst=channel_convert<Ch2>(src);
0476 }
0477 };
0478
0479 namespace detail
0480 {
0481
0482 inline auto div255(uint32_t in) -> uint32_t
0483 {
0484 uint32_t tmp = in + 128;
0485 return (tmp + (tmp >> 8)) >> 8;
0486 }
0487
0488
0489 inline auto div32768(uint32_t in) -> uint32_t
0490 {
0491 return (in + 16384) >> 15;
0492 }
0493 }
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509 template <typename ChannelValue>
0510 struct channel_multiplier_unsigned {
0511 using first_argument_type = ChannelValue;
0512 using second_argument_type = ChannelValue;
0513 using result_type = ChannelValue;
0514 auto operator()(ChannelValue a, ChannelValue b) const -> ChannelValue
0515 {
0516 return ChannelValue(static_cast<typename base_channel_type<ChannelValue>::type>(a / double(channel_traits<ChannelValue>::max_value()) * b));
0517 }
0518 };
0519
0520
0521 template<> struct channel_multiplier_unsigned<uint8_t> {
0522 using first_argument_type = uint8_t;
0523 using second_argument_type = uint8_t;
0524 using result_type = uint8_t;
0525 auto operator()(uint8_t a, uint8_t b) const -> uint8_t { return uint8_t(detail::div255(uint32_t(a) * uint32_t(b))); }
0526 };
0527
0528
0529 template<> struct channel_multiplier_unsigned<uint16_t> {
0530 using first_argument_type = uint16_t;
0531 using second_argument_type = uint16_t;
0532 using result_type = uint16_t;
0533 auto operator()(uint16_t a, uint16_t b) const -> uint16_t { return uint16_t((uint32_t(a) * uint32_t(b))/65535); }
0534 };
0535
0536
0537 template<> struct channel_multiplier_unsigned<float32_t> {
0538 using first_argument_type = float32_t;
0539 using second_argument_type = float32_t;
0540 using result_type = float32_t;
0541 auto operator()(float32_t a, float32_t b) const -> float32_t { return a*b; }
0542 };
0543
0544
0545 template <typename ChannelValue>
0546 struct channel_multiplier {
0547 using first_argument_type = ChannelValue;
0548 using second_argument_type = ChannelValue;
0549 using result_type = ChannelValue;
0550 auto operator()(ChannelValue a, ChannelValue b) const -> ChannelValue
0551 {
0552 using to_unsigned = detail::channel_convert_to_unsigned<ChannelValue>;
0553 using from_unsigned = detail::channel_convert_from_unsigned<ChannelValue>;
0554 using multiplier_unsigned = channel_multiplier_unsigned<typename to_unsigned::result_type>;
0555 return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b)));
0556 }
0557 };
0558
0559
0560 template <typename Channel>
0561 inline auto channel_multiply(Channel a, Channel b) -> typename channel_traits<Channel>::value_type
0562 {
0563 return channel_multiplier<typename channel_traits<Channel>::value_type>()(a,b);
0564 }
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581 template <typename Channel>
0582 inline auto channel_invert(Channel x) -> typename channel_traits<Channel>::value_type
0583 {
0584 using base_t = typename base_channel_type<Channel>::type;
0585 using promoted_t = typename promote_integral<base_t>::type;
0586 promoted_t const promoted_x = x;
0587 promoted_t const promoted_max = channel_traits<Channel>::max_value();
0588 promoted_t const promoted_min = channel_traits<Channel>::min_value();
0589 promoted_t const promoted_inverted_x = promoted_max - promoted_x + promoted_min;
0590 auto const inverted_x = static_cast<base_t>(promoted_inverted_x);
0591 return inverted_x;
0592 }
0593
0594 }}
0595
0596 #endif