Boost GIL


locator.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_LOCATOR_HPP
9#define BOOST_GIL_LOCATOR_HPP
10
11#include <boost/gil/step_iterator.hpp>
12#include <boost/gil/point.hpp>
13
14#include <boost/assert.hpp>
15
16#include <cstddef>
17
18namespace boost { namespace gil {
19
21
22//forward declarations
23template <typename P> std::ptrdiff_t memunit_step(const P*);
24template <typename P> P* memunit_advanced(const P* p, std::ptrdiff_t diff);
25template <typename P> P& memunit_advanced_ref(P* p, std::ptrdiff_t diff);
26template <typename Iterator, typename D> struct iterator_add_deref;
27template <typename T> class point;
28namespace detail {
29 // helper class specialized for each axis of pixel_2d_locator
30 template <std::size_t D, typename Loc> class locator_axis;
31}
32
33template <typename T> struct channel_type;
34template <typename T> struct color_space_type;
35template <typename T> struct channel_mapping_type;
36template <typename T> struct is_planar;
37template <typename T> struct num_channels;
38
42template <typename LocatorOrView>
44{
45 using type = LocatorOrView;
46};
47
106
107template <typename Loc, typename XIterator, typename YIterator> // The concrete subclass, the X-iterator and the Y-iterator
109{
110public:
111 using x_iterator = XIterator;
112 using y_iterator = YIterator;
113
114 // aliasesrequired by ConstRandomAccessNDLocatorConcept
115 static const std::size_t num_dimensions=2;
116 using value_type = typename std::iterator_traits<x_iterator>::value_type;
117 using reference = typename std::iterator_traits<x_iterator>::reference; // result of dereferencing
118 using coord_t = typename std::iterator_traits<x_iterator>::difference_type; // 1D difference type (same for all dimensions)
119 using difference_type = point<coord_t>; // result of operator-(locator,locator)
120 using point_t = difference_type;
121 template <std::size_t D> struct axis
122 {
123 using coord_t = typename detail::locator_axis<D,Loc>::coord_t;
124 using iterator = typename detail::locator_axis<D,Loc>::iterator;
125 };
126
127// aliases required by ConstRandomAccess2DLocatorConcept
128 using x_coord_t = typename point_t::template axis<0>::coord_t;
129 using y_coord_t = typename point_t::template axis<1>::coord_t;
130
131 bool operator!=(const Loc& p) const { return !(concrete()==p); }
132
133 x_iterator x_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp.x(); }
134 x_iterator x_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp.x(); }
135 y_iterator y_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp.y(); }
136 y_iterator y_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp.y(); }
137 Loc xy_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp; }
138 Loc xy_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp; }
139
140 template <std::size_t D> typename axis<D>::iterator& axis_iterator() { return detail::locator_axis<D,Loc>()(concrete()); }
141 template <std::size_t D> typename axis<D>::iterator const& axis_iterator() const { return detail::locator_axis<D,Loc>()(concrete()); }
142 template <std::size_t D> typename axis<D>::iterator axis_iterator(point_t const& p) const { return detail::locator_axis<D,Loc>()(concrete(),p); }
143
144 reference operator()(x_coord_t dx, y_coord_t dy) const { return *x_at(dx,dy); }
145 reference operator[](const difference_type& d) const { return *x_at(d.x,d.y); }
146
147 reference operator*() const { return *concrete().x(); }
148
149 Loc& operator+=(const difference_type& d) { concrete().x()+=d.x; concrete().y()+=d.y; return concrete(); }
150 Loc& operator-=(const difference_type& d) { concrete().x()-=d.x; concrete().y()-=d.y; return concrete(); }
151
152 Loc operator+(const difference_type& d) const { return xy_at(d); }
153 Loc operator-(const difference_type& d) const { return xy_at(-d); }
154
155 // Some locators can cache 2D coordinates for faster subsequent access. By default there is no caching
157 cached_location_t cache_location(const difference_type& d) const { return d; }
158 cached_location_t cache_location(x_coord_t dx, y_coord_t dy)const { return difference_type(dx,dy); }
159
160private:
161 Loc& concrete() { return (Loc&)*this; }
162 const Loc& concrete() const { return (const Loc&)*this; }
163
164 template <typename X> friend class pixel_2d_locator;
165};
166
167// helper classes for each axis of pixel_2d_locator_base
168namespace detail {
169 template <typename Loc>
170 class locator_axis<0,Loc> {
171 using point_t = typename Loc::point_t;
172 public:
173 using coord_t = typename point_t::template axis<0>::coord_t;
174 using iterator = typename Loc::x_iterator;
175
176 inline iterator& operator()( Loc& loc) const { return loc.x(); }
177 inline iterator const& operator()(const Loc& loc) const { return loc.x(); }
178 inline iterator operator()( Loc& loc, point_t const& d) const { return loc.x_at(d); }
179 inline iterator operator()(const Loc& loc, point_t const& d) const { return loc.x_at(d); }
180 };
181
182 template <typename Loc>
183 class locator_axis<1,Loc> {
184 using point_t = typename Loc::point_t;
185 public:
186 using coord_t = typename point_t::template axis<1>::coord_t;
187 using iterator = typename Loc::y_iterator;
188
189 inline iterator& operator()( Loc& loc) const { return loc.y(); }
190 inline iterator const& operator()(const Loc& loc) const { return loc.y(); }
191 inline iterator operator()( Loc& loc, point_t const& d) const { return loc.y_at(d); }
192 inline iterator operator()(const Loc& loc, point_t const& d) const { return loc.y_at(d); }
193 };
194}
195
196template <typename Loc, typename XIt, typename YIt>
197struct channel_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public channel_type<XIt> {};
198
199template <typename Loc, typename XIt, typename YIt>
200struct color_space_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public color_space_type<XIt> {};
201
202template <typename Loc, typename XIt, typename YIt>
203struct channel_mapping_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public channel_mapping_type<XIt> {};
204
205template <typename Loc, typename XIt, typename YIt>
206struct is_planar<pixel_2d_locator_base<Loc,XIt,YIt> > : public is_planar<XIt> {};
207
228
229template <typename StepIterator>
230class memory_based_2d_locator : public pixel_2d_locator_base<memory_based_2d_locator<StepIterator>, typename iterator_adaptor_get_base<StepIterator>::type, StepIterator> {
232 BOOST_GIL_CLASS_REQUIRE(StepIterator, boost::gil, StepIteratorConcept)
233public:
235 using const_t = memory_based_2d_locator<typename const_iterator_type<StepIterator>::type>; // same as this type, but over const values
236
237 using coord_t = typename parent_t::coord_t;
238 using x_coord_t = typename parent_t::x_coord_t;
239 using y_coord_t = typename parent_t::y_coord_t;
240 using x_iterator = typename parent_t::x_iterator;
241 using y_iterator = typename parent_t::y_iterator;
242 using difference_type = typename parent_t::difference_type;
243 using reference = typename parent_t::reference;
244
245 template <typename Deref> struct add_deref
246 {
248 static type make(const memory_based_2d_locator<StepIterator>& loc, const Deref& nderef) {
249 return type(iterator_add_deref<StepIterator,Deref>::make(loc.y(),nderef));
250 }
251 };
252
254 memory_based_2d_locator(const StepIterator& yit) : _p(yit) {}
255 template <typename SI> memory_based_2d_locator(const memory_based_2d_locator<SI>& loc, coord_t y_step) : _p(loc.x(), loc.row_size()*y_step) {}
256 template <typename SI> memory_based_2d_locator(const memory_based_2d_locator<SI>& loc, coord_t x_step, coord_t y_step, bool transpose=false)
257 : _p(make_step_iterator(loc.x(),(transpose ? loc.row_size() : loc.pixel_size())*x_step),
258 (transpose ? loc.pixel_size() : loc.row_size())*y_step ) {}
259
260 memory_based_2d_locator(x_iterator xit, std::ptrdiff_t row_bytes) : _p(xit,row_bytes) {}
261 template <typename X> memory_based_2d_locator(const memory_based_2d_locator<X>& pl) : _p(pl._p) {}
262 memory_based_2d_locator(const memory_based_2d_locator& pl) : _p(pl._p) {}
263 memory_based_2d_locator& operator=(memory_based_2d_locator const& other) = default;
264
265 bool operator==(const this_t& p) const { return _p==p._p; }
266
267 x_iterator const& x() const { return _p.base(); }
268 y_iterator const& y() const { return _p; }
269 x_iterator& x() { return _p.base(); }
270 y_iterator& y() { return _p; }
271
272 // These are faster versions of functions already provided in the superclass
273 x_iterator x_at (x_coord_t dx, y_coord_t dy) const { return memunit_advanced(x(), offset(dx,dy)); }
274 x_iterator x_at (const difference_type& d) const { return memunit_advanced(x(), offset(d.x,d.y)); }
275 this_t xy_at (x_coord_t dx, y_coord_t dy) const { return this_t(x_at( dx , dy ), row_size()); }
276 this_t xy_at (const difference_type& d) const { return this_t(x_at( d.x, d.y), row_size()); }
277 reference operator()(x_coord_t dx, y_coord_t dy) const { return memunit_advanced_ref(x(),offset(dx,dy)); }
278 reference operator[](const difference_type& d) const { return memunit_advanced_ref(x(),offset(d.x,d.y)); }
279 this_t& operator+=(const difference_type& d) { memunit_advance(x(),offset(d.x,d.y)); return *this; }
280 this_t& operator-=(const difference_type& d) { memunit_advance(x(),offset(-d.x,-d.y)); return *this; }
281
282 // Memory-based locators can have 1D caching of 2D relative coordinates
283 using cached_location_t = std::ptrdiff_t; // type used to store relative location (to allow for more efficient repeated access)
284 cached_location_t cache_location(const difference_type& d) const { return offset(d.x,d.y); }
285 cached_location_t cache_location(x_coord_t dx, y_coord_t dy)const { return offset(dx,dy); }
286 reference operator[](const cached_location_t& loc) const { return memunit_advanced_ref(x(),loc); }
287
288 // Only make sense for memory-based locators
289 std::ptrdiff_t row_size() const { return memunit_step(y()); } // distance in mem units (bytes or bits) between adjacent rows
290 std::ptrdiff_t pixel_size() const { return memunit_step(x()); } // distance in mem units (bytes or bits) between adjacent pixels on the same row
291
292 bool is_1d_traversable(x_coord_t width) const { return row_size()-pixel_size()*width==0; } // is there no gap at the end of each row?
293
294 // Returns the vertical distance (it2.y-it1.y) between two x_iterators given the difference of their x positions
295 std::ptrdiff_t y_distance_to(this_t const& p2, x_coord_t xDiff) const
296 {
297 std::ptrdiff_t rowDiff = memunit_distance(x(), p2.x()) - pixel_size() * xDiff;
298 BOOST_ASSERT((rowDiff % row_size()) == 0);
299 return rowDiff / row_size();
300 }
301
302private:
303 template <typename X> friend class memory_based_2d_locator;
304 std::ptrdiff_t offset(x_coord_t x, y_coord_t y) const { return y*row_size() + x*pixel_size(); }
305 StepIterator _p;
306};
307
309// PixelBasedConcept
311
312template <typename SI>
313struct color_space_type<memory_based_2d_locator<SI> > : public color_space_type<typename memory_based_2d_locator<SI>::parent_t> {
314};
315
316template <typename SI>
317struct channel_mapping_type<memory_based_2d_locator<SI> > : public channel_mapping_type<typename memory_based_2d_locator<SI>::parent_t> {
318};
319
320template <typename SI>
321struct is_planar<memory_based_2d_locator<SI> > : public is_planar<typename memory_based_2d_locator<SI>::parent_t> {
322};
323
324template <typename SI>
325struct channel_type<memory_based_2d_locator<SI> > : public channel_type<typename memory_based_2d_locator<SI>::parent_t> {
326};
327
329// HasDynamicXStepTypeConcept
331
332// Take the base iterator of SI (which is typically a step iterator) and change it to have a step in x
333template <typename SI>
334struct dynamic_x_step_type<memory_based_2d_locator<SI> > {
335private:
336 using base_iterator_t = typename iterator_adaptor_get_base<SI>::type;
337 using base_iterator_step_t = typename dynamic_x_step_type<base_iterator_t>::type;
338 using dynamic_step_base_t = typename iterator_adaptor_rebind<SI, base_iterator_step_t>::type;
339public:
340 using type = memory_based_2d_locator<dynamic_step_base_t>;
341};
342
344// HasDynamicYStepTypeConcept
346
347template <typename SI>
348struct dynamic_y_step_type<memory_based_2d_locator<SI> > {
349 using type = memory_based_2d_locator<SI>;
350};
351} } // namespace boost::gil
352
353#endif
Memory-based pixel locator. Models: PixelLocatorConcept,HasDynamicXStepTypeConcept,...
Definition locator.hpp:230
base class for models of PixelLocatorConcept
Definition locator.hpp:109
2D point both axes of which have the same dimension typeModels: Point2DConcept
Definition point.hpp:36
defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
Definition algorithm.hpp:36
Step iterator concept.
Definition concepts/pixel_iterator.hpp:258
returns the base iterator for a given iterator adaptor. Provide an specialization when introducing ne...
Definition metafunctions.hpp:36
Returns the type (and creates an instance) of an iterator that invokes the given dereference adaptor ...
Definition pixel_iterator_adaptor.hpp:176
Definition locator.hpp:44