pixel_iterator_adaptor.hpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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. #include <boost/gil/concepts.hpp>
  11. #include <boost/gil/pixel_iterator.hpp>
  12. #include <boost/iterator/iterator_facade.hpp>
  13. #include <iterator>
  14. namespace boost { namespace gil {
  15. /// \defgroup PixelIteratorModelDerefPtr dereference_iterator_adaptor
  16. /// \ingroup PixelIteratorModel
  17. /// \brief An iterator that invokes a provided function object upon dereference. Models: IteratorAdaptorConcept, PixelIteratorConcept
  18. /// \ingroup PixelIteratorModelDerefPtr PixelBasedModel
  19. /// \brief An adaptor over an existing iterator that provides for custom filter on dereferencing the object. Models: IteratorAdaptorConcept, PixelIteratorConcept
  20. template <typename Iterator, // Models Iterator
  21. typename DFn> // Models Returns the result of dereferencing a given iterator of type Iterator
  22. class dereference_iterator_adaptor : public iterator_adaptor<dereference_iterator_adaptor<Iterator,DFn>,
  23. Iterator,
  24. typename DFn::value_type,
  25. typename std::iterator_traits<Iterator>::iterator_category,
  26. typename DFn::reference,
  27. use_default> {
  28. DFn _deref_fn;
  29. public:
  30. using parent_t = iterator_adaptor<dereference_iterator_adaptor<Iterator,DFn>,
  31. Iterator,
  32. typename DFn::value_type,
  33. typename std::iterator_traits<Iterator>::iterator_category,
  34. typename DFn::reference,
  35. use_default>;
  36. using reference = typename DFn::result_type;
  37. using difference_type = typename std::iterator_traits<Iterator>::difference_type;
  38. using dereference_fn = DFn;
  39. dereference_iterator_adaptor() {}
  40. template <typename Iterator1>
  41. dereference_iterator_adaptor(const dereference_iterator_adaptor<Iterator1,DFn>& dit) : parent_t(dit.base()), _deref_fn(dit._deref_fn) {}
  42. dereference_iterator_adaptor(Iterator it, DFn deref_fn=DFn()) : parent_t(it), _deref_fn(deref_fn) {}
  43. template <typename Iterator1, typename DFn1>
  44. dereference_iterator_adaptor(const dereference_iterator_adaptor<Iterator1,DFn1>& it) : parent_t(it.base()), _deref_fn(it._deref_fn) {}
  45. /// For some reason operator[] provided by iterator_facade returns a custom class that is convertible to reference
  46. /// We require our own reference because it is registered in iterator_traits
  47. reference operator[](difference_type d) const { return *(*this+d);}
  48. // although iterator_adaptor defines these, the default implementation computes distance and compares for zero.
  49. // it is often faster to just apply the relation operator to the base
  50. bool operator> (const dereference_iterator_adaptor& p) const { return this->base_reference()> p.base_reference(); }
  51. bool operator< (const dereference_iterator_adaptor& p) const { return this->base_reference()< p.base_reference(); }
  52. bool operator>=(const dereference_iterator_adaptor& p) const { return this->base_reference()>=p.base_reference(); }
  53. bool operator<=(const dereference_iterator_adaptor& p) const { return this->base_reference()<=p.base_reference(); }
  54. bool operator==(const dereference_iterator_adaptor& p) const { return this->base_reference()==p.base_reference(); }
  55. bool operator!=(const dereference_iterator_adaptor& p) const { return this->base_reference()!=p.base_reference(); }
  56. Iterator& base() { return this->base_reference(); }
  57. const Iterator& base() const { return this->base_reference(); }
  58. const DFn& deref_fn() const { return _deref_fn; }
  59. private:
  60. template <typename Iterator1, typename DFn1>
  61. friend class dereference_iterator_adaptor;
  62. friend class boost::iterator_core_access;
  63. reference dereference() const { return _deref_fn(*(this->base_reference())); }
  64. };
  65. template <typename I, typename DFn>
  66. struct const_iterator_type<dereference_iterator_adaptor<I,DFn> > {
  67. using type = dereference_iterator_adaptor<typename const_iterator_type<I>::type,typename DFn::const_t>;
  68. };
  69. template <typename I, typename DFn>
  70. struct iterator_is_mutable<dereference_iterator_adaptor<I,DFn> > : public mpl::bool_<DFn::is_mutable> {};
  71. template <typename I, typename DFn>
  72. struct is_iterator_adaptor<dereference_iterator_adaptor<I,DFn> > : public mpl::true_{};
  73. template <typename I, typename DFn>
  74. struct iterator_adaptor_get_base<dereference_iterator_adaptor<I,DFn> > {
  75. using type = I;
  76. };
  77. template <typename I, typename DFn, typename NewBaseIterator>
  78. struct iterator_adaptor_rebind<dereference_iterator_adaptor<I,DFn>,NewBaseIterator> {
  79. using type = dereference_iterator_adaptor<NewBaseIterator,DFn>;
  80. };
  81. /////////////////////////////
  82. // PixelBasedConcept
  83. /////////////////////////////
  84. template <typename I, typename DFn>
  85. struct color_space_type<dereference_iterator_adaptor<I,DFn> > : public color_space_type<typename DFn::value_type> {};
  86. template <typename I, typename DFn>
  87. struct channel_mapping_type<dereference_iterator_adaptor<I,DFn> > : public channel_mapping_type<typename DFn::value_type> {};
  88. template <typename I, typename DFn>
  89. struct is_planar<dereference_iterator_adaptor<I,DFn> > : public is_planar<typename DFn::value_type> {};
  90. template <typename I, typename DFn>
  91. struct channel_type<dereference_iterator_adaptor<I,DFn> > : public channel_type<typename DFn::value_type> {};
  92. /////////////////////////////
  93. // MemoryBasedIteratorConcept
  94. /////////////////////////////
  95. template <typename Iterator, typename DFn>
  96. struct byte_to_memunit<dereference_iterator_adaptor<Iterator,DFn> > : public byte_to_memunit<Iterator> {};
  97. template <typename Iterator, typename DFn>
  98. inline typename std::iterator_traits<Iterator>::difference_type
  99. memunit_step(const dereference_iterator_adaptor<Iterator,DFn>& p) {
  100. return memunit_step(p.base());
  101. }
  102. template <typename Iterator, typename DFn>
  103. inline typename std::iterator_traits<Iterator>::difference_type
  104. memunit_distance(const dereference_iterator_adaptor<Iterator,DFn>& p1,
  105. const dereference_iterator_adaptor<Iterator,DFn>& p2) {
  106. return memunit_distance(p1.base(),p2.base());
  107. }
  108. template <typename Iterator, typename DFn>
  109. inline void memunit_advance(dereference_iterator_adaptor<Iterator,DFn>& p,
  110. typename std::iterator_traits<Iterator>::difference_type diff) {
  111. memunit_advance(p.base(), diff);
  112. }
  113. template <typename Iterator, typename DFn>
  114. inline dereference_iterator_adaptor<Iterator,DFn>
  115. memunit_advanced(const dereference_iterator_adaptor<Iterator,DFn>& p,
  116. typename std::iterator_traits<Iterator>::difference_type diff) {
  117. return dereference_iterator_adaptor<Iterator,DFn>(memunit_advanced(p.base(), diff), p.deref_fn());
  118. }
  119. template <typename Iterator, typename DFn>
  120. inline
  121. typename std::iterator_traits<dereference_iterator_adaptor<Iterator,DFn> >::reference
  122. memunit_advanced_ref(const dereference_iterator_adaptor<Iterator,DFn>& p,
  123. typename std::iterator_traits<Iterator>::difference_type diff) {
  124. return *memunit_advanced(p, diff);
  125. }
  126. /////////////////////////////
  127. // HasDynamicXStepTypeConcept
  128. /////////////////////////////
  129. template <typename Iterator, typename DFn>
  130. struct dynamic_x_step_type<dereference_iterator_adaptor<Iterator,DFn> > {
  131. using type = dereference_iterator_adaptor<typename dynamic_x_step_type<Iterator>::type,DFn>;
  132. };
  133. /// \brief Returns the type (and creates an instance) of an iterator that invokes the given dereference adaptor upon dereferencing
  134. /// \ingroup PixelIteratorModelDerefPtr
  135. template <typename Iterator, typename Deref>
  136. struct iterator_add_deref {
  137. GIL_CLASS_REQUIRE(Deref, boost::gil, PixelDereferenceAdaptorConcept)
  138. using type = dereference_iterator_adaptor<Iterator, Deref>;
  139. static type make(const Iterator& it, const Deref& d) { return type(it,d); }
  140. };
  141. /// \ingroup PixelIteratorModelDerefPtr
  142. /// \brief For dereference iterator adaptors, compose the new function object after the old one
  143. template <typename Iterator, typename PREV_DEREF, typename Deref>
  144. struct iterator_add_deref<dereference_iterator_adaptor<Iterator, PREV_DEREF>,Deref> {
  145. // GIL_CLASS_REQUIRE(Deref, boost::gil, PixelDereferenceAdaptorConcept)
  146. using type = dereference_iterator_adaptor<Iterator, deref_compose<Deref,PREV_DEREF>>;
  147. static type make(const dereference_iterator_adaptor<Iterator, PREV_DEREF>& it, const Deref& d) {
  148. return type(it.base(),deref_compose<Deref,PREV_DEREF>(d,it.deref_fn()));
  149. }
  150. };
  151. }} // namespace boost::gil
  152. #endif