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