TuttleOFX
1
|
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