Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / gil / concepts / image_view.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_IMAGE_VIEW_HPP
9 #define BOOST_GIL_CONCEPTS_IMAGE_VIEW_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/pixel_locator.hpp>
18 #include <boost/gil/concepts/point.hpp>
19 #include <boost/gil/concepts/detail/utility.hpp>
20
21 #include <cstddef>
22 #include <iterator>
23 #include <type_traits>
24
25 #if defined(BOOST_CLANG)
26 #pragma clang diagnostic push
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 ImageViewNDConcept ImageViewNDLocatorConcept
39 /// \ingroup ImageViewConcept
40 /// \brief N-dimensional range
41
42 /// \defgroup ImageView2DConcept ImageView2DConcept
43 /// \ingroup ImageViewConcept
44 /// \brief 2-dimensional range
45
46 /// \defgroup PixelImageViewConcept ImageViewConcept
47 /// \ingroup ImageViewConcept
48 /// \brief 2-dimensional range over pixel data
49
50 /// \ingroup ImageViewNDConcept
51 /// \brief N-dimensional view over immutable values
52 ///
53 /// \code
54 /// concept RandomAccessNDImageViewConcept<Regular View>
55 /// {
56 ///     typename value_type;
57 ///     typename reference;       // result of dereferencing
58 ///     typename difference_type; // result of operator-(iterator,iterator) (1-dimensional!)
59 ///     typename const_t;  where RandomAccessNDImageViewConcept<View>; // same as View, but over immutable values
60 ///     typename point_t;  where PointNDConcept<point_t>; // N-dimensional point
61 ///     typename locator;  where RandomAccessNDLocatorConcept<locator>; // N-dimensional locator.
62 ///     typename iterator; where RandomAccessTraversalConcept<iterator>; // 1-dimensional iterator over all values
63 ///     typename reverse_iterator; where RandomAccessTraversalConcept<reverse_iterator>;
64 ///     typename size_type;       // the return value of size()
65 ///
66 ///     // Equivalent to RandomAccessNDLocatorConcept::axis
67 ///     template <size_t D> struct axis {
68 ///         typename coord_t = point_t::axis<D>::coord_t;
69 ///         typename iterator; where RandomAccessTraversalConcept<iterator>;   // iterator along D-th axis.
70 ///         where SameType<coord_t, iterator::difference_type>;
71 ///         where SameType<iterator::value_type,value_type>;
72 ///     };
73 ///
74 ///     // Defines the type of a view similar to this type, except it invokes Deref upon dereferencing
75 ///     template <PixelDereferenceAdaptorConcept Deref> struct add_deref {
76 ///         typename type;        where RandomAccessNDImageViewConcept<type>;
77 ///         static type make(const View& v, const Deref& deref);
78 ///     };
79 ///
80 ///     static const size_t num_dimensions = point_t::num_dimensions;
81 ///
82 ///     // Create from a locator at the top-left corner and dimensions
83 ///     View::View(const locator&, const point_type&);
84 ///
85 ///     size_type        View::size()       const; // total number of elements
86 ///     reference        operator[](View, const difference_type&) const; // 1-dimensional reference
87 ///     iterator         View::begin()      const;
88 ///     iterator         View::end()        const;
89 ///     reverse_iterator View::rbegin()     const;
90 ///     reverse_iterator View::rend()       const;
91 ///     iterator         View::at(const point_t&);
92 ///     point_t          View::dimensions() const; // number of elements along each dimension
93 ///     bool             View::is_1d_traversable() const;   // can an iterator over the first dimension visit each value? I.e. are there gaps between values?
94 ///
95 ///     // iterator along a given dimension starting at a given point
96 ///     template <size_t D> View::axis<D>::iterator View::axis_iterator(const point_t&) const;
97 ///
98 ///     reference operator()(View,const point_t&) const;
99 /// };
100 /// \endcode
101 template <typename View>
102 struct RandomAccessNDImageViewConcept
103 {
104     void constraints()
105     {
106         gil_function_requires<Regular<View>>();
107
108         using value_type = typename View::value_type;
109         using reference = typename View::reference; // result of dereferencing
110         using pointer = typename View::pointer;
111         using difference_type = typename View::difference_type; // result of operator-(1d_iterator,1d_iterator)
112         using const_t = typename View::const_t; // same as this type, but over const values
113         using point_t = typename View::point_t; // N-dimensional point
114         using locator = typename View::locator; // N-dimensional locator
115         using iterator = typename View::iterator;
116         using const_iterator = typename View::const_iterator;
117         using reverse_iterator = typename View::reverse_iterator;
118         using size_type = typename View::size_type;
119         static const std::size_t N=View::num_dimensions;
120
121         gil_function_requires<RandomAccessNDLocatorConcept<locator>>();
122         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<iterator>>();
123         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<reverse_iterator>>();
124
125         using first_it_type = typename View::template axis<0>::iterator;
126         using last_it_type = typename View::template axis<N-1>::iterator;
127         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<first_it_type>>();
128         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<last_it_type>>();
129
130 //        static_assert(typename std::iterator_traits<first_it_type>::difference_type, typename point_t::template axis<0>::coord_t>::value, "");
131 //        static_assert(typename std::iterator_traits<last_it_type>::difference_type, typename point_t::template axis<N-1>::coord_t>::value, "");
132
133         // point_t must be an N-dimensional point, each dimension of which must have the same type as difference_type of the corresponding iterator
134         gil_function_requires<PointNDConcept<point_t>>();
135         static_assert(point_t::num_dimensions == N, "");
136         static_assert(std::is_same
137             <
138                 typename std::iterator_traits<first_it_type>::difference_type,
139                 typename point_t::template axis<0>::coord_t
140             >::value, "");
141         static_assert(std::is_same
142             <
143                 typename std::iterator_traits<last_it_type>::difference_type,
144                 typename point_t::template axis<N-1>::coord_t
145             >::value, "");
146
147         point_t p;
148         locator lc;
149         iterator it;
150         reverse_iterator rit;
151         difference_type d; detail::initialize_it(d); ignore_unused_variable_warning(d);
152
153         View(p,lc); // view must be constructible from a locator and a point
154
155         p = view.dimensions();
156         lc = view.pixels();
157         size_type sz = view.size(); ignore_unused_variable_warning(sz);
158         bool is_contiguous = view.is_1d_traversable();
159         ignore_unused_variable_warning(is_contiguous);
160
161         it = view.begin();
162         it = view.end();
163         rit = view.rbegin();
164         rit = view.rend();
165
166         reference r1 = view[d]; ignore_unused_variable_warning(r1); // 1D access
167         reference r2 = view(p); ignore_unused_variable_warning(r2); // 2D access
168
169         // get 1-D iterator of any dimension at a given pixel location
170         first_it_type fi = view.template axis_iterator<0>(p);
171         ignore_unused_variable_warning(fi);
172         last_it_type li = view.template axis_iterator<N-1>(p);
173         ignore_unused_variable_warning(li);
174
175         using deref_t = PixelDereferenceAdaptorArchetype<typename View::value_type>;
176         using dtype = typename View::template add_deref<deref_t>::type;
177     }
178     View view;
179 };
180
181 /// \ingroup ImageView2DConcept
182 /// \brief 2-dimensional view over immutable values
183 ///
184 /// \code
185 /// concept RandomAccess2DImageViewConcept<RandomAccessNDImageViewConcept View> {
186 ///     where num_dimensions==2;
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 ///     typename xy_locator = locator;
193 ///
194 ///     x_coord_t View::width()  const;
195 ///     y_coord_t View::height() const;
196 ///
197 ///     // X-navigation
198 ///     x_iterator View::x_at(const point_t&) const;
199 ///     x_iterator View::row_begin(y_coord_t) const;
200 ///     x_iterator View::row_end  (y_coord_t) const;
201 ///
202 ///     // Y-navigation
203 ///     y_iterator View::y_at(const point_t&) const;
204 ///     y_iterator View::col_begin(x_coord_t) const;
205 ///     y_iterator View::col_end  (x_coord_t) const;
206 ///
207 ///     // navigating in 2D
208 ///     xy_locator View::xy_at(const point_t&) const;
209 ///
210 ///     // (x,y) versions of all methods taking point_t
211 ///     View::View(x_coord_t,y_coord_t,const locator&);
212 ///     iterator View::at(x_coord_t,y_coord_t) const;
213 ///     reference operator()(View,x_coord_t,y_coord_t) const;
214 ///     xy_locator View::xy_at(x_coord_t,y_coord_t) const;
215 ///     x_iterator View::x_at(x_coord_t,y_coord_t) const;
216 ///     y_iterator View::y_at(x_coord_t,y_coord_t) const;
217 /// };
218 /// \endcode
219 template <typename View>
220 struct RandomAccess2DImageViewConcept
221 {
222     void constraints()
223     {
224         gil_function_requires<RandomAccessNDImageViewConcept<View>>();
225         static_assert(View::num_dimensions == 2, "");
226
227         // TODO: This executes the requirements for RandomAccessNDLocatorConcept again. Fix it to improve compile time
228         gil_function_requires<RandomAccess2DLocatorConcept<typename View::locator>>();
229
230         using dynamic_x_step_t = typename dynamic_x_step_type<View>::type;
231         using dynamic_y_step_t = typename dynamic_y_step_type<View>::type;
232         using transposed_t = typename transposed_type<View>::type;
233         using x_iterator = typename View::x_iterator;
234         using y_iterator = typename View::y_iterator;
235         using x_coord_t = typename View::x_coord_t;
236         using y_coord_t = typename View::y_coord_t;
237         using xy_locator = typename View::xy_locator;
238
239         x_coord_t xd = 0; ignore_unused_variable_warning(xd);
240         y_coord_t yd = 0; ignore_unused_variable_warning(yd);
241         x_iterator xit;
242         y_iterator yit;
243         typename View::point_t d;
244
245         View(xd, yd, xy_locator()); // constructible with width, height, 2d_locator
246
247         xy_locator lc = view.xy_at(xd, yd);
248         lc = view.xy_at(d);
249
250         typename View::reference r = view(xd, yd);
251         ignore_unused_variable_warning(r);
252         xd = view.width();
253         yd = view.height();
254
255         xit = view.x_at(d);
256         xit = view.x_at(xd,yd);
257         xit = view.row_begin(xd);
258         xit = view.row_end(xd);
259
260         yit = view.y_at(d);
261         yit = view.y_at(xd,yd);
262         yit = view.col_begin(xd);
263         yit = view.col_end(xd);
264     }
265     View view;
266 };
267
268 /// \brief GIL view as Collection.
269 ///
270 /// \see https://www.boost.org/libs/utility/Collection.html
271 ///
272 template <typename View>
273 struct CollectionImageViewConcept
274 {
275     void constraints()
276     {
277         using value_type = typename View::value_type;
278         using iterator = typename View::iterator;
279         using const_iterator =  typename View::const_iterator;
280         using reference = typename View::reference;
281         using const_reference = typename View::const_reference;
282         using pointer = typename View::pointer;
283         using difference_type = typename View::difference_type;
284         using size_type=  typename View::size_type;
285
286         iterator i;
287         i = view1.begin();
288         i = view2.end();
289
290         const_iterator ci;
291         ci = view1.begin();
292         ci = view2.end();
293
294         size_type s;
295         s = view1.size();
296         s = view2.size();
297         ignore_unused_variable_warning(s);
298
299         view1.empty();
300
301         view1.swap(view2);
302     }
303     View view1;
304     View view2;
305 };
306
307 /// \brief GIL view as ForwardCollection.
308 ///
309 /// \see https://www.boost.org/libs/utility/Collection.html
310 ///
311 template <typename View>
312 struct ForwardCollectionImageViewConcept
313 {
314     void constraints()
315     {
316         gil_function_requires<CollectionImageViewConcept<View>>();
317
318         using reference = typename View::reference;
319         using const_reference = typename View::const_reference;
320
321         reference r = view.front();
322         ignore_unused_variable_warning(r);
323
324         const_reference cr = view.front();
325         ignore_unused_variable_warning(cr);
326     }
327     View view;
328 };
329
330 /// \brief GIL view as ReversibleCollection.
331 ///
332 /// \see https://www.boost.org/libs/utility/Collection.html
333 ///
334 template <typename View>
335 struct ReversibleCollectionImageViewConcept
336 {
337     void constraints()
338     {
339         gil_function_requires<CollectionImageViewConcept<View>>();
340
341         using reverse_iterator = typename View::reverse_iterator;
342         using reference = typename View::reference;
343         using const_reference = typename View::const_reference;
344
345         reverse_iterator i;
346         i = view.rbegin();
347         i = view.rend();
348
349         reference r = view.back();
350         ignore_unused_variable_warning(r);
351
352         const_reference cr = view.back();
353         ignore_unused_variable_warning(cr);
354     }
355     View view;
356 };
357
358 /// \ingroup PixelImageViewConcept
359 /// \brief GIL's 2-dimensional view over immutable GIL pixels
360 /// \code
361 /// concept ImageViewConcept<RandomAccess2DImageViewConcept View>
362 /// {
363 ///     where PixelValueConcept<value_type>;
364 ///     where PixelIteratorConcept<x_iterator>;
365 ///     where PixelIteratorConcept<y_iterator>;
366 ///     where x_coord_t == y_coord_t;
367 ///
368 ///     typename coord_t = x_coord_t;
369 ///
370 ///     std::size_t View::num_channels() const;
371 /// };
372 /// \endcode
373 template <typename View>
374 struct ImageViewConcept
375 {
376     void constraints()
377     {
378         gil_function_requires<RandomAccess2DImageViewConcept<View>>();
379
380         // TODO: This executes the requirements for RandomAccess2DLocatorConcept again. Fix it to improve compile time
381         gil_function_requires<PixelLocatorConcept<typename View::xy_locator>>();
382
383         static_assert(std::is_same<typename View::x_coord_t, typename View::y_coord_t>::value, "");
384
385         using coord_t = typename View::coord_t; // 1D difference type (same for all dimensions)
386         std::size_t num_chan = view.num_channels(); ignore_unused_variable_warning(num_chan);
387     }
388     View view;
389 };
390
391 namespace detail {
392
393 /// \tparam View Models RandomAccessNDImageViewConcept
394 template <typename View>
395 struct RandomAccessNDImageViewIsMutableConcept
396 {
397     void constraints()
398     {
399         gil_function_requires<detail::RandomAccessNDLocatorIsMutableConcept<typename View::locator>>();
400
401         gil_function_requires<detail::RandomAccessIteratorIsMutableConcept<typename View::iterator>>();
402
403         gil_function_requires<detail::RandomAccessIteratorIsMutableConcept
404             <
405                 typename View::reverse_iterator
406             >>();
407
408         gil_function_requires<detail::RandomAccessIteratorIsMutableConcept
409             <
410                 typename View::template axis<0>::iterator
411             >>();
412
413         gil_function_requires<detail::RandomAccessIteratorIsMutableConcept
414             <
415                 typename View::template axis<View::num_dimensions - 1>::iterator
416             >>();
417
418         typename View::difference_type diff;
419         initialize_it(diff);
420         ignore_unused_variable_warning(diff);
421
422         typename View::point_t pt;
423         typename View::value_type v;
424         initialize_it(v);
425
426         view[diff] = v;
427         view(pt) = v;
428     }
429     View view;
430 };
431
432 /// \tparam View Models RandomAccessNDImageViewConcept
433 template <typename View>
434 struct RandomAccess2DImageViewIsMutableConcept
435 {
436     void constraints()
437     {
438         gil_function_requires<detail::RandomAccessNDImageViewIsMutableConcept<View>>();
439         typename View::x_coord_t xd = 0; ignore_unused_variable_warning(xd);
440         typename View::y_coord_t yd = 0; ignore_unused_variable_warning(yd);
441         typename View::value_type v; initialize_it(v);
442         view(xd, yd) = v;
443     }
444     View view;
445 };
446
447 /// \tparam View Models ImageViewConcept
448 template <typename View>
449 struct PixelImageViewIsMutableConcept
450 {
451     void constraints()
452     {
453         gil_function_requires<detail::RandomAccess2DImageViewIsMutableConcept<View>>();
454     }
455 };
456
457 } // namespace detail
458
459 /// \ingroup ImageViewNDConcept
460 /// \brief N-dimensional view over mutable values
461 ///
462 /// \code
463 /// concept MutableRandomAccessNDImageViewConcept<RandomAccessNDImageViewConcept View>
464 /// {
465 ///     where Mutable<reference>;
466 /// };
467 /// \endcode
468 template <typename View>
469 struct MutableRandomAccessNDImageViewConcept
470 {
471     void constraints()
472     {
473         gil_function_requires<RandomAccessNDImageViewConcept<View>>();
474         gil_function_requires<detail::RandomAccessNDImageViewIsMutableConcept<View>>();
475     }
476 };
477
478 /// \ingroup ImageView2DConcept
479 /// \brief 2-dimensional view over mutable values
480 ///
481 /// \code
482 /// concept MutableRandomAccess2DImageViewConcept<RandomAccess2DImageViewConcept View>
483 ///     : MutableRandomAccessNDImageViewConcept<View> {};
484 /// \endcode
485 template <typename View>
486 struct MutableRandomAccess2DImageViewConcept
487 {
488     void constraints()
489     {
490         gil_function_requires<RandomAccess2DImageViewConcept<View>>();
491         gil_function_requires<detail::RandomAccess2DImageViewIsMutableConcept<View>>();
492     }
493 };
494
495 /// \ingroup PixelImageViewConcept
496 /// \brief GIL's 2-dimensional view over mutable GIL pixels
497 ///
498 /// \code
499 /// concept MutableImageViewConcept<ImageViewConcept View>
500 ///     : MutableRandomAccess2DImageViewConcept<View> {};
501 /// \endcode
502 template <typename View>
503 struct MutableImageViewConcept
504 {
505     void constraints()
506     {
507         gil_function_requires<ImageViewConcept<View>>();
508         gil_function_requires<detail::PixelImageViewIsMutableConcept<View>>();
509     }
510 };
511
512 /// \brief Returns whether two views are compatible
513 ///
514 /// Views are compatible if their pixels are compatible.
515 /// Compatible views can be assigned and copy constructed from one another.
516 ///
517 /// \tparam V1 Models ImageViewConcept
518 /// \tparam V2 Models ImageViewConcept
519 ///
520 template <typename V1, typename V2>
521 struct views_are_compatible
522     : pixels_are_compatible<typename V1::value_type, typename V2::value_type>
523 {
524 };
525
526 /// \ingroup ImageViewConcept
527 /// \brief Views are compatible if they have the same color spaces and compatible channel values.
528 ///
529 /// Constness and layout are not important for compatibility.
530 ///
531 /// \code
532 /// concept ViewsCompatibleConcept<ImageViewConcept V1, ImageViewConcept V2>
533 /// {
534 ///     where PixelsCompatibleConcept<V1::value_type, P2::value_type>;
535 /// };
536 /// \endcode
537 template <typename V1, typename V2>
538 struct ViewsCompatibleConcept
539 {
540     void constraints()
541     {
542         static_assert(views_are_compatible<V1, V2>::value, "");
543     }
544 };
545
546 }} // namespace boost::gil
547
548 #if defined(BOOST_CLANG)
549 #pragma clang diagnostic pop
550 #endif
551
552 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
553 #pragma GCC diagnostic pop
554 #endif
555
556 #endif