Chris@16: /* Chris@16: Copyright 2005-2007 Adobe Systems Incorporated Chris@16: Chris@16: Use, modification and distribution are subject to the Boost Software License, Chris@16: Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: http://www.boost.org/LICENSE_1_0.txt). Chris@16: Chris@16: See http://opensource.adobe.com/gil for most recent version including documentation. Chris@16: */ Chris@16: /*************************************************************************************************/ Chris@16: Chris@16: #ifndef GIL_ITERATOR_FROM_2D_H Chris@16: #define GIL_ITERATOR_FROM_2D_H Chris@16: Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file Chris@16: /// \brief pixel step iterator, pixel image iterator and pixel dereference iterator Chris@16: /// \author Lubomir Bourdev and Hailin Jin \n Chris@16: /// Adobe Systems Incorporated Chris@16: /// \date 2005-2007 \n Last updated on September 18, 2007 Chris@16: /// Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include "gil_concept.hpp" Chris@16: #include "gil_config.hpp" Chris@16: #include "pixel_iterator.hpp" Chris@16: #include "locator.hpp" Chris@16: Chris@16: namespace boost { namespace gil { Chris@16: Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: /// Chris@16: /// ITERATOR FROM 2D ADAPTOR Chris@16: /// Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: Chris@16: /// \defgroup PixelIteratorModelFromLocator iterator_from_2d Chris@16: /// \ingroup PixelIteratorModel Chris@16: /// \brief An iterator over two-dimensional locator. Useful for iterating over the pixels of an image view. Models PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept Chris@16: Chris@16: Chris@16: /// \ingroup PixelIteratorModelFromLocator PixelBasedModel Chris@16: /// \brief Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept Chris@16: /// Chris@16: /// Pixels are traversed from the top to the bottom row and from the left to the right Chris@16: /// within each row Chris@16: Chris@16: template // Models PixelLocatorConcept Chris@16: class iterator_from_2d : public iterator_facade, Chris@16: typename Loc2::value_type, Chris@16: std::random_access_iterator_tag, Chris@16: typename Loc2::reference, Chris@16: typename Loc2::coord_t> { Chris@16: GIL_CLASS_REQUIRE(Loc2, boost::gil, PixelLocatorConcept) Chris@16: public: Chris@16: typedef iterator_facade, Chris@16: typename Loc2::value_type, Chris@16: std::random_access_iterator_tag, Chris@16: typename Loc2::reference, Chris@16: typename Loc2::coord_t> parent_t; Chris@16: typedef typename parent_t::reference reference; Chris@16: typedef typename parent_t::difference_type difference_type; Chris@16: typedef typename Loc2::x_iterator x_iterator; Chris@16: typedef typename Loc2::point_t point_t; Chris@16: Chris@16: std::ptrdiff_t width() const { return _width; } // number of pixels per image row Chris@16: std::ptrdiff_t x_pos() const { return _coords.x; } // current x position Chris@16: std::ptrdiff_t y_pos() const { return _coords.y; } // current y position Chris@16: Chris@16: /// For some reason operator[] provided by iterator_adaptor returns a custom class that is convertible to reference Chris@16: /// We require our own reference because it is registered in iterator_traits Chris@16: reference operator[](difference_type d) const { return *(*this+d); } Chris@16: Chris@16: bool is_1d_traversable() const { return _p.is_1d_traversable(width()); } // is there no gap at the end of each row? Chris@16: x_iterator& x() { return _p.x(); } Chris@16: Chris@16: iterator_from_2d(){} Chris@16: iterator_from_2d(const Loc2& p, std::ptrdiff_t width, std::ptrdiff_t x=0, std::ptrdiff_t y=0) : _coords(x,y), _width(width), _p(p) {} Chris@16: iterator_from_2d(const iterator_from_2d& pit) : _coords(pit._coords), _width(pit._width), _p(pit._p) {} Chris@16: template iterator_from_2d(const iterator_from_2d& pit) : _coords(pit._coords), _width(pit._width), _p(pit._p) {} Chris@16: Chris@16: private: Chris@16: template friend class iterator_from_2d; Chris@16: friend class boost::iterator_core_access; Chris@16: reference dereference() const { return *_p; } Chris@16: void increment() { Chris@16: ++_coords.x; Chris@16: ++_p.x(); Chris@16: if (_coords.x>=_width) { Chris@16: _coords.x=0; Chris@16: ++_coords.y; Chris@16: _p+=point_t(-_width,1); Chris@16: } Chris@16: } Chris@16: void decrement() { Chris@16: --_coords.x; Chris@16: --_p.x(); Chris@16: if (_coords.x<0) { Chris@16: _coords.x=_width-1; Chris@16: --_coords.y; Chris@16: _p+=point_t(_width,-1); Chris@16: } Chris@16: } Chris@16: Chris@16: GIL_FORCEINLINE void advance(difference_type d) { Chris@16: if (_width==0) return; // unfortunately we need to check for that. Default-constructed images have width of 0 and the code below will throw if executed. Chris@16: point_t delta; Chris@16: if (_coords.x+d>=0) { // not going back to a previous row? Chris@16: delta.x=(_coords.x+(std::ptrdiff_t)d)%_width - _coords.x; Chris@16: delta.y=(_coords.x+(std::ptrdiff_t)d)/_width; Chris@16: } else { Chris@16: delta.x=(_coords.x+(std::ptrdiff_t)d*(1-_width))%_width -_coords.x; Chris@16: delta.y=-(_width-_coords.x-(std::ptrdiff_t)d-1)/_width; Chris@16: } Chris@16: _p+=delta; Chris@16: _coords.x+=delta.x; Chris@16: _coords.y+=delta.y; Chris@16: } Chris@16: Chris@16: difference_type distance_to(const iterator_from_2d& it) const { Chris@16: if (_width==0) return 0; Chris@16: return (it.y_pos()-_coords.y)*_width + (it.x_pos()-_coords.x); Chris@16: } Chris@16: Chris@16: bool equal(const iterator_from_2d& it) const { Chris@16: assert(_width==it.width()); // they must belong to the same image Chris@16: return _coords==it._coords && _p==it._p; Chris@16: } Chris@16: Chris@16: point2 _coords; Chris@16: std::ptrdiff_t _width; Chris@16: Loc2 _p; Chris@16: }; Chris@16: Chris@16: template // Models PixelLocatorConcept Chris@16: struct const_iterator_type > { Chris@16: typedef iterator_from_2d type; Chris@16: }; Chris@16: Chris@16: template // Models PixelLocatorConcept Chris@16: struct iterator_is_mutable > : public iterator_is_mutable {}; Chris@16: Chris@16: Chris@16: ///////////////////////////// Chris@16: // HasDynamicXStepTypeConcept Chris@16: ///////////////////////////// Chris@16: Chris@16: template Chris@16: struct dynamic_x_step_type > { Chris@16: typedef iterator_from_2d::type> type; Chris@16: }; Chris@16: Chris@16: Chris@16: ///////////////////////////// Chris@16: // PixelBasedConcept Chris@16: ///////////////////////////// Chris@16: Chris@16: template // Models PixelLocatorConcept Chris@16: struct color_space_type > : public color_space_type {}; Chris@16: Chris@16: template // Models PixelLocatorConcept Chris@16: struct channel_mapping_type > : public channel_mapping_type {}; Chris@16: Chris@16: template // Models PixelLocatorConcept Chris@16: struct is_planar > : public is_planar {}; Chris@16: Chris@16: template // Models PixelLocatorConcept Chris@16: struct channel_type > : public channel_type {}; Chris@16: Chris@16: } } // namespace boost::gil Chris@16: Chris@16: #endif