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