1 | /* |
2 | Copyright 2005-2007 Adobe Systems Incorporated |
3 | |
4 | Use, modification and distribution are subject to the Boost Software License, |
5 | Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
6 | http://www.boost.org/LICENSE_1_0.txt). |
7 | |
8 | See http://opensource.adobe.com/gil for most recent version including documentation. |
9 | */ |
10 | |
11 | /*************************************************************************************************/ |
12 | |
13 | #ifndef GIL_PIXEL_ITERATOR_ADAPTOR_H |
14 | #define GIL_PIXEL_ITERATOR_ADAPTOR_H |
15 | |
16 | //////////////////////////////////////////////////////////////////////////////////////// |
17 | /// \file |
18 | /// \brief pixel step iterator, pixel image iterator and pixel dereference iterator |
19 | /// \author Lubomir Bourdev and Hailin Jin \n |
20 | /// Adobe Systems Incorporated |
21 | /// \date 2005-2007 \n Last updated on February 16, 2007 |
22 | /// |
23 | //////////////////////////////////////////////////////////////////////////////////////// |
24 | |
25 | #include <iterator> |
26 | #include <boost/iterator/iterator_facade.hpp> |
27 | #include "gil_config.hpp" |
28 | #include "gil_concept.hpp" |
29 | #include "pixel_iterator.hpp" |
30 | |
31 | namespace boost { namespace gil { |
32 | |
33 | |
34 | /// \defgroup PixelIteratorModelDerefPtr dereference_iterator_adaptor |
35 | /// \ingroup PixelIteratorModel |
36 | /// \brief An iterator that invokes a provided function object upon dereference. Models: IteratorAdaptorConcept, PixelIteratorConcept |
37 | |
38 | |
39 | /// \ingroup PixelIteratorModelDerefPtr PixelBasedModel |
40 | /// \brief An adaptor over an existing iterator that provides for custom filter on dereferencing the object. Models: IteratorAdaptorConcept, PixelIteratorConcept |
41 | |
42 | template <typename Iterator, // Models Iterator |
43 | typename DFn> // Models Returns the result of dereferencing a given iterator of type Iterator |
44 | class dereference_iterator_adaptor : public iterator_adaptor<dereference_iterator_adaptor<Iterator,DFn>, |
45 | Iterator, |
46 | typename DFn::value_type, |
47 | typename std::iterator_traits<Iterator>::iterator_category, |
48 | typename DFn::reference, |
49 | use_default> { |
50 | DFn _deref_fn; |
51 | public: |
52 | typedef iterator_adaptor<dereference_iterator_adaptor<Iterator,DFn>, |
53 | Iterator, |
54 | typename DFn::value_type, |
55 | typename std::iterator_traits<Iterator>::iterator_category, |
56 | typename DFn::reference, |
57 | use_default> parent_t; |
58 | typedef typename DFn::result_type reference; |
59 | typedef typename std::iterator_traits<Iterator>::difference_type difference_type; |
60 | typedef DFn dereference_fn; |
61 | |
62 | dereference_iterator_adaptor() {} |
63 | template <typename Iterator1> |
64 | dereference_iterator_adaptor(const dereference_iterator_adaptor<Iterator1,DFn>& dit) : parent_t(dit.base()), _deref_fn(dit._deref_fn) {} |
65 | dereference_iterator_adaptor(Iterator it, DFn deref_fn=DFn()) : parent_t(it), _deref_fn(deref_fn) {} |
66 | template <typename Iterator1, typename DFn1> |
67 | dereference_iterator_adaptor(const dereference_iterator_adaptor<Iterator1,DFn1>& it) : parent_t(it.base()), _deref_fn(it._deref_fn) {} |
68 | /// For some reason operator[] provided by iterator_facade returns a custom class that is convertible to reference |
69 | /// We require our own reference because it is registered in iterator_traits |
70 | reference operator[](difference_type d) const { return *(*this+d);} |
71 | |
72 | // although iterator_adaptor defines these, the default implementation computes distance and compares for zero. |
73 | // it is often faster to just apply the relation operator to the base |
74 | bool operator> (const dereference_iterator_adaptor& p) const { return this->base_reference()> p.base_reference(); } |
75 | bool operator< (const dereference_iterator_adaptor& p) const { return this->base_reference()< p.base_reference(); } |
76 | bool operator>=(const dereference_iterator_adaptor& p) const { return this->base_reference()>=p.base_reference(); } |
77 | bool operator<=(const dereference_iterator_adaptor& p) const { return this->base_reference()<=p.base_reference(); } |
78 | bool operator==(const dereference_iterator_adaptor& p) const { return this->base_reference()==p.base_reference(); } |
79 | bool operator!=(const dereference_iterator_adaptor& p) const { return this->base_reference()!=p.base_reference(); } |
80 | |
81 | Iterator& base() { return this->base_reference(); } |
82 | const Iterator& base() const { return this->base_reference(); } |
83 | const DFn& deref_fn() const { return _deref_fn; } |
84 | private: |
85 | template <typename Iterator1, typename DFn1> |
86 | friend class dereference_iterator_adaptor; |
87 | friend class boost::iterator_core_access; |
88 | |
89 | reference dereference() const { return _deref_fn(*(this->base_reference())); } |
90 | }; |
91 | |
92 | template <typename I, typename DFn> |
93 | struct const_iterator_type<dereference_iterator_adaptor<I,DFn> > { |
94 | typedef dereference_iterator_adaptor<typename const_iterator_type<I>::type,typename DFn::const_t> type; |
95 | }; |
96 | |
97 | template <typename I, typename DFn> |
98 | struct iterator_is_mutable<dereference_iterator_adaptor<I,DFn> > : public mpl::bool_<DFn::is_mutable> {}; |
99 | |
100 | |
101 | template <typename I, typename DFn> |
102 | struct is_iterator_adaptor<dereference_iterator_adaptor<I,DFn> > : public mpl::true_{}; |
103 | |
104 | template <typename I, typename DFn> |
105 | struct iterator_adaptor_get_base<dereference_iterator_adaptor<I,DFn> > { |
106 | typedef I type; |
107 | }; |
108 | |
109 | template <typename I, typename DFn, typename NewBaseIterator> |
110 | struct iterator_adaptor_rebind<dereference_iterator_adaptor<I,DFn>,NewBaseIterator> { |
111 | typedef dereference_iterator_adaptor<NewBaseIterator,DFn> type; |
112 | }; |
113 | |
114 | ///////////////////////////// |
115 | // PixelBasedConcept |
116 | ///////////////////////////// |
117 | |
118 | template <typename I, typename DFn> |
119 | struct color_space_type<dereference_iterator_adaptor<I,DFn> > : public color_space_type<typename DFn::value_type> {}; |
120 | |
121 | template <typename I, typename DFn> |
122 | struct channel_mapping_type<dereference_iterator_adaptor<I,DFn> > : public channel_mapping_type<typename DFn::value_type> {}; |
123 | |
124 | template <typename I, typename DFn> |
125 | struct is_planar<dereference_iterator_adaptor<I,DFn> > : public is_planar<typename DFn::value_type> {}; |
126 | |
127 | template <typename I, typename DFn> |
128 | struct channel_type<dereference_iterator_adaptor<I,DFn> > : public channel_type<typename DFn::value_type> {}; |
129 | |
130 | |
131 | ///////////////////////////// |
132 | // MemoryBasedIteratorConcept |
133 | ///////////////////////////// |
134 | |
135 | template <typename Iterator, typename DFn> |
136 | struct byte_to_memunit<dereference_iterator_adaptor<Iterator,DFn> > : public byte_to_memunit<Iterator> {}; |
137 | |
138 | template <typename Iterator, typename DFn> |
139 | inline typename std::iterator_traits<Iterator>::difference_type |
140 | memunit_step(const dereference_iterator_adaptor<Iterator,DFn>& p) { |
141 | return memunit_step(p.base()); |
142 | } |
143 | |
144 | template <typename Iterator, typename DFn> |
145 | inline typename std::iterator_traits<Iterator>::difference_type |
146 | memunit_distance(const dereference_iterator_adaptor<Iterator,DFn>& p1, |
147 | const dereference_iterator_adaptor<Iterator,DFn>& p2) { |
148 | return memunit_distance(p1.base(),p2.base()); |
149 | } |
150 | |
151 | template <typename Iterator, typename DFn> |
152 | inline void memunit_advance(dereference_iterator_adaptor<Iterator,DFn>& p, |
153 | typename std::iterator_traits<Iterator>::difference_type diff) { |
154 | memunit_advance(p.base(), diff); |
155 | } |
156 | |
157 | template <typename Iterator, typename DFn> |
158 | inline dereference_iterator_adaptor<Iterator,DFn> |
159 | memunit_advanced(const dereference_iterator_adaptor<Iterator,DFn>& p, |
160 | typename std::iterator_traits<Iterator>::difference_type diff) { |
161 | return dereference_iterator_adaptor<Iterator,DFn>(memunit_advanced(p.base(), diff), p.deref_fn()); |
162 | } |
163 | |
164 | |
165 | template <typename Iterator, typename DFn> |
166 | inline |
167 | typename std::iterator_traits<dereference_iterator_adaptor<Iterator,DFn> >::reference |
168 | memunit_advanced_ref(const dereference_iterator_adaptor<Iterator,DFn>& p, |
169 | typename std::iterator_traits<Iterator>::difference_type diff) { |
170 | return *memunit_advanced(p, diff); |
171 | } |
172 | |
173 | ///////////////////////////// |
174 | // HasDynamicXStepTypeConcept |
175 | ///////////////////////////// |
176 | |
177 | template <typename Iterator, typename DFn> |
178 | struct dynamic_x_step_type<dereference_iterator_adaptor<Iterator,DFn> > { |
179 | typedef dereference_iterator_adaptor<typename dynamic_x_step_type<Iterator>::type,DFn> type; |
180 | }; |
181 | |
182 | /// \brief Returns the type (and creates an instance) of an iterator that invokes the given dereference adaptor upon dereferencing |
183 | /// \ingroup PixelIteratorModelDerefPtr |
184 | template <typename Iterator, typename Deref> |
185 | struct iterator_add_deref { |
186 | GIL_CLASS_REQUIRE(Deref, boost::gil, PixelDereferenceAdaptorConcept) |
187 | |
188 | typedef dereference_iterator_adaptor<Iterator, Deref> type; |
189 | |
190 | static type make(const Iterator& it, const Deref& d) { return type(it,d); } |
191 | }; |
192 | |
193 | /// \ingroup PixelIteratorModelDerefPtr |
194 | /// \brief For dereference iterator adaptors, compose the new function object after the old one |
195 | template <typename Iterator, typename PREV_DEREF, typename Deref> |
196 | struct iterator_add_deref<dereference_iterator_adaptor<Iterator, PREV_DEREF>,Deref> { |
197 | // GIL_CLASS_REQUIRE(Deref, boost::gil, PixelDereferenceAdaptorConcept) |
198 | |
199 | typedef dereference_iterator_adaptor<Iterator, deref_compose<Deref,PREV_DEREF> > type; |
200 | |
201 | static type make(const dereference_iterator_adaptor<Iterator, PREV_DEREF>& it, const Deref& d) { |
202 | return type(it.base(),deref_compose<Deref,PREV_DEREF>(d,it.deref_fn())); |
203 | } |
204 | }; |
205 | |
206 | } } // namespace boost::gil |
207 | |
208 | #endif |
209 | |