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