iterator_from_2d.hpp 6.5 KB

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