• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_PIXEL_ITERATOR_ADAPTOR_HPP
9 #define BOOST_GIL_PIXEL_ITERATOR_ADAPTOR_HPP
10 
11 #include <boost/gil/concepts.hpp>
12 #include <boost/gil/pixel_iterator.hpp>
13 
14 #include <boost/iterator/iterator_facade.hpp>
15 
16 #include <iterator>
17 
18 namespace boost { namespace gil {
19 
20 /// \defgroup PixelIteratorModelDerefPtr dereference_iterator_adaptor
21 /// \ingroup PixelIteratorModel
22 /// \brief An iterator that invokes a provided function object upon dereference. Models: IteratorAdaptorConcept, PixelIteratorConcept
23 
24 /// \ingroup PixelIteratorModelDerefPtr PixelBasedModel
25 /// \brief An adaptor over an existing iterator that provides for custom filter on dereferencing the object. Models: IteratorAdaptorConcept, PixelIteratorConcept
26 
27 template <typename Iterator,    // Models Iterator
28           typename DFn>  // Models Returns the result of dereferencing a given iterator of type Iterator
29 class dereference_iterator_adaptor : public iterator_adaptor<dereference_iterator_adaptor<Iterator,DFn>,
30                                                              Iterator,
31                                                              typename DFn::value_type,
32                                                              typename std::iterator_traits<Iterator>::iterator_category,
33                                                              typename DFn::reference,
34                                                              use_default> {
35     DFn _deref_fn;
36 public:
37     using parent_t = iterator_adaptor<dereference_iterator_adaptor<Iterator,DFn>,
38                                     Iterator,
39                                     typename DFn::value_type,
40                                     typename std::iterator_traits<Iterator>::iterator_category,
41                                     typename DFn::reference,
42                                     use_default>;
43     using reference = typename DFn::result_type;
44     using difference_type = typename std::iterator_traits<Iterator>::difference_type;
45     using dereference_fn = DFn;
46 
dereference_iterator_adaptor()47     dereference_iterator_adaptor() {}
48     template <typename Iterator1>
dereference_iterator_adaptor(const dereference_iterator_adaptor<Iterator1,DFn> & dit)49     dereference_iterator_adaptor(const dereference_iterator_adaptor<Iterator1,DFn>& dit) : parent_t(dit.base()), _deref_fn(dit._deref_fn) {}
dereference_iterator_adaptor(Iterator it,DFn deref_fn=DFn ())50     dereference_iterator_adaptor(Iterator it, DFn deref_fn=DFn()) : parent_t(it), _deref_fn(deref_fn) {}
51     template <typename Iterator1, typename DFn1>
dereference_iterator_adaptor(const dereference_iterator_adaptor<Iterator1,DFn1> & it)52     dereference_iterator_adaptor(const dereference_iterator_adaptor<Iterator1,DFn1>& it) : parent_t(it.base()), _deref_fn(it._deref_fn) {}
53     /// For some reason operator[] provided by iterator_facade returns a custom class that is convertible to reference
54     /// We require our own reference because it is registered in iterator_traits
operator [](difference_type d) const55     reference operator[](difference_type d) const { return *(*this+d);}
56 
57     // although iterator_adaptor defines these, the default implementation computes distance and compares for zero.
58     // it is often faster to just apply the relation operator to the base
operator >(const dereference_iterator_adaptor & p) const59     bool    operator> (const dereference_iterator_adaptor& p) const { return this->base_reference()> p.base_reference(); }
operator <(const dereference_iterator_adaptor & p) const60     bool    operator< (const dereference_iterator_adaptor& p) const { return this->base_reference()< p.base_reference(); }
operator >=(const dereference_iterator_adaptor & p) const61     bool    operator>=(const dereference_iterator_adaptor& p) const { return this->base_reference()>=p.base_reference(); }
operator <=(const dereference_iterator_adaptor & p) const62     bool    operator<=(const dereference_iterator_adaptor& p) const { return this->base_reference()<=p.base_reference(); }
operator ==(const dereference_iterator_adaptor & p) const63     bool    operator==(const dereference_iterator_adaptor& p) const { return this->base_reference()==p.base_reference(); }
operator !=(const dereference_iterator_adaptor & p) const64     bool    operator!=(const dereference_iterator_adaptor& p) const { return this->base_reference()!=p.base_reference(); }
65 
base()66     Iterator& base()              { return this->base_reference(); }
base() const67     const Iterator& base() const  { return this->base_reference(); }
deref_fn() const68     const DFn& deref_fn() const { return _deref_fn; }
69 private:
70     template <typename Iterator1, typename DFn1>
71     friend class dereference_iterator_adaptor;
72     friend class boost::iterator_core_access;
73 
dereference() const74     reference dereference() const { return _deref_fn(*(this->base_reference())); }
75 };
76 
77 template <typename I, typename DFn>
78 struct const_iterator_type<dereference_iterator_adaptor<I,DFn> > {
79     using type = dereference_iterator_adaptor<typename const_iterator_type<I>::type,typename DFn::const_t>;
80 };
81 
82 template <typename I, typename DFn>
83 struct iterator_is_mutable<dereference_iterator_adaptor<I, DFn>>
84     : std::integral_constant<bool, DFn::is_mutable>
85 {};
86 
87 
88 template <typename I, typename DFn>
89 struct is_iterator_adaptor<dereference_iterator_adaptor<I, DFn>> : std::true_type {};
90 
91 template <typename I, typename DFn>
92 struct iterator_adaptor_get_base<dereference_iterator_adaptor<I, DFn>>
93 {
94     using type = I;
95 };
96 
97 template <typename I, typename DFn, typename NewBaseIterator>
98 struct iterator_adaptor_rebind<dereference_iterator_adaptor<I,DFn>,NewBaseIterator> {
99     using type = dereference_iterator_adaptor<NewBaseIterator,DFn>;
100 };
101 
102 /////////////////////////////
103 //  PixelBasedConcept
104 /////////////////////////////
105 
106 template <typename I, typename DFn>
107 struct color_space_type<dereference_iterator_adaptor<I,DFn> > : public color_space_type<typename DFn::value_type> {};
108 
109 template <typename I, typename DFn>
110 struct channel_mapping_type<dereference_iterator_adaptor<I,DFn> > : public channel_mapping_type<typename DFn::value_type> {};
111 
112 template <typename I, typename DFn>
113 struct is_planar<dereference_iterator_adaptor<I,DFn> > : public is_planar<typename DFn::value_type> {};
114 
115 template <typename I, typename DFn>
116 struct channel_type<dereference_iterator_adaptor<I,DFn> > : public channel_type<typename DFn::value_type> {};
117 
118 
119 /////////////////////////////
120 //  MemoryBasedIteratorConcept
121 /////////////////////////////
122 
123 template <typename Iterator, typename DFn>
124 struct byte_to_memunit<dereference_iterator_adaptor<Iterator,DFn> > : public byte_to_memunit<Iterator> {};
125 
126 template <typename Iterator, typename DFn>
127 inline typename std::iterator_traits<Iterator>::difference_type
memunit_step(const dereference_iterator_adaptor<Iterator,DFn> & p)128 memunit_step(const dereference_iterator_adaptor<Iterator,DFn>& p) {
129     return memunit_step(p.base());
130 }
131 
132 template <typename Iterator, typename DFn>
133 inline typename std::iterator_traits<Iterator>::difference_type
memunit_distance(const dereference_iterator_adaptor<Iterator,DFn> & p1,const dereference_iterator_adaptor<Iterator,DFn> & p2)134 memunit_distance(const dereference_iterator_adaptor<Iterator,DFn>& p1,
135               const dereference_iterator_adaptor<Iterator,DFn>& p2) {
136     return memunit_distance(p1.base(),p2.base());
137 }
138 
139 template <typename Iterator, typename DFn>
memunit_advance(dereference_iterator_adaptor<Iterator,DFn> & p,typename std::iterator_traits<Iterator>::difference_type diff)140 inline void memunit_advance(dereference_iterator_adaptor<Iterator,DFn>& p,
141                          typename std::iterator_traits<Iterator>::difference_type diff) {
142     memunit_advance(p.base(), diff);
143 }
144 
145 template <typename Iterator, typename DFn>
146 inline dereference_iterator_adaptor<Iterator,DFn>
memunit_advanced(const dereference_iterator_adaptor<Iterator,DFn> & p,typename std::iterator_traits<Iterator>::difference_type diff)147 memunit_advanced(const dereference_iterator_adaptor<Iterator,DFn>& p,
148               typename std::iterator_traits<Iterator>::difference_type diff) {
149     return dereference_iterator_adaptor<Iterator,DFn>(memunit_advanced(p.base(), diff), p.deref_fn());
150 }
151 
152 
153 template <typename Iterator, typename DFn>
154 inline
155 typename std::iterator_traits<dereference_iterator_adaptor<Iterator,DFn> >::reference
memunit_advanced_ref(const dereference_iterator_adaptor<Iterator,DFn> & p,typename std::iterator_traits<Iterator>::difference_type diff)156 memunit_advanced_ref(const dereference_iterator_adaptor<Iterator,DFn>& p,
157                   typename std::iterator_traits<Iterator>::difference_type diff) {
158     return *memunit_advanced(p, diff);
159 }
160 
161 /////////////////////////////
162 //  HasDynamicXStepTypeConcept
163 /////////////////////////////
164 
165 template <typename Iterator, typename DFn>
166 struct dynamic_x_step_type<dereference_iterator_adaptor<Iterator,DFn> > {
167     using type = dereference_iterator_adaptor<typename dynamic_x_step_type<Iterator>::type,DFn>;
168 };
169 
170 /// \brief Returns the type (and creates an instance) of an iterator that invokes the given dereference adaptor upon dereferencing
171 /// \ingroup PixelIteratorModelDerefPtr
172 template <typename Iterator, typename Deref>
173 struct iterator_add_deref {
174     BOOST_GIL_CLASS_REQUIRE(Deref, boost::gil, PixelDereferenceAdaptorConcept)
175 
176     using type = dereference_iterator_adaptor<Iterator, Deref>;
177 
makeboost::gil::iterator_add_deref178     static type make(const Iterator& it, const Deref& d) { return type(it,d); }
179 };
180 
181 /// \ingroup PixelIteratorModelDerefPtr
182 /// \brief For dereference iterator adaptors, compose the new function object after the old one
183 template <typename Iterator, typename PREV_DEREF, typename Deref>
184 struct iterator_add_deref<dereference_iterator_adaptor<Iterator, PREV_DEREF>,Deref> {
185 //    BOOST_GIL_CLASS_REQUIRE(Deref, boost::gil, PixelDereferenceAdaptorConcept)
186 
187     using type = dereference_iterator_adaptor<Iterator, deref_compose<Deref,PREV_DEREF>>;
188 
makeboost::gil::iterator_add_deref189     static type make(const dereference_iterator_adaptor<Iterator, PREV_DEREF>& it, const Deref& d) {
190         return type(it.base(),deref_compose<Deref,PREV_DEREF>(d,it.deref_fn()));
191     }
192 };
193 
194 }}  // namespace boost::gil
195 
196 #endif
197