Adobe Systems, Inc.

pixel_iterator.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2006 Adobe Systems Incorporated
00003     Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
00004     or a copy at http://opensource.adobe.com/licenses.html)
00005 */
00006 
00007 /*************************************************************************************************/
00008 
00009 #ifndef GIL_PIXEL_ITERATOR_H
00010 #define GIL_PIXEL_ITERATOR_H
00011 
00020 
00021 #include <cassert>
00022 #include <cstddef>
00023 #include <iterator>
00024 #include "gil_config.hpp"
00025 #include "gil_concept.hpp"
00026 #include "pixel.hpp"
00027 #include "planar_ptr.hpp"
00028 #include "locator.hpp"
00029 #include "pixel_iterator_traits.hpp"
00030 
00031 ADOBE_GIL_NAMESPACE_BEGIN
00032 
00035 template <typename IC, typename C> struct planar_ptr;
00036 namespace detail {template <typename T, typename C> struct color_base;}
00037 
00038 
00047 
00049 //  Byte step
00051 
00053 template <typename P>
00054 inline std::ptrdiff_t byte_step(const P*) { return sizeof(P); }
00055 
00057 template <typename IC, typename C>
00058 inline std::ptrdiff_t byte_step(const planar_ptr<IC,C>&) { return sizeof(typename std::iterator_traits<IC>::value_type); }
00059 
00060 
00062 //  byte_distance
00064 
00066 template <typename P>
00067 inline std::ptrdiff_t byte_distance(const P* p1, const P* p2) { 
00068     return (reinterpret_cast<const unsigned char*>(p2)-reinterpret_cast<const unsigned char*>(p1)); 
00069 }
00070 
00072 template <typename IC, typename C>
00073 inline std::ptrdiff_t byte_distance(const planar_ptr<IC,C>& p1, const planar_ptr<IC,C>& p2) { 
00074     return byte_distance(p1.template channel<0>(),p2.template channel<0>()); 
00075 }
00076 
00078 //  byte_advance
00080 
00081 template <typename P> P* byte_advanced(const P* p, std::ptrdiff_t byteDiff);
00082 
00084 template <typename P>
00085 inline void byte_advance(P* &p, std::ptrdiff_t byteDiff) { 
00086     p=(P*)((unsigned char*)(p)+byteDiff);
00087 }
00088 
00090 template <typename IC>
00091 struct byte_advance_fn {
00092     byte_advance_fn(std::ptrdiff_t byte_diff) : _byte_diff(byte_diff) {}
00093     IC operator()(const IC& p) const { return byte_advanced(p,_byte_diff); }
00094 
00095     std::ptrdiff_t _byte_diff;
00096 };
00097 
00099 template <typename IC, typename C>
00100 inline void byte_advance(planar_ptr<IC,C>& p, std::ptrdiff_t byte_diff) { 
00101     transform_channels(p, p, byte_advance_fn<IC>(byte_diff));
00102 }
00103 
00105 //  byte_advanced
00107 
00109 template <typename P>
00110 inline P* byte_advanced(const P* p, std::ptrdiff_t byteDiff) {
00111     return (P*)((unsigned char*)(p)+byteDiff);
00112 }
00113 
00115 template <typename IC, typename C>
00116 inline planar_ptr<IC,C> byte_advanced(const planar_ptr<IC,C>& p, std::ptrdiff_t byteDiff) {
00117     planar_ptr<IC,C> ret=p;
00118     byte_advance(ret, byteDiff);
00119     return ret;
00120 }
00121 
00122 
00124 //  byte_advanced_ref
00125 //  (shortcut to advancing a pointer by a given number of bytes and taking the reference in case the compiler is not smart enough)
00127 
00128 
00130 template <typename P>
00131 inline P& byte_advanced_ref(P* p, std::ptrdiff_t byteDiff) {
00132     return *byte_advanced(p,byteDiff);
00133 }
00134 
00135 template <typename I> class pixel_step_iterator;
00136 
00140 
00159 
00162 template <typename IT>
00163 struct byte_step_fn {
00164     typedef std::ptrdiff_t difference_type;
00165 
00166     byte_step_fn(difference_type step=byte_step(IT())) : _step(step) {}
00167 
00168     difference_type difference(const IT& it1, const IT& it2) const { return byte_distance(it1,it2)/_step; }
00169     void            advance(IT& it, difference_type d)       const { byte_advance(it,d*_step); } 
00170     difference_type step()                                   const { return _step; }
00171 
00172     void            set_step(std::ptrdiff_t step) { _step=step; }
00173 private:
00174     GIL_CLASS_REQUIRE(IT, GIL, ByteAdvancableIteratorConcept);
00175     difference_type _step;
00176 };
00177 
00178 template <typename IT>
00179 class pixel_step_iterator : public adobe::step_iterator_adaptor<pixel_step_iterator<IT>, IT, byte_step_fn<IT> > {
00180     GIL_CLASS_REQUIRE(IT, GIL, ByteAdvancableIteratorConcept);
00181     GIL_CLASS_REQUIRE(IT, GIL, PixelIteratorConcept);
00182 public:
00183     typedef adobe::step_iterator_adaptor<pixel_step_iterator<IT>, IT, byte_step_fn<IT> > parent_t;
00184     typedef std::random_access_iterator_tag                   iterator_category;    // TODO: Fix that!
00185     typedef typename parent_t::reference                      reference;
00186     typedef typename parent_t::difference_type                difference_type;
00187     typedef typename pixel_iterator_traits<IT>::channel_t     channel_t;
00188     typedef typename pixel_iterator_traits<IT>::color_space_t color_space_t;
00189     typedef IT                                                x_iterator;
00190 
00191     pixel_step_iterator() : parent_t(IT()) {}
00192     pixel_step_iterator(IT it, std::ptrdiff_t byte_step) : parent_t(it, byte_step_fn<IT>(byte_step)) {}
00193     template <typename I2> pixel_step_iterator(const pixel_step_iterator<I2>& it)
00194         : parent_t(it.base(), byte_step_fn<IT>(it.step())) {}
00195 
00198     reference operator[](difference_type d) const { return *(*this+d); }
00199 
00200     void set_step(std::ptrdiff_t byte_step) { this->_step_fn.set_step(byte_step); }
00201 
00202     x_iterator& base()              { return parent_t::base_reference(); }
00203     x_iterator const& base() const  { return parent_t::base_reference(); }
00204 };
00205 
00206 
00207 
00211 
00213 template <typename IT>
00214 inline std::ptrdiff_t byte_step(const pixel_step_iterator<IT>& p) { return p.step(); }
00215 
00217 template <typename IT>
00218 inline std::ptrdiff_t byte_distance(const pixel_step_iterator<IT>& p1, const pixel_step_iterator<IT>& p2) { 
00219     return byte_distance(p1.base(),p2.base()); 
00220 }
00221 
00223 template <typename IT>
00224 inline void byte_advance(pixel_step_iterator<IT>& p, std::ptrdiff_t byteDiff) { 
00225     byte_advance(p.base(), byteDiff);
00226 }
00227 
00229 template <typename IT>
00230 inline pixel_step_iterator<IT> byte_advanced(const pixel_step_iterator<IT>& p, std::ptrdiff_t byteDiff) {
00231     return pixel_step_iterator<IT>(byte_advanced(p.base(), byteDiff),p.step());
00232 }
00233 
00234 
00236 template <typename IT>
00237 inline typename std::iterator_traits<IT>::reference byte_advanced_ref(const pixel_step_iterator<IT>& p, std::ptrdiff_t byteDiff) { 
00238     return byte_advanced_ref(p.base(), byteDiff);
00239 }
00240 
00241 template <typename IT> 
00242 struct iterator_is_step<pixel_step_iterator<IT> > {
00243     static const bool value = true; 
00244 };
00245 
00251 
00252 
00264 
00265 template <typename LOC2>    // Models PixelLocatorConcept
00266 class pixel_image_iterator : public boost::iterator_facade<pixel_image_iterator<LOC2>,
00267                                                            typename LOC2::value_type,
00268                                                            boost::random_access_traversal_tag,
00269                                                            typename LOC2::reference,
00270                                                            typename LOC2::coord_t> {
00271     GIL_CLASS_REQUIRE(LOC2, GIL, PixelLocatorConcept);
00272 public:
00273     typedef boost::iterator_facade<pixel_image_iterator<LOC2>,
00274                                    typename LOC2::value_type,
00275                                    boost::random_access_traversal_tag,
00276                                    typename LOC2::reference,
00277                                    typename LOC2::coord_t> parent_t;
00278     typedef std::random_access_iterator_tag    iterator_category;   // TODO: Fix that!
00279     typedef typename parent_t::reference       reference;
00280     typedef typename parent_t::difference_type difference_type;
00281     typedef typename LOC2::x_iterator          x_iterator;
00282     typedef typename LOC2::point_t             point_t;
00283     typedef typename LOC2::pixel_t             pixel_t;
00284 
00285     int width()         const { return _width; }            // number of pixels per image row
00286     int x_pos()         const { return _x; }                // current x position
00287 
00290     reference operator[](difference_type d) const { return *(*this+d); }
00291 
00292     bool            is_contiguous() const { return _p.row_bytes()-_p.pix_bytestep()*width()==0; }   // is there no gap at the end of each row?
00293     x_iterator&     x()                   { return _p.x(); }
00294 
00295     pixel_image_iterator(){}
00296     pixel_image_iterator(const LOC2& p, int width, int x=0) : _x(x), _width(width), _p(p) {}
00297     pixel_image_iterator(const pixel_image_iterator& pit) : _x(pit._x), _width(pit._width), _p(pit._p) {}
00298     template <typename LOC> pixel_image_iterator(const pixel_image_iterator<LOC>& pit) : _x(pit._x), _width(pit._width), _p(pit._p) {}
00299 
00300 private:
00301     template <typename LOC> friend class pixel_image_iterator;
00302     friend class boost::iterator_core_access;
00303     reference dereference() const { return *_p; }
00304     void increment() {
00305         ++_x;
00306         ++_p.x();
00307         if (_x>=_width) {
00308             _x=0;
00309             _p+=point_t(-_width,1);
00310         }           
00311     }
00312     void decrement() {
00313         --_x;
00314         --_p.x();
00315         if (_x<0) {
00316             _x=_width-1;
00317             _p+=point_t(_width,-1);
00318         }
00319     }
00320 
00321     GIL_FORCEINLINE void advance(difference_type d) {  
00322         if (_width==0) return;  // unfortunately we need to check for that. Default-constructed images have width of 0 and the code below will throw if executed.
00323         point_t delta;
00324         if (_x+d>=0) {  // not going back to a previous row?
00325             delta.x=(_x+(int)d)%_width - _x;
00326             delta.y=(_x+(int)d)/_width;
00327         } else {
00328             delta.x=(_x+(int)d*(1-_width))%_width -_x;
00329             delta.y=-(_width-_x-(int)d-1)/_width;
00330         }   
00331         _p+=delta;
00332         _x+=delta.x;
00333     }
00334 
00335     difference_type distance_to(const pixel_image_iterator& it) const { 
00336         if (_width==0) return 0;
00337         std::ptrdiff_t xByteDiff=_p.pix_bytestep()*(it.x_pos()-_x);      // distance to align the x coordinate
00338         std::ptrdiff_t rowDiff=byte_distance(_p.x(),it._p.x())-xByteDiff;
00339         assert(( rowDiff % _p.row_bytes())==0);
00340         std::ptrdiff_t rows=rowDiff / _p.row_bytes();
00341         return rows*_width+it.x_pos()-_x;
00342     }
00343 
00344     bool equal(const pixel_image_iterator& it) const {
00345         assert(_width==it.width());     // they must belong to the same image
00346         return _p==it._p;
00347     }
00348 
00349     int _x,_width;
00350     LOC2 _p;
00351 };
00352 
00355 //                  DEREFERENCE ITERATOR ADAPTOR
00363 
00364 template <typename IT,    // Models Iterator
00365           typename D_FN>  // Models Unary Function. Returns the result of dereferencing a given iterator of type IT
00366 class dereference_iterator_adaptor : public boost::iterator_adaptor<dereference_iterator_adaptor<IT,D_FN>,
00367                                                                     IT,
00368                                                                     boost::use_default,
00369                                                                     boost::use_default,
00370                                                                     typename D_FN::result_type,
00371                                                                     boost::use_default> {
00372     D_FN _deref_fn;
00373 public:
00374     typedef boost::iterator_adaptor<dereference_iterator_adaptor<IT,D_FN>,
00375                                     IT,
00376                                     boost::use_default,
00377                                     boost::use_default,
00378                                     typename D_FN::result_type,
00379                                     boost::use_default> parent_t;
00380     typedef typename D_FN::result_type                         reference;
00381     typedef typename std::iterator_traits<IT>::difference_type difference_type;
00382     typedef std::random_access_iterator_tag                    iterator_category;   // TODO: Fix that!
00383     typedef D_FN                                               dereference_fn;
00384 
00385     dereference_iterator_adaptor() {}
00386     dereference_iterator_adaptor(IT it, D_FN deref_fn=D_FN()) : parent_t(it), _deref_fn(deref_fn) {}
00387     template <typename IT1, typename DFN1> dereference_iterator_adaptor(const dereference_iterator_adaptor<IT1,DFN1>& it) : parent_t(it.base()), _deref_fn(it._deref_fn) {}
00390     reference operator[](difference_type d) const { return *(*this+d);}
00391 
00392     // although boost::iterator_adaptor defines these, the default implementation computes distance and compares for zero.
00393     // it is often faster to just apply the relation operator to the base
00394     bool    operator> (const dereference_iterator_adaptor& p) const { return this->base_reference()> p.base_reference(); }
00395     bool    operator< (const dereference_iterator_adaptor& p) const { return this->base_reference()< p.base_reference(); }
00396     bool    operator>=(const dereference_iterator_adaptor& p) const { return this->base_reference()>=p.base_reference(); }
00397     bool    operator<=(const dereference_iterator_adaptor& p) const { return this->base_reference()<=p.base_reference(); }
00398     bool    operator==(const dereference_iterator_adaptor& p) const { return this->base_reference()==p.base_reference(); }
00399     bool    operator!=(const dereference_iterator_adaptor& p) const { return this->base_reference()!=p.base_reference(); }
00400 
00401     IT& base()              { return this->base_reference(); }
00402     const IT& base() const  { return this->base_reference(); }
00403 private:
00404     template <typename IT1, typename DFN1> friend class dereference_iterator_adaptor;
00405     friend class boost::iterator_core_access;
00406 
00407     reference dereference() const { return _deref_fn(this->base_reference()); }
00408 };
00409 
00411 template <typename IT, typename D_FN>
00412 inline typename std::iterator_traits<IT>::difference_type byte_step(const dereference_iterator_adaptor<IT,D_FN>& p) { 
00413     return byte_step(p.base());
00414 }
00415 
00417 template <typename IT, typename D_FN>
00418 inline typename std::iterator_traits<IT>::difference_type byte_distance(const dereference_iterator_adaptor<IT,D_FN>& p1, const dereference_iterator_adaptor<IT,D_FN>& p2) { 
00419     return byte_distance(p1.base(),p2.base()); 
00420 }
00421 
00423 template <typename IT, typename D_FN>
00424 inline void byte_advance(dereference_iterator_adaptor<IT,D_FN>& p, typename std::iterator_traits<IT>::difference_type byteDiff) { 
00425     byte_advance(p.base(), byteDiff);
00426 }
00427 
00429 template <typename IT, typename D_FN>
00430 inline dereference_iterator_adaptor<IT,D_FN> byte_advanced(dereference_iterator_adaptor<IT,D_FN>& p, typename std::iterator_traits<IT>::difference_type byteDiff) {
00431     return dereference_iterator_adaptor<IT,D_FN>(byte_advanced(p.base(), byteDiff));
00432 }
00433 
00435 template <typename IT, typename D_FN>
00436 inline dereference_iterator_adaptor<IT,D_FN> byte_advanced(const dereference_iterator_adaptor<IT,D_FN>& p, typename std::iterator_traits<IT>::difference_type byteDiff) { 
00437     return dereference_iterator_adaptor<IT,D_FN>(byte_advanced(p.base(), byteDiff)); 
00438 }
00439 
00441 template <typename IT, typename D_FN>
00442 inline typename std::iterator_traits<dereference_iterator_adaptor<IT,D_FN> >::reference byte_advanced_ref(const dereference_iterator_adaptor<IT,D_FN>& p, typename std::iterator_traits<IT>::difference_type byteDiff) { 
00443     return *byte_advanced(p, byteDiff);
00444 }
00446 
00447 template <typename I, typename D_FN> 
00448 struct iterator_is_step<dereference_iterator_adaptor<I,D_FN> > {
00449     static const bool value = iterator_is_step<I>::value; 
00450 };
00451 
00452 
00453 ADOBE_GIL_NAMESPACE_END
00454 
00455 #endif

Copyright © 2006 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google