File indexing completed on 2024-11-15 09:12:38
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_GIL_CHANNEL_HPP
0009 #define BOOST_GIL_CHANNEL_HPP
0010
0011 #include <boost/gil/utilities.hpp>
0012
0013 #include <boost/assert.hpp>
0014 #include <boost/config.hpp>
0015 #include <boost/config/pragma_message.hpp>
0016 #include <boost/integer/integer_mask.hpp>
0017
0018 #include <cstdint>
0019 #include <limits>
0020 #include <type_traits>
0021
0022 #ifdef BOOST_GIL_DOXYGEN_ONLY
0023
0024
0025
0026
0027
0028
0029
0030 #define BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS
0031 #endif
0032
0033 #ifdef BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS
0034 #if defined(sun) || defined(__sun) || \
0035 defined(__osf__) || defined(__osf) || \
0036 defined(_hpux) || defined(hpux) || \
0037 defined(__arm__) || defined(__ARM_ARCH) || \
0038 defined(_AIX)
0039 #error Unaligned access strictly disabled for some UNIX platforms or ARM architecture
0040 #elif defined(__i386__) || defined(__x86_64__) || defined(__vax__)
0041
0042
0043
0044
0045
0046
0047
0048 BOOST_PRAGMA_MESSAGE("CAUTION: Unaligned access tolerated on little-endian may cause undefined behaviour")
0049 #else
0050 #error Unaligned access disabled for unknown platforms and architectures
0051 #endif
0052 #endif
0053
0054 namespace boost { namespace gil {
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 namespace detail {
0072
0073 template <typename T, bool IsClass>
0074 struct channel_traits_impl;
0075
0076
0077 template <typename T>
0078 struct channel_traits_impl<T, true>
0079 {
0080 using value_type = typename T::value_type;
0081 using reference = typename T::reference;
0082 using pointer = typename T::pointer;
0083 using const_reference = typename T::const_reference;
0084 using const_pointer = typename T::const_pointer;
0085 static constexpr bool is_mutable = T::is_mutable;
0086 static value_type min_value() { return T::min_value(); }
0087 static value_type max_value() { return T::max_value(); }
0088 };
0089
0090
0091 template <typename T>
0092 struct channel_traits_impl<T, false>
0093 {
0094 using value_type = T;
0095 using reference = T&;
0096 using pointer = T*;
0097 using const_reference = T const&;
0098 using const_pointer = T const*;
0099 static constexpr bool is_mutable = true;
0100 static value_type min_value() { return (std::numeric_limits<T>::min)(); }
0101 static value_type max_value() { return (std::numeric_limits<T>::max)(); }
0102 };
0103
0104
0105 template <typename T>
0106 struct channel_traits_impl<T const, false> : channel_traits_impl<T, false>
0107 {
0108 using reference = T const&;
0109 using pointer = T const*;
0110 static constexpr bool is_mutable = false;
0111 };
0112
0113 }
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 template <typename T>
0134 struct channel_traits : detail::channel_traits_impl<T, std::is_class<T>::value> {};
0135
0136
0137 template <typename T>
0138 struct channel_traits<T&> : channel_traits<T> {};
0139
0140
0141 template <typename T>
0142 struct channel_traits<T const&> : channel_traits<T>
0143 {
0144 using reference = typename channel_traits<T>::const_reference;
0145 using pointer = typename channel_traits<T>::const_pointer;
0146 static constexpr bool is_mutable = false;
0147 };
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176 template <typename BaseChannelValue, typename MinVal, typename MaxVal>
0177 struct scoped_channel_value
0178 {
0179 using value_type = scoped_channel_value<BaseChannelValue, MinVal, MaxVal>;
0180 using reference = value_type&;
0181 using pointer = value_type*;
0182 using const_reference = value_type const&;
0183 using const_pointer = value_type const*;
0184 static constexpr bool is_mutable = channel_traits<BaseChannelValue>::is_mutable;
0185
0186 using base_channel_t = BaseChannelValue;
0187
0188 static value_type min_value() { return MinVal::apply(); }
0189 static value_type max_value() { return MaxVal::apply(); }
0190
0191 scoped_channel_value() = default;
0192 scoped_channel_value(scoped_channel_value const& other) : value_(other.value_) {}
0193 scoped_channel_value& operator=(scoped_channel_value const& other) = default;
0194 scoped_channel_value(BaseChannelValue value) : value_(value) {}
0195 scoped_channel_value& operator=(BaseChannelValue value)
0196 {
0197 value_ = value;
0198 return *this;
0199 }
0200
0201 auto operator++() -> scoped_channel_value& { ++value_; return *this; }
0202 auto operator--() -> scoped_channel_value& { --value_; return *this; }
0203
0204 auto operator++(int) -> scoped_channel_value
0205 {
0206 scoped_channel_value tmp=*this;
0207 this->operator++(); return tmp;
0208 }
0209
0210 auto operator--(int) -> scoped_channel_value
0211 {
0212 scoped_channel_value tmp=*this;
0213 this->operator--(); return tmp;
0214 }
0215
0216 template <typename Scalar2>
0217 auto operator+=(Scalar2 v) -> scoped_channel_value& { value_+=v; return *this; }
0218
0219 template <typename Scalar2>
0220 auto operator-=(Scalar2 v) -> scoped_channel_value& { value_-=v; return *this; }
0221
0222 template <typename Scalar2>
0223 auto operator*=(Scalar2 v) -> scoped_channel_value& { value_*=v; return *this; }
0224
0225 template <typename Scalar2>
0226 auto operator/=(Scalar2 v) -> scoped_channel_value& { value_/=v; return *this; }
0227
0228 operator BaseChannelValue() const { return value_; }
0229 private:
0230 BaseChannelValue value_{};
0231 };
0232
0233 template <typename T>
0234 struct float_point_zero
0235 {
0236 static constexpr T apply() { return 0.0f; }
0237 };
0238
0239 template <typename T>
0240 struct float_point_one
0241 {
0242 static constexpr T apply() { return 1.0f; }
0243 };
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253 namespace detail {
0254
0255
0256 template <int NumBits>
0257 struct min_fast_uint :
0258 std::conditional
0259 <
0260 NumBits <= 8,
0261 std::uint_least8_t,
0262 typename std::conditional
0263 <
0264 NumBits <= 16,
0265 std::uint_least16_t,
0266 typename std::conditional
0267 <
0268 NumBits <= 32,
0269 std::uint_least32_t,
0270 std::uintmax_t
0271 >::type
0272 >::type
0273 >
0274 {};
0275
0276 template <int NumBits>
0277 struct num_value_fn
0278 : std::conditional<NumBits < 32, std::uint32_t, std::uint64_t>
0279 {};
0280
0281 template <int NumBits>
0282 struct max_value_fn
0283 : std::conditional<NumBits <= 32, std::uint32_t, std::uint64_t>
0284 {};
0285
0286 }
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304 template <int NumBits>
0305 class packed_channel_value
0306 {
0307 public:
0308 using integer_t = typename detail::min_fast_uint<NumBits>::type;
0309
0310 using value_type = packed_channel_value<NumBits>;
0311 using reference = value_type&;
0312 using const_reference = value_type const&;
0313 using pointer = value_type*;
0314 using const_pointer = value_type const*;
0315 static constexpr bool is_mutable = true;
0316
0317 static value_type min_value() { return 0; }
0318 static value_type max_value() { return low_bits_mask_t< NumBits >::sig_bits; }
0319
0320 packed_channel_value() = default;
0321 packed_channel_value(integer_t v)
0322 {
0323 value_ = static_cast<integer_t>(v & low_bits_mask_t<NumBits>::sig_bits_fast);
0324 }
0325
0326 template <typename Scalar>
0327 packed_channel_value(Scalar v)
0328 {
0329 value_ = packed_channel_value(static_cast<integer_t>(v));
0330 }
0331
0332 static auto num_bits() -> unsigned int { return NumBits; }
0333
0334 operator integer_t() const { return value_; }
0335
0336 private:
0337 integer_t value_{};
0338 };
0339
0340 namespace detail {
0341
0342 template <std::size_t K>
0343 struct static_copy_bytes
0344 {
0345 void operator()(unsigned char const* from, unsigned char* to) const
0346 {
0347 *to = *from;
0348 static_copy_bytes<K - 1>()(++from, ++to);
0349 }
0350 };
0351
0352 template <>
0353 struct static_copy_bytes<0>
0354 {
0355 void operator()(unsigned char const*, unsigned char*) const {}
0356 };
0357
0358 template <typename Derived, typename BitField, int NumBits, bool IsMutable>
0359 class packed_channel_reference_base
0360 {
0361 protected:
0362 using data_ptr_t = typename std::conditional<IsMutable, void*, void const*>::type;
0363 public:
0364 data_ptr_t _data_ptr;
0365
0366 using value_type = packed_channel_value<NumBits>;
0367 using reference = Derived const;
0368 using pointer = value_type*;
0369 using const_pointer = value_type const*;
0370 static constexpr int num_bits = NumBits;
0371 static constexpr bool is_mutable = IsMutable;
0372
0373 static auto min_value() -> value_type { return channel_traits<value_type>::min_value(); }
0374 static auto max_value() -> value_type { return channel_traits<value_type>::max_value(); }
0375
0376 using bitfield_t = BitField;
0377 using integer_t = typename value_type::integer_t;
0378
0379 packed_channel_reference_base(data_ptr_t data_ptr) : _data_ptr(data_ptr) {}
0380 packed_channel_reference_base(packed_channel_reference_base const& ref) : _data_ptr(ref._data_ptr) {}
0381
0382 auto operator=(integer_t v) const -> Derived const& { set(v); return derived(); }
0383
0384 auto operator++() const -> Derived const& { set(get()+1); return derived(); }
0385 auto operator--() const -> Derived const& { set(get()-1); return derived(); }
0386
0387 auto operator++(int) const -> Derived
0388 {
0389 Derived tmp=derived();
0390 this->operator++(); return tmp;
0391 }
0392
0393 auto operator--(int) const -> Derived
0394 {
0395 Derived tmp=derived();
0396 this->operator--();
0397 return tmp;
0398 }
0399
0400 template <typename Scalar2>
0401 auto operator+=(Scalar2 v) const -> Derived const&
0402 {
0403 set( static_cast<integer_t>( get() + v ));
0404 return derived();
0405 }
0406
0407 template <typename Scalar2>
0408 auto operator-=(Scalar2 v) const -> Derived const&
0409 {
0410 set( static_cast<integer_t>( get() - v )); return derived();
0411 }
0412
0413 template <typename Scalar2>
0414 auto operator*=(Scalar2 v) const -> Derived const&
0415 {
0416 set( static_cast<integer_t>( get() * v ));
0417 return derived();
0418 }
0419
0420 template <typename Scalar2>
0421 auto operator/=(Scalar2 v) const -> Derived const&
0422 {
0423 set( static_cast<integer_t>( get() / v ));
0424 return derived();
0425 }
0426
0427 operator integer_t() const { return get(); }
0428 auto operator&() const -> data_ptr_t {return _data_ptr;}
0429
0430 protected:
0431
0432 using num_value_t = typename detail::num_value_fn<NumBits>::type;
0433 using max_value_t = typename detail::max_value_fn<NumBits>::type;
0434
0435 static const num_value_t num_values = static_cast< num_value_t >( 1 ) << NumBits ;
0436 static const max_value_t max_val = static_cast< max_value_t >( num_values - 1 );
0437
0438 #if defined(BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS)
0439 const bitfield_t& get_data() const { return *static_cast<const bitfield_t*>(_data_ptr); }
0440 void set_data(const bitfield_t& val) const { *static_cast< bitfield_t*>(_data_ptr) = val; }
0441 #else
0442 auto get_data() const -> bitfield_t
0443 {
0444 bitfield_t ret;
0445 static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(_data_ptr),gil_reinterpret_cast<unsigned char*>(&ret));
0446 return ret;
0447 }
0448
0449 void set_data(bitfield_t const& val) const
0450 {
0451 static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(&val),gil_reinterpret_cast<unsigned char*>(_data_ptr));
0452 }
0453 #endif
0454
0455 private:
0456 void set(integer_t value) const {
0457 this->derived().set_unsafe(((value % num_values) + num_values) % num_values);
0458 }
0459 auto get() const -> integer_t { return derived().get(); }
0460 auto derived() const -> Derived const& { return static_cast<const Derived&>(*this); }
0461 };
0462 }
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481 template <typename BitField, int FirstBit, int NumBits, bool IsMutable>
0482 class packed_channel_reference;
0483
0484
0485
0486
0487 template <typename BitField, int NumBits, bool IsMutable>
0488 class packed_dynamic_channel_reference;
0489
0490
0491
0492 template <typename BitField, int FirstBit, int NumBits>
0493 class packed_channel_reference<BitField, FirstBit, NumBits, false>
0494 : public detail::packed_channel_reference_base
0495 <
0496 packed_channel_reference<BitField, FirstBit, NumBits, false>,
0497 BitField,
0498 NumBits,
0499 false
0500 >
0501 {
0502 using parent_t = detail::packed_channel_reference_base
0503 <
0504 packed_channel_reference<BitField, FirstBit, NumBits, false>,
0505 BitField,
0506 NumBits,
0507 false
0508 >;
0509
0510 friend class packed_channel_reference<BitField, FirstBit, NumBits, true>;
0511
0512 static const BitField channel_mask = static_cast<BitField>(parent_t::max_val) << FirstBit;
0513
0514 void operator=(packed_channel_reference const&);
0515 public:
0516 using const_reference = packed_channel_reference<BitField,FirstBit,NumBits,false> const;
0517 using mutable_reference = packed_channel_reference<BitField,FirstBit,NumBits,true> const;
0518 using integer_t = typename parent_t::integer_t;
0519
0520 explicit packed_channel_reference(const void* data_ptr) : parent_t(data_ptr) {}
0521 packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
0522 packed_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr) {}
0523
0524 auto first_bit() const -> unsigned int { return FirstBit; }
0525
0526 auto get() const -> integer_t { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
0527 };
0528
0529
0530
0531 template <typename BitField, int FirstBit, int NumBits>
0532 class packed_channel_reference<BitField,FirstBit,NumBits,true>
0533 : public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true>
0534 {
0535 using parent_t = detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true>;
0536 friend class packed_channel_reference<BitField,FirstBit,NumBits,false>;
0537
0538 static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
0539
0540 public:
0541 using const_reference = packed_channel_reference<BitField,FirstBit,NumBits,false> const;
0542 using mutable_reference = packed_channel_reference<BitField,FirstBit,NumBits,true> const;
0543 using integer_t = typename parent_t::integer_t;
0544
0545 explicit packed_channel_reference(void* data_ptr) : parent_t(data_ptr) {}
0546 packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
0547
0548 packed_channel_reference const& operator=(integer_t value) const
0549 {
0550 BOOST_ASSERT(value <= parent_t::max_val);
0551 set_unsafe(value);
0552 return *this;
0553 }
0554
0555 auto operator=(mutable_reference const& ref) const -> packed_channel_reference const& { set_from_reference(ref.get_data()); return *this; }
0556 auto operator=(const_reference const& ref) const -> packed_channel_reference const& { set_from_reference(ref.get_data()); return *this; }
0557
0558 template <bool Mutable1>
0559 auto operator=(packed_dynamic_channel_reference<BitField,NumBits,Mutable1> const& ref) const -> packed_channel_reference const& { set_unsafe(ref.get()); return *this; }
0560
0561 auto first_bit() const -> unsigned int { return FirstBit; }
0562
0563 auto get() const -> integer_t { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
0564 void set_unsafe(integer_t value) const { this->set_data((this->get_data() & ~channel_mask) | (( static_cast< BitField >( value )<<FirstBit))); }
0565
0566 private:
0567 void set_from_reference(const BitField& other_bits) const { this->set_data((this->get_data() & ~channel_mask) | (other_bits & channel_mask)); }
0568 };
0569
0570 }}
0571
0572 namespace std {
0573
0574
0575
0576
0577
0578
0579
0580
0581 template <typename BF, int FB, int NB, bool M, typename R>
0582 inline
0583 void swap(boost::gil::packed_channel_reference<BF, FB, NB, M> const x, R& y)
0584 {
0585 boost::gil::swap_proxy
0586 <
0587 typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type
0588 >(x, y);
0589 }
0590
0591
0592
0593
0594 template <typename BF, int FB, int NB, bool M>
0595 inline
0596 void swap(
0597 typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type& x,
0598 boost::gil::packed_channel_reference<BF, FB, NB, M> const y)
0599 {
0600 boost::gil::swap_proxy
0601 <
0602 typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type
0603 >(x,y);
0604 }
0605
0606
0607
0608 template <typename BF, int FB, int NB, bool M> inline
0609 void swap(
0610 boost::gil::packed_channel_reference<BF, FB, NB, M> const x,
0611 boost::gil::packed_channel_reference<BF, FB, NB, M> const y)
0612 {
0613 boost::gil::swap_proxy
0614 <
0615 typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type
0616 >(x,y);
0617 }
0618
0619 }
0620
0621 namespace boost { namespace gil {
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641 template <typename BitField, int NumBits>
0642 class packed_dynamic_channel_reference<BitField,NumBits,false>
0643 : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false>
0644 {
0645 using parent_t = detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false>;
0646 friend class packed_dynamic_channel_reference<BitField,NumBits,true>;
0647
0648 unsigned _first_bit;
0649
0650 void operator=(const packed_dynamic_channel_reference&);
0651 public:
0652 using const_reference = packed_dynamic_channel_reference<BitField,NumBits,false> const;
0653 using mutable_reference = packed_dynamic_channel_reference<BitField,NumBits,true> const;
0654 using integer_t = typename parent_t::integer_t;
0655
0656 packed_dynamic_channel_reference(void const* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
0657 packed_dynamic_channel_reference(const_reference const& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
0658 packed_dynamic_channel_reference(mutable_reference const& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
0659
0660 auto first_bit() const -> unsigned int { return _first_bit; }
0661
0662 auto get() const -> integer_t
0663 {
0664 const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) <<_first_bit;
0665 return static_cast< integer_t >(( this->get_data()&channel_mask ) >> _first_bit );
0666 }
0667 };
0668
0669
0670
0671
0672 template <typename BitField, int NumBits>
0673 class packed_dynamic_channel_reference<BitField,NumBits,true>
0674 : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,true>
0675 {
0676 using parent_t = detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,true>;
0677 friend class packed_dynamic_channel_reference<BitField,NumBits,false>;
0678
0679 unsigned _first_bit;
0680
0681 public:
0682 using const_reference = packed_dynamic_channel_reference<BitField,NumBits,false> const;
0683 using mutable_reference = packed_dynamic_channel_reference<BitField,NumBits,true> const;
0684 using integer_t = typename parent_t::integer_t;
0685
0686 packed_dynamic_channel_reference(void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
0687 packed_dynamic_channel_reference(packed_dynamic_channel_reference const& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
0688
0689 auto operator=(integer_t value) const -> packed_dynamic_channel_reference const&
0690 {
0691 BOOST_ASSERT(value <= parent_t::max_val);
0692 set_unsafe(value);
0693 return *this;
0694 }
0695
0696 auto operator=(mutable_reference const& ref) const -> packed_dynamic_channel_reference const& { set_unsafe(ref.get()); return *this; }
0697 auto operator=(const_reference const& ref) const -> packed_dynamic_channel_reference const& { set_unsafe(ref.get()); return *this; }
0698
0699 template <typename BitField1, int FirstBit1, bool Mutable1>
0700 auto operator=(packed_channel_reference<BitField1, FirstBit1, NumBits, Mutable1> const& ref) const -> packed_dynamic_channel_reference const&
0701 {
0702 set_unsafe(ref.get());
0703 return *this;
0704 }
0705
0706 auto first_bit() const -> unsigned int { return _first_bit; }
0707
0708 auto get() const -> integer_t
0709 {
0710 BitField const channel_mask = static_cast< integer_t >( parent_t::max_val ) << _first_bit;
0711 return static_cast< integer_t >(( this->get_data()&channel_mask ) >> _first_bit );
0712 }
0713
0714 void set_unsafe(integer_t value) const {
0715 const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) << _first_bit;
0716 this->set_data((this->get_data() & ~channel_mask) | value<<_first_bit);
0717 }
0718 };
0719 } }
0720
0721 namespace std {
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731 template <typename BF, int NB, bool M, typename R> inline
0732 void swap(const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, R& y) {
0733 boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
0734 }
0735
0736
0737
0738
0739 template <typename BF, int NB, bool M> inline
0740 void swap(typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type& x, const boost::gil::packed_dynamic_channel_reference<BF,NB,M> y) {
0741 boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
0742 }
0743
0744
0745
0746 template <typename BF, int NB, bool M> inline
0747 void swap(const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, const boost::gil::packed_dynamic_channel_reference<BF,NB,M> y) {
0748 boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
0749 }
0750 }
0751
0752
0753 namespace boost { namespace gil {
0754 template <typename T>
0755 struct base_channel_type_impl { using type = T; };
0756
0757 template <int N>
0758 struct base_channel_type_impl<packed_channel_value<N> >
0759 { using type = typename packed_channel_value<N>::integer_t; };
0760
0761 template <typename B, int F, int N, bool M>
0762 struct base_channel_type_impl<packed_channel_reference<B, F, N, M> >
0763 {
0764 using type = typename packed_channel_reference<B,F,N,M>::integer_t;
0765 };
0766
0767 template <typename B, int N, bool M>
0768 struct base_channel_type_impl<packed_dynamic_channel_reference<B, N, M> >
0769 {
0770 using type = typename packed_dynamic_channel_reference<B,N,M>::integer_t;
0771 };
0772
0773 template <typename ChannelValue, typename MinV, typename MaxV>
0774 struct base_channel_type_impl<scoped_channel_value<ChannelValue, MinV, MaxV> >
0775 { using type = ChannelValue; };
0776
0777 template <typename T>
0778 struct base_channel_type : base_channel_type_impl<typename std::remove_cv<T>::type> {};
0779
0780 }}
0781
0782 #endif