Boost GIL


channel.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2005-2007 Adobe Systems Incorporated
3 
4  Use, modification and distribution are subject to the Boost Software License,
5  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6  http://www.boost.org/LICENSE_1_0.txt).
7 
8  See http://stlab.adobe.com/gil for most recent version including documentation.
9 */
10 
11 /*************************************************************************************************/
12 
13 #ifndef GIL_CHANNEL_HPP
14 #define GIL_CHANNEL_HPP
15 
26 
27 #include <limits>
28 #include <cassert>
29 #include <cstdint>
30 
31 #include <boost/config.hpp>
32 #include <boost/integer/integer_mask.hpp>
33 #include <boost/type_traits/remove_cv.hpp>
34 
35 #include "gil_config.hpp"
36 #include "utilities.hpp"
37 
38 
39 namespace boost { namespace gil {
40 
41 
56 
57 namespace detail {
58  template <typename T, bool is_class> struct channel_traits_impl;
59 
60  // channel traits for custom class
61  template <typename T>
62  struct channel_traits_impl<T, true> {
63  typedef typename T::value_type value_type;
64  typedef typename T::reference reference;
65  typedef typename T::pointer pointer;
66  typedef typename T::const_reference const_reference;
67  typedef typename T::const_pointer const_pointer;
68  BOOST_STATIC_CONSTANT(bool, is_mutable=T::is_mutable);
69  static value_type min_value() { return T::min_value(); }
70  static value_type max_value() { return T::max_value(); }
71  };
72 
73  // channel traits implementation for built-in integral or floating point channel type
74  template <typename T>
75  struct channel_traits_impl<T, false> {
76  typedef T value_type;
77  typedef T& reference;
78  typedef T* pointer;
79  typedef const T& const_reference;
80  typedef T const* const_pointer;
81  BOOST_STATIC_CONSTANT(bool, is_mutable=true);
82  static value_type min_value() { return (std::numeric_limits<T>::min)(); }
83  static value_type max_value() { return (std::numeric_limits<T>::max)(); }
84  };
85 
86  // channel traits implementation for constant built-in scalar or floating point type
87  template <typename T>
88  struct channel_traits_impl<const T, false> : public channel_traits_impl<T, false> {
89  typedef const T& reference;
90  typedef const T* pointer;
91  BOOST_STATIC_CONSTANT(bool, is_mutable=false);
92  };
93 }
94 
113 template <typename T>
114 struct channel_traits : public detail::channel_traits_impl<T, is_class<T>::value> {};
115 
116 // Channel traits for C++ reference type - remove the reference
117 template <typename T> struct channel_traits< T&> : public channel_traits<T> {};
118 
119 // Channel traits for constant C++ reference type
120 template <typename T> struct channel_traits<const T&> : public channel_traits<T> {
121  typedef typename channel_traits<T>::const_reference reference;
122  typedef typename channel_traits<T>::const_pointer pointer;
123  BOOST_STATIC_CONSTANT(bool, is_mutable=false);
124 };
125 
131 
152 template <typename BaseChannelValue, // base channel (models ChannelValueConcept)
155  typename MinVal, typename MaxVal> // classes with a static apply() function returning the minimum/maximum channel values
158  typedef value_type& reference;
159  typedef value_type* pointer;
160  typedef const value_type& const_reference;
161  typedef const value_type* const_pointer;
162  BOOST_STATIC_CONSTANT(bool, is_mutable=channel_traits<BaseChannelValue>::is_mutable);
163 
164  typedef BaseChannelValue base_channel_t;
165 
166  static value_type min_value() { return MinVal::apply(); }
167  static value_type max_value() { return MaxVal::apply(); }
168 
170  scoped_channel_value(const scoped_channel_value& c) : _value(c._value) {}
171  scoped_channel_value(BaseChannelValue val) : _value(val) {}
172 
173  scoped_channel_value& operator++() { ++_value; return *this; }
174  scoped_channel_value& operator--() { --_value; return *this; }
175 
176  scoped_channel_value operator++(int) { scoped_channel_value tmp=*this; this->operator++(); return tmp; }
177  scoped_channel_value operator--(int) { scoped_channel_value tmp=*this; this->operator--(); return tmp; }
178 
179  template <typename Scalar2> scoped_channel_value& operator+=(Scalar2 v) { _value+=v; return *this; }
180  template <typename Scalar2> scoped_channel_value& operator-=(Scalar2 v) { _value-=v; return *this; }
181  template <typename Scalar2> scoped_channel_value& operator*=(Scalar2 v) { _value*=v; return *this; }
182  template <typename Scalar2> scoped_channel_value& operator/=(Scalar2 v) { _value/=v; return *this; }
183 
184  scoped_channel_value& operator=(BaseChannelValue v) { _value=v; return *this; }
185  operator BaseChannelValue() const { return _value; }
186 private:
187  BaseChannelValue _value;
188 };
189 
190 template <typename T>
191 struct float_point_zero
192 {
193  static constexpr T apply() { return 0.0f; }
194 };
195 
196 template <typename T>
197 struct float_point_one
198 {
199  static constexpr T apply() { return 1.0f; }
200 };
201 
207 
208 // 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:
209 // - Any operation that requires returning the result by value will otherwise return the built-in integral type, which will have incorrect range
210 // That means that after getting the value of the channel we cannot properly do channel_convert, channel_invert, etc.
211 // - 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
212 namespace detail {
213  // returns the smallest fast unsigned integral type that has at least NumBits bits
214  template <int NumBits>
215  struct min_fast_uint : public mpl::if_c< (NumBits<=8),
216  uint_least8_t,
217  typename mpl::if_c< (NumBits<=16),
218  uint_least16_t,
219  typename mpl::if_c< (NumBits<=32),
220  uint_least32_t,
221  uintmax_t
222  >::type
223  >::type
224  > {};
225 
226  template <int NumBits>
227  struct num_value_fn : public mpl::if_c< ( NumBits < 32 )
228  , uint32_t
229  , uint64_t
230  > {};
231 
232  template <int NumBits>
233  struct max_value_fn : public mpl::if_c< ( NumBits <= 32 )
234  , uint32_t
235  , uint64_t
236  > {};
237 }
238 
255 template <int NumBits>
258 class packed_channel_value {
259 
260 public:
261  typedef typename detail::min_fast_uint<NumBits>::type integer_t;
262 
263 
264  typedef packed_channel_value value_type;
265  typedef value_type& reference;
266  typedef const value_type& const_reference;
267  typedef value_type* pointer;
268  typedef const value_type* const_pointer;
269 
270  static value_type min_value() { return 0; }
271  static value_type max_value() { return low_bits_mask_t< NumBits >::sig_bits; }
272 
273  BOOST_STATIC_CONSTANT(bool, is_mutable=true);
274 
275  packed_channel_value() {}
276 
277  packed_channel_value(integer_t v) { _value = static_cast< integer_t >( v & low_bits_mask_t<NumBits>::sig_bits_fast ); }
278  template <typename Scalar> packed_channel_value(Scalar v) { _value = packed_channel_value( static_cast< integer_t >( v ) ); }
279 
280  static unsigned int num_bits() { return NumBits; }
281 
282  operator integer_t() const { return _value; }
283 private:
284  integer_t _value;
285 };
286 
287 namespace detail {
288 
289 template <std::size_t K>
290 struct static_copy_bytes {
291  void operator()(const unsigned char* from, unsigned char* to) const {
292  *to = *from;
293  static_copy_bytes<K-1>()(++from,++to);
294  }
295 };
296 
297 template <>
298 struct static_copy_bytes<0> {
299  void operator()(const unsigned char* , unsigned char*) const {}
300 };
301 
302 template <typename Derived, typename BitField, int NumBits, bool Mutable>
303 class packed_channel_reference_base {
304 protected:
305  typedef typename mpl::if_c<Mutable,void*,const void*>::type data_ptr_t;
306 public:
307  data_ptr_t _data_ptr; // void* pointer to the first byte of the bit range
308 
309  typedef packed_channel_value<NumBits> value_type;
310  typedef const Derived reference;
311  typedef value_type* pointer;
312  typedef const value_type* const_pointer;
313  BOOST_STATIC_CONSTANT(int, num_bits=NumBits);
314  BOOST_STATIC_CONSTANT(bool, is_mutable=Mutable);
315 
316  static value_type min_value() { return channel_traits<value_type>::min_value(); }
317  static value_type max_value() { return channel_traits<value_type>::max_value(); }
318 
319  typedef BitField bitfield_t;
320  typedef typename value_type::integer_t integer_t;
321 
322  packed_channel_reference_base(data_ptr_t data_ptr) : _data_ptr(data_ptr) {}
323  packed_channel_reference_base(const packed_channel_reference_base& ref) : _data_ptr(ref._data_ptr) {}
324  const Derived& operator=(integer_t v) const { set(v); return derived(); }
325 
326  const Derived& operator++() const { set(get()+1); return derived(); }
327  const Derived& operator--() const { set(get()-1); return derived(); }
328 
329  Derived operator++(int) const { Derived tmp=derived(); this->operator++(); return tmp; }
330  Derived operator--(int) const { Derived tmp=derived(); this->operator--(); return tmp; }
331 
332  template <typename Scalar2> const Derived& operator+=(Scalar2 v) const { set( static_cast<integer_t>( get() + v )); return derived(); }
333  template <typename Scalar2> const Derived& operator-=(Scalar2 v) const { set( static_cast<integer_t>( get() - v )); return derived(); }
334  template <typename Scalar2> const Derived& operator*=(Scalar2 v) const { set( static_cast<integer_t>( get() * v )); return derived(); }
335  template <typename Scalar2> const Derived& operator/=(Scalar2 v) const { set( static_cast<integer_t>( get() / v )); return derived(); }
336 
337  operator integer_t() const { return get(); }
338  data_ptr_t operator &() const {return _data_ptr;}
339 protected:
340 
341  typedef typename detail::num_value_fn< NumBits >::type num_value_t;
342  typedef typename detail::max_value_fn< NumBits >::type max_value_t;
343 
344  static const num_value_t num_values = static_cast< num_value_t >( 1 ) << NumBits ;
345  static const max_value_t max_val = static_cast< max_value_t >( num_values - 1 );
346 
347 #if defined(BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS)
348  const bitfield_t& get_data() const { return *static_cast<const bitfield_t*>(_data_ptr); }
349  void set_data(const bitfield_t& val) const { *static_cast< bitfield_t*>(_data_ptr) = val; }
350 #else
351  bitfield_t get_data() const {
352  bitfield_t ret;
353  static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(_data_ptr),gil_reinterpret_cast<unsigned char*>(&ret));
354  return ret;
355  }
356  void set_data(const bitfield_t& val) const {
357  static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(&val),gil_reinterpret_cast<unsigned char*>(_data_ptr));
358  }
359 #endif
360 
361 private:
362  void set(integer_t value) const { // can this be done faster??
363  this->derived().set_unsafe(((value % num_values) + num_values) % num_values);
364  }
365  integer_t get() const { return derived().get(); }
366  const Derived& derived() const { return static_cast<const Derived&>(*this); }
367 };
368 } // namespace detail
369 
386 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
387  int FirstBit, int NumBits,// Defines the sequence of bits in the data value that contain the channel
388  bool Mutable> // true if the reference is mutable
389 class packed_channel_reference;
390 
391 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
392  int NumBits, // Defines the sequence of bits in the data value that contain the channel
393  bool Mutable> // true if the reference is mutable
394 class packed_dynamic_channel_reference;
395 
398 template <typename BitField, int FirstBit, int NumBits>
399 class packed_channel_reference<BitField,FirstBit,NumBits,false>
400  : public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false> {
401  typedef detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false> parent_t;
402  friend class packed_channel_reference<BitField,FirstBit,NumBits,true>;
403 
404  static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
405 
406  void operator=(const packed_channel_reference&);
407 public:
408  typedef const packed_channel_reference<BitField,FirstBit,NumBits,false> const_reference;
409  typedef const packed_channel_reference<BitField,FirstBit,NumBits,true> mutable_reference;
410  typedef typename parent_t::integer_t integer_t;
411 
412  explicit packed_channel_reference(const void* data_ptr) : parent_t(data_ptr) {}
413  packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
414  packed_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr) {}
415 
416  unsigned first_bit() const { return FirstBit; }
417 
418  integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
419 };
420 
423 template <typename BitField, int FirstBit, int NumBits>
424 class packed_channel_reference<BitField,FirstBit,NumBits,true>
425  : public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true> {
426  typedef detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true> parent_t;
427  friend class packed_channel_reference<BitField,FirstBit,NumBits,false>;
428 
429  static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
430 
431 public:
432  typedef const packed_channel_reference<BitField,FirstBit,NumBits,false> const_reference;
433  typedef const packed_channel_reference<BitField,FirstBit,NumBits,true> mutable_reference;
434  typedef typename parent_t::integer_t integer_t;
435 
436  explicit packed_channel_reference(void* data_ptr) : parent_t(data_ptr) {}
437  packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
438 
439  const packed_channel_reference& operator=(integer_t value) const { assert(value<=parent_t::max_val); set_unsafe(value); return *this; }
440  const packed_channel_reference& operator=(const mutable_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
441  const packed_channel_reference& operator=(const const_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
442 
443  template <bool Mutable1>
444  const packed_channel_reference& operator=(const packed_dynamic_channel_reference<BitField,NumBits,Mutable1>& ref) const { set_unsafe(ref.get()); return *this; }
445 
446  unsigned first_bit() const { return FirstBit; }
447 
448  integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
449  void set_unsafe(integer_t value) const { this->set_data((this->get_data() & ~channel_mask) | (( static_cast< BitField >( value )<<FirstBit))); }
450 private:
451  void set_from_reference(const BitField& other_bits) const { this->set_data((this->get_data() & ~channel_mask) | (other_bits & channel_mask)); }
452 };
453 
454 } } // namespace boost::gil
455 
456 namespace std {
457 // We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified.
458 // swap with 'left bias':
459 // - swap between proxy and anything
460 // - swap between value type and proxy
461 // - swap between proxy and proxy
462 
465 template <typename BF, int FB, int NB, bool M, typename R> inline
466 void swap(const boost::gil::packed_channel_reference<BF,FB,NB,M> x, R& y) {
467  boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
468 }
469 
470 
473 template <typename BF, int FB, int NB, bool M> inline
474 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) {
475  boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
476 }
477 
478 
481 template <typename BF, int FB, int NB, bool M> inline
482 void swap(const boost::gil::packed_channel_reference<BF,FB,NB,M> x, const boost::gil::packed_channel_reference<BF,FB,NB,M> y) {
483  boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
484 }
485 } // namespace std
486 
487 namespace boost { namespace gil {
488 
506 template <typename BitField, int NumBits>
510 class packed_dynamic_channel_reference<BitField,NumBits,false>
511  : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false> {
512  typedef detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false> parent_t;
513  friend class packed_dynamic_channel_reference<BitField,NumBits,true>;
514 
515  unsigned _first_bit; // 0..7
516 
517  void operator=(const packed_dynamic_channel_reference&);
518 public:
519  typedef const packed_dynamic_channel_reference<BitField,NumBits,false> const_reference;
520  typedef const packed_dynamic_channel_reference<BitField,NumBits,true> mutable_reference;
521  typedef typename parent_t::integer_t integer_t;
522 
523  packed_dynamic_channel_reference(const void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
524  packed_dynamic_channel_reference(const const_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
525  packed_dynamic_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
526 
527  unsigned first_bit() const { return _first_bit; }
528 
529  integer_t get() const {
530  const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) <<_first_bit;
531  return static_cast< integer_t >(( this->get_data()&channel_mask ) >> _first_bit );
532  }
533 };
534 
538 template <typename BitField, int NumBits>
539 class packed_dynamic_channel_reference<BitField,NumBits,true>
540  : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,true> {
541  typedef detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,true> parent_t;
542  friend class packed_dynamic_channel_reference<BitField,NumBits,false>;
543 
544  unsigned _first_bit;
545 
546 public:
549  typedef typename parent_t::integer_t integer_t;
550 
551  packed_dynamic_channel_reference(void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
552  packed_dynamic_channel_reference(const packed_dynamic_channel_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
553 
554  const packed_dynamic_channel_reference& operator=(integer_t value) const { assert(value<=parent_t::max_val); set_unsafe(value); return *this; }
555  const packed_dynamic_channel_reference& operator=(const mutable_reference& ref) const { set_unsafe(ref.get()); return *this; }
556  const packed_dynamic_channel_reference& operator=(const const_reference& ref) const { set_unsafe(ref.get()); return *this; }
557 
558  template <typename BitField1, int FirstBit1, bool Mutable1>
559  const packed_dynamic_channel_reference& operator=(const packed_channel_reference<BitField1, FirstBit1, NumBits, Mutable1>& ref) const
560  { set_unsafe(ref.get()); return *this; }
561 
562  unsigned first_bit() const { return _first_bit; }
563 
564  integer_t get() const {
565  const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) << _first_bit;
566  return static_cast< integer_t >(( this->get_data()&channel_mask ) >> _first_bit );
567  }
568 
569  void set_unsafe(integer_t value) const {
570  const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) << _first_bit;
571  this->set_data((this->get_data() & ~channel_mask) | value<<_first_bit);
572  }
573 };
574 } } // namespace boost::gil
575 
576 namespace std {
577 // We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified.
578 // swap with 'left bias':
579 // - swap between proxy and anything
580 // - swap between value type and proxy
581 // - swap between proxy and proxy
582 
583 
586 template <typename BF, int NB, bool M, typename R> inline
587 void swap(const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, R& y) {
588  boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
589 }
590 
591 
594 template <typename BF, int NB, bool M> inline
595 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) {
596  boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
597 }
598 
599 
602 template <typename BF, int NB, bool M> inline
603 void swap(const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, const boost::gil::packed_dynamic_channel_reference<BF,NB,M> y) {
604  boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
605 }
606 } // namespace std
607 
608 namespace boost {
609 
610 template <int NumBits>
611 struct is_integral<gil::packed_channel_value<NumBits> > : public mpl::true_ {};
612 
613 template <typename BitField, int FirstBit, int NumBits, bool IsMutable>
614 struct is_integral<gil::packed_channel_reference<BitField,FirstBit,NumBits,IsMutable> > : public mpl::true_ {};
615 
616 template <typename BitField, int NumBits, bool IsMutable>
617 struct is_integral<gil::packed_dynamic_channel_reference<BitField,NumBits,IsMutable> > : public mpl::true_ {};
618 
619 template <typename BaseChannelValue, typename MinVal, typename MaxVal>
620 struct is_integral<gil::scoped_channel_value<BaseChannelValue,MinVal,MaxVal> > : public is_integral<BaseChannelValue> {};
621 
622 } // namespace boost
623 
624 // \brief Determines the fundamental type which may be used, e.g., to cast from larger to smaller channel types.
625 namespace boost { namespace gil {
626 template <typename T>
627 struct base_channel_type_impl { typedef T type; };
628 
629 template <int N>
630 struct base_channel_type_impl<packed_channel_value<N> >
631 { typedef typename packed_channel_value<N>::integer_t type; };
632 
633 template <typename B, int F, int N, bool M>
634 struct base_channel_type_impl<packed_channel_reference<B, F, N, M> >
635 { typedef typename packed_channel_reference<B,F,N,M>::integer_t type; };
636 
637 template <typename B, int N, bool M>
638 struct base_channel_type_impl<packed_dynamic_channel_reference<B, N, M> >
639 { typedef typename packed_dynamic_channel_reference<B,N,M>::integer_t type; };
640 
641 template <typename ChannelValue, typename MinV, typename MaxV>
642 struct base_channel_type_impl<scoped_channel_value<ChannelValue, MinV, MaxV> >
643 { typedef ChannelValue type; };
644 
645 template <typename T>
646 struct base_channel_type : base_channel_type_impl<typename remove_cv<T>::type > {};
647 
648 }} //namespace boost::gil
649 
650 #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:603
A channel adaptor that modifies the range of the source channel. Models: ChannelValueConcept.
Definition: channel.hpp:156
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:510
Traits for channels. Contains the following members:
Definition: channel.hpp:114
GIL configuration file.
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:539
Various utilities not specific to the image library. Some are non-standard STL extensions or generic ...