locator.hppGo 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 1.5.6 |