Modules | Alphabetical List | Class List | Directories | File List | File Members | GIL Home Page # locator.hpp Go to the documentation of this file.
    00001 /*
    00002     Copyright 2005-2007 Adobe Systems Incorporated
    00003
    00004     Use, modification and distribution are subject to the Boost Software License,
    00005     Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    00006     http://www.boost.org/LICENSE_1_0.txt).
    00007
    00008     See http://opensource.adobe.com/gil for most recent version including documentation.
    00009 */
    00010
    00011 /*************************************************************************************************/
    00012
    00013 #ifndef GIL_LOCATOR_H
    00014 #define GIL_LOCATOR_H
    00015
    00016
    00025
    00026 #include <cstddef>
    00027 #include <cassert>
    00028 #include "pixel_iterator.hpp"
    00029
    00033
    00034
    00035 namespace boost { namespace gil {
    00036
    00037 //forward declarations
    00038 template <typename P> ptrdiff_t memunit_step(const P*);
    00039 template <typename P> P* memunit_advanced(const P* p, ptrdiff_t diff);
    00040 template <typename P> P& memunit_advanced_ref(P* p, ptrdiff_t diff);
    00041 template <typename Iterator, typename D> struct iterator_add_deref;
    00042 template <typename T> class point2;
    00043 namespace detail {
    00044     // helper class specialized for each axis of pixel_2d_locator
    00045     template <std::size_t D, typename Loc>  class locator_axis;
    00046 }
    00047 template <typename T> struct dynamic_x_step_type;
    00048 template <typename T> struct dynamic_y_step_type;
    00049
    00050 template <typename T> struct channel_type;
    00051 template <typename T> struct color_space_type;
    00052 template <typename T> struct channel_mapping_type;
    00053 template <typename T> struct is_planar;
    00054 template <typename T> struct num_channels;
    00055
    00056 // The type of a locator or a view that has X and Y swapped. By default it is the same
    00057 template <typename T> struct transposed_type {
    00058     typedef T type;
    00059 };
    00060
    00119
    00120 template <typename Loc, typename XIterator, typename YIterator>    // The concrete subclass, the X-iterator and the Y-iterator
    00121 class pixel_2d_locator_base {
    00122 public:
    00123     typedef XIterator           x_iterator;
    00124     typedef YIterator           y_iterator;
    00125
    00126     // typedefs required by ConstRandomAccessNDLocatorConcept
    00127     static const std::size_t num_dimensions=2;
    00128     typedef typename std::iterator_traits<x_iterator>::value_type       value_type;
    00129     typedef typename std::iterator_traits<x_iterator>::reference        reference;    // result of dereferencing
    00130     typedef typename std::iterator_traits<x_iterator>::difference_type  coord_t;      // 1D difference type (same for all dimensions)
    00131     typedef point2<coord_t>                                             difference_type; // result of operator-(locator,locator)
    00132     typedef difference_type                                             point_t;
    00133     template <std::size_t D> struct axis {
    00134         typedef typename detail::locator_axis<D,Loc>::coord_t           coord_t;
    00135         typedef typename detail::locator_axis<D,Loc>::iterator          iterator;
    00136     };
    00137
    00138 // typedefs required by ConstRandomAccess2DLocatorConcept
    00139     typedef typename point_t::template axis<0>::coord_t                 x_coord_t;
    00140     typedef typename point_t::template axis<1>::coord_t                 y_coord_t;
    00141
    00142     bool              operator!=(const Loc& p)          const { return !(concrete()==p); }
    00143
    00144     x_iterator        x_at(x_coord_t dx, y_coord_t dy)  const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp.x(); }
    00145     x_iterator        x_at(const difference_type& d)    const { Loc tmp=concrete(); tmp+=d;              return tmp.x(); }
    00146     y_iterator        y_at(x_coord_t dx, y_coord_t dy)  const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp.y(); }
    00147     y_iterator        y_at(const difference_type& d)    const { Loc tmp=concrete(); tmp+=d;              return tmp.y(); }
    00148     Loc               xy_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp; }
    00149     Loc               xy_at(const difference_type& d)   const { Loc tmp=concrete(); tmp+=d;              return tmp; }
    00150
    00151     template <std::size_t D> typename axis<D>::iterator&       axis_iterator()                       { return detail::locator_axis<D,Loc>()(concrete()); }
    00152     template <std::size_t D> typename axis<D>::iterator const& axis_iterator()                 const { return detail::locator_axis<D,Loc>()(concrete()); }
    00153     template <std::size_t D> typename axis<D>::iterator        axis_iterator(const point_t& p) const { return detail::locator_axis<D,Loc>()(concrete(),p); }
    00154
    00155     reference         operator()(x_coord_t dx, y_coord_t dy) const { return *x_at(dx,dy); }
    00156     reference         operator[](const difference_type& d)   const { return *x_at(d.x,d.y); }
    00157
    00158     reference         operator*()                            const { return *concrete().x(); }
    00159
    00160     Loc&              operator+=(const difference_type& d)         { concrete().x()+=d.x; concrete().y()+=d.y; return concrete(); }
    00161     Loc&              operator-=(const difference_type& d)         { concrete().x()-=d.x; concrete().y()-=d.y; return concrete(); }
    00162
    00163     Loc               operator+(const difference_type& d)    const { return xy_at(d); }
    00164     Loc               operator-(const difference_type& d)    const { return xy_at(-d); }
    00165
    00166     // Some locators can cache 2D coordinates for faster subsequent access. By default there is no caching
    00167     typedef difference_type    cached_location_t;
    00168     cached_location_t cache_location(const difference_type& d)  const { return d; }
    00169     cached_location_t cache_location(x_coord_t dx, y_coord_t dy)const { return difference_type(dx,dy); }
    00170
    00171 private:
    00172     Loc&              concrete()       { return (Loc&)*this; }
    00173     const Loc&        concrete() const { return (const Loc&)*this; }
    00174
    00175     template <typename X> friend class pixel_2d_locator;
    00176 };
    00177
    00178 // helper classes for each axis of pixel_2d_locator_base
    00179 namespace detail {
    00180     template <typename Loc>
    00181     class locator_axis<0,Loc> {
    00182         typedef typename Loc::point_t                       point_t;
    00183     public:
    00184         typedef typename point_t::template axis<0>::coord_t coord_t;
    00185         typedef typename Loc::x_iterator                    iterator;
    00186
    00187         inline iterator&        operator()(      Loc& loc)                   const { return loc.x(); }
    00188         inline iterator  const& operator()(const Loc& loc)                   const { return loc.x(); }
    00189         inline iterator         operator()(      Loc& loc, const point_t& d) const { return loc.x_at(d); }
    00190         inline iterator         operator()(const Loc& loc, const point_t& d) const { return loc.x_at(d); }
    00191     };
    00192
    00193     template <typename Loc>
    00194     class locator_axis<1,Loc> {
    00195         typedef typename Loc::point_t                       point_t;
    00196     public:
    00197         typedef typename point_t::template axis<1>::coord_t coord_t;
    00198         typedef typename Loc::y_iterator                    iterator;
    00199
    00200         inline iterator&        operator()(      Loc& loc)               const { return loc.y(); }
    00201         inline iterator const&  operator()(const Loc& loc)               const { return loc.y(); }
    00202         inline iterator     operator()(      Loc& loc, const point_t& d) const { return loc.y_at(d); }
    00203         inline iterator     operator()(const Loc& loc, const point_t& d) const { return loc.y_at(d); }
    00204     };
    00205 }
    00206
    00207 template <typename Loc, typename XIt, typename YIt>
    00208 struct channel_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public channel_type<XIt> {};
    00209
    00210 template <typename Loc, typename XIt, typename YIt>
    00211 struct color_space_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public color_space_type<XIt> {};
    00212
    00213 template <typename Loc, typename XIt, typename YIt>
    00214 struct channel_mapping_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public channel_mapping_type<XIt> {};
    00215
    00216 template <typename Loc, typename XIt, typename YIt>
    00217 struct is_planar<pixel_2d_locator_base<Loc,XIt,YIt> > : public is_planar<XIt> {};
    00218
    00239
    00240 template <typename StepIterator>
    00241 class memory_based_2d_locator : public pixel_2d_locator_base<memory_based_2d_locator<StepIterator>, typename iterator_adaptor_get_base<StepIterator>::type, StepIterator> {
    00242     typedef memory_based_2d_locator<StepIterator>  this_t;
    00243     GIL_CLASS_REQUIRE(StepIterator, boost::gil, StepIteratorConcept)
    00244 public:
    00245     typedef pixel_2d_locator_base<memory_based_2d_locator<StepIterator>, typename iterator_adaptor_get_base<StepIterator>::type, StepIterator> parent_t;
    00246     typedef memory_based_2d_locator<typename const_iterator_type<StepIterator>::type> const_t; // same as this type, but over const values
    00247
    00248     typedef typename parent_t::coord_t          coord_t;
    00249     typedef typename parent_t::x_coord_t        x_coord_t;
    00250     typedef typename parent_t::y_coord_t        y_coord_t;
    00251     typedef typename parent_t::x_iterator       x_iterator;
    00252     typedef typename parent_t::y_iterator       y_iterator;
    00253     typedef typename parent_t::difference_type  difference_type;
    00254     typedef typename parent_t::reference        reference;
    00255
    00256     template <typename Deref> struct add_deref {
    00257         typedef memory_based_2d_locator<typename iterator_add_deref<StepIterator,Deref>::type> type;
    00258         static type make(const memory_based_2d_locator<StepIterator>& loc, const Deref& nderef) {
    00259             return type(iterator_add_deref<StepIterator,Deref>::make(loc.y(),nderef));
    00260         }
    00261     };
    00262
    00263     memory_based_2d_locator() {}
    00264     memory_based_2d_locator(const StepIterator& yit) : _p(yit) {}
    00265     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) {}
    00266     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)
    00267         : _p(make_step_iterator(loc.x(),(transpose ? loc.row_size() : loc.pixel_size())*x_step),
    00268                                         (transpose ? loc.pixel_size() : loc.row_size())*y_step ) {}
    00269
    00270     memory_based_2d_locator(x_iterator xit, std::ptrdiff_t row_bytes) : _p(xit,row_bytes) {}
    00271     template <typename X> memory_based_2d_locator(const memory_based_2d_locator<X>& pl) : _p(pl._p) {}
    00272     memory_based_2d_locator(const memory_based_2d_locator& pl) : _p(pl._p) {}
    00273
    00274     bool                  operator==(const this_t& p)  const { return _p==p._p; }
    00275
    00276     x_iterator const&     x()                          const { return _p.base(); }
    00277     y_iterator const&     y()                          const { return _p; }
    00278     x_iterator&           x()                                { return _p.base(); }
    00279     y_iterator&           y()                                { return _p; }
    00280
    00281     // These are faster versions of functions already provided in the superclass
    00282     x_iterator x_at      (x_coord_t dx, y_coord_t dy)  const { return memunit_advanced(x(), offset(dx,dy)); }
    00283     x_iterator x_at      (const difference_type& d)    const { return memunit_advanced(x(), offset(d.x,d.y)); }
    00284     this_t     xy_at     (x_coord_t dx, y_coord_t dy)  const { return this_t(x_at( dx , dy ), row_size()); }
    00285     this_t     xy_at     (const difference_type& d)    const { return this_t(x_at( d.x, d.y), row_size()); }
    00286     reference  operator()(x_coord_t dx, y_coord_t dy)  const { return memunit_advanced_ref(x(),offset(dx,dy)); }
    00287     reference  operator[](const difference_type& d)    const { return memunit_advanced_ref(x(),offset(d.x,d.y)); }
    00288     this_t&    operator+=(const difference_type& d)          { memunit_advance(x(),offset(d.x,d.y)); return *this; }
    00289     this_t&    operator-=(const difference_type& d)          { memunit_advance(x(),offset(-d.x,-d.y)); return *this; }
    00290
    00291     // Memory-based locators can have 1D caching of 2D relative coordinates
    00292     typedef std::ptrdiff_t cached_location_t; // type used to store relative location (to allow for more efficient repeated access)
    00293     cached_location_t cache_location(const difference_type& d)  const { return offset(d.x,d.y); }
    00294     cached_location_t cache_location(x_coord_t dx, y_coord_t dy)const { return offset(dx,dy); }
    00295     reference         operator[](const cached_location_t& loc)  const { return memunit_advanced_ref(x(),loc); }
    00296
    00297     // Only make sense for memory-based locators
    00298     std::ptrdiff_t         row_size()                           const { return memunit_step(y()); }    // distance in mem units (bytes or bits) between adjacent rows
    00299     std::ptrdiff_t         pixel_size()                         const { return memunit_step(x()); }    // distance in mem units (bytes or bits) between adjacent pixels on the same row
    00300
    00301     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?
    00302
    00303     // Returns the vertical distance (it2.y-it1.y) between two x_iterators given the difference of their x positions
    00304     std::ptrdiff_t y_distance_to(const this_t& p2, x_coord_t xDiff) const {
    00305         std::ptrdiff_t rowDiff=memunit_distance(x(),p2.x())-pixel_size()*xDiff;
    00306         assert(( rowDiff % row_size())==0);
    00307         return rowDiff / row_size();
    00308     }
    00309
    00310 private:
    00311     template <typename X> friend class memory_based_2d_locator;
    00312     std::ptrdiff_t offset(x_coord_t x, y_coord_t y)        const { return y*row_size() + x*pixel_size(); }
    00313     StepIterator _p;
    00314 };
    00315
    00317 //  PixelBasedConcept
    00319
    00320 template <typename SI>
    00321 struct color_space_type<memory_based_2d_locator<SI> > : public color_space_type<typename memory_based_2d_locator<SI>::parent_t> {
    00322 };
    00323
    00324 template <typename SI>
    00325 struct channel_mapping_type<memory_based_2d_locator<SI> > : public channel_mapping_type<typename memory_based_2d_locator<SI>::parent_t> {
    00326 };
    00327
    00328 template <typename SI>
    00329 struct is_planar<memory_based_2d_locator<SI> > : public is_planar<typename memory_based_2d_locator<SI>::parent_t> {
    00330 };
    00331
    00332 template <typename SI>
    00333 struct channel_type<memory_based_2d_locator<SI> > : public channel_type<typename memory_based_2d_locator<SI>::parent_t> {
    00334 };
    00335
    00337 //  HasDynamicXStepTypeConcept
    00339
    00340 // Take the base iterator of SI (which is typically a step iterator) and change it to have a step in x
    00341 template <typename SI>
    00342 struct dynamic_x_step_type<memory_based_2d_locator<SI> > {
    00343 private:
    00344     typedef typename iterator_adaptor_get_base<SI>::type                        base_iterator_t;
    00345     typedef typename dynamic_x_step_type<base_iterator_t>::type                 base_iterator_step_t;
    00346     typedef typename iterator_adaptor_rebind<SI, base_iterator_step_t>::type    dynamic_step_base_t;
    00347 public:
    00348     typedef memory_based_2d_locator<dynamic_step_base_t> type;
    00349 };
    00350
    00352 //  HasDynamicYStepTypeConcept
    00354
    00355 template <typename SI>
    00356 struct dynamic_y_step_type<memory_based_2d_locator<SI> > {
    00357     typedef memory_based_2d_locator<SI> type;
    00358 };
    00359
    00360 } }  // namespace boost::gil
    00361
    00362 #endif