00001
00002
00003
00004
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
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
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
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
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
00125
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;
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>
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;
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; }
00286 int x_pos() const { return _x; }
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; }
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;
00323 point_t delta;
00324 if (_x+d>=0) {
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);
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());
00346 return _p==it._p;
00347 }
00348
00349 int _x,_width;
00350 LOC2 _p;
00351 };
00352
00355
00363
00364 template <typename IT,
00365 typename D_FN>
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;
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
00393
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