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>    20 #include <type_traits>    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 {
    73 template <
typename T, 
bool IsClass>
    74 struct channel_traits_impl;
    78 struct channel_traits_impl<T, true>
    80     using value_type = 
typename T::value_type;
    81     using reference = 
typename T::reference;
    82     using pointer = 
typename T::pointer;
    83     using const_reference = 
typename T::const_reference;
    84     using const_pointer = 
typename T::const_pointer;
    85     static constexpr 
bool is_mutable = T::is_mutable;
    86     static value_type min_value() { 
return T::min_value(); }
    87     static value_type max_value() { 
return T::max_value(); }
    92 struct channel_traits_impl<T, false>
    97     using const_reference = T 
const&;
    98     using const_pointer = T 
const*;
    99     static constexpr 
bool is_mutable = 
true;
   100     static value_type min_value() { 
return (std::numeric_limits<T>::min)(); }
   101     static value_type max_value() { 
return (std::numeric_limits<T>::max)(); }
   105 template <
typename T>
   106 struct channel_traits_impl<T const, false> : channel_traits_impl<T, false>
   108     using reference = T 
const&;
   109     using pointer = T 
const*;
   110     static constexpr 
bool is_mutable = 
false;
   133 template <
typename T>
   134 struct channel_traits : detail::channel_traits_impl<T, std::is_class<T>::value> {};
   137 template <
typename T>
   138 struct channel_traits<T&> : channel_traits<T> {};
   141 template <
typename T>
   142 struct channel_traits<T const&> : channel_traits<T>
   144     using reference = 
typename channel_traits<T>::const_reference;
   145     using pointer = 
typename channel_traits<T>::const_pointer;
   146     static constexpr 
bool is_mutable = 
false;
   176 template <
typename BaseChannelValue, 
typename MinVal, 
typename MaxVal>
   177 struct scoped_channel_value
   179     using value_type = scoped_channel_value<BaseChannelValue, MinVal, MaxVal>;
   180     using reference = value_type&;
   181     using pointer = value_type*;
   182     using const_reference = value_type 
const&;
   183     using const_pointer = value_type 
const*;
   184     static constexpr 
bool is_mutable = channel_traits<BaseChannelValue>::is_mutable;
   186     using base_channel_t = BaseChannelValue;
   188     static value_type min_value() { 
return MinVal::apply(); }
   189     static value_type max_value() { 
return MaxVal::apply(); }
   191     scoped_channel_value() = 
default;
   192     scoped_channel_value(scoped_channel_value 
const& other) : value_(other.value_) {}
   193     scoped_channel_value& operator=(scoped_channel_value 
const& other) = 
default;
   194     scoped_channel_value(BaseChannelValue value) : value_(value) {}
   195     scoped_channel_value& operator=(BaseChannelValue value)
   201     scoped_channel_value& operator++() { ++value_; 
return *
this; }
   202     scoped_channel_value& operator--() { --value_; 
return *
this; }
   204     scoped_channel_value operator++(
int) { scoped_channel_value tmp=*
this; this->operator++(); 
return tmp; }
   205     scoped_channel_value operator--(
int) { scoped_channel_value tmp=*
this; this->operator--(); 
return tmp; }
   207     template <
typename Scalar2> scoped_channel_value& operator+=(Scalar2 v) { value_+=v; 
return *
this; }
   208     template <
typename Scalar2> scoped_channel_value& operator-=(Scalar2 v) { value_-=v; 
return *
this; }
   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; }
   212     operator BaseChannelValue()
 const { 
return value_; }
   214     BaseChannelValue value_{};
   217 template <
typename T>
   218 struct float_point_zero
   220     static constexpr T apply() { 
return 0.0f; }
   223 template <
typename T>
   224 struct float_point_one
   226     static constexpr T apply() { 
return 1.0f; }
   240 template <
int NumBits>
   241 struct min_fast_uint :
   246         typename std::conditional
   250             typename std::conditional
   260 template <int NumBits>
   262     : std::conditional<NumBits < 32, std::uint32_t, std::uint64_t>
   265 template <int NumBits>
   267     : std::conditional<NumBits <= 32, std::uint32_t, std::uint64_t>
   288 template <int NumBits>
   289 class packed_channel_value
   292     using integer_t = typename detail::min_fast_uint<NumBits>::type;
   294     using value_type = packed_channel_value<NumBits>;
   295     using reference = value_type&;
   296     using const_reference = value_type const&;
   297     using pointer = value_type*;
   298     using const_pointer = value_type const*;
   299     static constexpr bool is_mutable = true;
   301     static value_type min_value() { return 0; }
   302     static value_type max_value() { return low_bits_mask_t< NumBits >::sig_bits; }
   304     packed_channel_value() = default;
   305     packed_channel_value(integer_t v)
   307         value_ = static_cast<integer_t>(v & low_bits_mask_t<NumBits>::sig_bits_fast);
   310     template <typename Scalar>
   311     packed_channel_value(Scalar v)
   313         value_ = packed_channel_value(static_cast<integer_t>(v));
   316     static unsigned int num_bits() { return NumBits; }
   318     operator integer_t() const { return value_; }
   326 template <std::size_t K>
   327 struct static_copy_bytes
   329     void operator()(unsigned char const* from, unsigned char* to) const
   332         static_copy_bytes<K - 1>()(++from, ++to);
   337 struct static_copy_bytes<0>
   339     void operator()(unsigned char const*, unsigned char*) const {}
   342 template <typename Derived, typename BitField, int NumBits, bool IsMutable>
   343 class packed_channel_reference_base
   346     using data_ptr_t = typename std::conditional<IsMutable, void*, void const*>::type;
   348     data_ptr_t _data_ptr;   
   350     using value_type = packed_channel_value<NumBits>;
   351     using reference = const Derived;
   352     using pointer = value_type *;
   353     using const_pointer = const value_type *;
   354     static constexpr int num_bits = NumBits;
   355     static constexpr bool is_mutable = IsMutable;
   357     static value_type min_value()       { return channel_traits<value_type>::min_value(); }
   358     static value_type max_value()       { return channel_traits<value_type>::max_value(); }
   360     using bitfield_t = BitField;
   361     using integer_t = typename value_type::integer_t;
   363     packed_channel_reference_base(data_ptr_t data_ptr) : _data_ptr(data_ptr) {}
   364     packed_channel_reference_base(const packed_channel_reference_base& ref) : _data_ptr(ref._data_ptr) {}
   365     const Derived& operator=(integer_t v) const { set(v); return derived(); }
   367     const Derived& operator++() const { set(get()+1); return derived(); }
   368     const Derived& operator--() const { set(get()-1); return derived(); }
   370     Derived operator++(int) const { Derived tmp=derived(); this->operator++(); return tmp; }
   371     Derived operator--(int) const { Derived tmp=derived(); this->operator--(); return tmp; }
   373     template <typename Scalar2> const Derived& operator+=(Scalar2 v) const { set( static_cast<integer_t>(  get() + v )); return derived(); }
   374     template <typename Scalar2> const Derived& operator-=(Scalar2 v) const { set( static_cast<integer_t>(  get() - v )); return derived(); }
   375     template <typename Scalar2> const Derived& operator*=(Scalar2 v) const { set( static_cast<integer_t>(  get() * v )); return derived(); }
   376     template <typename Scalar2> const Derived& operator/=(Scalar2 v) const { set( static_cast<integer_t>(  get() / v )); return derived(); }
   378     operator integer_t() const { return get(); }
   379     data_ptr_t operator &() const {return _data_ptr;}
   382     using num_value_t = typename detail::num_value_fn<NumBits>::type;
   383     using max_value_t = typename detail::max_value_fn<NumBits>::type;
   385     static const num_value_t num_values = static_cast< num_value_t >( 1 ) << NumBits ;
   386     static const max_value_t max_val    = static_cast< max_value_t >( num_values - 1 );
   388 #if defined(BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS)
   389     const bitfield_t& get_data()                      const { return *static_cast<const bitfield_t*>(_data_ptr); }
   390     void              set_data(const bitfield_t& val) const {        *static_cast<      bitfield_t*>(_data_ptr) = val; }
   392     bitfield_t get_data() const {
   394         static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(_data_ptr),gil_reinterpret_cast<unsigned char*>(&ret));
   397     void set_data(const bitfield_t& val) const {
   398         static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(&val),gil_reinterpret_cast<unsigned char*>(_data_ptr));
   403     void set(integer_t value) const {     
   404         this->derived().set_unsafe(((value % num_values) + num_values) % num_values);
   406     integer_t get() const { return derived().get(); }
   407     const Derived& derived() const { return static_cast<const Derived&>(*this); }
   428 template <typename BitField, int FirstBit, int NumBits, bool IsMutable>
   429 class packed_channel_reference;
   434 template <typename BitField, int NumBits, bool IsMutable>
   435 class packed_dynamic_channel_reference;
   439 template <typename BitField, int FirstBit, int NumBits>
   440 class packed_channel_reference<BitField, FirstBit, NumBits, false>
   441     : public detail::packed_channel_reference_base
   443             packed_channel_reference<BitField, FirstBit, NumBits, false>,
   449     using parent_t = detail::packed_channel_reference_base
   451             packed_channel_reference<BitField, FirstBit, NumBits, false>,
   457     friend class packed_channel_reference<BitField, FirstBit, NumBits, true>;
   459     static const BitField channel_mask = static_cast<BitField>(parent_t::max_val) << FirstBit;
   461     void operator=(packed_channel_reference const&);
   463     using const_reference = packed_channel_reference<BitField,FirstBit,NumBits,false> const;
   464     using mutable_reference = packed_channel_reference<BitField,FirstBit,NumBits,true> const;
   465     using integer_t = typename parent_t::integer_t;
   467     explicit packed_channel_reference(const void* data_ptr) : parent_t(data_ptr) {}
   468     packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
   469     packed_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr) {}
   471     unsigned first_bit() const { return FirstBit; }
   473     integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
   478 template <typename BitField, int FirstBit, int NumBits>
   479 class packed_channel_reference<BitField,FirstBit,NumBits,true>
   480    : public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true>
   482     using parent_t = detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true>;
   483     friend class packed_channel_reference<BitField,FirstBit,NumBits,false>;
   485     static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
   488     using const_reference = packed_channel_reference<BitField,FirstBit,NumBits,false> const;
   489     using mutable_reference = packed_channel_reference<BitField,FirstBit,NumBits,true> const;
   490     using integer_t = typename parent_t::integer_t;
   492     explicit packed_channel_reference(void* data_ptr) : parent_t(data_ptr) {}
   493     packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
   495     packed_channel_reference const& operator=(integer_t value) const
   497         BOOST_ASSERT(value <= parent_t::max_val);
   502     const packed_channel_reference& operator=(const mutable_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
   503     const packed_channel_reference& operator=(const const_reference&   ref) const { set_from_reference(ref.get_data()); return *this; }
   505     template <bool Mutable1>
   506     const packed_channel_reference& operator=(const packed_dynamic_channel_reference<BitField,NumBits,Mutable1>& ref) const { set_unsafe(ref.get()); return *this; }
   508     unsigned first_bit() const { return FirstBit; }
   510     integer_t get()                  const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
   511     void set_unsafe(integer_t value) const { this->set_data((this->get_data() & ~channel_mask) | (( static_cast< BitField >( value )<<FirstBit))); }
   513     void set_from_reference(const BitField& other_bits) const { this->set_data((this->get_data() & ~channel_mask) | (other_bits & channel_mask)); }
   527 template <typename BF, int FB, int NB, bool M, typename R>
   529 void swap(boost::gil::packed_channel_reference<BF, FB, NB, M> const x, R& y)
   531     boost::gil::swap_proxy
   533         typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type
   540 template <typename BF, int FB, int NB, bool M>
   543     typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type& x,
   544     boost::gil::packed_channel_reference<BF, FB, NB, M> const y)
   546     boost::gil::swap_proxy
   548         typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type
   554 template <typename BF, int FB, int NB, bool M> inline
   556     boost::gil::packed_channel_reference<BF, FB, NB, M> const x,
   557     boost::gil::packed_channel_reference<BF, FB, NB, M> const y)
   559     boost::gil::swap_proxy
   561         typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type
   567 namespace boost { namespace gil {
   587 template <typename BitField, int NumBits>
   588 class packed_dynamic_channel_reference<BitField,NumBits,false>
   589    : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false>
   591     using parent_t = detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false>;
   592     friend class packed_dynamic_channel_reference<BitField,NumBits,true>;
   596     void operator=(const packed_dynamic_channel_reference&);
   598     using const_reference = packed_dynamic_channel_reference<BitField,NumBits,false> const;
   599     using mutable_reference = packed_dynamic_channel_reference<BitField,NumBits,true> const;
   600     using integer_t = typename parent_t::integer_t;
   602     packed_dynamic_channel_reference(const void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
   603     packed_dynamic_channel_reference(const const_reference&   ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
   604     packed_dynamic_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
   606     unsigned first_bit() const { return _first_bit; }
   608     integer_t get() const {
   609         const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) <<_first_bit;
   610         return static_cast< integer_t >(( this->get_data()&channel_mask ) >> _first_bit );
   617 template <typename BitField, int NumBits>
   618 class packed_dynamic_channel_reference<BitField,NumBits,true>
   619    : 
public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,true>
   621     using parent_t = detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,
true>;
   622     friend class packed_dynamic_channel_reference<BitField,NumBits,false>;
   629     using integer_t = 
typename parent_t::integer_t;
   631     packed_dynamic_channel_reference(
void* data_ptr, 
unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
   632     packed_dynamic_channel_reference(
const packed_dynamic_channel_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
   634     packed_dynamic_channel_reference 
const& operator=(integer_t value)
 const   636         BOOST_ASSERT(value <= parent_t::max_val);
   641     const packed_dynamic_channel_reference& operator=(
const mutable_reference& ref)
 const {  set_unsafe(ref.get()); 
return *
this; }
   642     const packed_dynamic_channel_reference& operator=(
const const_reference&   ref)
 const {  set_unsafe(ref.get()); 
return *
this; }
   644     template <
typename BitField1, 
int FirstBit1, 
bool Mutable1>
   645     const packed_dynamic_channel_reference& operator=(
const packed_channel_reference<BitField1, FirstBit1, NumBits, Mutable1>& ref)
 const   646         {  set_unsafe(ref.get()); 
return *
this; }
   648     unsigned first_bit()
 const { 
return _first_bit; }
   650     integer_t get()
 const {
   651         const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) << _first_bit;
   652         return static_cast< integer_t >(( this->get_data()&channel_mask ) >> _first_bit );
   655     void set_unsafe(integer_t value)
 const {
   656         const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) << _first_bit;
   657         this->set_data((this->get_data() & ~channel_mask) | value<<_first_bit);
   672 template <
typename BF, 
int NB, 
bool M, 
typename R> 
inline   673 void swap(
const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, R& y) {
   674     boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
   680 template <
typename BF, 
int NB, 
bool M> 
inline   681 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) {
   682     boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
   687 template <
typename BF, 
int NB, 
bool M> 
inline   688 void swap(
const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, 
const boost::gil::packed_dynamic_channel_reference<BF,NB,M> y) {
   689     boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y);
   694 namespace boost { 
namespace gil {
   695 template <
typename T>
   696 struct base_channel_type_impl { 
using type = T; };
   699 struct base_channel_type_impl<packed_channel_value<N> >
   700 { 
using type = 
typename packed_channel_value<N>::integer_t; };
   702 template <
typename B, 
int F, 
int N, 
bool M>
   703 struct base_channel_type_impl<packed_channel_reference<B, F, N, M> >
   705     using type = 
typename packed_channel_reference<B,F,N,M>::integer_t;
   708 template <
typename B, 
int N, 
bool M>
   709 struct base_channel_type_impl<packed_dynamic_channel_reference<B, N, M> >
   711     using type = 
typename packed_dynamic_channel_reference<B,N,M>::integer_t;
   714 template <
typename ChannelValue, 
typename MinV, 
typename MaxV>
   715 struct base_channel_type_impl<scoped_channel_value<ChannelValue, MinV, MaxV> >
   716 { 
using type = ChannelValue; };
   718 template <
typename T>
   719 struct base_channel_type : base_channel_type_impl<typename std::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:688
Models a constant subbyte channel reference whose bit offset is a runtime parameter....
Definition: channel.hpp:588
Models a mutable subbyte channel reference whose bit offset is a runtime parameter....
Definition: channel.hpp:618