Boost GIL


channel.hpp
1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 #ifndef BOOST_GIL_CHANNEL_HPP
9 #define BOOST_GIL_CHANNEL_HPP
10 
11 #include <boost/gil/utilities.hpp>
12 
13 #include <boost/config.hpp>
14 #include <boost/config/pragma_message.hpp>
15 #include <boost/integer/integer_mask.hpp>
16 #include <boost/type_traits/remove_cv.hpp>
17 
18 #include <cassert>
19 #include <cstdint>
20 #include <limits>
21 
22 #ifdef BOOST_GIL_DOXYGEN_ONLY
23 #define BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS
31 #endif
32 
33 #ifdef BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS
34 #if defined(sun) || defined(__sun) || \ // SunOS
35  defined(__osf__) || defined(__osf) || \ // Tru64
36  defined(_hpux) || defined(hpux) || \ // HP-UX
37  defined(__arm__) || defined(__ARM_ARCH) || \ // ARM
38  defined(_AIX) // AIX
39 #error Unaligned access strictly disabled for some UNIX platforms or ARM architecture
40 #elif defined(__i386__) || defined(__x86_64__) || defined(__vax__)
41  // The check for little-endian architectures that tolerate unaligned memory
42  // accesses is just an optimization. Nothing will break if it fails to detect
43  // a suitable architecture.
44  //
45  // Unfortunately, this optimization may be a C/C++ strict aliasing rules violation
46  // if accessed data buffer has effective type that cannot be aliased
47  // without leading to undefined behaviour.
48 BOOST_PRAGMA_MESSAGE("CAUTION: Unaligned access tolerated on little-endian may cause undefined behaviour")
49 #else
50 #error Unaligned access disabled for unknown platforms and architectures
51 #endif
52 #endif // defined(BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS)
53 
54 namespace boost { namespace gil {
55 
70 
71 namespace detail {
72  template <typename T, bool is_class> struct channel_traits_impl;
73 
74  // channel traits for custom class
75  template <typename T>
76  struct channel_traits_impl<T, true> {
77  typedef typename T::value_type value_type;
78  typedef typename T::reference reference;
79  typedef typename T::pointer pointer;
80  typedef typename T::const_reference const_reference;
81  typedef typename T::const_pointer const_pointer;
82  BOOST_STATIC_CONSTANT(bool, is_mutable=T::is_mutable);
83  static value_type min_value() { return T::min_value(); }
84  static value_type max_value() { return T::max_value(); }
85  };
86 
87  // channel traits implementation for built-in integral or floating point channel type
88  template <typename T>
89  struct channel_traits_impl<T, false> {
90  typedef T value_type;
91  typedef T& reference;
92  typedef T* pointer;
93  typedef const T& const_reference;
94  typedef T const* const_pointer;
95  BOOST_STATIC_CONSTANT(bool, is_mutable=true);
96  static value_type min_value() { return (std::numeric_limits<T>::min)(); }
97  static value_type max_value() { return (std::numeric_limits<T>::max)(); }
98  };
99 
100  // channel traits implementation for constant built-in scalar or floating point type
101  template <typename T>
102  struct channel_traits_impl<const T, false> : public channel_traits_impl<T, false> {
103  typedef const T& reference;
104  typedef const T* pointer;
105  BOOST_STATIC_CONSTANT(bool, is_mutable=false);
106  };
107 }
108 
127 template <typename T>
128 struct channel_traits : public detail::channel_traits_impl<T, is_class<T>::value> {};
129 
130 // Channel traits for C++ reference type - remove the reference
131 template <typename T> struct channel_traits< T&> : public channel_traits<T> {};
132 
133 // Channel traits for constant C++ reference type
134 template <typename T> struct channel_traits<const T&> : public channel_traits<T> {
135  typedef typename channel_traits<T>::const_reference reference;
136  typedef typename channel_traits<T>::const_pointer pointer;
137  BOOST_STATIC_CONSTANT(bool, is_mutable=false);
138 };
139 
145 
166 template <typename BaseChannelValue, // base channel (models ChannelValueConcept)
169  typename MinVal, typename MaxVal> // classes with a static apply() function returning the minimum/maximum channel values
170 struct scoped_channel_value {
171  typedef scoped_channel_value value_type;
172  typedef value_type& reference;
173  typedef value_type* pointer;
174  typedef const value_type& const_reference;
175  typedef const value_type* const_pointer;
176  BOOST_STATIC_CONSTANT(bool, is_mutable=channel_traits<BaseChannelValue>::is_mutable);
177 
178  typedef BaseChannelValue base_channel_t;
179 
180  static value_type min_value() { return MinVal::apply(); }
181  static value_type max_value() { return MaxVal::apply(); }
182 
183  scoped_channel_value() {}
184  scoped_channel_value(const scoped_channel_value& c) : _value(c._value) {}
185  scoped_channel_value(BaseChannelValue val) : _value(val) {}
186 
187  scoped_channel_value& operator++() { ++_value; return *this; }
188  scoped_channel_value& operator--() { --_value; return *this; }
189 
190  scoped_channel_value operator++(int) { scoped_channel_value tmp=*this; this->operator++(); return tmp; }
191  scoped_channel_value operator--(int) { scoped_channel_value tmp=*this; this->operator--(); return tmp; }
192 
193  template <typename Scalar2> scoped_channel_value& operator+=(Scalar2 v) { _value+=v; return *this; }
194  template <typename Scalar2> scoped_channel_value& operator-=(Scalar2 v) { _value-=v; return *this; }
195  template <typename Scalar2> scoped_channel_value& operator*=(Scalar2 v) { _value*=v; return *this; }
196  template <typename Scalar2> scoped_channel_value& operator/=(Scalar2 v) { _value/=v; return *this; }
197 
198  scoped_channel_value& operator=(BaseChannelValue v) { _value=v; return *this; }
199  operator BaseChannelValue() const { return _value; }
200 private:
201  BaseChannelValue _value;
202 };
203 
204 template <typename T>
205 struct float_point_zero
206 {
207  static constexpr T apply() { return 0.0f; }
208 };
209 
210 template <typename T>
211 struct float_point_one
212 {
213  static constexpr T apply() { return 1.0f; }
214 };
215 
221 
222 // It is necessary for packed channels to have their own value type. They cannot simply use an integral large enough to store the data. Here is why:
223 // - Any operation that requires returning the result by value will otherwise return the built-in integral type, which will have incorrect range
224 // That means that after getting the value of the channel we cannot properly do channel_convert, channel_invert, etc.
225 // - Two channels are declared compatible if they have the same value type. That means that a packed channel is incorrectly declared compatible with an integral type
226 namespace detail {
227  // returns the smallest fast unsigned integral type that has at least NumBits bits
228  template <int NumBits>
229  struct min_fast_uint : public mpl::if_c< (NumBits<=8),
230  uint_least8_t,
231  typename mpl::if_c< (NumBits<=16),
232  uint_least16_t,
233  typename mpl::if_c< (NumBits<=32),
234  uint_least32_t,
235  uintmax_t
236  >::type
237  >::type
238  > {};
239 
240  template <int NumBits>
241  struct num_value_fn : public mpl::if_c< ( NumBits < 32 )
242  , uint32_t
243  , uint64_t
244  > {};
245 
246  template <int NumBits>
247  struct max_value_fn : public mpl::if_c< ( NumBits <= 32 )
248  , uint32_t
249  , uint64_t
250  > {};
251 }
252 
269 template <int NumBits>
272 class packed_channel_value {
273 
274 public:
275  typedef typename detail::min_fast_uint<NumBits>::type integer_t;
276 
277 
278  typedef packed_channel_value value_type;
279  typedef value_type& reference;
280  typedef const value_type& const_reference;
281  typedef value_type* pointer;
282  typedef const value_type* const_pointer;
283 
284  static value_type min_value() { return 0; }
285  static value_type max_value() { return low_bits_mask_t< NumBits >::sig_bits; }
286 
287  BOOST_STATIC_CONSTANT(bool, is_mutable=true);
288 
289  packed_channel_value() {}
290 
291  packed_channel_value(integer_t v) { _value = static_cast< integer_t >( v & low_bits_mask_t<NumBits>::sig_bits_fast ); }
292  template <typename Scalar> packed_channel_value(Scalar v) { _value = packed_channel_value( static_cast< integer_t >( v ) ); }
293 
294  static unsigned int num_bits() { return NumBits; }
295 
296  operator integer_t() const { return _value; }
297 private:
298  integer_t _value;
299 };
300 
301 namespace detail {
302 
303 template <std::size_t K>
304 struct static_copy_bytes {
305  void operator()(const unsigned char* from, unsigned char* to) const {
306  *to = *from;
307  static_copy_bytes<K-1>()(++from,++to);
308  }
309 };
310 
311 template <>
312 struct static_copy_bytes<0> {
313  void operator()(const unsigned char* , unsigned char*) const {}
314 };
315 
316 template <typename Derived, typename BitField, int NumBits, bool Mutable>
317 class packed_channel_reference_base {
318 protected:
319  typedef typename mpl::if_c<Mutable,void*,const void*>::type data_ptr_t;
320 public:
321  data_ptr_t _data_ptr; // void* pointer to the first byte of the bit range
322 
323  typedef packed_channel_value<NumBits> value_type;
324  typedef const Derived reference;
325  typedef value_type* pointer;
326  typedef const value_type* const_pointer;
327  BOOST_STATIC_CONSTANT(int, num_bits=NumBits);
328  BOOST_STATIC_CONSTANT(bool, is_mutable=Mutable);
329 
330  static value_type min_value() { return channel_traits<value_type>::min_value(); }
331  static value_type max_value() { return channel_traits<value_type>::max_value(); }
332 
333  typedef BitField bitfield_t;
334  typedef typename value_type::integer_t integer_t;
335 
336  packed_channel_reference_base(data_ptr_t data_ptr) : _data_ptr(data_ptr) {}
337  packed_channel_reference_base(const packed_channel_reference_base& ref) : _data_ptr(ref._data_ptr) {}
338  const Derived& operator=(integer_t v) const { set(v); return derived(); }
339 
340  const Derived& operator++() const { set(get()+1); return derived(); }
341  const Derived& operator--() const { set(get()-1); return derived(); }
342 
343  Derived operator++(int) const { Derived tmp=derived(); this->operator++(); return tmp; }
344  Derived operator--(int) const { Derived tmp=derived(); this->operator--(); return tmp; }
345 
346  template <typename Scalar2> const Derived& operator+=(Scalar2 v) const { set( static_cast<integer_t>( get() + v )); return derived(); }
347  template <typename Scalar2> const Derived& operator-=(Scalar2 v) const { set( static_cast<integer_t>( get() - v )); return derived(); }
348  template <typename Scalar2> const Derived& operator*=(Scalar2 v) const { set( static_cast<integer_t>( get() * v )); return derived(); }
349  template <typename Scalar2> const Derived& operator/=(Scalar2 v) const { set( static_cast<integer_t>( get() / v )); return derived(); }
350 
351  operator integer_t() const { return get(); }
352  data_ptr_t operator &() const {return _data_ptr;}
353 protected:
354 
355  typedef typename detail::num_value_fn< NumBits >::type num_value_t;
356  typedef typename detail::max_value_fn< NumBits >::type max_value_t;
357 
358  static const num_value_t num_values = static_cast< num_value_t >( 1 ) << NumBits ;
359  static const max_value_t max_val = static_cast< max_value_t >( num_values - 1 );
360 
361 #if defined(BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS)
362  const bitfield_t& get_data() const { return *static_cast<const bitfield_t*>(_data_ptr); }
363  void set_data(const bitfield_t& val) const { *static_cast< bitfield_t*>(_data_ptr) = val; }
364 #else
365  bitfield_t get_data() const {
366  bitfield_t ret;
367  static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(_data_ptr),gil_reinterpret_cast<unsigned char*>(&ret));
368  return ret;
369  }
370  void set_data(const bitfield_t& val) const {
371  static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(&val),gil_reinterpret_cast<unsigned char*>(_data_ptr));
372  }
373 #endif
374 
375 private:
376  void set(integer_t value) const { // can this be done faster??
377  this->derived().set_unsafe(((value % num_values) + num_values) % num_values);
378  }
379  integer_t get() const { return derived().get(); }
380  const Derived& derived() const { return static_cast<const Derived&>(*this); }
381 };
382 } // namespace detail
383 
400 template <typename BitField, // A type that holds the bits of the pixel from which the channel is referenced. Typically an integral type, like std::uint16_t
401  int FirstBit, int NumBits,// Defines the sequence of bits in the data value that contain the channel
402  bool Mutable> // true if the reference is mutable
403 class packed_channel_reference;
404 
405 template <typename BitField, // A type that holds the bits of the pixel from which the channel is referenced. Typically an integral type, like std::uint16_t
406  int NumBits, // Defines the sequence of bits in the data value that contain the channel
407  bool Mutable> // true if the reference is mutable
408 class packed_dynamic_channel_reference;
409 
412 template <typename BitField, int FirstBit, int NumBits>
413 class packed_channel_reference<BitField,FirstBit,NumBits,false>
414  : public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false> {
415  typedef detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false> parent_t;
416  friend class packed_channel_reference<BitField,FirstBit,NumBits,true>;
417 
418  static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
419 
420  void operator=(const packed_channel_reference&);
421 public:
422  typedef const packed_channel_reference<BitField,FirstBit,NumBits,false> const_reference;
423  typedef const packed_channel_reference<BitField,FirstBit,NumBits,true> mutable_reference;
424  typedef typename parent_t::integer_t integer_t;
425 
426  explicit packed_channel_reference(const void* data_ptr) : parent_t(data_ptr) {}
427  packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
428  packed_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr) {}
429 
430  unsigned first_bit() const { return FirstBit; }
431 
432  integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
433 };
434 
437 template <typename BitField, int FirstBit, int NumBits>
438 class packed_channel_reference<BitField,FirstBit,NumBits,true>
439  : public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true> {
440  typedef detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true> parent_t;
441  friend class packed_channel_reference<BitField,FirstBit,NumBits,false>;
442 
443  static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
444 
445 public:
446  typedef const packed_channel_reference<BitField,FirstBit,NumBits,false> const_reference;
447  typedef const packed_channel_reference<BitField,FirstBit,NumBits,true> mutable_reference;
448  typedef typename parent_t::integer_t integer_t;
449 
450  explicit packed_channel_reference(void* data_ptr) : parent_t(data_ptr) {}
451  packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
452 
453  const packed_channel_reference& operator=(integer_t value) const { assert(value<=parent_t::max_val); set_unsafe(value); return *this; }
454  const packed_channel_reference& operator=(const mutable_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
455  const packed_channel_reference& operator=(const const_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
456 
457  template <bool Mutable1>
458  const packed_channel_reference& operator=(const packed_dynamic_channel_reference<BitField,NumBits,Mutable1>& ref) const { set_unsafe(ref.get()); return *this; }
459 
460  unsigned first_bit() const { return FirstBit; }
461 
462  integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
463  void set_unsafe(integer_t value) const { this->set_data((this->get_data() & ~channel_mask) | (( static_cast< BitField >( value )<<FirstBit))); }
464 private:
465  void set_from_reference(const BitField& other_bits) const { this->set_data((this->get_data() & ~channel_mask) | (other_bits & channel_mask)); }
466 };
467 
468 } } // namespace boost::gil
469 
470 namespace std {
471 // We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified.
472 // swap with 'left bias':
473 // - swap between proxy and anything
474 // - swap between value type and proxy
475 // - swap between proxy and proxy
476 
479 template <typename BF, int FB, int NB, bool M, typename R> inline
480 void swap(const boost::gil::packed_channel_reference<BF,FB,NB,M> x, R& y) {
481  boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
482 }
483 
484 
487 template <typename BF, int FB, int NB, bool M> inline
488 void swap(typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type& x, const boost::gil::packed_channel_reference<BF,FB,NB,M> y) {
489  boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
490 }
491 
494 template <typename BF, int FB, int NB, bool M> inline
495 void swap(const boost::gil::packed_channel_reference<BF,FB,NB,M> x, const boost::gil::packed_channel_reference<BF,FB,NB,M> y) {
496  boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
497 }
498 } // namespace std
499 
500 namespace boost { namespace gil {
501 
519 template <typename BitField, int NumBits>
523 class packed_dynamic_channel_reference<BitField,NumBits,false>
524  : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false> {
525  typedef detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false> parent_t;
526  friend class packed_dynamic_channel_reference<BitField,NumBits,true>;
527 
528  unsigned _first_bit; // 0..7
529 
530  void operator=(const packed_dynamic_channel_reference&);
531 public:
532  typedef const packed_dynamic_channel_reference<BitField,NumBits,false> const_reference;
533  typedef const packed_dynamic_channel_reference<BitField,NumBits,true> mutable_reference;
534  typedef typename parent_t::integer_t integer_t;
535 
536  packed_dynamic_channel_reference(const void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
537  packed_dynamic_channel_reference(const const_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
538  packed_dynamic_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
539 
540  unsigned first_bit() const { return _first_bit; }
541 
542  integer_t get() const {
543  const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) <<_first_bit;
544  return static_cast< integer_t >(( this->get_data()&channel_mask ) >> _first_bit );
545  }
546 };
547 
551 template <typename BitField, int NumBits>
552 class packed_dynamic_channel_reference<BitField,NumBits,true>
553  : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,true> {
554  typedef detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,true> parent_t;
555  friend class packed_dynamic_channel_reference<BitField,NumBits,false>;
556 
557  unsigned _first_bit;
558 
559 public:
562  typedef typename parent_t::integer_t integer_t;
563 
564  packed_dynamic_channel_reference(void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
565  packed_dynamic_channel_reference(const packed_dynamic_channel_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
566 
567  const packed_dynamic_channel_reference& operator=(integer_t value) const { assert(value<=parent_t::max_val); set_unsafe(value); return *this; }
568  const packed_dynamic_channel_reference& operator=(const mutable_reference& ref) const { set_unsafe(ref.get()); return *this; }
569  const packed_dynamic_channel_reference& operator=(const const_reference& ref) const { set_unsafe(ref.get()); return *this; }
570 
571  template <typename BitField1, int FirstBit1, bool Mutable1>
572  const packed_dynamic_channel_reference& operator=(const packed_channel_reference<BitField1, FirstBit1, NumBits, Mutable1>& ref) const
573  { set_unsafe(ref.get()); return *this; }
574 
575  unsigned first_bit() const { return _first_bit; }
576 
577  integer_t get() const {
578  const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) << _first_bit;
579  return static_cast< integer_t >(( this->get_data()&channel_mask ) >> _first_bit );
580  }
581 
582  void set_unsafe(integer_t value) const {
583  const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) << _first_bit;
584  this->set_data((this->get_data() & ~channel_mask) | value<<_first_bit);
585  }
586 };
587 } } // namespace boost::gil
588 
589 namespace std {
590 // We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified.
591 // swap with 'left bias':
592 // - swap between proxy and anything
593 // - swap between value type and proxy
594 // - swap between proxy and proxy
595 
596 
599 template <typename BF, int NB, bool M, typename R> inline
600 void swap(const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, R& y) {
601  boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
602 }
603 
604 
607 template <typename BF, int NB, bool M> inline
608 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) {
609  boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
610 }
611 
614 template <typename BF, int NB, bool M> inline
615 void swap(const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, const boost::gil::packed_dynamic_channel_reference<BF,NB,M> y) {
616  boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
617 }
618 } // namespace std
619 
620 namespace boost {
621 
622 template <int NumBits>
623 struct is_integral<gil::packed_channel_value<NumBits> > : public mpl::true_ {};
624 
625 template <typename BitField, int FirstBit, int NumBits, bool IsMutable>
626 struct is_integral<gil::packed_channel_reference<BitField,FirstBit,NumBits,IsMutable> > : public mpl::true_ {};
627 
628 template <typename BitField, int NumBits, bool IsMutable>
629 struct is_integral<gil::packed_dynamic_channel_reference<BitField,NumBits,IsMutable> > : public mpl::true_ {};
630 
631 template <typename BaseChannelValue, typename MinVal, typename MaxVal>
632 struct is_integral<gil::scoped_channel_value<BaseChannelValue,MinVal,MaxVal> > : public is_integral<BaseChannelValue> {};
633 
634 } // namespace boost
635 
636 // \brief Determines the fundamental type which may be used, e.g., to cast from larger to smaller channel types.
637 namespace boost { namespace gil {
638 template <typename T>
639 struct base_channel_type_impl { typedef T type; };
640 
641 template <int N>
642 struct base_channel_type_impl<packed_channel_value<N> >
643 { typedef typename packed_channel_value<N>::integer_t type; };
644 
645 template <typename B, int F, int N, bool M>
646 struct base_channel_type_impl<packed_channel_reference<B, F, N, M> >
647 { typedef typename packed_channel_reference<B,F,N,M>::integer_t type; };
648 
649 template <typename B, int N, bool M>
650 struct base_channel_type_impl<packed_dynamic_channel_reference<B, N, M> >
651 { typedef typename packed_dynamic_channel_reference<B,N,M>::integer_t type; };
652 
653 template <typename ChannelValue, typename MinV, typename MaxV>
654 struct base_channel_type_impl<scoped_channel_value<ChannelValue, MinV, MaxV> >
655 { typedef ChannelValue type; };
656 
657 template <typename T>
658 struct base_channel_type : base_channel_type_impl<typename remove_cv<T>::type > {};
659 
660 }} //namespace boost::gil
661 
662 #endif
void swap(const boost::gil::packed_dynamic_channel_reference< BF, NB, M > x, const boost::gil::packed_dynamic_channel_reference< BF, NB, M > y)
swap for packed_dynamic_channel_reference
Definition: channel.hpp:615
Models a constant subbyte channel reference whose bit offset is a runtime parameter. Models ChannelConcept Same as packed_channel_reference, except that the offset is a runtime parameter.
Definition: channel.hpp:523
Models a mutable subbyte channel reference whose bit offset is a runtime parameter. Models ChannelConcept Same as packed_channel_reference, except that the offset is a runtime parameter.
Definition: channel.hpp:552