1 // 2 // Copyright 2005-2007 Adobe Systems Incorporated 3 // 4 // Distributed under the Boost Software License, Version 1.0 5 // See accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt 7 // 8 #ifndef BOOST_GIL_VIRTUAL_LOCATOR_HPP 9 #define BOOST_GIL_VIRTUAL_LOCATOR_HPP 10 11 #include <boost/gil/dynamic_step.hpp> 12 #include <boost/gil/position_iterator.hpp> 13 14 #include <boost/assert.hpp> 15 #include <boost/iterator/iterator_facade.hpp> 16 17 namespace boost { namespace gil { 18 19 /// \ingroup PixelLocatorModel PixelBasedModel 20 /// \brief A 2D locator over a virtual image 21 /// Upon dereferencing, invokes a given function object passing it its coordinates. 22 /// Models: 23 /// PixelLocatorConcept, 24 /// HasDynamicXStepTypeConcept, 25 /// HasDynamicYStepTypeConcept, 26 /// HasTransposedTypeConcept 27 /// 28 /// \tparam DerefFn Function object that given a point returns a reference. 29 /// Models PixelDereferenceAdaptorConcept. 30 /// \tparam IsTransposed Indicates if locator should navigate in transposed mode. 31 template <typename DerefFn, bool IsTransposed> 32 class virtual_2d_locator 33 : public pixel_2d_locator_base 34 < 35 virtual_2d_locator<DerefFn, IsTransposed>, 36 position_iterator<DerefFn, IsTransposed>, 37 position_iterator<DerefFn, 1-IsTransposed> 38 > 39 { 40 using this_t = virtual_2d_locator<DerefFn, IsTransposed>; 41 public: 42 using parent_t = pixel_2d_locator_base 43 < 44 virtual_2d_locator<DerefFn, IsTransposed>, 45 position_iterator<DerefFn, IsTransposed>, 46 position_iterator<DerefFn, 1-IsTransposed> 47 >; 48 using const_t = virtual_2d_locator<typename DerefFn::const_t, IsTransposed>; 49 using deref_fn_t = DerefFn; 50 using point_t = typename parent_t::point_t; 51 using coord_t = typename parent_t::coord_t; 52 using x_coord_t = typename parent_t::x_coord_t; 53 using y_coord_t = typename parent_t::y_coord_t; 54 using x_iterator = typename parent_t::x_iterator; 55 using y_iterator = typename parent_t::y_iterator; 56 57 template <typename NewDerefFn> 58 struct add_deref 59 { 60 using type = virtual_2d_locator<deref_compose<NewDerefFn, DerefFn>, IsTransposed>; 61 makeboost::gil::virtual_2d_locator::add_deref62 static type make(this_t const& loc, NewDerefFn const& new_deref_fn) 63 { 64 return type(loc.pos(), loc.step(), 65 deref_compose<NewDerefFn, DerefFn>(new_deref_fn, loc.deref_fn())); 66 } 67 }; 68 virtual_2d_locator(point_t const & p={0, 0},point_t const & step={1, 1},deref_fn_t const & deref_fn=deref_fn_t ())69 virtual_2d_locator( 70 point_t const& p = {0, 0}, 71 point_t const& step = {1, 1}, 72 deref_fn_t const& deref_fn = deref_fn_t()) 73 : y_pos_(p, step, deref_fn) 74 {} 75 76 template <typename D, bool TR> virtual_2d_locator(virtual_2d_locator<D,TR> const & loc,coord_t y_step)77 virtual_2d_locator(virtual_2d_locator<D, TR> const &loc, coord_t y_step) 78 : y_pos_(loc.pos(), point_t(loc.step().x, loc.step().y * y_step), loc.deref_fn()) 79 {} 80 81 template <typename D, bool TR> virtual_2d_locator(virtual_2d_locator<D,TR> const & loc,coord_t x_step,coord_t y_step,bool transpose=false)82 virtual_2d_locator(virtual_2d_locator<D, TR> const& loc, coord_t x_step, coord_t y_step, bool transpose = false) 83 : y_pos_(loc.pos() 84 , transpose ? 85 point_t(loc.step().x * y_step, loc.step().y * x_step) : 86 point_t(loc.step().x * x_step, loc.step().y * y_step) 87 , loc.deref_fn()) 88 { 89 BOOST_ASSERT(transpose == (IsTransposed != TR)); 90 } 91 92 template <typename D, bool TR> virtual_2d_locator(virtual_2d_locator<D,TR> const & other)93 virtual_2d_locator(virtual_2d_locator<D, TR> const& other) : y_pos_(other.y_pos_) {} 94 virtual_2d_locator(virtual_2d_locator const & other)95 virtual_2d_locator(virtual_2d_locator const& other) : y_pos_(other.y_pos_) {} 96 virtual_2d_locator& operator=(virtual_2d_locator const& other) = default; 97 operator ==(const this_t & p) const98 bool operator==(const this_t& p) const { return y_pos_ == p.y_pos_; } 99 x()100 auto x() -> x_iterator& 101 { 102 return *gil_reinterpret_cast<x_iterator*>(this); 103 } 104 x() const105 auto x() const -> x_iterator const& 106 { 107 return *gil_reinterpret_cast_c<x_iterator const*>(this); 108 } 109 y()110 auto y() -> y_iterator& { return y_pos_; } y() const111 auto y() const -> y_iterator const& { return y_pos_; } 112 113 /// Returns the y distance between two x_iterators given the difference of their x positions y_distance_to(this_t const & it2,x_coord_t) const114 auto y_distance_to(this_t const& it2, x_coord_t) const -> y_coord_t 115 { 116 return (it2.pos()[1 - IsTransposed] - pos()[1 - IsTransposed]) 117 / step()[1 - IsTransposed]; 118 } 119 120 /// \todo TODO: is there no gap at the end of each row? 121 /// i.e. can we use x_iterator to visit every pixel instead of nested loops? is_1d_traversable(x_coord_t) const122 bool is_1d_traversable(x_coord_t) const { return false; } 123 124 // Methods specific for virtual 2D locator pos() const125 auto pos() const -> point_t const& { return y_pos_.pos(); } step() const126 auto step() const -> point_t const& { return y_pos_.step(); } deref_fn() const127 auto deref_fn() const -> deref_fn_t const& { return y_pos_.deref_fn(); } 128 129 private: 130 template <typename D, bool TR> 131 friend class virtual_2d_locator; 132 133 y_iterator y_pos_; // current position, the step and the dereference object 134 }; 135 136 ///////////////////////////// 137 // PixelBasedConcept 138 ///////////////////////////// 139 140 template <typename D, bool TR> 141 struct channel_type<virtual_2d_locator<D, TR>> 142 : channel_type<typename virtual_2d_locator<D, TR>::parent_t> 143 { 144 }; 145 146 template <typename D, bool TR> 147 struct color_space_type<virtual_2d_locator<D, TR>> 148 : color_space_type<typename virtual_2d_locator<D, TR>::parent_t> 149 { 150 }; 151 152 template <typename D, bool TR> 153 struct channel_mapping_type<virtual_2d_locator<D, TR>> 154 : channel_mapping_type<typename virtual_2d_locator<D, TR>::parent_t> 155 { 156 }; 157 158 template <typename D, bool TR> 159 struct is_planar<virtual_2d_locator<D, TR>> 160 : is_planar<typename virtual_2d_locator<D, TR>::parent_t> 161 { 162 }; 163 164 ///////////////////////////// 165 // HasDynamicXStepTypeConcept 166 ///////////////////////////// 167 168 template <typename D, bool TR> 169 struct dynamic_x_step_type<virtual_2d_locator<D,TR>> 170 { 171 using type = virtual_2d_locator<D,TR>; 172 }; 173 174 ///////////////////////////// 175 // HasDynamicYStepTypeConcept 176 ///////////////////////////// 177 178 template <typename D, bool TR> 179 struct dynamic_y_step_type<virtual_2d_locator<D,TR>> 180 { 181 using type = virtual_2d_locator<D,TR>; 182 }; 183 184 ///////////////////////////// 185 // HasTransposedTypeConcept 186 ///////////////////////////// 187 188 template <typename D, bool IsTransposed> 189 struct transposed_type<virtual_2d_locator<D,IsTransposed>> 190 { 191 using type = virtual_2d_locator<D,1-IsTransposed>; 192 }; 193 194 }} // namespace boost::gil 195 196 #endif 197