• 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_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