planar_pixel_iterator.hpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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_PLANAR_PIXEL_ITERATOR_HPP
  9. #define BOOST_GIL_PLANAR_PIXEL_ITERATOR_HPP
  10. #include <boost/gil/pixel.hpp>
  11. #include <boost/gil/step_iterator.hpp>
  12. #include <boost/gil/detail/mp11.hpp>
  13. #include <boost/iterator/iterator_facade.hpp>
  14. #include <iterator>
  15. #include <type_traits>
  16. namespace boost { namespace gil {
  17. //forward declaration (as this file is included in planar_pixel_reference.hpp)
  18. template <typename ChannelReference, typename ColorSpace>
  19. struct planar_pixel_reference;
  20. /// \defgroup ColorBaseModelPlanarPtr planar_pixel_iterator
  21. /// \ingroup ColorBaseModel
  22. /// \brief A homogeneous color base whose element is a channel iterator. Models HomogeneousColorBaseValueConcept
  23. /// This class is used as an iterator to a planar pixel.
  24. /// \defgroup PixelIteratorModelPlanarPtr planar_pixel_iterator
  25. /// \ingroup PixelIteratorModel
  26. /// \brief An iterator over planar pixels. Models PixelIteratorConcept, HomogeneousPixelBasedConcept, MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept
  27. ////////////////////////////////////////////////////////////////////////////////////////
  28. /// \brief An iterator over planar pixels. Models HomogeneousColorBaseConcept, PixelIteratorConcept, HomogeneousPixelBasedConcept, MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept
  29. ///
  30. /// Planar pixels have channel data that is not consecutive in memory.
  31. /// To abstract this we use classes to represent references and pointers to planar pixels.
  32. ///
  33. /// \ingroup PixelIteratorModelPlanarPtr ColorBaseModelPlanarPtr PixelBasedModel
  34. template <typename ChannelPtr, typename ColorSpace>
  35. struct planar_pixel_iterator
  36. :
  37. iterator_facade
  38. <
  39. planar_pixel_iterator<ChannelPtr, ColorSpace>,
  40. pixel<typename std::iterator_traits<ChannelPtr>::value_type,layout<ColorSpace>>,
  41. std::random_access_iterator_tag,
  42. planar_pixel_reference<typename std::iterator_traits<ChannelPtr>::reference, ColorSpace> const
  43. >,
  44. detail::homogeneous_color_base
  45. <
  46. ChannelPtr,
  47. layout<ColorSpace>,
  48. mp11::mp_size<ColorSpace>::value
  49. >
  50. {
  51. private:
  52. using parent_t = iterator_facade
  53. <
  54. planar_pixel_iterator<ChannelPtr, ColorSpace>,
  55. pixel<typename std::iterator_traits<ChannelPtr>::value_type,layout<ColorSpace>>,
  56. std::random_access_iterator_tag,
  57. planar_pixel_reference<typename std::iterator_traits<ChannelPtr>::reference, ColorSpace> const
  58. >;
  59. using color_base_parent_t = detail::homogeneous_color_base
  60. <
  61. ChannelPtr,
  62. layout<ColorSpace>,
  63. mp11::mp_size<ColorSpace>::value
  64. >;
  65. using channel_t = typename std::iterator_traits<ChannelPtr>::value_type;
  66. public:
  67. using value_type = typename parent_t::value_type;
  68. using reference = typename parent_t::reference;
  69. using difference_type = typename parent_t::difference_type;
  70. planar_pixel_iterator() : color_base_parent_t(0) {}
  71. planar_pixel_iterator(bool) {} // constructor that does not fill with zero (for performance)
  72. planar_pixel_iterator(const ChannelPtr& v0, const ChannelPtr& v1) : color_base_parent_t(v0,v1) {}
  73. planar_pixel_iterator(const ChannelPtr& v0, const ChannelPtr& v1, const ChannelPtr& v2) : color_base_parent_t(v0,v1,v2) {}
  74. planar_pixel_iterator(const ChannelPtr& v0, const ChannelPtr& v1, const ChannelPtr& v2, const ChannelPtr& v3) : color_base_parent_t(v0,v1,v2,v3) {}
  75. planar_pixel_iterator(const ChannelPtr& v0, const ChannelPtr& v1, const ChannelPtr& v2, const ChannelPtr& v3, const ChannelPtr& v4) : color_base_parent_t(v0,v1,v2,v3,v4) {}
  76. template <typename IC1,typename C1>
  77. planar_pixel_iterator(const planar_pixel_iterator<IC1,C1>& ptr) : color_base_parent_t(ptr) {}
  78. /// Copy constructor and operator= from pointers to compatible planar pixels or planar pixel references.
  79. /// That allow constructs like pointer = &value or pointer = &reference
  80. /// Since we should not override operator& that's the best we can do.
  81. template <typename P>
  82. planar_pixel_iterator(P* pix) : color_base_parent_t(pix, true) {
  83. function_requires<PixelsCompatibleConcept<P,value_type> >();
  84. }
  85. struct address_of { template <typename T> T* operator()(T& t) { return &t; } };
  86. template <typename P>
  87. planar_pixel_iterator& operator=(P* pix) {
  88. function_requires<PixelsCompatibleConcept<P,value_type> >();
  89. static_transform(*pix,*this, address_of());
  90. // PERFORMANCE_CHECK: Compare to this:
  91. //this->template semantic_at_c<0>()=&pix->template semantic_at_c<0>();
  92. //this->template semantic_at_c<1>()=&pix->template semantic_at_c<1>();
  93. //this->template semantic_at_c<2>()=&pix->template semantic_at_c<2>();
  94. return *this;
  95. }
  96. /// For some reason operator[] provided by iterator_facade returns a custom class that is convertible to reference
  97. /// We require our own reference because it is registered in iterator_traits
  98. reference operator[](difference_type d) const { return memunit_advanced_ref(*this,d*sizeof(channel_t));}
  99. reference operator->() const { return **this; }
  100. // PERFORMANCE_CHECK: Remove?
  101. bool operator< (const planar_pixel_iterator& ptr) const { return gil::at_c<0>(*this)< gil::at_c<0>(ptr); }
  102. bool operator!=(const planar_pixel_iterator& ptr) const { return gil::at_c<0>(*this)!=gil::at_c<0>(ptr); }
  103. private:
  104. friend class boost::iterator_core_access;
  105. void increment() { static_transform(*this,*this,detail::inc<ChannelPtr>()); }
  106. void decrement() { static_transform(*this,*this,detail::dec<ChannelPtr>()); }
  107. void advance(std::ptrdiff_t d){ static_transform(*this,*this,std::bind(detail::plus_asymmetric<ChannelPtr,std::ptrdiff_t>(),std::placeholders::_1,d)); }
  108. reference dereference() const { return this->template deref<reference>(); }
  109. std::ptrdiff_t distance_to(const planar_pixel_iterator& it) const { return gil::at_c<0>(it)-gil::at_c<0>(*this); }
  110. bool equal(const planar_pixel_iterator& it) const { return gil::at_c<0>(*this)==gil::at_c<0>(it); }
  111. };
  112. namespace detail {
  113. template <typename I>
  114. struct channel_iterator_is_mutable : std::true_type {};
  115. template <typename I>
  116. struct channel_iterator_is_mutable<I const*> : std::false_type {};
  117. } // namespace detail
  118. template <typename IC, typename C>
  119. struct const_iterator_type<planar_pixel_iterator<IC,C> > {
  120. private:
  121. using channel_t = typename std::iterator_traits<IC>::value_type;
  122. public:
  123. using type = planar_pixel_iterator<typename channel_traits<channel_t>::const_pointer,C>;
  124. };
  125. // The default implementation when the iterator is a C pointer is to use the standard constness semantics
  126. template <typename IC, typename C>
  127. struct iterator_is_mutable<planar_pixel_iterator<IC,C> > : public detail::channel_iterator_is_mutable<IC> {};
  128. /////////////////////////////
  129. // ColorBasedConcept
  130. /////////////////////////////
  131. template <typename IC, typename C, int K>
  132. struct kth_element_type<planar_pixel_iterator<IC, C>, K>
  133. {
  134. using type = IC;
  135. };
  136. template <typename IC, typename C, int K>
  137. struct kth_element_reference_type<planar_pixel_iterator<IC, C>, K>
  138. : std::add_lvalue_reference<IC> {};
  139. template <typename IC, typename C, int K>
  140. struct kth_element_const_reference_type<planar_pixel_iterator<IC, C>, K>
  141. : std::add_lvalue_reference<typename std::add_const<IC>::type>
  142. {};
  143. /////////////////////////////
  144. // HomogeneousPixelBasedConcept
  145. /////////////////////////////
  146. template <typename IC, typename C>
  147. struct color_space_type<planar_pixel_iterator<IC,C>>
  148. {
  149. using type = C;
  150. };
  151. template <typename IC, typename C>
  152. struct channel_mapping_type<planar_pixel_iterator<IC, C>>
  153. : channel_mapping_type<typename planar_pixel_iterator<IC,C>::value_type>
  154. {};
  155. template <typename IC, typename C>
  156. struct is_planar<planar_pixel_iterator<IC, C>> : std::true_type {};
  157. template <typename IC, typename C>
  158. struct channel_type<planar_pixel_iterator<IC, C>>
  159. {
  160. using type = typename std::iterator_traits<IC>::value_type;
  161. };
  162. /////////////////////////////
  163. // MemoryBasedIteratorConcept
  164. /////////////////////////////
  165. template <typename IC, typename C>
  166. inline auto memunit_step(planar_pixel_iterator<IC,C> const&)
  167. -> std::ptrdiff_t
  168. {
  169. return sizeof(typename std::iterator_traits<IC>::value_type);
  170. }
  171. template <typename IC, typename C>
  172. inline auto memunit_distance(planar_pixel_iterator<IC,C> const& p1, planar_pixel_iterator<IC,C> const& p2)
  173. -> std::ptrdiff_t
  174. {
  175. return memunit_distance(gil::at_c<0>(p1),gil::at_c<0>(p2));
  176. }
  177. template <typename IC>
  178. struct memunit_advance_fn {
  179. memunit_advance_fn(std::ptrdiff_t diff) : _diff(diff) {}
  180. IC operator()(const IC& p) const { return memunit_advanced(p,_diff); }
  181. std::ptrdiff_t _diff;
  182. };
  183. template <typename IC, typename C>
  184. inline void memunit_advance(planar_pixel_iterator<IC,C>& p, std::ptrdiff_t diff) {
  185. static_transform(p, p, memunit_advance_fn<IC>(diff));
  186. }
  187. template <typename IC, typename C>
  188. inline auto memunit_advanced(planar_pixel_iterator<IC,C> const& p, std::ptrdiff_t diff)
  189. -> planar_pixel_iterator<IC,C>
  190. {
  191. planar_pixel_iterator<IC,C> ret=p;
  192. memunit_advance(ret, diff);
  193. return ret;
  194. }
  195. template <typename ChannelPtr, typename ColorSpace>
  196. inline auto memunit_advanced_ref(planar_pixel_iterator<ChannelPtr,ColorSpace> const& ptr, std::ptrdiff_t diff)
  197. -> planar_pixel_reference<typename std::iterator_traits<ChannelPtr>::reference,ColorSpace>
  198. {
  199. return planar_pixel_reference<typename std::iterator_traits<ChannelPtr>::reference,ColorSpace>(ptr, diff);
  200. }
  201. /////////////////////////////
  202. // HasDynamicXStepTypeConcept
  203. /////////////////////////////
  204. template <typename IC, typename C>
  205. struct dynamic_x_step_type<planar_pixel_iterator<IC,C> > {
  206. using type = memory_based_step_iterator<planar_pixel_iterator<IC,C>>;
  207. };
  208. } } // namespace boost::gil
  209. #endif