TuttleOFX  1
channel.hpp
Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2007 Adobe Systems Incorporated
00003 
00004     Use, modification and distribution are subject to the Boost Software License,
00005     Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
00006     http://www.boost.org/LICENSE_1_0.txt).
00007 
00008     See http://stlab.adobe.com/gil for most recent version including documentation.
00009  */
00010 
00011 /*************************************************************************************************/
00012 
00013 #ifndef GIL_CHANNEL_HPP
00014 #define GIL_CHANNEL_HPP
00015 
00016 ////////////////////////////////////////////////////////////////////////////////////////
00017 /// \file
00018 /// \brief Channel utilities
00019 /// \author Lubomir Bourdev and Hailin Jin \n
00020 ///         Adobe Systems Incorporated
00021 /// \date   2005-2007 \n Last updated on May 6, 2007
00022 ///
00023 /// Definitions of standard GIL channel models
00024 ///
00025 ////////////////////////////////////////////////////////////////////////////////////////
00026 
00027 #include <limits>
00028 #include <cassert>
00029 #include <boost/cstdint.hpp>
00030 #include "gil_config.hpp"
00031 #include "utilities.hpp"
00032 
00033 namespace boost {
00034 namespace gil {
00035 
00036 ///////////////////////////////////////////
00037 ////  channel_traits
00038 ////
00039 ////  \ingroup ChannelModel
00040 ////  \class channel_traits
00041 ////  \brief defines properties of channels, such as their range and associated types
00042 ////
00043 ////  The channel traits must be defined for every model of ChannelConcept
00044 ////  Default traits are provided. For built-in types the default traits use
00045 ////  built-in pointer and reference and the channel range is the physical
00046 ////  range of the type. For classes, the default traits forward the associated types
00047 ////  and range to the class.
00048 ////
00049 ///////////////////////////////////////////
00050 
00051 namespace detail {
00052 template <typename T, bool is_class>
00053 struct channel_traits_impl;
00054 
00055 // channel traits for custom class
00056 template <typename T>
00057 struct channel_traits_impl<T, true>
00058 {
00059         typedef typename T::value_type value_type;
00060         typedef typename T::reference reference;
00061         typedef typename T::pointer pointer;
00062         typedef typename T::const_reference const_reference;
00063         typedef typename T::const_pointer const_pointer;
00064         BOOST_STATIC_CONSTANT( bool, is_mutable = T::is_mutable );
00065         static value_type min_value() { return T::min_value(); }
00066         static value_type max_value() { return T::max_value(); }
00067 };
00068 
00069 // channel traits implementation for built-in integral or floating point channel type
00070 template <typename T>
00071 struct channel_traits_impl<T, false>
00072 {
00073         typedef T value_type;
00074         typedef T&          reference;
00075         typedef T*          pointer;
00076         typedef const T&    const_reference;
00077         typedef T const*    const_pointer;
00078         BOOST_STATIC_CONSTANT( bool, is_mutable = true );
00079         static value_type min_value() { return ( std::numeric_limits<T>::min )(); }
00080         static value_type max_value() { return ( std::numeric_limits<T>::max )(); }
00081 };
00082 
00083 // channel traits implementation for constant built-in scalar or floating point type
00084 template <typename T>
00085 struct channel_traits_impl<const T, false> : public channel_traits_impl<T, false>
00086 {
00087         typedef const T&    reference;
00088         typedef const T*    pointer;
00089         BOOST_STATIC_CONSTANT( bool, is_mutable = false );
00090 };
00091 }
00092 
00093 /**
00094    \ingroup ChannelModel
00095    \brief Traits for channels. Contains the following members:
00096    \code
00097    template <typename Channel>
00098    struct channel_traits {
00099     typedef ... value_type;
00100     typedef ... reference;
00101     typedef ... pointer;
00102     typedef ... const_reference;
00103     typedef ... const_pointer;
00104 
00105     static const bool is_mutable;
00106     static value_type min_value();
00107     static value_type max_value();
00108    };
00109    \endcode
00110  */
00111 template <typename T>
00112 struct channel_traits : public detail::channel_traits_impl<T, is_class<T>::value> {};
00113 
00114 // Channel traits for C++ reference type - remove the reference
00115 template <typename T>
00116 struct channel_traits<      T&> : public channel_traits<T> {};
00117 
00118 // Channel traits for constant C++ reference type
00119 template <typename T>
00120 struct channel_traits<const T&> : public channel_traits<T>
00121 {
00122         typedef typename channel_traits<T>::const_reference reference;
00123         typedef typename channel_traits<T>::const_pointer pointer;
00124         BOOST_STATIC_CONSTANT( bool, is_mutable = false );
00125 };
00126 
00127 ///////////////////////////////////////////
00128 ////
00129 ////  scoped_channel_value
00130 ////
00131 ///////////////////////////////////////////
00132 
00133 /**
00134    \defgroup ScopedChannelValue scoped_channel_value
00135    \ingroup ChannelModel
00136    \brief A channel adaptor that modifies the range of the source channel. Models: ChannelValueConcept
00137 
00138    Example:
00139    \code
00140    // Create a double channel with range [-0.5 .. 0.5]
00141    struct double_minus_half  { static double apply() { return -0.5; } };
00142    struct double_plus_half   { static double apply() { return  0.5; } };
00143    typedef scoped_channel_value<double, double_minus_half, double_plus_half> bits64custom_t;
00144 
00145    // channel_convert its maximum should map to the maximum
00146    bits64custom_t x = channel_traits<bits64custom_t>::max_value();
00147    assert(x == 0.5);
00148    bits16 y = channel_convert<bits16>(x);
00149    assert(y == 65535);
00150    \endcode
00151  */
00152 
00153 /// \ingroup ScopedChannelValue
00154 /// \brief A channel adaptor that modifies the range of the source channel. Models: ChannelValueConcept
00155 template <typename BaseChannelValue,        // base channel (models ChannelValueConcept)
00156           typename MinVal, typename MaxVal>
00157 // classes with a static apply() function returning the minimum/maximum channel values
00158 struct scoped_channel_value
00159 {
00160         typedef scoped_channel_value value_type;
00161         typedef value_type&             reference;
00162         typedef value_type*             pointer;
00163         typedef const value_type&       const_reference;
00164         typedef const value_type*       const_pointer;
00165         BOOST_STATIC_CONSTANT( bool, is_mutable = channel_traits<BaseChannelValue>::is_mutable );
00166 
00167         static value_type min_value() { return MinVal::apply(); }
00168         static value_type max_value() { return MaxVal::apply(); }
00169 
00170         scoped_channel_value() {}
00171         scoped_channel_value( const scoped_channel_value& c ) : _value( c._value ) {}
00172         scoped_channel_value( BaseChannelValue val ) : _value( val ) {}
00173 
00174         scoped_channel_value& operator++() { ++_value; return *this; }
00175         scoped_channel_value& operator--() { --_value; return *this; }
00176 
00177         scoped_channel_value operator++( int ) { scoped_channel_value tmp = *this; this->operator++(); return tmp; }
00178         scoped_channel_value operator--( int ) { scoped_channel_value tmp = *this; this->operator--(); return tmp; }
00179 
00180         template <typename Scalar2>
00181         scoped_channel_value& operator+=( Scalar2 v ) { _value += v; return *this; }
00182         template <typename Scalar2>
00183         scoped_channel_value& operator-=( Scalar2 v ) { _value -= v; return *this; }
00184         template <typename Scalar2>
00185         scoped_channel_value& operator*=( Scalar2 v ) { _value *= v; return *this; }
00186         template <typename Scalar2>
00187         scoped_channel_value& operator/=( Scalar2 v ) { _value /= v; return *this; }
00188 
00189         scoped_channel_value& operator=( BaseChannelValue v ) { _value = v; return *this; }
00190         operator BaseChannelValue() const { return _value; }
00191 
00192         private:
00193                 BaseChannelValue _value;
00194 };
00195 
00196 struct float_zero
00197 {
00198         static float apply() { return 0.0f; }
00199 };
00200 struct float_one
00201 {
00202         static float apply() { return 1.0f; }
00203 };
00204 
00205 ///////////////////////////////////////////
00206 ////
00207 ////  Support for sub-byte channels. These are integral channels whose value is contained in a range of bits inside an integral type
00208 ////
00209 ///////////////////////////////////////////
00210 
00211 // 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:
00212 // - Any operation that requires returning the result by value will otherwise return the built-in integral type, which will have incorrect range
00213 //   That means that after getting the value of the channel we cannot properly do channel_convert, channel_invert, etc.
00214 // - 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
00215 namespace detail {
00216 // returns the smallest fast unsigned integral type that has at least NumBits bits
00217 template <int NumBits>
00218 struct min_fast_uint : public mpl::if_c< ( NumBits <= 8 ),
00219                                              uint_least8_t,
00220                                              typename mpl::if_c< ( NumBits <= 16 ),
00221                                                                  uint_least16_t,
00222                                                                  typename mpl::if_c< ( NumBits <= 32 ),
00223                                                                                      uint_least32_t,
00224                                                                                      uintmax_t
00225                                                                                      >::type
00226                                                                  >::type
00227                                              > {};
00228 }
00229 
00230 /**
00231    \defgroup PackedChannelValueModel packed_channel_value
00232    \ingroup ChannelModel
00233    \brief Represents the value of an unsigned integral channel operating over a bit range. Models: ChannelValueConcept
00234    Example:
00235    \code
00236    // A 4-bit unsigned integral channel.
00237    typedef packed_channel_value<4> bits4;
00238 
00239    assert(channel_traits<bits4>::min_value()==0);
00240    assert(channel_traits<bits4>::max_value()==15);
00241    assert(sizeof(bits4)==1);
00242    BOOST_STATIC_ASSERT((boost::is_integral<bits4>::value));
00243    \endcode
00244  */
00245 
00246 /// \ingroup PackedChannelValueModel
00247 /// \brief The value of a subbyte channel. Models: ChannelValueConcept
00248 template <int NumBits>
00249 class packed_channel_value
00250 {
00251 static const std::size_t num_values = 1 << NumBits;
00252 
00253 public:
00254         typedef typename detail::min_fast_uint<NumBits>::type integer_t;
00255 
00256         typedef packed_channel_value value_type;
00257         typedef value_type&            reference;
00258         typedef const value_type&      const_reference;
00259         typedef value_type*            pointer;
00260         typedef const value_type*      const_pointer;
00261 
00262         static value_type min_value() { return value_type( 0 ); }
00263         static value_type max_value() { return value_type( num_values - 1 ); }
00264         BOOST_STATIC_CONSTANT( bool, is_mutable = true );
00265 
00266         packed_channel_value() {}
00267         packed_channel_value( integer_t v ) : _value( v % num_values ) {}
00268         packed_channel_value( const packed_channel_value& v ) : _value( v._value ) {}
00269         template <typename Scalar>
00270         packed_channel_value( Scalar v ) : _value( integer_t( v ) % num_values ) {}                          // suppress GCC implicit conversion warnings in channel regression file
00271 
00272         operator integer_t() const { return _value; }
00273 
00274 private:
00275         integer_t _value;
00276 };
00277 
00278 namespace detail {
00279 
00280 template <std::size_t K>
00281 struct static_copy_bytes
00282 {
00283         void operator()( const unsigned char* from, unsigned char* to ) const
00284         {
00285                 * to = *from;
00286 
00287                 static_copy_bytes<K - 1>( )( ++from, ++to );
00288         }
00289 
00290 };
00291 
00292 template <>
00293 struct static_copy_bytes<0>
00294 {
00295         void operator()( const unsigned char*, unsigned char* ) const {}
00296 };
00297 
00298 template <typename Derived, typename BitField, int NumBits, bool Mutable>
00299 class packed_channel_reference_base
00300 {
00301 protected:
00302         typedef typename mpl::if_c<Mutable, void*, const void*>::type data_ptr_t;
00303 
00304 public:
00305         data_ptr_t _data_ptr;   // void* pointer to the first byte of the bit range
00306 
00307         typedef packed_channel_value<NumBits>   value_type;
00308         typedef const Derived reference;
00309         typedef value_type*                     pointer;
00310         typedef const value_type*               const_pointer;
00311         BOOST_STATIC_CONSTANT( int,  num_bits = NumBits );
00312         BOOST_STATIC_CONSTANT( bool, is_mutable = Mutable );
00313 
00314         static value_type min_value() { return channel_traits<value_type>::min_value(); }
00315         static value_type max_value() { return channel_traits<value_type>::max_value(); }
00316 
00317         typedef BitField bitfield_t;
00318         typedef typename value_type::integer_t integer_t;
00319 
00320         packed_channel_reference_base( data_ptr_t data_ptr ) : _data_ptr( data_ptr ) {}
00321         packed_channel_reference_base( const packed_channel_reference_base& ref ) : _data_ptr( ref._data_ptr ) {}
00322         const Derived& operator=( integer_t v ) const { set( v ); return derived(); }
00323 
00324         const Derived& operator++() const { set( get() + 1 ); return derived(); }
00325         const Derived& operator--() const { set( get() - 1 ); return derived(); }
00326 
00327         Derived operator++( int ) const { Derived tmp = derived(); this->operator++(); return tmp; }
00328         Derived operator--( int ) const { Derived tmp = derived(); this->operator--(); return tmp; }
00329 
00330         template <typename Scalar2>
00331         const Derived& operator+=( Scalar2 v ) const { set( get() + v ); return derived(); }
00332         template <typename Scalar2>
00333         const Derived& operator-=( Scalar2 v ) const { set( get() - v ); return derived(); }
00334         template <typename Scalar2>
00335         const Derived& operator*=( Scalar2 v ) const { set( get() * v ); return derived(); }
00336         template <typename Scalar2>
00337         const Derived& operator/=( Scalar2 v ) const { set( get() / v ); return derived(); }
00338 
00339         operator integer_t() const { return get(); }
00340         data_ptr_t operator &() const { return _data_ptr; }
00341 
00342 protected:
00343         static const integer_t max_val = ( 1 << NumBits ) - 1;
00344 
00345         #ifdef GIL_NONWORD_POINTER_ALIGNMENT_SUPPORTED
00346         const bitfield_t& get_data()                      const   { return *static_cast<const bitfield_t*>( _data_ptr ); }
00347         void              set_data( const bitfield_t& val ) const {        *static_cast<      bitfield_t*>( _data_ptr ) = val; }
00348         #else
00349         bitfield_t get_data() const
00350         {
00351                 bitfield_t ret;
00352 
00353                 static_copy_bytes<sizeof( bitfield_t ) >() ( gil_reinterpret_cast_c<const unsigned char*>( _data_ptr ), gil_reinterpret_cast<unsigned char*>( &ret ) );
00354                 return ret;
00355         }
00356 
00357         void set_data( const bitfield_t& val ) const
00358         {
00359                 static_copy_bytes<sizeof( bitfield_t ) >() ( gil_reinterpret_cast_c<const unsigned char*>( &val ), gil_reinterpret_cast<unsigned char*>( _data_ptr ) );
00360         }
00361 
00362         #endif
00363 
00364 private:
00365         void set( integer_t value ) const
00366         {
00367                 // can this be done faster??
00368                 const integer_t num_values = max_val + 1;
00369 
00370                 this->derived().set_unsafe( ( ( value % num_values ) + num_values ) % num_values );
00371         }
00372 
00373         integer_t      get() const     { return derived().get(); }
00374         const Derived& derived() const { return static_cast<const Derived&>( *this ); }
00375 };
00376 }   // namespace detail
00377 
00378 /**
00379    \defgroup PackedChannelReferenceModel packed_channel_reference
00380    \ingroup ChannelModel
00381    \brief Represents a reference proxy to a channel operating over a bit range whose offset is fixed at compile time. Models ChannelConcept
00382    Example:
00383    \code
00384    // Reference to a 2-bit channel starting at bit 1 (i.e. the second bit)
00385    typedef const packed_channel_reference<uint16_t,1,2,true> bits2_1_ref_t;
00386 
00387    uint16_t data=0;
00388    bits2_1_ref_t channel_ref(&data);
00389    channel_ref = channel_traits<bits2_1_ref_t>::max_value();   // == 3
00390    assert(data == 6);                                          // == 3<<1 == 6
00391    \endcode
00392  */
00393 
00394 template <typename BitField,        // A type that holds the bits of the pixel from which the channel is referenced. Typically an integral type, like boost::uint16_t
00395           int FirstBit, int NumBits, // Defines the sequence of bits in the data value that contain the channel
00396           bool Mutable>
00397 // true if the reference is mutable
00398 class packed_channel_reference;
00399 
00400 template <typename BitField,        // A type that holds the bits of the pixel from which the channel is referenced. Typically an integral type, like boost::uint16_t
00401           int NumBits,              // Defines the sequence of bits in the data value that contain the channel
00402           bool Mutable>
00403 // true if the reference is mutable
00404 class packed_dynamic_channel_reference;
00405 
00406 /// \ingroup PackedChannelReferenceModel
00407 /// \brief A constant subbyte channel reference whose bit offset is fixed at compile time. Models ChannelConcept
00408 template <typename BitField, int FirstBit, int NumBits>
00409 class packed_channel_reference<BitField, FirstBit, NumBits, false>
00410         : public detail::packed_channel_reference_base<packed_channel_reference<BitField, FirstBit, NumBits, false>, BitField, NumBits, false>
00411 {
00412 typedef detail::packed_channel_reference_base<packed_channel_reference<BitField, FirstBit, NumBits, false>, BitField, NumBits, false> parent_t;
00413 friend class packed_channel_reference<BitField, FirstBit, NumBits, true>;
00414 
00415 // CHH - Begin
00416 //static const BitField channel_mask = parent_t::max_val<<FirstBit;
00417 static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
00418 // CHH - End
00419 
00420 void operator=( const packed_channel_reference& );
00421 
00422 public:
00423         typedef const packed_channel_reference<BitField, FirstBit, NumBits, false> const_reference;
00424         typedef const packed_channel_reference<BitField, FirstBit, NumBits, true>  mutable_reference;
00425         typedef typename parent_t::integer_t integer_t;
00426 
00427         explicit packed_channel_reference( const void* data_ptr ) : parent_t( data_ptr ) {}
00428         packed_channel_reference( const packed_channel_reference& ref ) : parent_t( ref._data_ptr ) {}
00429         packed_channel_reference( const mutable_reference& ref ) : parent_t( ref._data_ptr ) {}
00430 
00431         unsigned first_bit() const { return FirstBit; }
00432 
00433         integer_t get() const { return integer_t( ( this->get_data() & channel_mask ) >> FirstBit ); }
00434 };
00435 
00436 /// \ingroup PackedChannelReferenceModel
00437 /// \brief A mutable subbyte channel reference whose bit offset is fixed at compile time. Models ChannelConcept
00438 template <typename BitField, int FirstBit, int NumBits>
00439 class packed_channel_reference<BitField, FirstBit, NumBits, true>
00440         : public detail::packed_channel_reference_base<packed_channel_reference<BitField, FirstBit, NumBits, true>, BitField, NumBits, true>
00441 {
00442 typedef detail::packed_channel_reference_base<packed_channel_reference<BitField, FirstBit, NumBits, true>, BitField, NumBits, true> parent_t;
00443 friend class packed_channel_reference<BitField, FirstBit, NumBits, false>;
00444 
00445 // CHH - Begin
00446 //static const BitField channel_mask = parent_t::max_val<<FirstBit;
00447 static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
00448 // CHH - End
00449 
00450 public:
00451         typedef const packed_channel_reference<BitField, FirstBit, NumBits, false> const_reference;
00452         typedef const packed_channel_reference<BitField, FirstBit, NumBits, true>  mutable_reference;
00453         typedef typename parent_t::integer_t integer_t;
00454 
00455         explicit packed_channel_reference( void* data_ptr ) : parent_t( data_ptr ) {}
00456         packed_channel_reference( const packed_channel_reference& ref ) : parent_t( ref._data_ptr ) {}
00457 
00458         const packed_channel_reference& operator=( integer_t value ) const              { assert( value <= parent_t::max_val ); set_unsafe( value ); return *this; }
00459         const packed_channel_reference& operator=( const mutable_reference& ref ) const { set_from_reference( ref.get_data() ); return *this; }
00460         const packed_channel_reference& operator=( const const_reference&   ref ) const { set_from_reference( ref.get_data() ); return *this; }
00461 
00462         template <bool Mutable1>
00463         const packed_channel_reference& operator=( const packed_dynamic_channel_reference<BitField, NumBits, Mutable1>& ref ) const { set_unsafe( ref.get() ); return *this; }
00464 
00465         unsigned first_bit() const { return FirstBit; }
00466 
00467         integer_t get()                               const { return integer_t( ( this->get_data() & channel_mask ) >> FirstBit ); }
00468         // CHH - Begin
00469         //void set_unsafe(integer_t value)              const { this->set_data((this->get_data() & ~channel_mask) | (value<<FirstBit)); }
00470         void set_unsafe( integer_t value )              const { this->set_data( ( this->get_data() & ~channel_mask ) | ( ( static_cast< BitField >( value ) << FirstBit ) ) ); }
00471         // CHH - End
00472 
00473 private:
00474         void set_from_reference( const BitField& other_bits ) const { this->set_data( ( this->get_data() & ~channel_mask ) | ( other_bits & channel_mask ) ); }
00475 };
00476 
00477 }
00478 }    // namespace boost::gil
00479 
00480 namespace std {
00481 // We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified.
00482 // swap with 'left bias':
00483 // - swap between proxy and anything
00484 // - swap between value type and proxy
00485 // - swap between proxy and proxy
00486 
00487 /// \ingroup PackedChannelReferenceModel
00488 /// \brief swap for packed_channel_reference
00489 template <typename BF, int FB, int NB, bool M, typename R>
00490 inline
00491 void swap( const boost::gil::packed_channel_reference<BF, FB, NB, M> x, R& y )
00492 {
00493         boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type>( x, y );
00494 }
00495 
00496 /// \ingroup PackedChannelReferenceModel
00497 /// \brief swap for packed_channel_reference
00498 template <typename BF, int FB, int NB, bool M>
00499 inline
00500 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 )
00501 {
00502         boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type>( x, y );
00503 }
00504 
00505 /// \ingroup PackedChannelReferenceModel
00506 /// \brief swap for packed_channel_reference
00507 template <typename BF, int FB, int NB, bool M>
00508 inline
00509 void swap( const boost::gil::packed_channel_reference<BF, FB, NB, M> x, const boost::gil::packed_channel_reference<BF, FB, NB, M> y )
00510 {
00511         boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type>( x, y );
00512 }
00513 
00514 }   // namespace std
00515 
00516 namespace boost {
00517 namespace gil {
00518 
00519 /**
00520    \defgroup PackedChannelDynamicReferenceModel packed_dynamic_channel_reference
00521    \ingroup ChannelModel
00522    \brief Represents a reference proxy to a channel operating over a bit range whose offset is specified at run time. Models ChannelConcept
00523 
00524    Example:
00525    \code
00526    // Reference to a 2-bit channel whose offset is specified at construction time
00527    typedef const packed_dynamic_channel_reference<uint8_t,2,true> bits2_dynamic_ref_t;
00528 
00529    uint16_t data=0;
00530    bits2_dynamic_ref_t channel_ref(&data,1);
00531    channel_ref = channel_traits<bits2_dynamic_ref_t>::max_value();     // == 3
00532    assert(data == 6);                                                  // == (3<<1) == 6
00533    \endcode
00534  */
00535 
00536 /// \brief Models a constant subbyte channel reference whose bit offset is a runtime parameter. Models ChannelConcept
00537 ///        Same as packed_channel_reference, except that the offset is a runtime parameter
00538 /// \ingroup PackedChannelDynamicReferenceModel
00539 template <typename BitField, int NumBits>
00540 class packed_dynamic_channel_reference<BitField, NumBits, false>
00541         : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField, NumBits, false>, BitField, NumBits, false>
00542 {
00543 typedef detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField, NumBits, false>, BitField, NumBits, false> parent_t;
00544 friend class packed_dynamic_channel_reference<BitField, NumBits, true>;
00545 
00546 unsigned _first_bit;         // 0..7
00547 
00548 void operator=( const packed_dynamic_channel_reference& );
00549 
00550 public:
00551         typedef const packed_dynamic_channel_reference<BitField, NumBits, false> const_reference;
00552         typedef const packed_dynamic_channel_reference<BitField, NumBits, true>  mutable_reference;
00553         typedef typename parent_t::integer_t integer_t;
00554 
00555         packed_dynamic_channel_reference( const void* data_ptr, unsigned first_bit ) : parent_t( data_ptr )
00556                 , _first_bit( first_bit ) {}
00557         packed_dynamic_channel_reference( const const_reference& ref ) : parent_t( ref._data_ptr )
00558                 , _first_bit( ref._first_bit ) {}
00559         packed_dynamic_channel_reference( const mutable_reference& ref ) : parent_t( ref._data_ptr )
00560                 , _first_bit( ref._first_bit ) {}
00561 
00562         unsigned first_bit() const { return _first_bit; }
00563 
00564         integer_t get() const
00565         {
00566                 const BitField channel_mask = parent_t::max_val << _first_bit;
00567 
00568                 // CHH - Begin
00569                 // remove notorious C4244
00570                 //return (this->get_data()&channel_mask) >> _first_bit;
00571                 return ( static_cast< integer_t >( this->get_data() & channel_mask ) >> _first_bit );
00572                 // CHH - End
00573         }
00574 
00575 };
00576 
00577 /// \brief Models a mutable subbyte channel reference whose bit offset is a runtime parameter. Models ChannelConcept
00578 ///        Same as packed_channel_reference, except that the offset is a runtime parameter
00579 /// \ingroup PackedChannelDynamicReferenceModel
00580 template <typename BitField, int NumBits>
00581 class packed_dynamic_channel_reference<BitField, NumBits, true>
00582         : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField, NumBits, true>, BitField, NumBits, true>
00583 {
00584 typedef detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField, NumBits, true>, BitField, NumBits, true> parent_t;
00585 friend class packed_dynamic_channel_reference<BitField, NumBits, false>;
00586 
00587 unsigned _first_bit;
00588 
00589 public:
00590         typedef const packed_dynamic_channel_reference<BitField, NumBits, false> const_reference;
00591         typedef const packed_dynamic_channel_reference<BitField, NumBits, true>  mutable_reference;
00592         typedef typename parent_t::integer_t integer_t;
00593 
00594         packed_dynamic_channel_reference( void* data_ptr, unsigned first_bit ) : parent_t( data_ptr )
00595                 , _first_bit( first_bit ) {}
00596         packed_dynamic_channel_reference( const packed_dynamic_channel_reference& ref ) : parent_t( ref._data_ptr )
00597                 , _first_bit( ref._first_bit ) {}
00598 
00599         const packed_dynamic_channel_reference& operator=( integer_t value ) const              { assert( value <= parent_t::max_val ); set_unsafe( value ); return *this; }
00600         const packed_dynamic_channel_reference& operator=( const mutable_reference& ref ) const {  set_unsafe( ref.get() ); return *this; }
00601         const packed_dynamic_channel_reference& operator=( const const_reference&   ref ) const {  set_unsafe( ref.get() ); return *this; }
00602 
00603         template <typename BitField1, int FirstBit1, bool Mutable1>
00604         const packed_dynamic_channel_reference& operator=( const packed_channel_reference<BitField1, FirstBit1, NumBits, Mutable1>& ref ) const
00605         {  set_unsafe( ref.get() ); return *this; }
00606 
00607         unsigned first_bit() const { return _first_bit; }
00608 
00609         integer_t get() const
00610         {
00611                 const BitField channel_mask = parent_t::max_val << _first_bit;
00612 
00613                 // CHH - Begin
00614                 // remove notorious C4244
00615                 //return (this->get_data()&channel_mask) >> _first_bit;
00616                 return ( static_cast< integer_t >( this->get_data() & channel_mask ) >> _first_bit );
00617                 // CHH - End
00618         }
00619 
00620         void set_unsafe( integer_t value ) const
00621         {
00622                 const BitField channel_mask = parent_t::max_val << _first_bit;
00623 
00624                 this->set_data( ( this->get_data() & ~channel_mask ) | value << _first_bit );
00625         }
00626 
00627 };
00628 }
00629 }    // namespace boost::gil
00630 
00631 namespace std {
00632 // We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified.
00633 // swap with 'left bias':
00634 // - swap between proxy and anything
00635 // - swap between value type and proxy
00636 // - swap between proxy and proxy
00637 
00638 /// \ingroup PackedChannelDynamicReferenceModel
00639 /// \brief swap for packed_dynamic_channel_reference
00640 template <typename BF, int NB, bool M, typename R>
00641 inline
00642 void swap( const boost::gil::packed_dynamic_channel_reference<BF, NB, M> x, R& y )
00643 {
00644         boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF, NB, M>::value_type>( x, y );
00645 }
00646 
00647 /// \ingroup PackedChannelDynamicReferenceModel
00648 /// \brief swap for packed_dynamic_channel_reference
00649 template <typename BF, int NB, bool M>
00650 inline
00651 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 )
00652 {
00653         boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF, NB, M>::value_type>( x, y );
00654 }
00655 
00656 /// \ingroup PackedChannelDynamicReferenceModel
00657 /// \brief swap for packed_dynamic_channel_reference
00658 template <typename BF, int NB, bool M>
00659 inline
00660 void swap( const boost::gil::packed_dynamic_channel_reference<BF, NB, M> x, const boost::gil::packed_dynamic_channel_reference<BF, NB, M> y )
00661 {
00662         boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF, NB, M>::value_type>( x, y );
00663 }
00664 
00665 }   // namespace std
00666 
00667 namespace boost {
00668 namespace gil {
00669 ///////////////////////////////////////////
00670 ////
00671 ////  Built-in channel models
00672 ////
00673 ///////////////////////////////////////////
00674 
00675 /// \defgroup bits8 bits8
00676 /// \ingroup ChannelModel
00677 /// \brief 8-bit unsigned integral channel type (typedef from uint8_t). Models ChannelValueConcept
00678 
00679 /// \ingroup bits8
00680 typedef uint8_t bits8;
00681 
00682 /// \defgroup bits16 bits16
00683 /// \ingroup ChannelModel
00684 /// \brief 16-bit unsigned integral channel type (typedef from uint16_t). Models ChannelValueConcept
00685 
00686 /// \ingroup bits16
00687 typedef uint16_t bits16;
00688 
00689 /// \defgroup bits32 bits32
00690 /// \ingroup ChannelModel
00691 /// \brief 32-bit unsigned integral channel type  (typedef from uint32_t). Models ChannelValueConcept
00692 
00693 /// \ingroup bits32
00694 typedef uint32_t bits32;
00695 
00696 /// \defgroup bits8s bits8s
00697 /// \ingroup ChannelModel
00698 /// \brief 8-bit signed integral channel type (typedef from int8_t). Models ChannelValueConcept
00699 
00700 /// \ingroup bits8s
00701 typedef int8_t bits8s;
00702 
00703 /// \defgroup bits16s bits16s
00704 /// \ingroup ChannelModel
00705 /// \brief 16-bit signed integral channel type (typedef from int16_t). Models ChannelValueConcept
00706 
00707 /// \ingroup bits16s
00708 typedef int16_t bits16s;
00709 
00710 /// \defgroup bits32s bits32s
00711 /// \ingroup ChannelModel
00712 /// \brief 32-bit signed integral channel type (typedef from int32_t). Models ChannelValueConcept
00713 
00714 /// \ingroup bits32s
00715 typedef int32_t bits32s;
00716 
00717 /// \defgroup bits32f bits32f
00718 /// \ingroup ChannelModel
00719 /// \brief 32-bit floating point channel type with range [0.0f ... 1.0f]. Models ChannelValueConcept
00720 
00721 /// \ingroup bits32f
00722 typedef scoped_channel_value<float, float_zero, float_one> bits32f;
00723 
00724 }
00725 }    // namespace boost::gil
00726 
00727 namespace boost {
00728 
00729 template <int NumBits>
00730 struct is_integral<gil::packed_channel_value<NumBits> > : public mpl::true_ {};
00731 
00732 template <typename BitField, int FirstBit, int NumBits, bool IsMutable>
00733 struct is_integral<gil::packed_channel_reference<BitField, FirstBit, NumBits, IsMutable> > : public mpl::true_ {};
00734 
00735 template <typename BitField, int NumBits, bool IsMutable>
00736 struct is_integral<gil::packed_dynamic_channel_reference<BitField, NumBits, IsMutable> > : public mpl::true_ {};
00737 
00738 template <typename BaseChannelValue, typename MinVal, typename MaxVal>
00739 struct is_integral<gil::scoped_channel_value<BaseChannelValue, MinVal, MaxVal> > : public is_integral<BaseChannelValue> {};
00740 
00741 }
00742 
00743 #endif