8 #ifndef BOOST_GIL_CHANNEL_HPP 9 #define BOOST_GIL_CHANNEL_HPP 11 #include <boost/gil/utilities.hpp> 13 #include <boost/assert.hpp> 14 #include <boost/config.hpp> 15 #include <boost/config/pragma_message.hpp> 16 #include <boost/integer/integer_mask.hpp> 17 #include <boost/type_traits/remove_cv.hpp> 22 #ifdef BOOST_GIL_DOXYGEN_ONLY 23 #define BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS 33 #ifdef BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS 34 #if defined(sun) || defined(__sun) || \ // SunOS 35 defined(__osf__) || defined(__osf) || \
36 defined(_hpux) || defined(hpux) || \
37 defined(__arm__) || defined(__ARM_ARCH) || \
39 #error Unaligned access strictly disabled for some UNIX platforms or ARM architecture 40 #elif defined(__i386__) || defined(__x86_64__) || defined(__vax__) 48 BOOST_PRAGMA_MESSAGE(
"CAUTION: Unaligned access tolerated on little-endian may cause undefined behaviour")
50 #error Unaligned access disabled for unknown platforms and architectures 52 #endif // defined(BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS) 54 namespace boost {
namespace gil {
72 template <
typename T,
bool is_
class>
struct channel_traits_impl;
76 struct channel_traits_impl<T, true> {
77 using value_type =
typename T::value_type;
78 using reference =
typename T::reference;
79 using pointer =
typename T::pointer;
80 using const_reference =
typename T::const_reference;
81 using const_pointer =
typename T::const_pointer;
82 static constexpr
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(); }
89 struct channel_traits_impl<T, false> {
93 using const_reference = T
const&;
94 using const_pointer = T
const*;
95 static constexpr
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)(); }
101 template <
typename T>
102 struct channel_traits_impl<const T, false> :
public channel_traits_impl<T, false> {
103 using reference =
const T &;
104 using pointer =
const T *;
105 static constexpr
bool is_mutable =
false;
127 template <
typename T>
128 struct channel_traits :
public detail::channel_traits_impl<T, is_class<T>::value> {};
131 template <
typename T>
struct channel_traits<T&> :
public channel_traits<T> {};
134 template <
typename T>
135 struct channel_traits<T const&> :
public channel_traits<T>
137 using reference =
typename channel_traits<T>::const_reference;
138 using pointer =
typename channel_traits<T>::const_pointer;
139 static constexpr
bool is_mutable =
false;
171 template <
typename BaseChannelValue,
typename MinVal,
typename MaxVal>
172 struct scoped_channel_value
174 using value_type = scoped_channel_value<BaseChannelValue, MinVal, MaxVal>;
175 using reference = value_type&;
176 using pointer = value_type*;
177 using const_reference = value_type
const&;
178 using const_pointer = value_type
const*;
179 static constexpr
bool is_mutable = channel_traits<BaseChannelValue>::is_mutable;
181 using base_channel_t = BaseChannelValue;
183 static value_type min_value() {
return MinVal::apply(); }
184 static value_type max_value() {
return MaxVal::apply(); }
186 scoped_channel_value() {}
187 scoped_channel_value(
const scoped_channel_value& c) : _value(c._value) {}
188 scoped_channel_value(BaseChannelValue val) : _value(val) {}
190 scoped_channel_value& operator++() { ++_value;
return *
this; }
191 scoped_channel_value& operator--() { --_value;
return *
this; }
193 scoped_channel_value operator++(
int) { scoped_channel_value tmp=*
this; this->operator++();
return tmp; }
194 scoped_channel_value operator--(
int) { scoped_channel_value tmp=*
this; this->operator--();
return tmp; }
196 template <
typename Scalar2> scoped_channel_value& operator+=(Scalar2 v) { _value+=v;
return *
this; }
197 template <
typename Scalar2> scoped_channel_value& operator-=(Scalar2 v) { _value-=v;
return *
this; }
198 template <
typename Scalar2> scoped_channel_value& operator*=(Scalar2 v) { _value*=v;
return *
this; }
199 template <
typename Scalar2> scoped_channel_value& operator/=(Scalar2 v) { _value/=v;
return *
this; }
201 scoped_channel_value& operator=(BaseChannelValue v) { _value=v;
return *
this; }
202 operator BaseChannelValue()
const {
return _value; }
204 BaseChannelValue _value;
207 template <
typename T>
208 struct float_point_zero
210 static constexpr T apply() {
return 0.0f; }
213 template <
typename T>
214 struct float_point_one
216 static constexpr T apply() {
return 1.0f; }
231 template <
int NumBits>
232 struct min_fast_uint :
public mpl::if_c< (NumBits<=8),
234 typename mpl::if_c< (NumBits<=16),
236 typename mpl::if_c< (NumBits<=32),
243 template <int NumBits>
244 struct num_value_fn : public mpl::if_c< ( NumBits < 32 )
249 template <int NumBits>
250 struct max_value_fn : public mpl::if_c< ( NumBits <= 32 )
272 template <int NumBits>
273 class packed_channel_value {
276 using integer_t = typename detail::min_fast_uint<NumBits>::type;
278 using value_type = packed_channel_value<NumBits>;
279 using reference = value_type&;
280 using const_reference = value_type const&;
281 using pointer = value_type*;
282 using const_pointer = value_type const*;
283 static constexpr bool is_mutable = true;
285 static value_type min_value() { return 0; }
286 static value_type max_value() { return low_bits_mask_t< NumBits >::sig_bits; }
288 packed_channel_value() {}
289 packed_channel_value(integer_t v) { _value = static_cast< integer_t >( v & low_bits_mask_t<NumBits>::sig_bits_fast ); }
290 template <typename Scalar>
291 packed_channel_value(Scalar v) { _value = packed_channel_value( static_cast< integer_t >( v ) ); }
293 static unsigned int num_bits() { return NumBits; }
295 operator integer_t() const { return _value; }
302 template <std::size_t K>
303 struct static_copy_bytes {
304 void operator()(const unsigned char* from, unsigned char* to) const {
306 static_copy_bytes<K-1>()(++from,++to);
311 struct static_copy_bytes<0> {
312 void operator()(const unsigned char* , unsigned char*) const {}
315 template <typename Derived, typename BitField, int NumBits, bool Mutable>
316 class packed_channel_reference_base {
318 using data_ptr_t = typename mpl::if_c<Mutable,void*,const void*>::type;
320 data_ptr_t _data_ptr;
322 using value_type = packed_channel_value<NumBits>;
323 using reference = const Derived;
324 using pointer = value_type *;
325 using const_pointer = const value_type *;
326 static constexpr int num_bits = NumBits;
327 static constexpr bool is_mutable = Mutable;
329 static value_type min_value() { return channel_traits<value_type>::min_value(); }
330 static value_type max_value() { return channel_traits<value_type>::max_value(); }
332 using bitfield_t = BitField;
333 using integer_t = typename value_type::integer_t;
335 packed_channel_reference_base(data_ptr_t data_ptr) : _data_ptr(data_ptr) {}
336 packed_channel_reference_base(const packed_channel_reference_base& ref) : _data_ptr(ref._data_ptr) {}
337 const Derived& operator=(integer_t v) const { set(v); return derived(); }
339 const Derived& operator++() const { set(get()+1); return derived(); }
340 const Derived& operator--() const { set(get()-1); return derived(); }
342 Derived operator++(int) const { Derived tmp=derived(); this->operator++(); return tmp; }
343 Derived operator--(int) const { Derived tmp=derived(); this->operator--(); return tmp; }
345 template <typename Scalar2> const Derived& operator+=(Scalar2 v) const { set( static_cast<integer_t>( get() + v )); return derived(); }
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(); }
350 operator integer_t() const { return get(); }
351 data_ptr_t operator &() const {return _data_ptr;}
354 using num_value_t = typename detail::num_value_fn<NumBits>::type;
355 using max_value_t = typename detail::max_value_fn<NumBits>::type;
357 static const num_value_t num_values = static_cast< num_value_t >( 1 ) << NumBits ;
358 static const max_value_t max_val = static_cast< max_value_t >( num_values - 1 );
360 #if defined(BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS)
361 const bitfield_t& get_data() const { return *static_cast<const bitfield_t*>(_data_ptr); }
362 void set_data(const bitfield_t& val) const { *static_cast< bitfield_t*>(_data_ptr) = val; }
364 bitfield_t get_data() const {
366 static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(_data_ptr),gil_reinterpret_cast<unsigned char*>(&ret));
369 void set_data(const bitfield_t& val) const {
370 static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(&val),gil_reinterpret_cast<unsigned char*>(_data_ptr));
375 void set(integer_t value) const {
376 this->derived().set_unsafe(((value % num_values) + num_values) % num_values);
378 integer_t get() const { return derived().get(); }
379 const Derived& derived() const { return static_cast<const Derived&>(*this); }
397 template <typename BitField,
398 int FirstBit, int NumBits,
400 class packed_channel_reference;
402 template <typename BitField,
405 class packed_dynamic_channel_reference;
409 template <typename BitField, int FirstBit, int NumBits>
410 class packed_channel_reference<BitField,FirstBit,NumBits,false>
411 : public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false>
413 using parent_t = detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false>;
414 friend class packed_channel_reference<BitField,FirstBit,NumBits,true>;
416 static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
418 void operator=(const packed_channel_reference&);
420 using const_reference = packed_channel_reference<BitField,FirstBit,NumBits,false> const;
421 using mutable_reference = packed_channel_reference<BitField,FirstBit,NumBits,true> const;
422 using integer_t = typename parent_t::integer_t;
424 explicit packed_channel_reference(const void* data_ptr) : parent_t(data_ptr) {}
425 packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
426 packed_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr) {}
428 unsigned first_bit() const { return FirstBit; }
430 integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
435 template <typename BitField, int FirstBit, int NumBits>
436 class packed_channel_reference<BitField,FirstBit,NumBits,true>
437 : public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true>
439 using parent_t = detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true>;
440 friend class packed_channel_reference<BitField,FirstBit,NumBits,false>;
442 static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
445 using const_reference = packed_channel_reference<BitField,FirstBit,NumBits,false> const;
446 using mutable_reference = packed_channel_reference<BitField,FirstBit,NumBits,true> const;
447 using integer_t = typename parent_t::integer_t;
449 explicit packed_channel_reference(void* data_ptr) : parent_t(data_ptr) {}
450 packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
452 packed_channel_reference const& operator=(integer_t value) const
454 BOOST_ASSERT(value <= parent_t::max_val);
459 const packed_channel_reference& operator=(const mutable_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
460 const packed_channel_reference& operator=(const const_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
462 template <bool Mutable1>
463 const packed_channel_reference& operator=(const packed_dynamic_channel_reference<BitField,NumBits,Mutable1>& ref) const { set_unsafe(ref.get()); return *this; }
465 unsigned first_bit() const { return FirstBit; }
467 integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
468 void set_unsafe(integer_t value) const { this->set_data((this->get_data() & ~channel_mask) | (( static_cast< BitField >( value )<<FirstBit))); }
470 void set_from_reference(const BitField& other_bits) const { this->set_data((this->get_data() & ~channel_mask) | (other_bits & channel_mask)); }
484 template <typename BF, int FB, int NB, bool M, typename R> inline
485 void swap(const boost::gil::packed_channel_reference<BF,FB,NB,M> x, R& y) {
486 boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
492 template <typename BF, int FB, int NB, bool M> inline
493 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) {
494 boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
499 template <typename BF, int FB, int NB, bool M> inline
500 void swap(const boost::gil::packed_channel_reference<BF,FB,NB,M> x, const boost::gil::packed_channel_reference<BF,FB,NB,M> y) {
501 boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
505 namespace boost { namespace gil {
525 template <typename BitField, int NumBits>
526 class packed_dynamic_channel_reference<BitField,NumBits,false>
527 : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false>
529 using parent_t = detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false>;
530 friend class packed_dynamic_channel_reference<BitField,NumBits,true>;
534 void operator=(const packed_dynamic_channel_reference&);
536 using const_reference = packed_dynamic_channel_reference<BitField,NumBits,false> const;
537 using mutable_reference = packed_dynamic_channel_reference<BitField,NumBits,true> const;
538 using integer_t = typename parent_t::integer_t;
540 packed_dynamic_channel_reference(const void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
541 packed_dynamic_channel_reference(const const_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
542 packed_dynamic_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
544 unsigned first_bit() const { return _first_bit; }
546 integer_t get() const {
547 const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) <<_first_bit;
548 return static_cast< integer_t >(( this->get_data()&channel_mask ) >> _first_bit );
555 template <typename BitField, int NumBits>
556 class packed_dynamic_channel_reference<BitField,NumBits,true>
557 :
public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,true>
559 using parent_t = detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,
true>;
560 friend class packed_dynamic_channel_reference<BitField,NumBits,false>;
567 using integer_t =
typename parent_t::integer_t;
569 packed_dynamic_channel_reference(
void* data_ptr,
unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
570 packed_dynamic_channel_reference(
const packed_dynamic_channel_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
572 packed_dynamic_channel_reference
const& operator=(integer_t value)
const 574 BOOST_ASSERT(value <= parent_t::max_val);
579 const packed_dynamic_channel_reference& operator=(
const mutable_reference& ref)
const { set_unsafe(ref.get());
return *
this; }
580 const packed_dynamic_channel_reference& operator=(
const const_reference& ref)
const { set_unsafe(ref.get());
return *
this; }
582 template <
typename BitField1,
int FirstBit1,
bool Mutable1>
583 const packed_dynamic_channel_reference& operator=(
const packed_channel_reference<BitField1, FirstBit1, NumBits, Mutable1>& ref)
const 584 { set_unsafe(ref.get());
return *
this; }
586 unsigned first_bit()
const {
return _first_bit; }
588 integer_t
get()
const {
589 const BitField channel_mask =
static_cast< integer_t
>( parent_t::max_val ) << _first_bit;
590 return static_cast< integer_t
>(( this->get_data()&channel_mask ) >> _first_bit );
593 void set_unsafe(integer_t value)
const {
594 const BitField channel_mask =
static_cast< integer_t
>( parent_t::max_val ) << _first_bit;
595 this->set_data((this->get_data() & ~channel_mask) | value<<_first_bit);
610 template <
typename BF,
int NB,
bool M,
typename R>
inline 611 void swap(
const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, R& y) {
612 boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
618 template <
typename BF,
int NB,
bool M>
inline 619 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) {
620 boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
625 template <
typename BF,
int NB,
bool M>
inline 626 void swap(
const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x,
const boost::gil::packed_dynamic_channel_reference<BF,NB,M> y) {
627 boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
633 template <
int NumBits>
634 struct is_integral<gil::packed_channel_value<NumBits> > :
public mpl::true_ {};
636 template <
typename BitField,
int FirstBit,
int NumBits,
bool IsMutable>
637 struct is_integral<gil::packed_channel_reference<BitField,FirstBit,NumBits,IsMutable> > :
public mpl::true_ {};
639 template <
typename BitField,
int NumBits,
bool IsMutable>
640 struct is_integral<gil::packed_dynamic_channel_reference<BitField,NumBits,IsMutable> > :
public mpl::true_ {};
642 template <
typename BaseChannelValue,
typename MinVal,
typename MaxVal>
643 struct is_integral<gil::scoped_channel_value<BaseChannelValue,MinVal,MaxVal> > :
public is_integral<BaseChannelValue> {};
648 namespace boost {
namespace gil {
649 template <
typename T>
650 struct base_channel_type_impl {
using type = T; };
653 struct base_channel_type_impl<packed_channel_value<N> >
654 {
using type =
typename packed_channel_value<N>::integer_t; };
656 template <
typename B,
int F,
int N,
bool M>
657 struct base_channel_type_impl<packed_channel_reference<B, F, N, M> >
659 using type =
typename packed_channel_reference<B,F,N,M>::integer_t;
662 template <
typename B,
int N,
bool M>
663 struct base_channel_type_impl<packed_dynamic_channel_reference<B, N, M> >
665 using type =
typename packed_dynamic_channel_reference<B,N,M>::integer_t;
668 template <
typename ChannelValue,
typename MinV,
typename MaxV>
669 struct base_channel_type_impl<scoped_channel_value<ChannelValue, MinV, MaxV> >
670 {
using type = ChannelValue; };
672 template <
typename T>
673 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:626
Definition: algorithm.hpp:30
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:526
Definition: algorithm.hpp:127
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:556