channel.hppGo 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://opensource.adobe.com/gil for most recent version including documentation. 00009 */ 00010 00011 /*************************************************************************************************/ 00012 00013 #ifndef GIL_CHANNEL_HPP 00014 #define GIL_CHANNEL_HPP 00015 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 { namespace gil { 00034 00035 00050 00051 namespace detail { 00052 template <typename T, bool is_class> struct channel_traits_impl; 00053 00054 // channel traits for custom class 00055 template <typename T> 00056 struct channel_traits_impl<T, true> { 00057 typedef typename T::value_type value_type; 00058 typedef typename T::reference reference; 00059 typedef typename T::pointer pointer; 00060 typedef typename T::const_reference const_reference; 00061 typedef typename T::const_pointer const_pointer; 00062 BOOST_STATIC_CONSTANT(bool, is_mutable=T::is_mutable); 00063 static value_type min_value() { return T::min_value(); } 00064 static value_type max_value() { return T::max_value(); } 00065 }; 00066 00067 // channel traits implementation for built-in integral or floating point channel type 00068 template <typename T> 00069 struct channel_traits_impl<T, false> { 00070 typedef T value_type; 00071 typedef T& reference; 00072 typedef T* pointer; 00073 typedef const T& const_reference; 00074 typedef T const* const_pointer; 00075 BOOST_STATIC_CONSTANT(bool, is_mutable=true); 00076 static value_type min_value() { return (std::numeric_limits<T>::min)(); } 00077 static value_type max_value() { return (std::numeric_limits<T>::max)(); } 00078 }; 00079 00080 // channel traits implementation for constant built-in scalar or floating point type 00081 template <typename T> 00082 struct channel_traits_impl<const T, false> : public channel_traits_impl<T, false> { 00083 typedef const T& reference; 00084 typedef const T* pointer; 00085 BOOST_STATIC_CONSTANT(bool, is_mutable=false); 00086 }; 00087 } 00088 00107 template <typename T> 00108 struct channel_traits : public detail::channel_traits_impl<T, is_class<T>::value> {}; 00109 00110 // Channel traits for C++ reference type - remove the reference 00111 template <typename T> struct channel_traits< T&> : public channel_traits<T> {}; 00112 00113 // Channel traits for constant C++ reference type 00114 template <typename T> struct channel_traits<const T&> : public channel_traits<T> { 00115 typedef typename channel_traits<T>::const_reference reference; 00116 typedef typename channel_traits<T>::const_pointer pointer; 00117 BOOST_STATIC_CONSTANT(bool, is_mutable=false); 00118 }; 00119 00125 00146 00147 00148 template <typename BaseChannelValue, // base channel (models ChannelValueConcept) 00149 typename MinVal, typename MaxVal> // classes with a static apply() function returning the minimum/maximum channel values 00150 struct scoped_channel_value { 00151 typedef scoped_channel_value value_type; 00152 typedef value_type& reference; 00153 typedef value_type* pointer; 00154 typedef const value_type& const_reference; 00155 typedef const value_type* const_pointer; 00156 BOOST_STATIC_CONSTANT(bool, is_mutable=channel_traits<BaseChannelValue>::is_mutable); 00157 00158 static value_type min_value() { return MinVal::apply(); } 00159 static value_type max_value() { return MaxVal::apply(); } 00160 00161 scoped_channel_value() {} 00162 scoped_channel_value(const scoped_channel_value& c) : _value(c._value) {} 00163 scoped_channel_value(BaseChannelValue val) : _value(val) {} 00164 00165 scoped_channel_value& operator++() { ++_value; return *this; } 00166 scoped_channel_value& operator--() { --_value; return *this; } 00167 00168 scoped_channel_value operator++(int) { scoped_channel_value tmp=*this; this->operator++(); return tmp; } 00169 scoped_channel_value operator--(int) { scoped_channel_value tmp=*this; this->operator--(); return tmp; } 00170 00171 template <typename Scalar2> scoped_channel_value& operator+=(Scalar2 v) { _value+=v; return *this; } 00172 template <typename Scalar2> scoped_channel_value& operator-=(Scalar2 v) { _value-=v; return *this; } 00173 template <typename Scalar2> scoped_channel_value& operator*=(Scalar2 v) { _value*=v; return *this; } 00174 template <typename Scalar2> scoped_channel_value& operator/=(Scalar2 v) { _value/=v; return *this; } 00175 00176 scoped_channel_value& operator=(BaseChannelValue v) { _value=v; return *this; } 00177 operator BaseChannelValue() const { return _value; } 00178 private: 00179 BaseChannelValue _value; 00180 }; 00181 00182 struct float_zero { static float apply() { return 0.0f; } }; 00183 struct float_one { static float apply() { return 1.0f; } }; 00184 00185 00191 00192 // 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: 00193 // - Any operation that requires returning the result by value will otherwise return the built-in integral type, which will have incorrect range 00194 // That means that after getting the value of the channel we cannot properly do channel_convert, channel_invert, etc. 00195 // - 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 00196 namespace detail { 00197 // returns the smallest fast unsigned integral type that has at least NumBits bits 00198 template <int NumBits> 00199 struct min_fast_uint : public mpl::if_c< (NumBits<=8), 00200 uint_least8_t, 00201 typename mpl::if_c< (NumBits<=16), 00202 uint_least16_t, 00203 typename mpl::if_c< (NumBits<=32), 00204 uint_least32_t, 00205 uintmax_t 00206 >::type 00207 >::type 00208 > {}; 00209 } 00210 00227 00228 00229 template <int NumBits> 00230 class packed_channel_value { 00231 static const std::size_t num_values = 1<<NumBits; 00232 public: 00233 typedef typename detail::min_fast_uint<NumBits>::type integer_t; 00234 00235 typedef packed_channel_value value_type; 00236 typedef value_type& reference; 00237 typedef const value_type& const_reference; 00238 typedef value_type* pointer; 00239 typedef const value_type* const_pointer; 00240 00241 static value_type min_value() { return value_type(0); } 00242 static value_type max_value() { return value_type(num_values-1); } 00243 BOOST_STATIC_CONSTANT(bool, is_mutable=true); 00244 00245 packed_channel_value() {} 00246 packed_channel_value(integer_t v) : _value(v % num_values) {} 00247 packed_channel_value(const packed_channel_value& v) : _value(v._value) {} 00248 template <typename Scalar> packed_channel_value(Scalar v) : _value(integer_t(v) % num_values) {} // suppress GCC implicit conversion warnings in channel regression file 00249 00250 operator integer_t() const { return _value; } 00251 private: 00252 integer_t _value; 00253 }; 00254 00255 namespace detail { 00256 template <typename Derived, typename BitField, int NumBits, bool Mutable> 00257 class packed_channel_reference_base { 00258 protected: 00259 typedef typename mpl::if_c<Mutable,void*,const void*>::type data_ptr_t; 00260 public: 00261 data_ptr_t _data_ptr; // void* pointer to the first byte of the bit range 00262 00263 typedef packed_channel_value<NumBits> value_type; 00264 typedef const Derived reference; 00265 typedef value_type* pointer; 00266 typedef const value_type* const_pointer; 00267 BOOST_STATIC_CONSTANT(int, num_bits=NumBits); 00268 BOOST_STATIC_CONSTANT(bool, is_mutable=Mutable); 00269 00270 static value_type min_value() { return channel_traits<value_type>::min_value(); } 00271 static value_type max_value() { return channel_traits<value_type>::max_value(); } 00272 00273 typedef BitField bitfield_t; 00274 typedef typename value_type::integer_t integer_t; 00275 00276 packed_channel_reference_base(data_ptr_t data_ptr) : _data_ptr(data_ptr) {} 00277 packed_channel_reference_base(const packed_channel_reference_base& ref) : _data_ptr(ref._data_ptr) {} 00278 const Derived& operator=(integer_t v) const { set(v); return derived(); } 00279 00280 const Derived& operator++() const { set(get()+1); return derived(); } 00281 const Derived& operator--() const { set(get()-1); return derived(); } 00282 00283 Derived operator++(int) const { Derived tmp=derived(); this->operator++(); return tmp; } 00284 Derived operator--(int) const { Derived tmp=derived(); this->operator--(); return tmp; } 00285 00286 template <typename Scalar2> const Derived& operator+=(Scalar2 v) const { set(get()+v); return derived(); } 00287 template <typename Scalar2> const Derived& operator-=(Scalar2 v) const { set(get()-v); return derived(); } 00288 template <typename Scalar2> const Derived& operator*=(Scalar2 v) const { set(get()*v); return derived(); } 00289 template <typename Scalar2> const Derived& operator/=(Scalar2 v) const { set(get()/v); return derived(); } 00290 00291 operator integer_t() const { return get(); } 00292 data_ptr_t operator &() const {return _data_ptr;} 00293 protected: 00294 static const integer_t max_val = (1<<NumBits) - 1; 00295 const bitfield_t& const_data() const { return *static_cast<const bitfield_t*>(_data_ptr); } 00296 bitfield_t& data() const { return *static_cast< bitfield_t*>(_data_ptr); } 00297 private: 00298 void set(integer_t value) const { // can this be done faster?? 00299 const integer_t num_values = max_val+1; 00300 this->derived().set_unsafe(((value % num_values) + num_values) % num_values); 00301 } 00302 integer_t get() const { return derived().get(); } 00303 const Derived& derived() const { return static_cast<const Derived&>(*this); } 00304 }; 00305 } // namespace detail 00306 00323 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 00324 int FirstBit, int NumBits,// Defines the sequence of bits in the data value that contain the channel 00325 bool Mutable> // true if the reference is mutable 00326 class packed_channel_reference; 00327 00328 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 00329 int NumBits, // Defines the sequence of bits in the data value that contain the channel 00330 bool Mutable> // true if the reference is mutable 00331 class packed_dynamic_channel_reference; 00332 00335 template <typename BitField, int FirstBit, int NumBits> 00336 class packed_channel_reference<BitField,FirstBit,NumBits,false> 00337 : public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false> { 00338 typedef detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false> parent_t; 00339 friend class packed_channel_reference<BitField,FirstBit,NumBits,true>; 00340 00341 static const BitField channel_mask = parent_t::max_val<<FirstBit; 00342 void operator=(const packed_channel_reference&); 00343 public: 00344 typedef const packed_channel_reference<BitField,FirstBit,NumBits,false> const_reference; 00345 typedef const packed_channel_reference<BitField,FirstBit,NumBits,true> mutable_reference; 00346 typedef typename parent_t::integer_t integer_t; 00347 00348 explicit packed_channel_reference(const void* data_ptr) : parent_t(data_ptr) {} 00349 packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {} 00350 packed_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr) {} 00351 00352 unsigned first_bit() const { return FirstBit; } 00353 00354 integer_t get() const { return integer_t((this->const_data()&channel_mask) >> FirstBit); } 00355 }; 00356 00359 template <typename BitField, int FirstBit, int NumBits> 00360 class packed_channel_reference<BitField,FirstBit,NumBits,true> 00361 : public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true> { 00362 typedef detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,true>,BitField,NumBits,true> parent_t; 00363 friend class packed_channel_reference<BitField,FirstBit,NumBits,false>; 00364 00365 static const BitField channel_mask = parent_t::max_val<<FirstBit; 00366 public: 00367 typedef const packed_channel_reference<BitField,FirstBit,NumBits,false> const_reference; 00368 typedef const packed_channel_reference<BitField,FirstBit,NumBits,true> mutable_reference; 00369 typedef typename parent_t::integer_t integer_t; 00370 00371 explicit packed_channel_reference(void* data_ptr) : parent_t(data_ptr) {} 00372 packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {} 00373 00374 const packed_channel_reference& operator=(integer_t value) const { assert(value<=parent_t::max_val); set_unsafe(value); return *this; } 00375 const packed_channel_reference& operator=(const mutable_reference& ref) const { set_from_reference(ref.data()); return *this; } 00376 const packed_channel_reference& operator=(const const_reference& ref) const { set_from_reference(ref.const_data()); return *this; } 00377 00378 template <bool Mutable1> 00379 const packed_channel_reference& operator=(const packed_dynamic_channel_reference<BitField,NumBits,Mutable1>& ref) const { set_unsafe(ref.get()); return *this; } 00380 00381 unsigned first_bit() const { return FirstBit; } 00382 00383 integer_t get() const { return integer_t((this->const_data()&channel_mask) >> FirstBit); } 00384 void set_unsafe(integer_t value) const { this->data() = (this->const_data() & ~channel_mask) | (value<<FirstBit); } 00385 private: 00386 void set_from_reference(const BitField& other_bits) const { this->data() = (this->const_data() & ~channel_mask) | (other_bits & channel_mask); } 00387 }; 00388 00389 } } // namespace boost::gil 00390 00391 namespace std { 00392 // We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified. 00393 // swap with 'left bias': 00394 // - swap between proxy and anything 00395 // - swap between value type and proxy 00396 // - swap between proxy and proxy 00397 00400 template <typename BF, int FB, int NB, bool M, typename R> inline 00401 void swap(boost::gil::packed_channel_reference<BF,FB,NB,M> x, R& y) { 00402 boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y); 00403 } 00404 00405 00408 template <typename BF, int FB, int NB, bool M> inline 00409 void swap(typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type& x, boost::gil::packed_channel_reference<BF,FB,NB,M> y) { 00410 boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y); 00411 } 00412 00413 00416 template <typename BF, int FB, int NB, bool M> inline 00417 void swap(boost::gil::packed_channel_reference<BF,FB,NB,M> x, boost::gil::packed_channel_reference<BF,FB,NB,M> y) { 00418 boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y); 00419 } 00420 } // namespace std 00421 00422 namespace boost { namespace gil { 00423 00441 00442 00443 00444 template <typename BitField, int NumBits> 00445 class packed_dynamic_channel_reference<BitField,NumBits,false> 00446 : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false> { 00447 typedef detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,false>,BitField,NumBits,false> parent_t; 00448 friend class packed_dynamic_channel_reference<BitField,NumBits,true>; 00449 00450 unsigned _first_bit; // 0..7 00451 00452 void operator=(const packed_dynamic_channel_reference&); 00453 public: 00454 typedef const packed_dynamic_channel_reference<BitField,NumBits,false> const_reference; 00455 typedef const packed_dynamic_channel_reference<BitField,NumBits,true> mutable_reference; 00456 typedef typename parent_t::integer_t integer_t; 00457 00458 packed_dynamic_channel_reference(const void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {} 00459 packed_dynamic_channel_reference(const const_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {} 00460 packed_dynamic_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {} 00461 00462 unsigned first_bit() const { return _first_bit; } 00463 00464 integer_t get() const { 00465 const BitField channel_mask = parent_t::max_val<<_first_bit; 00466 return (this->const_data()&channel_mask) >> _first_bit; 00467 } 00468 }; 00469 00473 template <typename BitField, int NumBits> 00474 class packed_dynamic_channel_reference<BitField,NumBits,true> 00475 : public detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,true> { 00476 typedef detail::packed_channel_reference_base<packed_dynamic_channel_reference<BitField,NumBits,true>,BitField,NumBits,true> parent_t; 00477 friend class packed_dynamic_channel_reference<BitField,NumBits,false>; 00478 00479 unsigned _first_bit; 00480 00481 public: 00482 typedef const packed_dynamic_channel_reference<BitField,NumBits,false> const_reference; 00483 typedef const packed_dynamic_channel_reference<BitField,NumBits,true> mutable_reference; 00484 typedef typename parent_t::integer_t integer_t; 00485 00486 packed_dynamic_channel_reference(void* data_ptr, unsigned first_bit) : parent_t((((char*)data_ptr)+first_bit/8)), _first_bit(first_bit%8) {} 00487 packed_dynamic_channel_reference(const packed_dynamic_channel_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {} 00488 00489 const packed_dynamic_channel_reference& operator=(integer_t value) const { assert(value<=parent_t::max_val); set_unsafe(value); return *this; } 00490 const packed_dynamic_channel_reference& operator=(const mutable_reference& ref) const { set_unsafe(ref.get()); return *this; } 00491 const packed_dynamic_channel_reference& operator=(const const_reference& ref) const { set_unsafe(ref.get()); return *this; } 00492 00493 template <typename BitField1, int FirstBit1, bool Mutable1> 00494 const packed_dynamic_channel_reference& operator=(const packed_channel_reference<BitField1, FirstBit1, NumBits, Mutable1>& ref) const 00495 { set_unsafe(ref.get()); return *this; } 00496 00497 unsigned first_bit() const { return _first_bit; } 00498 00499 integer_t get() const { 00500 const BitField channel_mask = parent_t::max_val<<_first_bit; 00501 return (this->const_data()&channel_mask) >> _first_bit; 00502 } 00503 void set_unsafe(integer_t value) const { 00504 const BitField channel_mask = parent_t::max_val<<_first_bit; 00505 this->data() = (this->const_data() & ~channel_mask) | value<<_first_bit; 00506 } 00507 }; 00508 } } // namespace boost::gil 00509 00510 namespace std { 00511 // We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified. 00512 // swap with 'left bias': 00513 // - swap between proxy and anything 00514 // - swap between value type and proxy 00515 // - swap between proxy and proxy 00516 00517 00520 template <typename BF, int NB, bool M, typename R> inline 00521 void swap(boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, R& y) { 00522 boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y); 00523 } 00524 00525 00528 template <typename BF, int NB, bool M> inline 00529 void swap(typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type& x, boost::gil::packed_dynamic_channel_reference<BF,NB,M> y) { 00530 boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y); 00531 } 00532 00533 00536 template <typename BF, int NB, bool M> inline 00537 void swap(boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, boost::gil::packed_dynamic_channel_reference<BF,NB,M> y) { 00538 boost::gil::swap_proxy<typename boost::gil::packed_dynamic_channel_reference<BF,NB,M>::value_type>(x,y); 00539 } 00540 } // namespace std 00541 00542 namespace boost { namespace gil { 00548 00552 00554 typedef uint8_t bits8; 00555 00559 00561 typedef uint16_t bits16; 00562 00566 00568 typedef uint32_t bits32; 00569 00573 00575 typedef int8_t bits8s; 00576 00580 00582 typedef int16_t bits16s; 00583 00587 00589 typedef int32_t bits32s; 00590 00594 00596 typedef scoped_channel_value<float,float_zero,float_one> bits32f; 00597 00598 } } // namespace boost::gil 00599 00600 namespace boost { 00601 00602 template <int NumBits> 00603 struct is_integral<gil::packed_channel_value<NumBits> > : public mpl::true_ {}; 00604 00605 template <typename BitField, int FirstBit, int NumBits, bool IsMutable> 00606 struct is_integral<gil::packed_channel_reference<BitField,FirstBit,NumBits,IsMutable> > : public mpl::true_ {}; 00607 00608 template <typename BitField, int NumBits, bool IsMutable> 00609 struct is_integral<gil::packed_dynamic_channel_reference<BitField,NumBits,IsMutable> > : public mpl::true_ {}; 00610 00611 template <typename BaseChannelValue, typename MinVal, typename MaxVal> 00612 struct is_integral<gil::scoped_channel_value<BaseChannelValue,MinVal,MaxVal> > : public is_integral<BaseChannelValue> {}; 00613 00614 } 00615 00616 #endif Generated on Thu Nov 8 21:53:16 2007 for Generic Image Library by 1.4.4 |