13 #ifndef GIL_CHANNEL_HPP
14 #define GIL_CHANNEL_HPP
29 #include <boost/config.hpp>
30 #include <boost/config/pragma_message.hpp>
31 #include <boost/integer/integer_mask.hpp>
32 #include <boost/type_traits/remove_cv.hpp>
38 #if defined(BOOST_GIL_DOXYGEN_ONLY)
39 #define BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS
49 #if defined(BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS)
50 #if defined(sun) || defined(__sun) || \ // SunOS
51 defined(__osf__) || defined(__osf) || \
52 defined(_hpux) || defined(hpux) || \
53 defined(__arm__) || defined(__ARM_ARCH) || \
55 #error Unaligned access strictly disabled for some UNIX platforms or ARM architecture
56 #elif defined(__i386__) || defined(__x86_64__) || defined(__vax__)
64 BOOST_PRAGMA_MESSAGE(
"CAUTION: Unaligned access tolerated on little-endian may cause undefined behaviour")
66 #error Unaligned access disabled for unknown platforms and architectures
68 #endif // defined(BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS)
70 namespace boost {
namespace gil {
88 template <
typename T,
bool is_
class>
struct channel_traits_impl;
92 struct channel_traits_impl<T, true> {
93 typedef typename T::value_type value_type;
94 typedef typename T::reference reference;
95 typedef typename T::pointer pointer;
96 typedef typename T::const_reference const_reference;
97 typedef typename T::const_pointer const_pointer;
98 BOOST_STATIC_CONSTANT(
bool, is_mutable=T::is_mutable);
99 static value_type min_value() {
return T::min_value(); }
100 static value_type max_value() {
return T::max_value(); }
104 template <
typename T>
105 struct channel_traits_impl<T, false> {
106 typedef T value_type;
107 typedef T& reference;
109 typedef const T& const_reference;
110 typedef T
const* const_pointer;
111 BOOST_STATIC_CONSTANT(
bool, is_mutable=
true);
112 static value_type min_value() {
return (std::numeric_limits<T>::min)(); }
113 static value_type max_value() {
return (std::numeric_limits<T>::max)(); }
117 template <
typename T>
118 struct channel_traits_impl<const T, false> :
public channel_traits_impl<T, false> {
119 typedef const T& reference;
120 typedef const T* pointer;
121 BOOST_STATIC_CONSTANT(
bool, is_mutable=
false);
143 template <
typename T>
144 struct channel_traits :
public detail::channel_traits_impl<T, is_class<T>::value> {};
147 template <
typename T>
struct channel_traits< T&> :
public channel_traits<T> {};
150 template <
typename T>
struct channel_traits<const T&> :
public channel_traits<T> {
151 typedef typename channel_traits<T>::const_reference reference;
152 typedef typename channel_traits<T>::const_pointer pointer;
153 BOOST_STATIC_CONSTANT(
bool, is_mutable=
false);
182 template <
typename BaseChannelValue,
185 typename MinVal,
typename MaxVal>
186 struct scoped_channel_value {
187 typedef scoped_channel_value value_type;
188 typedef value_type& reference;
189 typedef value_type* pointer;
190 typedef const value_type& const_reference;
191 typedef const value_type* const_pointer;
192 BOOST_STATIC_CONSTANT(
bool, is_mutable=channel_traits<BaseChannelValue>::is_mutable);
194 typedef BaseChannelValue base_channel_t;
196 static value_type min_value() {
return MinVal::apply(); }
197 static value_type max_value() {
return MaxVal::apply(); }
199 scoped_channel_value() {}
200 scoped_channel_value(
const scoped_channel_value& c) : _value(c._value) {}
201 scoped_channel_value(BaseChannelValue val) : _value(val) {}
203 scoped_channel_value& operator++() { ++_value;
return *
this; }
204 scoped_channel_value& operator--() { --_value;
return *
this; }
206 scoped_channel_value operator++(
int) { scoped_channel_value tmp=*
this; this->operator++();
return tmp; }
207 scoped_channel_value operator--(
int) { scoped_channel_value tmp=*
this; this->operator--();
return tmp; }
209 template <
typename Scalar2> scoped_channel_value& operator+=(Scalar2 v) { _value+=v;
return *
this; }
210 template <
typename Scalar2> scoped_channel_value& operator-=(Scalar2 v) { _value-=v;
return *
this; }
211 template <
typename Scalar2> scoped_channel_value& operator*=(Scalar2 v) { _value*=v;
return *
this; }
212 template <
typename Scalar2> scoped_channel_value& operator/=(Scalar2 v) { _value/=v;
return *
this; }
214 scoped_channel_value& operator=(BaseChannelValue v) { _value=v;
return *
this; }
215 operator BaseChannelValue()
const {
return _value; }
217 BaseChannelValue _value;
220 template <
typename T>
221 struct float_point_zero
223 static constexpr T apply() {
return 0.0f; }
226 template <
typename T>
227 struct float_point_one
229 static constexpr T apply() {
return 1.0f; }
244 template <
int NumBits>
245 struct min_fast_uint :
public mpl::if_c< (NumBits<=8),
247 typename mpl::if_c< (NumBits<=16),
249 typename mpl::if_c< (NumBits<=32),
256 template <int NumBits>
257 struct num_value_fn : public mpl::if_c< ( NumBits < 32 )
262 template <int NumBits>
263 struct max_value_fn : public mpl::if_c< ( NumBits <= 32 )
285 template <int NumBits>
288 class packed_channel_value {
291 typedef typename detail::min_fast_uint<NumBits>::type integer_t;
294 typedef packed_channel_value value_type;
295 typedef value_type& reference;
296 typedef const value_type& const_reference;
297 typedef value_type* pointer;
298 typedef const value_type* const_pointer;
300 static value_type min_value() { return 0; }
301 static value_type max_value() { return low_bits_mask_t< NumBits >::sig_bits; }
303 BOOST_STATIC_CONSTANT(bool, is_mutable=true);
305 packed_channel_value() {}
307 packed_channel_value(integer_t v) { _value = static_cast< integer_t >( v & low_bits_mask_t<NumBits>::sig_bits_fast ); }
308 template <typename Scalar> packed_channel_value(Scalar v) { _value = packed_channel_value( static_cast< integer_t >( v ) ); }
310 static unsigned int num_bits() { return NumBits; }
312 operator integer_t() const { return _value; }
319 template <std::size_t K>
320 struct static_copy_bytes {
321 void operator()(const unsigned char* from, unsigned char* to) const {
323 static_copy_bytes<K-1>()(++from,++to);
328 struct static_copy_bytes<0> {
329 void operator()(const unsigned char* , unsigned char*) const {}
332 template <typename Derived, typename BitField, int NumBits, bool Mutable>
333 class packed_channel_reference_base {
335 typedef typename mpl::if_c<Mutable,void*,const void*>::type data_ptr_t;
337 data_ptr_t _data_ptr;
339 typedef packed_channel_value<NumBits> value_type;
340 typedef const Derived reference;
341 typedef value_type* pointer;
342 typedef const value_type* const_pointer;
343 BOOST_STATIC_CONSTANT(int, num_bits=NumBits);
344 BOOST_STATIC_CONSTANT(bool, is_mutable=Mutable);
346 static value_type min_value() { return channel_traits<value_type>::min_value(); }
347 static value_type max_value() { return channel_traits<value_type>::max_value(); }
349 typedef BitField bitfield_t;
350 typedef typename value_type::integer_t integer_t;
352 packed_channel_reference_base(data_ptr_t data_ptr) : _data_ptr(data_ptr) {}
353 packed_channel_reference_base(const packed_channel_reference_base& ref) : _data_ptr(ref._data_ptr) {}
354 const Derived& operator=(integer_t v) const { set(v); return derived(); }
356 const Derived& operator++() const { set(get()+1); return derived(); }
357 const Derived& operator--() const { set(get()-1); return derived(); }
359 Derived operator++(int) const { Derived tmp=derived(); this->operator++(); return tmp; }
360 Derived operator--(int) const { Derived tmp=derived(); this->operator--(); return tmp; }
362 template <typename Scalar2> const Derived& operator+=(Scalar2 v) const { set( static_cast<integer_t>( get() + v )); return derived(); }
363 template <typename Scalar2> const Derived& operator-=(Scalar2 v) const { set( static_cast<integer_t>( get() - v )); return derived(); }
364 template <typename Scalar2> const Derived& operator*=(Scalar2 v) const { set( static_cast<integer_t>( get() * v )); return derived(); }
365 template <typename Scalar2> const Derived& operator/=(Scalar2 v) const { set( static_cast<integer_t>( get() / v )); return derived(); }
367 operator integer_t() const { return get(); }
368 data_ptr_t operator &() const {return _data_ptr;}
371 typedef typename detail::num_value_fn< NumBits >::type num_value_t;
372 typedef typename detail::max_value_fn< NumBits >::type max_value_t;
374 static const num_value_t num_values = static_cast< num_value_t >( 1 ) << NumBits ;
375 static const max_value_t max_val = static_cast< max_value_t >( num_values - 1 );
377 #if defined(BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS)
378 const bitfield_t& get_data() const { return *static_cast<const bitfield_t*>(_data_ptr); }
379 void set_data(const bitfield_t& val) const { *static_cast< bitfield_t*>(_data_ptr) = val; }
381 bitfield_t get_data() const {
383 static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(_data_ptr),gil_reinterpret_cast<unsigned char*>(&ret));
386 void set_data(const bitfield_t& val) const {
387 static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(&val),gil_reinterpret_cast<unsigned char*>(_data_ptr));
392 void set(integer_t value) const {
393 this->derived().set_unsafe(((value % num_values) + num_values) % num_values);
395 integer_t get() const { return derived().get(); }
396 const Derived& derived() const { return static_cast<const Derived&>(*this); }
416 template <typename BitField,
417 int FirstBit, int NumBits,
419 class packed_channel_reference;
421 template <typename BitField,
424 class packed_dynamic_channel_reference;
428 template <typename BitField, int FirstBit, int NumBits>
429 class packed_channel_reference<BitField,FirstBit,NumBits,false>
430 : public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false> {
431 typedef detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false> parent_t;
432 friend class packed_channel_reference<BitField,FirstBit,NumBits,true>;
434 static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
436 void operator=(const packed_channel_reference&);
438 typedef const packed_channel_reference<BitField,FirstBit,NumBits,false> const_reference;
439 typedef const packed_channel_reference<BitField,FirstBit,NumBits,true> mutable_reference;
440 typedef typename parent_t::integer_t integer_t;
442 explicit packed_channel_reference(const void* data_ptr) : parent_t(data_ptr) {}
443 packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
444 packed_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr) {}
446 unsigned first_bit() const { return FirstBit; }
448 integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
453 template <typename BitField, int FirstBit, int NumBits>
454 class packed_channel_reference<BitField,FirstBit,NumBits,true>
455 : public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true> {
456 typedef detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true> parent_t;
457 friend class packed_channel_reference<BitField,FirstBit,NumBits,false>;
459 static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
462 typedef const packed_channel_reference<BitField,FirstBit,NumBits,false> const_reference;
463 typedef const packed_channel_reference<BitField,FirstBit,NumBits,true> mutable_reference;
464 typedef typename parent_t::integer_t integer_t;
466 explicit packed_channel_reference(void* data_ptr) : parent_t(data_ptr) {}
467 packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
469 const packed_channel_reference& operator=(integer_t value) const { assert(value<=parent_t::max_val); set_unsafe(value); return *this; }
470 const packed_channel_reference& operator=(const mutable_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
471 const packed_channel_reference& operator=(const const_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
473 template <bool Mutable1>
474 const packed_channel_reference& operator=(const packed_dynamic_channel_reference<BitField,NumBits,Mutable1>& ref) const { set_unsafe(ref.get()); return *this; }
476 unsigned first_bit() const { return FirstBit; }
478 integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
479 void set_unsafe(integer_t value) const { this->set_data((this->get_data() & ~channel_mask) | (( static_cast< BitField >( value )<<FirstBit))); }
481 void set_from_reference(const BitField& other_bits) const { this->set_data((this->get_data() & ~channel_mask) | (other_bits & channel_mask)); }
495 template <typename BF, int FB, int NB, bool M, typename R> inline
496 void swap(const boost::gil::packed_channel_reference<BF,FB,NB,M> x, R& y) {
497 boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
503 template <typename BF, int FB, int NB, bool M> inline
504 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) {
505 boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
510 template <typename BF, int FB, int NB, bool M> inline
511 void swap(const boost::gil::packed_channel_reference<BF,FB,NB,M> x, const boost::gil::packed_channel_reference<BF,FB,NB,M> y) {
512 boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
516 namespace boost { namespace gil {
535 template <typename BitField, int NumBits>
539 class packed_dynamic_channel_reference<BitField,NumBits,false>
540 : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false> {
541 typedef detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false> parent_t;
542 friend class packed_dynamic_channel_reference<BitField,NumBits,true>;
546 void operator=(const packed_dynamic_channel_reference&);
548 typedef const packed_dynamic_channel_reference<BitField,NumBits,false> const_reference;
549 typedef const packed_dynamic_channel_reference<BitField,NumBits,true> mutable_reference;
550 typedef typename parent_t::integer_t integer_t;
552 packed_dynamic_channel_reference(const void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
553 packed_dynamic_channel_reference(const const_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
554 packed_dynamic_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
556 unsigned first_bit() const { return _first_bit; }
558 integer_t get() const {
559 const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) <<_first_bit;
560 return static_cast< integer_t >(( this->get_data()&channel_mask ) >> _first_bit );
567 template <typename BitField, int NumBits>
568 class packed_dynamic_channel_reference<BitField,NumBits,true>
569 :
public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,true> {
570 typedef detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,
true> parent_t;
571 friend class packed_dynamic_channel_reference<BitField,NumBits,false>;
578 typedef typename parent_t::integer_t integer_t;
580 packed_dynamic_channel_reference(
void* data_ptr,
unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
581 packed_dynamic_channel_reference(
const packed_dynamic_channel_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
583 const packed_dynamic_channel_reference& operator=(integer_t value)
const { assert(value<=parent_t::max_val); set_unsafe(value);
return *
this; }
584 const packed_dynamic_channel_reference& operator=(
const mutable_reference& ref)
const { set_unsafe(ref.get());
return *
this; }
585 const packed_dynamic_channel_reference& operator=(
const const_reference& ref)
const { set_unsafe(ref.get());
return *
this; }
587 template <
typename BitField1,
int FirstBit1,
bool Mutable1>
588 const packed_dynamic_channel_reference& operator=(
const packed_channel_reference<BitField1, FirstBit1, NumBits, Mutable1>& ref)
const
589 { set_unsafe(ref.get());
return *
this; }
591 unsigned first_bit()
const {
return _first_bit; }
593 integer_t
get()
const {
594 const BitField channel_mask =
static_cast< integer_t
>( parent_t::max_val ) << _first_bit;
595 return static_cast< integer_t
>(( this->get_data()&channel_mask ) >> _first_bit );
598 void set_unsafe(integer_t value)
const {
599 const BitField channel_mask =
static_cast< integer_t
>( parent_t::max_val ) << _first_bit;
600 this->set_data((this->get_data() & ~channel_mask) | value<<_first_bit);
615 template <
typename BF,
int NB,
bool M,
typename R>
inline
616 void swap(
const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, R& y) {
617 boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
623 template <
typename BF,
int NB,
bool M>
inline
624 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) {
625 boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
630 template <
typename BF,
int NB,
bool M>
inline
631 void swap(
const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x,
const boost::gil::packed_dynamic_channel_reference<BF,NB,M> y) {
632 boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
638 template <
int NumBits>
639 struct is_integral<gil::packed_channel_value<NumBits> > :
public mpl::true_ {};
641 template <
typename BitField,
int FirstBit,
int NumBits,
bool IsMutable>
642 struct is_integral<gil::packed_channel_reference<BitField,FirstBit,NumBits,IsMutable> > :
public mpl::true_ {};
644 template <
typename BitField,
int NumBits,
bool IsMutable>
645 struct is_integral<gil::packed_dynamic_channel_reference<BitField,NumBits,IsMutable> > :
public mpl::true_ {};
647 template <
typename BaseChannelValue,
typename MinVal,
typename MaxVal>
648 struct is_integral<gil::scoped_channel_value<BaseChannelValue,MinVal,MaxVal> > :
public is_integral<BaseChannelValue> {};
653 namespace boost {
namespace gil {
654 template <
typename T>
655 struct base_channel_type_impl {
typedef T type; };
658 struct base_channel_type_impl<packed_channel_value<N> >
659 {
typedef typename packed_channel_value<N>::integer_t type; };
661 template <
typename B,
int F,
int N,
bool M>
662 struct base_channel_type_impl<packed_channel_reference<B, F, N, M> >
663 {
typedef typename packed_channel_reference<B,F,N,M>::integer_t type; };
665 template <
typename B,
int N,
bool M>
666 struct base_channel_type_impl<packed_dynamic_channel_reference<B, N, M> >
667 {
typedef typename packed_dynamic_channel_reference<B,N,M>::integer_t type; };
669 template <
typename ChannelValue,
typename MinV,
typename MaxV>
670 struct base_channel_type_impl<scoped_channel_value<ChannelValue, MinV, MaxV> >
671 {
typedef ChannelValue type; };
673 template <
typename T>
674 struct base_channel_type : base_channel_type_impl<typename remove_cv<T>::type > {};
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:631
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:539
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:568
Various utilities not specific to the image library. Some are non-standard STL extensions or generic ...