00001
00002
00003
00004
00005
00006
00007
00008
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
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
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
00057 template <typename T> struct transposed_type {
00058 typedef T type;
00059 };
00060
00119
00120 template <typename Loc, typename XIterator, typename YIterator>
00121 class pixel_2d_locator_base {
00122 public:
00123 typedef XIterator x_iterator;
00124 typedef YIterator y_iterator;
00125
00126
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;
00130 typedef typename std::iterator_traits<x_iterator>::difference_type coord_t;
00131 typedef point2<coord_t> difference_type;
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
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
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
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;
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
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
00292 typedef std::ptrdiff_t cached_location_t;
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
00298 std::ptrdiff_t row_size() const { return memunit_step(y()); }
00299 std::ptrdiff_t pixel_size() const { return memunit_step(x()); }
00300
00301 bool is_1d_traversable(x_coord_t width) const { return row_size()-pixel_size()*width==0; }
00302
00303
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
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
00339
00340
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
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 } }
00361
00362 #endif