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_CONCEPTS_PIXEL_ITERATOR_HPP 9 #define BOOST_GIL_CONCEPTS_PIXEL_ITERATOR_HPP 10 11 #include <boost/gil/concepts/channel.hpp> 12 #include <boost/gil/concepts/color.hpp> 13 #include <boost/gil/concepts/concept_check.hpp> 14 #include <boost/gil/concepts/fwd.hpp> 15 #include <boost/gil/concepts/pixel.hpp> 16 #include <boost/gil/concepts/pixel_based.hpp> 17 18 #include <boost/iterator/iterator_concepts.hpp> 19 20 #include <cstddef> 21 #include <iterator> 22 #include <type_traits> 23 24 #if defined(BOOST_CLANG) 25 #pragma clang diagnostic push 26 #pragma clang diagnostic ignored "-Wunknown-pragmas" 27 #pragma clang diagnostic ignored "-Wunused-local-typedefs" 28 #endif 29 30 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900) 31 #pragma GCC diagnostic push 32 #pragma GCC diagnostic ignored "-Wunused-local-typedefs" 33 #endif 34 35 namespace boost { namespace gil { 36 37 // Forward declarations 38 template <typename It> struct const_iterator_type; 39 template <typename It> struct iterator_is_mutable; 40 template <typename It> struct is_iterator_adaptor; 41 template <typename It, typename NewBaseIt> struct iterator_adaptor_rebind; 42 template <typename It> struct iterator_adaptor_get_base; 43 44 // These iterator mutability concepts are taken from Boost concept_check.hpp. 45 // Isolating mutability to result in faster compile time 46 namespace detail { 47 48 // Preconditions: TT Models boost_concepts::ForwardTraversalConcept 49 template <class TT> 50 struct ForwardIteratorIsMutableConcept 51 { constraintsboost::gil::detail::ForwardIteratorIsMutableConcept52 void constraints() 53 { 54 auto const tmp = *i; 55 *i++ = tmp; // require postincrement and assignment 56 } 57 TT i; 58 }; 59 60 // Preconditions: TT Models boost::BidirectionalIteratorConcept 61 template <class TT> 62 struct BidirectionalIteratorIsMutableConcept 63 { constraintsboost::gil::detail::BidirectionalIteratorIsMutableConcept64 void constraints() 65 { 66 gil_function_requires< ForwardIteratorIsMutableConcept<TT>>(); 67 auto const tmp = *i; 68 *i-- = tmp; // require postdecrement and assignment 69 } 70 TT i; 71 }; 72 73 // Preconditions: TT Models boost_concepts::RandomAccessTraversalConcept 74 template <class TT> 75 struct RandomAccessIteratorIsMutableConcept 76 { constraintsboost::gil::detail::RandomAccessIteratorIsMutableConcept77 void constraints() 78 { 79 gil_function_requires<BidirectionalIteratorIsMutableConcept<TT>>(); 80 81 typename std::iterator_traits<TT>::difference_type n = 0; 82 ignore_unused_variable_warning(n); 83 i[n] = *i; // require element access and assignment 84 } 85 TT i; 86 }; 87 88 // Iterators that can be used as the base of memory_based_step_iterator require some additional functions 89 // \tparam Iterator Models boost_concepts::RandomAccessTraversalConcept 90 template <typename Iterator> 91 struct RandomAccessIteratorIsMemoryBasedConcept 92 { constraintsboost::gil::detail::RandomAccessIteratorIsMemoryBasedConcept93 void constraints() 94 { 95 std::ptrdiff_t bs = memunit_step(it); 96 ignore_unused_variable_warning(bs); 97 98 it = memunit_advanced(it, 3); 99 std::ptrdiff_t bd = memunit_distance(it, it); 100 ignore_unused_variable_warning(bd); 101 102 memunit_advance(it,3); 103 // for performace you may also provide a customized implementation of memunit_advanced_ref 104 } 105 Iterator it; 106 }; 107 108 /// \tparam Iterator Models PixelIteratorConcept 109 template <typename Iterator> 110 struct PixelIteratorIsMutableConcept 111 { constraintsboost::gil::detail::PixelIteratorIsMutableConcept112 void constraints() 113 { 114 gil_function_requires<detail::RandomAccessIteratorIsMutableConcept<Iterator>>(); 115 116 using ref_t = typename std::remove_reference 117 < 118 typename std::iterator_traits<Iterator>::reference 119 >::type; 120 using channel_t = typename element_type<ref_t>::type; 121 gil_function_requires<detail::ChannelIsMutableConcept<channel_t>>(); 122 } 123 }; 124 125 } // namespace detail 126 127 /// \ingroup PixelLocatorConcept 128 /// \brief Concept for locators and views that can define a type just like the given locator or view, except X and Y is swapped 129 /// \code 130 /// concept HasTransposedTypeConcept<typename T> 131 /// { 132 /// typename transposed_type<T>; 133 /// where Metafunction<transposed_type<T> >; 134 /// }; 135 /// \endcode 136 template <typename T> 137 struct HasTransposedTypeConcept 138 { constraintsboost::gil::HasTransposedTypeConcept139 void constraints() 140 { 141 using type = typename transposed_type<T>::type; 142 ignore_unused_variable_warning(type{}); 143 } 144 }; 145 146 /// \defgroup PixelIteratorConceptPixelIterator PixelIteratorConcept 147 /// \ingroup PixelIteratorConcept 148 /// \brief STL iterator over pixels 149 150 /// \ingroup PixelIteratorConceptPixelIterator 151 /// \brief An STL random access traversal iterator over a model of PixelConcept. 152 /// 153 /// GIL's iterators must also provide the following metafunctions: 154 /// - \p const_iterator_type<Iterator>: Returns a read-only equivalent of \p Iterator 155 /// - \p iterator_is_mutable<Iterator>: Returns whether the given iterator is read-only or mutable 156 /// - \p is_iterator_adaptor<Iterator>: Returns whether the given iterator is an adaptor over another iterator. See IteratorAdaptorConcept for additional requirements of adaptors. 157 /// 158 /// \code 159 /// concept PixelIteratorConcept<typename Iterator> 160 /// : boost_concepts::RandomAccessTraversalConcept<Iterator>, PixelBasedConcept<Iterator> 161 /// { 162 /// where PixelValueConcept<value_type>; 163 /// typename const_iterator_type<It>::type; 164 /// where PixelIteratorConcept<const_iterator_type<It>::type>; 165 /// static const bool iterator_is_mutable<It>::value; 166 /// static const bool is_iterator_adaptor<It>::value; // is it an iterator adaptor 167 /// }; 168 /// \endcode 169 template <typename Iterator> 170 struct PixelIteratorConcept 171 { constraintsboost::gil::PixelIteratorConcept172 void constraints() 173 { 174 gil_function_requires<boost_concepts::RandomAccessTraversalConcept<Iterator>>(); 175 gil_function_requires<PixelBasedConcept<Iterator>>(); 176 177 using value_type = typename std::iterator_traits<Iterator>::value_type; 178 gil_function_requires<PixelValueConcept<value_type>>(); 179 180 using const_t = typename const_iterator_type<Iterator>::type; 181 static bool const is_mutable = iterator_is_mutable<Iterator>::value; 182 ignore_unused_variable_warning(is_mutable); 183 184 // immutable iterator must be constructible from (possibly mutable) iterator 185 const_t const_it(it); 186 ignore_unused_variable_warning(const_it); 187 188 check_base(typename is_iterator_adaptor<Iterator>::type()); 189 } 190 check_baseboost::gil::PixelIteratorConcept191 void check_base(std::false_type) {} 192 check_baseboost::gil::PixelIteratorConcept193 void check_base(std::true_type) 194 { 195 using base_t = typename iterator_adaptor_get_base<Iterator>::type; 196 gil_function_requires<PixelIteratorConcept<base_t>>(); 197 } 198 199 Iterator it; 200 }; 201 202 /// \brief Pixel iterator that allows for changing its pixel 203 /// \ingroup PixelIteratorConceptPixelIterator 204 /// \code 205 /// concept MutablePixelIteratorConcept<PixelIteratorConcept Iterator> 206 /// : MutableRandomAccessIteratorConcept<Iterator> {}; 207 /// \endcode 208 template <typename Iterator> 209 struct MutablePixelIteratorConcept 210 { constraintsboost::gil::MutablePixelIteratorConcept211 void constraints() 212 { 213 gil_function_requires<PixelIteratorConcept<Iterator>>(); 214 gil_function_requires<detail::PixelIteratorIsMutableConcept<Iterator>>(); 215 } 216 }; 217 218 /// \defgroup PixelIteratorConceptStepIterator StepIteratorConcept 219 /// \ingroup PixelIteratorConcept 220 /// \brief Iterator that advances by a specified step 221 222 /// \ingroup PixelIteratorConceptStepIterator 223 /// \brief Concept of a random-access iterator that can be advanced in memory units (bytes or bits) 224 /// \code 225 /// concept MemoryBasedIteratorConcept<boost_concepts::RandomAccessTraversalConcept Iterator> 226 /// { 227 /// typename byte_to_memunit<Iterator>; where metafunction<byte_to_memunit<Iterator> >; 228 /// std::ptrdiff_t memunit_step(const Iterator&); 229 /// std::ptrdiff_t memunit_distance(const Iterator& , const Iterator&); 230 /// void memunit_advance(Iterator&, std::ptrdiff_t diff); 231 /// Iterator memunit_advanced(const Iterator& p, std::ptrdiff_t diff) { Iterator tmp; memunit_advance(tmp,diff); return tmp; } 232 /// Iterator::reference memunit_advanced_ref(const Iterator& p, std::ptrdiff_t diff) { return *memunit_advanced(p,diff); } 233 /// }; 234 /// \endcode 235 template <typename Iterator> 236 struct MemoryBasedIteratorConcept 237 { constraintsboost::gil::MemoryBasedIteratorConcept238 void constraints() 239 { 240 gil_function_requires<boost_concepts::RandomAccessTraversalConcept<Iterator>>(); 241 gil_function_requires<detail::RandomAccessIteratorIsMemoryBasedConcept<Iterator>>(); 242 } 243 }; 244 245 /// \ingroup PixelIteratorConceptStepIterator 246 /// \brief Step iterator concept 247 /// 248 /// Step iterators are iterators that have a set_step method 249 /// \code 250 /// concept StepIteratorConcept<boost_concepts::ForwardTraversalConcept Iterator> 251 /// { 252 /// template <Integral D> 253 /// void Iterator::set_step(D step); 254 /// }; 255 /// \endcode 256 template <typename Iterator> 257 struct StepIteratorConcept 258 { constraintsboost::gil::StepIteratorConcept259 void constraints() 260 { 261 gil_function_requires<boost_concepts::ForwardTraversalConcept<Iterator>>(); 262 it.set_step(0); 263 } 264 Iterator it; 265 }; 266 267 268 /// \ingroup PixelIteratorConceptStepIterator 269 /// \brief Step iterator that allows for modifying its current value 270 /// \code 271 /// concept MutableStepIteratorConcept<Mutable_ForwardIteratorConcept Iterator> 272 /// : StepIteratorConcept<Iterator> {}; 273 /// \endcode 274 template <typename Iterator> 275 struct MutableStepIteratorConcept 276 { constraintsboost::gil::MutableStepIteratorConcept277 void constraints() 278 { 279 gil_function_requires<StepIteratorConcept<Iterator>>(); 280 gil_function_requires<detail::ForwardIteratorIsMutableConcept<Iterator>>(); 281 } 282 }; 283 284 /// \defgroup PixelIteratorConceptIteratorAdaptor IteratorAdaptorConcept 285 /// \ingroup PixelIteratorConcept 286 /// \brief Adaptor over another iterator 287 288 /// \ingroup PixelIteratorConceptIteratorAdaptor 289 /// \brief Iterator adaptor is a forward iterator adapting another forward iterator. 290 /// 291 /// In addition to GIL iterator requirements, 292 /// GIL iterator adaptors must provide the following metafunctions: 293 /// - \p is_iterator_adaptor<Iterator>: Returns \p std::true_type 294 /// - \p iterator_adaptor_get_base<Iterator>: Returns the base iterator type 295 /// - \p iterator_adaptor_rebind<Iterator,NewBase>: Replaces the base iterator with the new one 296 /// 297 /// The adaptee can be obtained from the iterator via the "base()" method. 298 /// 299 /// \code 300 /// concept IteratorAdaptorConcept<boost_concepts::ForwardTraversalConcept Iterator> 301 /// { 302 /// where SameType<is_iterator_adaptor<Iterator>::type, std::true_type>; 303 /// 304 /// typename iterator_adaptor_get_base<Iterator>; 305 /// where Metafunction<iterator_adaptor_get_base<Iterator> >; 306 /// where boost_concepts::ForwardTraversalConcept<iterator_adaptor_get_base<Iterator>::type>; 307 /// 308 /// typename another_iterator; 309 /// typename iterator_adaptor_rebind<Iterator,another_iterator>::type; 310 /// where boost_concepts::ForwardTraversalConcept<another_iterator>; 311 /// where IteratorAdaptorConcept<iterator_adaptor_rebind<Iterator,another_iterator>::type>; 312 /// 313 /// const iterator_adaptor_get_base<Iterator>::type& Iterator::base() const; 314 /// }; 315 /// \endcode 316 template <typename Iterator> 317 struct IteratorAdaptorConcept 318 { constraintsboost::gil::IteratorAdaptorConcept319 void constraints() 320 { 321 gil_function_requires<boost_concepts::ForwardTraversalConcept<Iterator>>(); 322 323 using base_t = typename iterator_adaptor_get_base<Iterator>::type; 324 gil_function_requires<boost_concepts::ForwardTraversalConcept<base_t>>(); 325 326 static_assert(is_iterator_adaptor<Iterator>::value, ""); 327 using rebind_t = typename iterator_adaptor_rebind<Iterator, void*>::type; 328 329 base_t base = it.base(); 330 ignore_unused_variable_warning(base); 331 } 332 Iterator it; 333 }; 334 335 /// \brief Iterator adaptor that is mutable 336 /// \ingroup PixelIteratorConceptIteratorAdaptor 337 /// \code 338 /// concept MutableIteratorAdaptorConcept<Mutable_ForwardIteratorConcept Iterator> 339 /// : IteratorAdaptorConcept<Iterator> {}; 340 /// \endcode 341 template <typename Iterator> 342 struct MutableIteratorAdaptorConcept 343 { constraintsboost::gil::MutableIteratorAdaptorConcept344 void constraints() 345 { 346 gil_function_requires<IteratorAdaptorConcept<Iterator>>(); 347 gil_function_requires<detail::ForwardIteratorIsMutableConcept<Iterator>>(); 348 } 349 }; 350 351 }} // namespace boost::gil 352 353 #if defined(BOOST_CLANG) 354 #pragma clang diagnostic pop 355 #endif 356 357 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900) 358 #pragma GCC diagnostic pop 359 #endif 360 361 #endif 362