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 |
176 | |