Boost GIL


locator.hpp
Go to the documentation of this file.
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 
13 #ifndef GIL_LOCATOR_H
14 #define GIL_LOCATOR_H
15 
24 
25 #include <cstddef>
26 #include <cassert>
27 #include "pixel_iterator.hpp"
28 
32 
33 namespace boost { namespace gil {
34 //forward declarations
35 template <typename P> std::ptrdiff_t memunit_step(const P*);
36 template <typename P> P* memunit_advanced(const P* p, std::ptrdiff_t diff);
37 template <typename P> P& memunit_advanced_ref(P* p, std::ptrdiff_t diff);
38 template <typename Iterator, typename D> struct iterator_add_deref;
39 template <typename T> class point2;
40 namespace detail {
41  // helper class specialized for each axis of pixel_2d_locator
42  template <std::size_t D, typename Loc> class locator_axis;
43 }
44 template <typename T> struct dynamic_x_step_type;
45 template <typename T> struct dynamic_y_step_type;
46 
47 template <typename T> struct channel_type;
48 template <typename T> struct color_space_type;
49 template <typename T> struct channel_mapping_type;
50 template <typename T> struct is_planar;
51 template <typename T> struct num_channels;
52 
53 // The type of a locator or a view that has X and Y swapped. By default it is the same
54 template <typename T> struct transposed_type {
55  typedef T type;
56 };
57 
116 
117 template <typename Loc, typename XIterator, typename YIterator> // The concrete subclass, the X-iterator and the Y-iterator
119 public:
120  typedef XIterator x_iterator;
121  typedef YIterator y_iterator;
122 
123  // typedefs required by ConstRandomAccessNDLocatorConcept
124  static const std::size_t num_dimensions=2;
125  typedef typename std::iterator_traits<x_iterator>::value_type value_type;
126  typedef typename std::iterator_traits<x_iterator>::reference reference; // result of dereferencing
127  typedef typename std::iterator_traits<x_iterator>::difference_type coord_t; // 1D difference type (same for all dimensions)
128  typedef point2<coord_t> difference_type; // result of operator-(locator,locator)
129  typedef difference_type point_t;
130  template <std::size_t D> struct axis {
131  typedef typename detail::locator_axis<D,Loc>::coord_t coord_t;
132  typedef typename detail::locator_axis<D,Loc>::iterator iterator;
133  };
134 
135 // typedefs required by ConstRandomAccess2DLocatorConcept
136  typedef typename point_t::template axis<0>::coord_t x_coord_t;
137  typedef typename point_t::template axis<1>::coord_t y_coord_t;
138 
139  bool operator!=(const Loc& p) const { return !(concrete()==p); }
140 
141  x_iterator x_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp.x(); }
142  x_iterator x_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp.x(); }
143  y_iterator y_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp.y(); }
144  y_iterator y_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp.y(); }
145  Loc xy_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp; }
146  Loc xy_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp; }
147 
148  template <std::size_t D> typename axis<D>::iterator& axis_iterator() { return detail::locator_axis<D,Loc>()(concrete()); }
149  template <std::size_t D> typename axis<D>::iterator const& axis_iterator() const { return detail::locator_axis<D,Loc>()(concrete()); }
150  template <std::size_t D> typename axis<D>::iterator axis_iterator(const point_t& p) const { return detail::locator_axis<D,Loc>()(concrete(),p); }
151 
152  reference operator()(x_coord_t dx, y_coord_t dy) const { return *x_at(dx,dy); }
153  reference operator[](const difference_type& d) const { return *x_at(d.x,d.y); }
154 
155  reference operator*() const { return *concrete().x(); }
156 
157  Loc& operator+=(const difference_type& d) { concrete().x()+=d.x; concrete().y()+=d.y; return concrete(); }
158  Loc& operator-=(const difference_type& d) { concrete().x()-=d.x; concrete().y()-=d.y; return concrete(); }
159 
160  Loc operator+(const difference_type& d) const { return xy_at(d); }
161  Loc operator-(const difference_type& d) const { return xy_at(-d); }
162 
163  // Some locators can cache 2D coordinates for faster subsequent access. By default there is no caching
165  cached_location_t cache_location(const difference_type& d) const { return d; }
166  cached_location_t cache_location(x_coord_t dx, y_coord_t dy)const { return difference_type(dx,dy); }
167 
168 private:
169  Loc& concrete() { return (Loc&)*this; }
170  const Loc& concrete() const { return (const Loc&)*this; }
171 
172  template <typename X> friend class pixel_2d_locator;
173 };
174 
175 // helper classes for each axis of pixel_2d_locator_base
176 namespace detail {
177  template <typename Loc>
178  class locator_axis<0,Loc> {
179  typedef typename Loc::point_t point_t;
180  public:
181  typedef typename point_t::template axis<0>::coord_t coord_t;
182  typedef typename Loc::x_iterator iterator;
183 
184  inline iterator& operator()( Loc& loc) const { return loc.x(); }
185  inline iterator const& operator()(const Loc& loc) const { return loc.x(); }
186  inline iterator operator()( Loc& loc, const point_t& d) const { return loc.x_at(d); }
187  inline iterator operator()(const Loc& loc, const point_t& d) const { return loc.x_at(d); }
188  };
189 
190  template <typename Loc>
191  class locator_axis<1,Loc> {
192  typedef typename Loc::point_t point_t;
193  public:
194  typedef typename point_t::template axis<1>::coord_t coord_t;
195  typedef typename Loc::y_iterator iterator;
196 
197  inline iterator& operator()( Loc& loc) const { return loc.y(); }
198  inline iterator const& operator()(const Loc& loc) const { return loc.y(); }
199  inline iterator operator()( Loc& loc, const point_t& d) const { return loc.y_at(d); }
200  inline iterator operator()(const Loc& loc, const point_t& d) const { return loc.y_at(d); }
201  };
202 }
203 
204 template <typename Loc, typename XIt, typename YIt>
205 struct channel_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public channel_type<XIt> {};
206 
207 template <typename Loc, typename XIt, typename YIt>
208 struct color_space_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public color_space_type<XIt> {};
209 
210 template <typename Loc, typename XIt, typename YIt>
211 struct channel_mapping_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public channel_mapping_type<XIt> {};
212 
213 template <typename Loc, typename XIt, typename YIt>
214 struct is_planar<pixel_2d_locator_base<Loc,XIt,YIt> > : public is_planar<XIt> {};
215 
236 
237 template <typename StepIterator>
238 class memory_based_2d_locator : public pixel_2d_locator_base<memory_based_2d_locator<StepIterator>, typename iterator_adaptor_get_base<StepIterator>::type, StepIterator> {
239  typedef memory_based_2d_locator<StepIterator> this_t;
240  GIL_CLASS_REQUIRE(StepIterator, boost::gil, StepIteratorConcept)
241 public:
242  typedef pixel_2d_locator_base<memory_based_2d_locator<StepIterator>, typename iterator_adaptor_get_base<StepIterator>::type, StepIterator> parent_t;
243  typedef memory_based_2d_locator<typename const_iterator_type<StepIterator>::type> const_t; // same as this type, but over const values
244 
245  typedef typename parent_t::coord_t coord_t;
246  typedef typename parent_t::x_coord_t x_coord_t;
247  typedef typename parent_t::y_coord_t y_coord_t;
248  typedef typename parent_t::x_iterator x_iterator;
249  typedef typename parent_t::y_iterator y_iterator;
250  typedef typename parent_t::difference_type difference_type;
251  typedef typename parent_t::reference reference;
252 
253  template <typename Deref> struct add_deref {
254  typedef memory_based_2d_locator<typename iterator_add_deref<StepIterator,Deref>::type> type;
255  static type make(const memory_based_2d_locator<StepIterator>& loc, const Deref& nderef) {
256  return type(iterator_add_deref<StepIterator,Deref>::make(loc.y(),nderef));
257  }
258  };
259 
260  memory_based_2d_locator() {}
261  memory_based_2d_locator(const StepIterator& yit) : _p(yit) {}
262  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) {}
263  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)
264  : _p(make_step_iterator(loc.x(),(transpose ? loc.row_size() : loc.pixel_size())*x_step),
265  (transpose ? loc.pixel_size() : loc.row_size())*y_step ) {}
266 
267  memory_based_2d_locator(x_iterator xit, std::ptrdiff_t row_bytes) : _p(xit,row_bytes) {}
268  template <typename X> memory_based_2d_locator(const memory_based_2d_locator<X>& pl) : _p(pl._p) {}
269  memory_based_2d_locator(const memory_based_2d_locator& pl) : _p(pl._p) {}
270 
271  bool operator==(const this_t& p) const { return _p==p._p; }
272 
273  x_iterator const& x() const { return _p.base(); }
274  y_iterator const& y() const { return _p; }
275  x_iterator& x() { return _p.base(); }
276  y_iterator& y() { return _p; }
277 
278  // These are faster versions of functions already provided in the superclass
279  x_iterator x_at (x_coord_t dx, y_coord_t dy) const { return memunit_advanced(x(), offset(dx,dy)); }
280  x_iterator x_at (const difference_type& d) const { return memunit_advanced(x(), offset(d.x,d.y)); }
281  this_t xy_at (x_coord_t dx, y_coord_t dy) const { return this_t(x_at( dx , dy ), row_size()); }
282  this_t xy_at (const difference_type& d) const { return this_t(x_at( d.x, d.y), row_size()); }
283  reference operator()(x_coord_t dx, y_coord_t dy) const { return memunit_advanced_ref(x(),offset(dx,dy)); }
284  reference operator[](const difference_type& d) const { return memunit_advanced_ref(x(),offset(d.x,d.y)); }
285  this_t& operator+=(const difference_type& d) { memunit_advance(x(),offset(d.x,d.y)); return *this; }
286  this_t& operator-=(const difference_type& d) { memunit_advance(x(),offset(-d.x,-d.y)); return *this; }
287 
288  // Memory-based locators can have 1D caching of 2D relative coordinates
289  typedef std::ptrdiff_t cached_location_t; // type used to store relative location (to allow for more efficient repeated access)
290  cached_location_t cache_location(const difference_type& d) const { return offset(d.x,d.y); }
291  cached_location_t cache_location(x_coord_t dx, y_coord_t dy)const { return offset(dx,dy); }
292  reference operator[](const cached_location_t& loc) const { return memunit_advanced_ref(x(),loc); }
293 
294  // Only make sense for memory-based locators
295  std::ptrdiff_t row_size() const { return memunit_step(y()); } // distance in mem units (bytes or bits) between adjacent rows
296  std::ptrdiff_t pixel_size() const { return memunit_step(x()); } // distance in mem units (bytes or bits) between adjacent pixels on the same row
297 
298  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?
299 
300  // Returns the vertical distance (it2.y-it1.y) between two x_iterators given the difference of their x positions
301  std::ptrdiff_t y_distance_to(const this_t& p2, x_coord_t xDiff) const {
302  std::ptrdiff_t rowDiff=memunit_distance(x(),p2.x())-pixel_size()*xDiff;
303  assert(( rowDiff % row_size())==0);
304  return rowDiff / row_size();
305  }
306 
307 private:
308  template <typename X> friend class memory_based_2d_locator;
309  std::ptrdiff_t offset(x_coord_t x, y_coord_t y) const { return y*row_size() + x*pixel_size(); }
310  StepIterator _p;
311 };
312 
314 // PixelBasedConcept
316 
317 template <typename SI>
318 struct color_space_type<memory_based_2d_locator<SI> > : public color_space_type<typename memory_based_2d_locator<SI>::parent_t> {
319 };
320 
321 template <typename SI>
322 struct channel_mapping_type<memory_based_2d_locator<SI> > : public channel_mapping_type<typename memory_based_2d_locator<SI>::parent_t> {
323 };
324 
325 template <typename SI>
326 struct is_planar<memory_based_2d_locator<SI> > : public is_planar<typename memory_based_2d_locator<SI>::parent_t> {
327 };
328 
329 template <typename SI>
330 struct channel_type<memory_based_2d_locator<SI> > : public channel_type<typename memory_based_2d_locator<SI>::parent_t> {
331 };
332 
334 // HasDynamicXStepTypeConcept
336 
337 // Take the base iterator of SI (which is typically a step iterator) and change it to have a step in x
338 template <typename SI>
339 struct dynamic_x_step_type<memory_based_2d_locator<SI> > {
340 private:
341  typedef typename iterator_adaptor_get_base<SI>::type base_iterator_t;
342  typedef typename dynamic_x_step_type<base_iterator_t>::type base_iterator_step_t;
343  typedef typename iterator_adaptor_rebind<SI, base_iterator_step_t>::type dynamic_step_base_t;
344 public:
345  typedef memory_based_2d_locator<dynamic_step_base_t> type;
346 };
347 
349 // HasDynamicYStepTypeConcept
351 
352 template <typename SI>
353 struct dynamic_y_step_type<memory_based_2d_locator<SI> > {
354  typedef memory_based_2d_locator<SI> type;
355 };
356 } } // namespace boost::gil
357 
358 #endif
base class for models of PixelLocatorConceptPixel locator is similar to a pixel iterator, but allows for 2D navigation of pixels within an image view. It has a 2D difference_type and supports random access operations like:
Definition: locator.hpp:118
Returns the type (and creates an instance) of an iterator that invokes the given dereference adaptor ...
Definition: locator.hpp:38
pixel iterator support
2D point both axes of which have the same dimension typeModels: Point2DConcept
Definition: gil_concept.hpp:52
Returns the number of channels of a pixel-based GIL construct.
Definition: gil_concept.hpp:66