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

Generated on Sat May 2 13:50:14 2009 for Generic Image Library by  doxygen 1.5.6