iterator_from_2d.hpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. Copyright 2005-2007 Adobe Systems Incorporated
  3. Use, modification and distribution are subject to the Boost Software License,
  4. Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. See http://opensource.adobe.com/gil for most recent version including documentation.
  7. */
  8. /*************************************************************************************************/
  9. #ifndef GIL_ITERATOR_FROM_2D_H
  10. #define GIL_ITERATOR_FROM_2D_H
  11. ////////////////////////////////////////////////////////////////////////////////////////
  12. /// \file
  13. /// \brief pixel step iterator, pixel image iterator and pixel dereference iterator
  14. /// \author Lubomir Bourdev and Hailin Jin \n
  15. /// Adobe Systems Incorporated
  16. /// \date 2005-2007 \n Last updated on September 18, 2007
  17. ///
  18. ////////////////////////////////////////////////////////////////////////////////////////
  19. #include <cassert>
  20. #include <boost/iterator/iterator_facade.hpp>
  21. #include "gil_concept.hpp"
  22. #include "gil_config.hpp"
  23. #include "pixel_iterator.hpp"
  24. #include "locator.hpp"
  25. namespace boost { namespace gil {
  26. ////////////////////////////////////////////////////////////////////////////////////////
  27. ///
  28. /// ITERATOR FROM 2D ADAPTOR
  29. ///
  30. ////////////////////////////////////////////////////////////////////////////////////////
  31. /// \defgroup PixelIteratorModelFromLocator iterator_from_2d
  32. /// \ingroup PixelIteratorModel
  33. /// \brief An iterator over two-dimensional locator. Useful for iterating over the pixels of an image view. Models PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept
  34. /// \ingroup PixelIteratorModelFromLocator PixelBasedModel
  35. /// \brief Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept
  36. ///
  37. /// Pixels are traversed from the top to the bottom row and from the left to the right
  38. /// within each row
  39. template <typename Loc2> // Models PixelLocatorConcept
  40. class iterator_from_2d : public iterator_facade<iterator_from_2d<Loc2>,
  41. typename Loc2::value_type,
  42. std::random_access_iterator_tag,
  43. typename Loc2::reference,
  44. typename Loc2::coord_t> {
  45. GIL_CLASS_REQUIRE(Loc2, boost::gil, PixelLocatorConcept)
  46. public:
  47. typedef iterator_facade<iterator_from_2d<Loc2>,
  48. typename Loc2::value_type,
  49. std::random_access_iterator_tag,
  50. typename Loc2::reference,
  51. typename Loc2::coord_t> parent_t;
  52. typedef typename parent_t::reference reference;
  53. typedef typename parent_t::difference_type difference_type;
  54. typedef typename Loc2::x_iterator x_iterator;
  55. typedef typename Loc2::point_t point_t;
  56. std::ptrdiff_t width() const { return _width; } // number of pixels per image row
  57. std::ptrdiff_t x_pos() const { return _coords.x; } // current x position
  58. std::ptrdiff_t y_pos() const { return _coords.y; } // current y position
  59. /// For some reason operator[] provided by iterator_adaptor returns a custom class that is convertible to reference
  60. /// We require our own reference because it is registered in iterator_traits
  61. reference operator[](difference_type d) const { return *(*this+d); }
  62. bool is_1d_traversable() const { return _p.is_1d_traversable(width()); } // is there no gap at the end of each row?
  63. x_iterator& x() { return _p.x(); }
  64. iterator_from_2d(){}
  65. iterator_from_2d(const Loc2& p, std::ptrdiff_t width, std::ptrdiff_t x=0, std::ptrdiff_t y=0) : _coords(x,y), _width(width), _p(p) {}
  66. iterator_from_2d(const iterator_from_2d& pit) : _coords(pit._coords), _width(pit._width), _p(pit._p) {}
  67. template <typename Loc> iterator_from_2d(const iterator_from_2d<Loc>& pit) : _coords(pit._coords), _width(pit._width), _p(pit._p) {}
  68. private:
  69. template <typename Loc> friend class iterator_from_2d;
  70. friend class boost::iterator_core_access;
  71. reference dereference() const { return *_p; }
  72. void increment() {
  73. ++_coords.x;
  74. ++_p.x();
  75. if (_coords.x>=_width) {
  76. _coords.x=0;
  77. ++_coords.y;
  78. _p+=point_t(-_width,1);
  79. }
  80. }
  81. void decrement() {
  82. --_coords.x;
  83. --_p.x();
  84. if (_coords.x<0) {
  85. _coords.x=_width-1;
  86. --_coords.y;
  87. _p+=point_t(_width,-1);
  88. }
  89. }
  90. GIL_FORCEINLINE void advance(difference_type d) {
  91. 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.
  92. point_t delta;
  93. if (_coords.x+d>=0) { // not going back to a previous row?
  94. delta.x=(_coords.x+(std::ptrdiff_t)d)%_width - _coords.x;
  95. delta.y=(_coords.x+(std::ptrdiff_t)d)/_width;
  96. } else {
  97. delta.x=(_coords.x+(std::ptrdiff_t)d*(1-_width))%_width -_coords.x;
  98. delta.y=-(_width-_coords.x-(std::ptrdiff_t)d-1)/_width;
  99. }
  100. _p+=delta;
  101. _coords.x+=delta.x;
  102. _coords.y+=delta.y;
  103. }
  104. difference_type distance_to(const iterator_from_2d& it) const {
  105. if (_width==0) return 0;
  106. return (it.y_pos()-_coords.y)*_width + (it.x_pos()-_coords.x);
  107. }
  108. bool equal(const iterator_from_2d& it) const {
  109. assert(_width==it.width()); // they must belong to the same image
  110. return _coords==it._coords && _p==it._p;
  111. }
  112. point2<std::ptrdiff_t> _coords;
  113. std::ptrdiff_t _width;
  114. Loc2 _p;
  115. };
  116. template <typename Loc> // Models PixelLocatorConcept
  117. struct const_iterator_type<iterator_from_2d<Loc> > {
  118. typedef iterator_from_2d<typename Loc::const_t> type;
  119. };
  120. template <typename Loc> // Models PixelLocatorConcept
  121. struct iterator_is_mutable<iterator_from_2d<Loc> > : public iterator_is_mutable<typename Loc::x_iterator> {};
  122. /////////////////////////////
  123. // HasDynamicXStepTypeConcept
  124. /////////////////////////////
  125. template <typename Loc>
  126. struct dynamic_x_step_type<iterator_from_2d<Loc> > {
  127. typedef iterator_from_2d<typename dynamic_x_step_type<Loc>::type> type;
  128. };
  129. /////////////////////////////
  130. // PixelBasedConcept
  131. /////////////////////////////
  132. template <typename Loc> // Models PixelLocatorConcept
  133. struct color_space_type<iterator_from_2d<Loc> > : public color_space_type<Loc> {};
  134. template <typename Loc> // Models PixelLocatorConcept
  135. struct channel_mapping_type<iterator_from_2d<Loc> > : public channel_mapping_type<Loc> {};
  136. template <typename Loc> // Models PixelLocatorConcept
  137. struct is_planar<iterator_from_2d<Loc> > : public is_planar<Loc> {};
  138. template <typename Loc> // Models PixelLocatorConcept
  139. struct channel_type<iterator_from_2d<Loc> > : public channel_type<Loc> {};
  140. } } // namespace boost::gil
  141. #endif