123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- #ifndef BOOST_GIL_LOCATOR_HPP
- #define BOOST_GIL_LOCATOR_HPP
- #include <boost/gil/dynamic_step.hpp>
- #include <boost/gil/pixel_iterator.hpp>
- #include <boost/gil/point.hpp>
- #include <boost/assert.hpp>
- #include <cstddef>
- namespace boost { namespace gil {
- template <typename P> std::ptrdiff_t memunit_step(const P*);
- template <typename P> P* memunit_advanced(const P* p, std::ptrdiff_t diff);
- template <typename P> P& memunit_advanced_ref(P* p, std::ptrdiff_t diff);
- template <typename Iterator, typename D> struct iterator_add_deref;
- template <typename T> class point;
- namespace detail {
-
- template <std::size_t D, typename Loc> class locator_axis;
- }
- template <typename T> struct channel_type;
- template <typename T> struct color_space_type;
- template <typename T> struct channel_mapping_type;
- template <typename T> struct is_planar;
- template <typename T> struct num_channels;
- template <typename LocatorOrView>
- struct transposed_type
- {
- using type = LocatorOrView;
- };
- template <typename Loc, typename XIterator, typename YIterator>
- class pixel_2d_locator_base
- {
- public:
- using x_iterator = XIterator;
- using y_iterator = YIterator;
-
- static const std::size_t num_dimensions=2;
- using value_type = typename std::iterator_traits<x_iterator>::value_type;
- using reference = typename std::iterator_traits<x_iterator>::reference;
- using coord_t = typename std::iterator_traits<x_iterator>::difference_type;
- using difference_type = point<coord_t>;
- using point_t = difference_type;
- template <std::size_t D> struct axis
- {
- using coord_t = typename detail::locator_axis<D,Loc>::coord_t;
- using iterator = typename detail::locator_axis<D,Loc>::iterator;
- };
- using x_coord_t = typename point_t::template axis<0>::coord_t;
- using y_coord_t = typename point_t::template axis<1>::coord_t;
- bool operator!=(const Loc& p) const { return !(concrete()==p); }
- x_iterator x_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp.x(); }
- x_iterator x_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp.x(); }
- y_iterator y_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp.y(); }
- y_iterator y_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp.y(); }
- Loc xy_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp; }
- Loc xy_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp; }
- template <std::size_t D> typename axis<D>::iterator& axis_iterator() { return detail::locator_axis<D,Loc>()(concrete()); }
- template <std::size_t D> typename axis<D>::iterator const& axis_iterator() const { return detail::locator_axis<D,Loc>()(concrete()); }
- template <std::size_t D> typename axis<D>::iterator axis_iterator(const point_t& p) const { return detail::locator_axis<D,Loc>()(concrete(),p); }
- reference operator()(x_coord_t dx, y_coord_t dy) const { return *x_at(dx,dy); }
- reference operator[](const difference_type& d) const { return *x_at(d.x,d.y); }
- reference operator*() const { return *concrete().x(); }
- Loc& operator+=(const difference_type& d) { concrete().x()+=d.x; concrete().y()+=d.y; return concrete(); }
- Loc& operator-=(const difference_type& d) { concrete().x()-=d.x; concrete().y()-=d.y; return concrete(); }
- Loc operator+(const difference_type& d) const { return xy_at(d); }
- Loc operator-(const difference_type& d) const { return xy_at(-d); }
-
- using cached_location_t = difference_type;
- cached_location_t cache_location(const difference_type& d) const { return d; }
- cached_location_t cache_location(x_coord_t dx, y_coord_t dy)const { return difference_type(dx,dy); }
- private:
- Loc& concrete() { return (Loc&)*this; }
- const Loc& concrete() const { return (const Loc&)*this; }
- template <typename X> friend class pixel_2d_locator;
- };
- namespace detail {
- template <typename Loc>
- class locator_axis<0,Loc> {
- using point_t = typename Loc::point_t;
- public:
- using coord_t = typename point_t::template axis<0>::coord_t;
- using iterator = typename Loc::x_iterator;
- inline iterator& operator()( Loc& loc) const { return loc.x(); }
- inline iterator const& operator()(const Loc& loc) const { return loc.x(); }
- inline iterator operator()( Loc& loc, const point_t& d) const { return loc.x_at(d); }
- inline iterator operator()(const Loc& loc, const point_t& d) const { return loc.x_at(d); }
- };
- template <typename Loc>
- class locator_axis<1,Loc> {
- using point_t = typename Loc::point_t;
- public:
- using coord_t = typename point_t::template axis<1>::coord_t;
- using iterator = typename Loc::y_iterator;
- inline iterator& operator()( Loc& loc) const { return loc.y(); }
- inline iterator const& operator()(const Loc& loc) const { return loc.y(); }
- inline iterator operator()( Loc& loc, const point_t& d) const { return loc.y_at(d); }
- inline iterator operator()(const Loc& loc, const point_t& d) const { return loc.y_at(d); }
- };
- }
- template <typename Loc, typename XIt, typename YIt>
- struct channel_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public channel_type<XIt> {};
- template <typename Loc, typename XIt, typename YIt>
- struct color_space_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public color_space_type<XIt> {};
- template <typename Loc, typename XIt, typename YIt>
- struct channel_mapping_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public channel_mapping_type<XIt> {};
- template <typename Loc, typename XIt, typename YIt>
- struct is_planar<pixel_2d_locator_base<Loc,XIt,YIt> > : public is_planar<XIt> {};
- template <typename StepIterator>
- class memory_based_2d_locator : public pixel_2d_locator_base<memory_based_2d_locator<StepIterator>, typename iterator_adaptor_get_base<StepIterator>::type, StepIterator> {
- using this_t = memory_based_2d_locator<StepIterator>;
- BOOST_GIL_CLASS_REQUIRE(StepIterator, boost::gil, StepIteratorConcept)
- public:
- using parent_t = pixel_2d_locator_base<memory_based_2d_locator<StepIterator>, typename iterator_adaptor_get_base<StepIterator>::type, StepIterator>;
- using const_t = memory_based_2d_locator<typename const_iterator_type<StepIterator>::type>;
- using coord_t = typename parent_t::coord_t;
- using x_coord_t = typename parent_t::x_coord_t;
- using y_coord_t = typename parent_t::y_coord_t;
- using x_iterator = typename parent_t::x_iterator;
- using y_iterator = typename parent_t::y_iterator;
- using difference_type = typename parent_t::difference_type;
- using reference = typename parent_t::reference;
- template <typename Deref> struct add_deref
- {
- using type = memory_based_2d_locator<typename iterator_add_deref<StepIterator,Deref>::type>;
- static type make(const memory_based_2d_locator<StepIterator>& loc, const Deref& nderef) {
- return type(iterator_add_deref<StepIterator,Deref>::make(loc.y(),nderef));
- }
- };
- memory_based_2d_locator() {}
- memory_based_2d_locator(const StepIterator& yit) : _p(yit) {}
- 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) {}
- 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)
- : _p(make_step_iterator(loc.x(),(transpose ? loc.row_size() : loc.pixel_size())*x_step),
- (transpose ? loc.pixel_size() : loc.row_size())*y_step ) {}
- memory_based_2d_locator(x_iterator xit, std::ptrdiff_t row_bytes) : _p(xit,row_bytes) {}
- template <typename X> memory_based_2d_locator(const memory_based_2d_locator<X>& pl) : _p(pl._p) {}
- memory_based_2d_locator(const memory_based_2d_locator& pl) : _p(pl._p) {}
- memory_based_2d_locator& operator=(memory_based_2d_locator const& other) = default;
- bool operator==(const this_t& p) const { return _p==p._p; }
- x_iterator const& x() const { return _p.base(); }
- y_iterator const& y() const { return _p; }
- x_iterator& x() { return _p.base(); }
- y_iterator& y() { return _p; }
-
- x_iterator x_at (x_coord_t dx, y_coord_t dy) const { return memunit_advanced(x(), offset(dx,dy)); }
- x_iterator x_at (const difference_type& d) const { return memunit_advanced(x(), offset(d.x,d.y)); }
- this_t xy_at (x_coord_t dx, y_coord_t dy) const { return this_t(x_at( dx , dy ), row_size()); }
- this_t xy_at (const difference_type& d) const { return this_t(x_at( d.x, d.y), row_size()); }
- reference operator()(x_coord_t dx, y_coord_t dy) const { return memunit_advanced_ref(x(),offset(dx,dy)); }
- reference operator[](const difference_type& d) const { return memunit_advanced_ref(x(),offset(d.x,d.y)); }
- this_t& operator+=(const difference_type& d) { memunit_advance(x(),offset(d.x,d.y)); return *this; }
- this_t& operator-=(const difference_type& d) { memunit_advance(x(),offset(-d.x,-d.y)); return *this; }
-
- using cached_location_t = std::ptrdiff_t;
- cached_location_t cache_location(const difference_type& d) const { return offset(d.x,d.y); }
- cached_location_t cache_location(x_coord_t dx, y_coord_t dy)const { return offset(dx,dy); }
- reference operator[](const cached_location_t& loc) const { return memunit_advanced_ref(x(),loc); }
-
- std::ptrdiff_t row_size() const { return memunit_step(y()); }
- std::ptrdiff_t pixel_size() const { return memunit_step(x()); }
- bool is_1d_traversable(x_coord_t width) const { return row_size()-pixel_size()*width==0; }
-
- std::ptrdiff_t y_distance_to(this_t const& p2, x_coord_t xDiff) const
- {
- std::ptrdiff_t rowDiff = memunit_distance(x(), p2.x()) - pixel_size() * xDiff;
- BOOST_ASSERT((rowDiff % row_size()) == 0);
- return rowDiff / row_size();
- }
- private:
- template <typename X> friend class memory_based_2d_locator;
- std::ptrdiff_t offset(x_coord_t x, y_coord_t y) const { return y*row_size() + x*pixel_size(); }
- StepIterator _p;
- };
- template <typename SI>
- struct color_space_type<memory_based_2d_locator<SI> > : public color_space_type<typename memory_based_2d_locator<SI>::parent_t> {
- };
- template <typename SI>
- struct channel_mapping_type<memory_based_2d_locator<SI> > : public channel_mapping_type<typename memory_based_2d_locator<SI>::parent_t> {
- };
- template <typename SI>
- struct is_planar<memory_based_2d_locator<SI> > : public is_planar<typename memory_based_2d_locator<SI>::parent_t> {
- };
- template <typename SI>
- struct channel_type<memory_based_2d_locator<SI> > : public channel_type<typename memory_based_2d_locator<SI>::parent_t> {
- };
- template <typename SI>
- struct dynamic_x_step_type<memory_based_2d_locator<SI> > {
- private:
- using base_iterator_t = typename iterator_adaptor_get_base<SI>::type;
- using base_iterator_step_t = typename dynamic_x_step_type<base_iterator_t>::type;
- using dynamic_step_base_t = typename iterator_adaptor_rebind<SI, base_iterator_step_t>::type;
- public:
- using type = memory_based_2d_locator<dynamic_step_base_t>;
- };
- template <typename SI>
- struct dynamic_y_step_type<memory_based_2d_locator<SI> > {
- using type = memory_based_2d_locator<SI>;
- };
- } }
- #endif
|