// // Copyright 2005-2007 Adobe Systems Incorporated // // Distributed under the Boost Software License, Version 1.0 // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt // #ifndef BOOST_GIL_VIRTUAL_LOCATOR_HPP #define BOOST_GIL_VIRTUAL_LOCATOR_HPP #include #include #include #include namespace boost { namespace gil { /// \ingroup PixelLocatorModel PixelBasedModel /// \brief A 2D locator over a virtual image /// Upon dereferencing, invokes a given function object passing it its coordinates. /// Models: /// PixelLocatorConcept, /// HasDynamicXStepTypeConcept, /// HasDynamicYStepTypeConcept, /// HasTransposedTypeConcept /// /// \tparam DerefFn Function object that given a point returns a reference. /// Models PixelDereferenceAdaptorConcept. /// \tparam IsTransposed Indicates if locator should navigate in transposed mode. template class virtual_2d_locator : public pixel_2d_locator_base < virtual_2d_locator, position_iterator, position_iterator > { using this_t = virtual_2d_locator; public: using parent_t = pixel_2d_locator_base < virtual_2d_locator, position_iterator, position_iterator >; using const_t = virtual_2d_locator; using deref_fn_t = DerefFn; using point_t = typename parent_t::point_t; 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; template struct add_deref { using type = virtual_2d_locator, IsTransposed>; static type make(this_t const& loc, NewDerefFn const& new_deref_fn) { return type(loc.pos(), loc.step(), deref_compose(new_deref_fn, loc.deref_fn())); } }; virtual_2d_locator( point_t const& p = {0, 0}, point_t const& step = {1, 1}, deref_fn_t const& deref_fn = deref_fn_t()) : y_pos_(p, step, deref_fn) {} template virtual_2d_locator(virtual_2d_locator const &loc, coord_t y_step) : y_pos_(loc.pos(), point_t(loc.step().x, loc.step().y * y_step), loc.deref_fn()) {} template virtual_2d_locator(virtual_2d_locator const& loc, coord_t x_step, coord_t y_step, bool transpose = false) : y_pos_(loc.pos() , transpose ? point_t(loc.step().x * y_step, loc.step().y * x_step) : point_t(loc.step().x * x_step, loc.step().y * y_step) , loc.deref_fn()) { BOOST_ASSERT(transpose == (IsTransposed != TR)); } template virtual_2d_locator(virtual_2d_locator const& other) : y_pos_(other.y_pos_) {} virtual_2d_locator(virtual_2d_locator const& other) : y_pos_(other.y_pos_) {} virtual_2d_locator& operator=(virtual_2d_locator const& other) = default; bool operator==(const this_t& p) const { return y_pos_ == p.y_pos_; } auto x() -> x_iterator& { return *gil_reinterpret_cast(this); } auto x() const -> x_iterator const& { return *gil_reinterpret_cast_c(this); } auto y() -> y_iterator& { return y_pos_; } auto y() const -> y_iterator const& { return y_pos_; } /// Returns the y distance between two x_iterators given the difference of their x positions auto y_distance_to(this_t const& it2, x_coord_t) const -> y_coord_t { return (it2.pos()[1 - IsTransposed] - pos()[1 - IsTransposed]) / step()[1 - IsTransposed]; } /// \todo TODO: is there no gap at the end of each row? /// i.e. can we use x_iterator to visit every pixel instead of nested loops? bool is_1d_traversable(x_coord_t) const { return false; } // Methods specific for virtual 2D locator auto pos() const -> point_t const& { return y_pos_.pos(); } auto step() const -> point_t const& { return y_pos_.step(); } auto deref_fn() const -> deref_fn_t const& { return y_pos_.deref_fn(); } private: template friend class virtual_2d_locator; y_iterator y_pos_; // current position, the step and the dereference object }; ///////////////////////////// // PixelBasedConcept ///////////////////////////// template struct channel_type> : channel_type::parent_t> { }; template struct color_space_type> : color_space_type::parent_t> { }; template struct channel_mapping_type> : channel_mapping_type::parent_t> { }; template struct is_planar> : is_planar::parent_t> { }; ///////////////////////////// // HasDynamicXStepTypeConcept ///////////////////////////// template struct dynamic_x_step_type> { using type = virtual_2d_locator; }; ///////////////////////////// // HasDynamicYStepTypeConcept ///////////////////////////// template struct dynamic_y_step_type> { using type = virtual_2d_locator; }; ///////////////////////////// // HasTransposedTypeConcept ///////////////////////////// template struct transposed_type> { using type = virtual_2d_locator; }; }} // namespace boost::gil #endif