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_LOCATOR_HPP 9 #define BOOST_GIL_CONCEPTS_PIXEL_LOCATOR_HPP 10 11 #include <boost/gil/concepts/basic.hpp> 12 #include <boost/gil/concepts/concept_check.hpp> 13 #include <boost/gil/concepts/fwd.hpp> 14 #include <boost/gil/concepts/pixel.hpp> 15 #include <boost/gil/concepts/pixel_dereference.hpp> 16 #include <boost/gil/concepts/pixel_iterator.hpp> 17 #include <boost/gil/concepts/point.hpp> 18 #include <boost/gil/concepts/detail/utility.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 #pragma GCC diagnostic ignored "-Wunused-but-set-variable" 34 #endif 35 36 namespace boost { namespace gil { 37 38 /// \defgroup LocatorNDConcept RandomAccessNDLocatorConcept 39 /// \ingroup PixelLocatorConcept 40 /// \brief N-dimensional locator 41 42 /// \defgroup Locator2DConcept RandomAccess2DLocatorConcept 43 /// \ingroup PixelLocatorConcept 44 /// \brief 2-dimensional locator 45 46 /// \defgroup PixelLocator2DConcept PixelLocatorConcept 47 /// \ingroup PixelLocatorConcept 48 /// \brief 2-dimensional locator over pixel data 49 50 /// \ingroup LocatorNDConcept 51 /// \brief N-dimensional locator over immutable values 52 /// 53 /// \code 54 /// concept RandomAccessNDLocatorConcept<Regular Loc> 55 /// { 56 /// typename value_type; // value over which the locator navigates 57 /// typename reference; // result of dereferencing 58 /// typename difference_type; where PointNDConcept<difference_type>; // return value of operator-. 59 /// typename const_t; // same as Loc, but operating over immutable values 60 /// typename cached_location_t; // type to store relative location (for efficient repeated access) 61 /// typename point_t = difference_type; 62 /// 63 /// static const size_t num_dimensions; // dimensionality of the locator 64 /// where num_dimensions = point_t::num_dimensions; 65 /// 66 /// // The difference_type and iterator type along each dimension. The iterators may only differ in 67 /// // difference_type. Their value_type must be the same as Loc::value_type 68 /// template <size_t D> 69 /// struct axis 70 /// { 71 /// typename coord_t = point_t::axis<D>::coord_t; 72 /// typename iterator; where RandomAccessTraversalConcept<iterator>; // iterator along D-th axis. 73 /// where iterator::value_type == value_type; 74 /// }; 75 /// 76 /// // Defines the type of a locator similar to this type, except it invokes Deref upon dereferencing 77 /// template <PixelDereferenceAdaptorConcept Deref> 78 /// struct add_deref 79 /// { 80 /// typename type; 81 /// where RandomAccessNDLocatorConcept<type>; 82 /// static type make(const Loc& loc, const Deref& deref); 83 /// }; 84 /// 85 /// Loc& operator+=(Loc&, const difference_type&); 86 /// Loc& operator-=(Loc&, const difference_type&); 87 /// Loc operator+(const Loc&, const difference_type&); 88 /// Loc operator-(const Loc&, const difference_type&); 89 /// 90 /// reference operator*(const Loc&); 91 /// reference operator[](const Loc&, const difference_type&); 92 /// 93 /// // Storing relative location for faster repeated access and accessing it 94 /// cached_location_t Loc::cache_location(const difference_type&) const; 95 /// reference operator[](const Loc&,const cached_location_t&); 96 /// 97 /// // Accessing iterators along a given dimension at the current location or at a given offset 98 /// template <size_t D> axis<D>::iterator& Loc::axis_iterator(); 99 /// template <size_t D> axis<D>::iterator const& Loc::axis_iterator() const; 100 /// template <size_t D> axis<D>::iterator Loc::axis_iterator(const difference_type&) const; 101 /// }; 102 /// \endcode 103 template <typename Loc> 104 struct RandomAccessNDLocatorConcept 105 { constraintsboost::gil::RandomAccessNDLocatorConcept106 void constraints() 107 { 108 gil_function_requires<Regular<Loc>>(); 109 110 // TODO: Should these be concept-checked instead of ignored? --mloskot 111 112 using value_type = typename Loc::value_type; 113 ignore_unused_variable_warning(value_type{}); 114 115 // result of dereferencing 116 using reference = typename Loc::reference; 117 //ignore_unused_variable_warning(reference{}); 118 119 // result of operator-(pixel_locator, pixel_locator) 120 using difference_type = typename Loc::difference_type; 121 ignore_unused_variable_warning(difference_type{}); 122 123 // type used to store relative location (to allow for more efficient repeated access) 124 using cached_location_t = typename Loc::cached_location_t; 125 ignore_unused_variable_warning(cached_location_t{}); 126 127 // same as this type, but over const values 128 using const_t = typename Loc::const_t; 129 ignore_unused_variable_warning(const_t{}); 130 131 // same as difference_type 132 using point_t = typename Loc::point_t; 133 ignore_unused_variable_warning(point_t{}); 134 135 static std::size_t const N = Loc::num_dimensions; ignore_unused_variable_warning(N); 136 137 using first_it_type = typename Loc::template axis<0>::iterator; 138 using last_it_type = typename Loc::template axis<N-1>::iterator; 139 gil_function_requires<boost_concepts::RandomAccessTraversalConcept<first_it_type>>(); 140 gil_function_requires<boost_concepts::RandomAccessTraversalConcept<last_it_type>>(); 141 142 // point_t must be an N-dimensional point, each dimension of which must 143 // have the same type as difference_type of the corresponding iterator 144 gil_function_requires<PointNDConcept<point_t>>(); 145 static_assert(point_t::num_dimensions == N, ""); 146 static_assert(std::is_same 147 < 148 typename std::iterator_traits<first_it_type>::difference_type, 149 typename point_t::template axis<0>::coord_t 150 >::value, ""); 151 static_assert(std::is_same 152 < 153 typename std::iterator_traits<last_it_type>::difference_type, 154 typename point_t::template axis<N-1>::coord_t 155 >::value, ""); 156 157 difference_type d; 158 loc += d; 159 loc -= d; 160 loc = loc + d; 161 loc = loc - d; 162 reference r1 = loc[d]; ignore_unused_variable_warning(r1); 163 reference r2 = *loc; ignore_unused_variable_warning(r2); 164 cached_location_t cl = loc.cache_location(d); ignore_unused_variable_warning(cl); 165 reference r3 = loc[d]; ignore_unused_variable_warning(r3); 166 167 first_it_type fi = loc.template axis_iterator<0>(); 168 fi = loc.template axis_iterator<0>(d); 169 last_it_type li = loc.template axis_iterator<N-1>(); 170 li = loc.template axis_iterator<N-1>(d); 171 172 using deref_t = PixelDereferenceAdaptorArchetype<typename Loc::value_type>; 173 using dtype = typename Loc::template add_deref<deref_t>::type; 174 // TODO: infinite recursion - FIXME? 175 //gil_function_requires<RandomAccessNDLocatorConcept<dtype>>(); 176 } 177 Loc loc; 178 }; 179 180 /// \ingroup Locator2DConcept 181 /// \brief 2-dimensional locator over immutable values 182 /// 183 /// \code 184 /// concept RandomAccess2DLocatorConcept<RandomAccessNDLocatorConcept Loc> 185 /// { 186 /// where num_dimensions==2; 187 /// where Point2DConcept<point_t>; 188 /// 189 /// typename x_iterator = axis<0>::iterator; 190 /// typename y_iterator = axis<1>::iterator; 191 /// typename x_coord_t = axis<0>::coord_t; 192 /// typename y_coord_t = axis<1>::coord_t; 193 /// 194 /// // Only available to locators that have dynamic step in Y 195 /// //Loc::Loc(const Loc& loc, y_coord_t); 196 /// 197 /// // Only available to locators that have dynamic step in X and Y 198 /// //Loc::Loc(const Loc& loc, x_coord_t, y_coord_t, bool transposed=false); 199 /// 200 /// x_iterator& Loc::x(); 201 /// x_iterator const& Loc::x() const; 202 /// y_iterator& Loc::y(); 203 /// y_iterator const& Loc::y() const; 204 /// 205 /// x_iterator Loc::x_at(const difference_type&) const; 206 /// y_iterator Loc::y_at(const difference_type&) const; 207 /// Loc Loc::xy_at(const difference_type&) const; 208 /// 209 /// // x/y versions of all methods that can take difference type 210 /// x_iterator Loc::x_at(x_coord_t, y_coord_t) const; 211 /// y_iterator Loc::y_at(x_coord_t, y_coord_t) const; 212 /// Loc Loc::xy_at(x_coord_t, y_coord_t) const; 213 /// reference operator()(const Loc&, x_coord_t, y_coord_t); 214 /// cached_location_t Loc::cache_location(x_coord_t, y_coord_t) const; 215 /// 216 /// bool Loc::is_1d_traversable(x_coord_t width) const; 217 /// y_coord_t Loc::y_distance_to(const Loc& loc2, x_coord_t x_diff) const; 218 /// }; 219 /// \endcode 220 template <typename Loc> 221 struct RandomAccess2DLocatorConcept 222 { constraintsboost::gil::RandomAccess2DLocatorConcept223 void constraints() 224 { 225 gil_function_requires<RandomAccessNDLocatorConcept<Loc>>(); 226 static_assert(Loc::num_dimensions == 2, ""); 227 228 using dynamic_x_step_t = typename dynamic_x_step_type<Loc>::type; 229 using dynamic_y_step_t = typename dynamic_y_step_type<Loc>::type; 230 using transposed_t = typename transposed_type<Loc>::type; 231 232 using cached_location_t = typename Loc::cached_location_t; 233 gil_function_requires<Point2DConcept<typename Loc::point_t>>(); 234 235 using x_iterator = typename Loc::x_iterator; 236 using y_iterator = typename Loc::y_iterator; 237 using x_coord_t = typename Loc::x_coord_t; 238 using y_coord_t = typename Loc::y_coord_t; 239 240 x_coord_t xd = 0; ignore_unused_variable_warning(xd); 241 y_coord_t yd = 0; ignore_unused_variable_warning(yd); 242 243 typename Loc::difference_type d; 244 typename Loc::reference r=loc(xd,yd); ignore_unused_variable_warning(r); 245 246 dynamic_x_step_t loc2(dynamic_x_step_t(), yd); 247 dynamic_x_step_t loc3(dynamic_x_step_t(), xd, yd); 248 249 using dynamic_xy_step_transposed_t = typename dynamic_y_step_type 250 < 251 typename dynamic_x_step_type<transposed_t>::type 252 >::type; 253 dynamic_xy_step_transposed_t loc4(loc, xd,yd,true); 254 255 bool is_contiguous = loc.is_1d_traversable(xd); 256 ignore_unused_variable_warning(is_contiguous); 257 258 loc.y_distance_to(loc, xd); 259 260 loc = loc.xy_at(d); 261 loc = loc.xy_at(xd, yd); 262 263 x_iterator xit = loc.x_at(d); 264 xit = loc.x_at(xd, yd); 265 xit = loc.x(); 266 267 y_iterator yit = loc.y_at(d); 268 yit = loc.y_at(xd, yd); 269 yit = loc.y(); 270 271 cached_location_t cl = loc.cache_location(xd, yd); 272 ignore_unused_variable_warning(cl); 273 } 274 Loc loc; 275 }; 276 277 /// \ingroup PixelLocator2DConcept 278 /// \brief GIL's 2-dimensional locator over immutable GIL pixels 279 /// \code 280 /// concept PixelLocatorConcept<RandomAccess2DLocatorConcept Loc> 281 /// { 282 /// where PixelValueConcept<value_type>; 283 /// where PixelIteratorConcept<x_iterator>; 284 /// where PixelIteratorConcept<y_iterator>; 285 /// where x_coord_t == y_coord_t; 286 /// 287 /// typename coord_t = x_coord_t; 288 /// }; 289 /// \endcode 290 template <typename Loc> 291 struct PixelLocatorConcept 292 { constraintsboost::gil::PixelLocatorConcept293 void constraints() 294 { 295 gil_function_requires<RandomAccess2DLocatorConcept<Loc>>(); 296 gil_function_requires<PixelIteratorConcept<typename Loc::x_iterator>>(); 297 gil_function_requires<PixelIteratorConcept<typename Loc::y_iterator>>(); 298 using coord_t = typename Loc::coord_t; 299 static_assert(std::is_same<typename Loc::x_coord_t, typename Loc::y_coord_t>::value, ""); 300 } 301 Loc loc; 302 }; 303 304 namespace detail { 305 306 /// \tparam Loc Models RandomAccessNDLocatorConcept 307 template <typename Loc> 308 struct RandomAccessNDLocatorIsMutableConcept 309 { constraintsboost::gil::detail::RandomAccessNDLocatorIsMutableConcept310 void constraints() 311 { 312 gil_function_requires<detail::RandomAccessIteratorIsMutableConcept 313 < 314 typename Loc::template axis<0>::iterator 315 >>(); 316 gil_function_requires<detail::RandomAccessIteratorIsMutableConcept 317 < 318 typename Loc::template axis<Loc::num_dimensions-1>::iterator 319 >>(); 320 321 typename Loc::difference_type d; initialize_it(d); 322 typename Loc::value_type v; initialize_it(v); 323 typename Loc::cached_location_t cl = loc.cache_location(d); 324 *loc = v; 325 loc[d] = v; 326 loc[cl] = v; 327 } 328 Loc loc; 329 }; 330 331 // \tparam Loc Models RandomAccess2DLocatorConcept 332 template <typename Loc> 333 struct RandomAccess2DLocatorIsMutableConcept 334 { constraintsboost::gil::detail::RandomAccess2DLocatorIsMutableConcept335 void constraints() 336 { 337 gil_function_requires<detail::RandomAccessNDLocatorIsMutableConcept<Loc>>(); 338 typename Loc::x_coord_t xd = 0; ignore_unused_variable_warning(xd); 339 typename Loc::y_coord_t yd = 0; ignore_unused_variable_warning(yd); 340 typename Loc::value_type v; initialize_it(v); 341 loc(xd, yd) = v; 342 } 343 Loc loc; 344 }; 345 346 } // namespace detail 347 348 /// \ingroup LocatorNDConcept 349 /// \brief N-dimensional locator over mutable pixels 350 /// 351 /// \code 352 /// concept MutableRandomAccessNDLocatorConcept<RandomAccessNDLocatorConcept Loc> 353 /// { 354 /// where Mutable<reference>; 355 /// }; 356 /// \endcode 357 template <typename Loc> 358 struct MutableRandomAccessNDLocatorConcept 359 { constraintsboost::gil::MutableRandomAccessNDLocatorConcept360 void constraints() 361 { 362 gil_function_requires<RandomAccessNDLocatorConcept<Loc>>(); 363 gil_function_requires<detail::RandomAccessNDLocatorIsMutableConcept<Loc>>(); 364 } 365 }; 366 367 /// \ingroup Locator2DConcept 368 /// \brief 2-dimensional locator over mutable pixels 369 /// 370 /// \code 371 /// concept MutableRandomAccess2DLocatorConcept<RandomAccess2DLocatorConcept Loc> 372 /// : MutableRandomAccessNDLocatorConcept<Loc> {}; 373 /// \endcode 374 template <typename Loc> 375 struct MutableRandomAccess2DLocatorConcept 376 { constraintsboost::gil::MutableRandomAccess2DLocatorConcept377 void constraints() 378 { 379 gil_function_requires<RandomAccess2DLocatorConcept<Loc>>(); 380 gil_function_requires<detail::RandomAccess2DLocatorIsMutableConcept<Loc>>(); 381 } 382 }; 383 384 /// \ingroup PixelLocator2DConcept 385 /// \brief GIL's 2-dimensional locator over mutable GIL pixels 386 /// 387 /// \code 388 /// concept MutablePixelLocatorConcept<PixelLocatorConcept Loc> 389 /// : MutableRandomAccess2DLocatorConcept<Loc> {}; 390 /// \endcode 391 template <typename Loc> 392 struct MutablePixelLocatorConcept 393 { constraintsboost::gil::MutablePixelLocatorConcept394 void constraints() 395 { 396 gil_function_requires<PixelLocatorConcept<Loc>>(); 397 gil_function_requires<detail::RandomAccess2DLocatorIsMutableConcept<Loc>>(); 398 } 399 }; 400 401 }} // namespace boost::gil 402 403 #if defined(BOOST_CLANG) 404 #pragma clang diagnostic pop 405 #endif 406 407 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900) 408 #pragma GCC diagnostic pop 409 #endif 410 411 #endif 412