1 /*
2     Copyright 2005-2007 Adobe Systems Incorporated
3 
4     Use, modification and distribution are subject to the Boost Software License,
5     Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6     http://www.boost.org/LICENSE_1_0.txt).
7 
8     See http://opensource.adobe.com/gil for most recent version including documentation.
9 */
10 
11 /*************************************************************************************************/
12 
13 #ifndef GIL_CONCEPT_H
14 #define GIL_CONCEPT_H
15 
16 ////////////////////////////////////////////////////////////////////////////////////////
17 /// \file
18 /// \brief Concept check classes for GIL concepts
19 /// \author Lubomir Bourdev and Hailin Jin \n
20 ///         Adobe Systems Incorporated
21 /// \date   2005-2007 \n Last updated on February 12, 2007
22 ///
23 ////////////////////////////////////////////////////////////////////////////////////////
24 
25 #include <functional>
26 #include "gil_config.hpp"
27 #include <boost/type_traits.hpp>
28 #include <boost/utility/enable_if.hpp>
29 #include <boost/concept_check.hpp>
30 #include <boost/iterator/iterator_concepts.hpp>
31 #include <boost/mpl/and.hpp>
32 #include <boost/mpl/size.hpp>
33 
34 namespace boost { namespace gil {
35 template <typename T> struct channel_traits;
36 template <typename P> struct is_pixel;
37 template <typename dstT, typename srcT>
38 typename channel_traits<dstT>::value_type channel_convert(const srcT& val);
39 template <typename T> class point2;
40 template <std::size_t K, typename T> const T& axis_value(const point2<T>& p);
41 template <std::size_t K, typename T>       T& axis_value(      point2<T>& p);
42 template <typename ColorBase, int K> struct kth_element_type;
43 template <typename ColorBase, int K> struct kth_element_reference_type;
44 template <typename ColorBase, int K> struct kth_element_const_reference_type;
45 template <typename ColorBase, int K> struct kth_semantic_element_reference_type;
46 template <typename ColorBase, int K> struct kth_semantic_element_const_reference_type;
47 template <typename ColorBase> struct size;
48 template <typename ColorBase> struct element_type;
49 template <typename T> struct channel_type;
50 template <typename T> struct color_space_type;
51 template <typename T> struct channel_mapping_type;
52 template <typename T> struct is_planar;
53 template <typename T> struct num_channels;
54 
55 template <typename It> struct const_iterator_type;
56 template <typename It> struct iterator_is_mutable;
57 template <typename It> struct is_iterator_adaptor;
58 template <typename It, typename NewBaseIt> struct iterator_adaptor_rebind;
59 template <typename It> struct iterator_adaptor_get_base;
60 
61 
62 // forward-declare at_c
63 namespace detail { template <typename Element, typename Layout, int K> struct homogeneous_color_base; }
64 template <int K, typename E, typename L, int N>
65 typename add_reference<E>::type                           at_c(      detail::homogeneous_color_base<E,L,N>& p);
66 
67 template <int K, typename E, typename L, int N>
68 typename add_reference<typename add_const<E>::type>::type at_c(const detail::homogeneous_color_base<E,L,N>& p);
69 
70 #if !defined(_MSC_VER)  || _MSC_VER > 1310
71 template <typename P, typename C, typename L> struct packed_pixel;
72 template <int K, typename P, typename C, typename L>
73 typename kth_element_reference_type<packed_pixel<P,C,L>, K>::type
74 at_c(packed_pixel<P,C,L>& p);
75 
76 template <int K, typename P, typename C, typename L>
77 typename kth_element_const_reference_type<packed_pixel<P,C,L>,K>::type
78 at_c(const packed_pixel<P,C,L>& p);
79 
80 template <typename B, typename C, typename L, bool M> struct bit_aligned_pixel_reference;
81 
82 template <int K, typename B, typename C, typename L, bool M> inline
83 typename kth_element_reference_type<bit_aligned_pixel_reference<B,C,L,M>, K>::type
84 at_c(const bit_aligned_pixel_reference<B,C,L,M>& p);
85 #endif
86 
87 // Forward-declare semantic_at_c
88 template <int K, typename ColorBase>
89 typename disable_if<is_const<ColorBase>,typename kth_semantic_element_reference_type<ColorBase,K>::type>::type semantic_at_c(ColorBase& p);
90 template <int K, typename ColorBase>
91 typename kth_semantic_element_const_reference_type<ColorBase,K>::type semantic_at_c(const ColorBase& p);
92 
93 template <typename T> struct dynamic_x_step_type;
94 template <typename T> struct dynamic_y_step_type;
95 template <typename T> struct transposed_type;
96 
97 namespace detail {
98 template <typename T>
initialize_it(T & x)99 void initialize_it(T& x) {}
100 } // namespace detail
101 
102 template <typename T>
103 struct remove_const_and_reference : public remove_const<typename remove_reference<T>::type> {};
104 
105 #ifdef BOOST_GIL_USE_CONCEPT_CHECK
106     #define GIL_CLASS_REQUIRE(type_var, ns, concept) BOOST_CLASS_REQUIRE(type_var, ns, concept);
gil_function_requires()107     template <typename C> void gil_function_requires() { function_requires<C>(); }
108 #else
109     #define GIL_CLASS_REQUIRE(T,NS,C)
gil_function_requires()110     template <typename C> void gil_function_requires() {}
111 #endif
112 
113 /// \ingroup BasicConcepts
114 /**
115 \code
116 auto concept DefaultConstructible<typename T> {
117     T::T();
118 };
119 \endcode
120 */
121 template <typename T>
122 struct DefaultConstructible {
constraintsboost::gil::DefaultConstructible123     void constraints() {
124         function_requires<boost::DefaultConstructibleConcept<T> >();
125     }
126 };
127 
128 /// \ingroup BasicConcepts
129 /**
130 \codeauto concept CopyConstructible<typename T> {
131     T::T(T);
132     T::~T();
133 };
134 \endcode
135 */
136 template <typename T>
137 struct CopyConstructible {
constraintsboost::gil::CopyConstructible138     void constraints() {
139         function_requires<boost::CopyConstructibleConcept<T> >();
140     }
141 };
142 
143 /// \ingroup BasicConcepts
144 /**
145 \code
146 auto concept Assignable<typename T, typename U = T> {
147     typename result_type;
148     result_type operator=(T&, U);
149 };
150 \endcode
151 */
152 template <typename T>
153 struct Assignable {
constraintsboost::gil::Assignable154     void constraints() {
155         function_requires<boost::AssignableConcept<T> >();
156     }
157 };
158 /// \ingroup BasicConcepts
159 /**
160 \code
161 auto concept EqualityComparable<typename T, typename U = T> {
162     bool operator==(T x, T y);
163     bool operator!=(T x, T y) { return !(x==y); }
164 };
165 \endcode
166 */
167 template <typename T>
168 struct EqualityComparable {
constraintsboost::gil::EqualityComparable169     void constraints() {
170         function_requires<boost::EqualityComparableConcept<T> >();
171     }
172 };
173 
174 /// \ingroup BasicConcepts
175 /**
176 \code
177 concept SameType<typename T, typename U>;// unspecified
178 \endcode
179 */
180 
181 template <typename T, typename U>
182 struct SameType {
constraintsboost::gil::SameType183     void constraints() {
184         BOOST_STATIC_ASSERT((boost::is_same<T,U>::value_core));
185     }
186 };
187 
188 /// \ingroup BasicConcepts
189 /**
190 \code
191 auto concept Swappable<typename T> {
192     void swap(T&,T&);
193 };
194 \endcode
195 */
196 template <typename T>
197 struct Swappable {
constraintsboost::gil::Swappable198     void constraints() {
199         using std::swap;
200         swap(x,y);
201     }
202     T x,y;
203 };
204 
205 /// \ingroup BasicConcepts
206 /**
207 \code
208 auto concept Regular<typename T> : DefaultConstructible<T>, CopyConstructible<T>, EqualityComparable<T>,
209                                    Assignable<T>, Swappable<T> {};
210 \endcode
211 */
212 
213 template <typename T>
214 struct Regular {
constraintsboost::gil::Regular215     void constraints() {
216         gil_function_requires< boost::DefaultConstructibleConcept<T> >();
217         gil_function_requires< boost::CopyConstructibleConcept<T> >();
218         gil_function_requires< boost::EqualityComparableConcept<T> >(); // ==, !=
219         gil_function_requires< boost::AssignableConcept<T> >();
220         gil_function_requires< Swappable<T> >();
221     }
222 };
223 
224 /// \ingroup BasicConcepts
225 /**
226 \code
227 auto concept Metafunction<typename T> {
228     typename type;
229 };
230 \endcode
231 */
232 template <typename T>
233 struct Metafunction {
constraintsboost::gil::Metafunction234     void constraints() {
235         typedef typename T::type type;
236     }
237 };
238 ////////////////////////////////////////////////////////////////////////////////////////
239 //
240 //          POINT CONCEPTS
241 //
242 ////////////////////////////////////////////////////////////////////////////////////////
243 
244 /// \brief N-dimensional point concept
245 /// \ingroup PointConcept
246 /**
247 \code
248 concept PointNDConcept<typename T> : Regular<T> {
249     // the type of a coordinate along each axis
250     template <size_t K> struct axis; where Metafunction<axis>;
251 
252     const size_t num_dimensions;
253 
254     // accessor/modifier of the value of each axis.
255     template <size_t K> const typename axis<K>::type& T::axis_value() const;
256     template <size_t K>       typename axis<K>::type& T::axis_value();
257 };
258 \endcode
259 */
260 
261 template <typename P>
262 struct PointNDConcept {
constraintsboost::gil::PointNDConcept263     void constraints() {
264         gil_function_requires< Regular<P> >();
265 
266         typedef typename P::value_type value_type;
267         static const std::size_t N=P::num_dimensions; ignore_unused_variable_warning(N);
268         typedef typename P::template axis<0>::coord_t FT;
269         typedef typename P::template axis<N-1>::coord_t LT;
270         FT ft=gil::axis_value<0>(point);
271         axis_value<0>(point)=ft;
272         LT lt=axis_value<N-1>(point);
273         axis_value<N-1>(point)=lt;
274 
275         value_type v=point[0];  ignore_unused_variable_warning(v);
276         point[0]=point[0];
277     }
278     P point;
279 };
280 
281 /// \brief 2-dimensional point concept
282 /// \ingroup PointConcept
283 /**
284 \code
285 concept Point2DConcept<typename T> : PointNDConcept<T> {
286     where num_dimensions == 2;
287     where SameType<axis<0>::type, axis<1>::type>;
288 
289     typename value_type = axis<0>::type;
290 
291     const value_type& operator[](const T&, size_t i);
292           value_type& operator[](      T&, size_t i);
293 
294     value_type x,y;
295 };
296 \endcode
297 */
298 
299 template <typename P>
300 struct Point2DConcept {
constraintsboost::gil::Point2DConcept301     void constraints() {
302         gil_function_requires< PointNDConcept<P> >();
303         BOOST_STATIC_ASSERT(P::num_dimensions == 2);
304         point.x=point.y;
305         point[0]=point[1];
306     }
307     P point;
308 };
309 
310 ////////////////////////////////////////////////////////////////////////////////////////
311 //
312 //          ITERATOR MUTABILITY CONCEPTS
313 //
314 // Taken from boost's concept_check.hpp. Isolating mutability to result in faster compile time
315 //
316 ////////////////////////////////////////////////////////////////////////////////////////
317 
318 namespace detail {
319     template <class TT> // Preconditions: TT Models boost_concepts::ForwardTraversalConcept
320     struct ForwardIteratorIsMutableConcept {
constraintsboost::gil::detail::ForwardIteratorIsMutableConcept321         void constraints() {
322             *i++ = *i;         // require postincrement and assignment
323         }
324         TT i;
325     };
326 
327     template <class TT> // Preconditions: TT Models boost::BidirectionalIteratorConcept
328     struct BidirectionalIteratorIsMutableConcept {
constraintsboost::gil::detail::BidirectionalIteratorIsMutableConcept329         void constraints() {
330             gil_function_requires< ForwardIteratorIsMutableConcept<TT> >();
331             *i-- = *i;                  // require postdecrement and assignment
332         }
333         TT i;
334     };
335 
336     template <class TT> // Preconditions: TT Models boost_concepts::RandomAccessTraversalConcept
337     struct RandomAccessIteratorIsMutableConcept {
constraintsboost::gil::detail::RandomAccessIteratorIsMutableConcept338         void constraints() {
339             gil_function_requires< BidirectionalIteratorIsMutableConcept<TT> >();
340             typename std::iterator_traits<TT>::difference_type n=0; ignore_unused_variable_warning(n);
341             i[n] = *i;                  // require element access and assignment
342         }
343         TT i;
344     };
345 }   // namespace detail
346 
347 ////////////////////////////////////////////////////////////////////////////////////////
348 //
349 //         COLOR SPACE CONCEPTS
350 //
351 ////////////////////////////////////////////////////////////////////////////////////////
352 
353 /// \brief Color space type concept
354 /// \ingroup ColorSpaceAndLayoutConcept
355 /**
356 \code
357 concept ColorSpaceConcept<MPLRandomAccessSequence Cs> {
358    // An MPL Random Access Sequence, whose elements are color tags
359 };
360 \endcode
361 */
362 template <typename Cs>
363 struct ColorSpaceConcept {
constraintsboost::gil::ColorSpaceConcept364     void constraints() {
365         // An MPL Random Access Sequence, whose elements are color tags
366     }
367 };
368 
369 template <typename ColorSpace1, typename ColorSpace2>  // Models ColorSpaceConcept
370 struct color_spaces_are_compatible : public is_same<ColorSpace1,ColorSpace2> {};
371 
372 /// \brief Two color spaces are compatible if they are the same
373 /// \ingroup ColorSpaceAndLayoutConcept
374 /**
375 \code
376 concept ColorSpacesCompatibleConcept<ColorSpaceConcept Cs1, ColorSpaceConcept Cs2> {
377     where SameType<Cs1,Cs2>;
378 };
379 \endcode
380 */
381 template <typename Cs1, typename Cs2>
382 struct ColorSpacesCompatibleConcept {
constraintsboost::gil::ColorSpacesCompatibleConcept383     void constraints() {
384         BOOST_STATIC_ASSERT((color_spaces_are_compatible<Cs1,Cs2>::value));
385     }
386 };
387 
388 /// \brief Channel mapping concept
389 /// \ingroup ColorSpaceAndLayoutConcept
390 /**
391 \code
392 concept ChannelMappingConcept<MPLRandomAccessSequence CM> {
393    // An MPL Random Access Sequence, whose elements model MPLIntegralConstant representing a permutation
394 };
395 \endcode
396 */
397 template <typename CM>
398 struct ChannelMappingConcept {
constraintsboost::gil::ChannelMappingConcept399     void constraints() {
400         // An MPL Random Access Sequence, whose elements model MPLIntegralConstant representing a permutation
401     }
402 };
403 
404 
405 
406 ////////////////////////////////////////////////////////////////////////////////////////
407 ///
408 ///         Channel CONCEPTS
409 ///
410 ////////////////////////////////////////////////////////////////////////////////////////
411 
412 /// \ingroup ChannelConcept
413 /// \brief A channel is the building block of a color. Color is defined as a mixture of primary colors and a channel defines the degree to which each primary color is used in the mixture.
414 /**
415 For example, in the RGB color space, using 8-bit unsigned channels, the color red is defined as [255 0 0], which means maximum of Red, and no Green and Blue.
416 
417 Built-in scalar types, such as \p int and \p float, are valid GIL channels. In more complex scenarios, channels may be represented as bit ranges or even individual bits.
418 In such cases special classes are needed to represent the value and reference to a channel.
419 
420 Channels have a traits class, \p channel_traits, which defines their associated types as well as their operating ranges.
421 
422 \code
423 concept ChannelConcept<typename T> : EqualityComparable<T> {
424     typename value_type      = T;        // use channel_traits<T>::value_type to access it
425     typename reference       = T&;       // use channel_traits<T>::reference to access it
426     typename pointer         = T*;       // use channel_traits<T>::pointer to access it
427     typename const_reference = const T&; // use channel_traits<T>::const_reference to access it
428     typename const_pointer   = const T*; // use channel_traits<T>::const_pointer to access it
429     static const bool is_mutable;        // use channel_traits<T>::is_mutable to access it
430 
431     static T min_value();                // use channel_traits<T>::min_value to access it
432     static T max_value();                // use channel_traits<T>::min_value to access it
433 };
434 \endcode
435 */
436 template <typename T>
437 struct ChannelConcept {
constraintsboost::gil::ChannelConcept438     void constraints() {
439         gil_function_requires< boost::EqualityComparableConcept<T> >();
440 
441         typedef typename channel_traits<T>::value_type v;
442         typedef typename channel_traits<T>::reference r;
443         typedef typename channel_traits<T>::pointer p;
444         typedef typename channel_traits<T>::const_reference cr;
445         typedef typename channel_traits<T>::const_pointer cp;
446 
447         channel_traits<T>::min_value();
448         channel_traits<T>::max_value();
449     }
450 
451      T c;
452 };
453 
454 namespace detail {
455     // Preconditions: T models ChannelConcept
456     template <typename T>
457     struct ChannelIsMutableConcept {
constraintsboost::gil::detail::ChannelIsMutableConcept458         void constraints() {
459             c=c;
460             using std::swap;
461             swap(c,c);
462         }
463         T c;
464     };
465 }
466 
467 /// \brief A channel that allows for modifying its value
468 /// \ingroup ChannelConcept
469 /**
470 \code
471 concept MutableChannelConcept<ChannelConcept T> : Assignable<T>, Swappable<T> {};
472 \endcode
473 */
474 template <typename T>
475 struct MutableChannelConcept {
constraintsboost::gil::MutableChannelConcept476     void constraints() {
477         gil_function_requires<ChannelConcept<T> >();
478         gil_function_requires<detail::ChannelIsMutableConcept<T> >();
479     }
480 };
481 
482 /// \brief A channel that supports default construction.
483 /// \ingroup ChannelConcept
484 /**
485 \code
486 concept ChannelValueConcept<ChannelConcept T> : Regular<T> {};
487 \endcode
488 */
489 template <typename T>
490 struct ChannelValueConcept {
constraintsboost::gil::ChannelValueConcept491     void constraints() {
492         gil_function_requires<ChannelConcept<T> >();
493         gil_function_requires<Regular<T> >();
494     }
495 };
496 
497 
498 /// \brief Predicate metafunction returning whether two channels are compatible
499 /// \ingroup ChannelAlgorithm
500 ///
501 /// Channels are considered compatible if their value types (ignoring constness and references) are the same.
502 /**
503 Example:
504 
505 \code
506 BOOST_STATIC_ASSERT((channels_are_compatible<bits8, const bits8&>::value));
507 \endcode
508 */
509 template <typename T1, typename T2>  // Models GIL Pixel
510 struct channels_are_compatible
511     : public is_same<typename channel_traits<T1>::value_type, typename channel_traits<T2>::value_type> {};
512 
513 /// \brief Channels are compatible if their associated value types (ignoring constness and references) are the same
514 /// \ingroup ChannelConcept
515 /**
516 \code
517 concept ChannelsCompatibleConcept<ChannelConcept T1, ChannelConcept T2> {
518     where SameType<T1::value_type, T2::value_type>;
519 };
520 \endcode
521 */
522 template <typename T1, typename T2>
523 struct ChannelsCompatibleConcept {
constraintsboost::gil::ChannelsCompatibleConcept524     void constraints() {
525         BOOST_STATIC_ASSERT((channels_are_compatible<T1,T2>::value));
526     }
527 };
528 
529 /// \brief A channel is convertible to another one if the \p channel_convert algorithm is defined for the two channels
530 ///
531 /// Convertibility is non-symmetric and implies that one channel can be converted to another. Conversion is explicit and often lossy operation.
532 /// \ingroup ChannelConcept
533 /**
534 \code
535 concept ChannelConvertibleConcept<ChannelConcept SrcChannel, ChannelValueConcept DstChannel> {
536     DstChannel channel_convert(const SrcChannel&);
537 };
538 \endcode
539 */
540 template <typename SrcChannel, typename DstChannel>
541 struct ChannelConvertibleConcept {
constraintsboost::gil::ChannelConvertibleConcept542     void constraints() {
543         gil_function_requires<ChannelConcept<SrcChannel> >();
544         gil_function_requires<MutableChannelConcept<DstChannel> >();
545         dst=channel_convert<DstChannel,SrcChannel>(src); ignore_unused_variable_warning(dst);
546     }
547     SrcChannel src;
548     DstChannel dst;
549 };
550 
551 
552 
553 
554 
555 ////////////////////////////////////////////////////////////////////////////////////////
556 ///
557 ///         COLOR BASE CONCEPTS
558 ///
559 ////////////////////////////////////////////////////////////////////////////////////////
560 
561 /// \ingroup ColorBaseConcept
562 /// \brief A color base is a container of color elements (such as channels, channel references or channel pointers)
563 /**
564 The most common use of color base is in the implementation of a pixel, in which case the color
565 elements are channel values. The color base concept, however, can be used in other scenarios. For example, a planar pixel has channels that are not
566 contiguous in memory. Its reference is a proxy class that uses a color base whose elements are channel references. Its iterator uses a color base
567 whose elements are channel iterators.
568 
569 A color base must have an associated layout (which consists of a color space, as well as an ordering of the channels).
570 There are two ways to index the elements of a color base: A physical index corresponds to the way they are ordered in memory, and
571 a semantic index corresponds to the way the elements are ordered in their color space.
572 For example, in the RGB color space the elements are ordered as {red_t, green_t, blue_t}. For a color base with a BGR layout, the first element
573 in physical ordering is the blue element, whereas the first semantic element is the red one.
574 Models of \p ColorBaseConcept are required to provide the \p at_c<K>(ColorBase) function, which allows for accessing the elements based on their
575 physical order. GIL provides a \p semantic_at_c<K>(ColorBase) function (described later) which can operate on any model of ColorBaseConcept and returns
576 the corresponding semantic element.
577 
578 \code
579 concept ColorBaseConcept<typename T> : CopyConstructible<T>, EqualityComparable<T> {
580     // a GIL layout (the color space and element permutation)
581     typename layout_t;
582 
583     // The type of K-th element
584     template <int K> struct kth_element_type;                 where Metafunction<kth_element_type>;
585 
586     // The result of at_c
587     template <int K> struct kth_element_const_reference_type; where Metafunction<kth_element_const_reference_type>;
588 
589     template <int K> kth_element_const_reference_type<T,K>::type at_c(T);
590 
591     // Copy-constructible and equality comparable with other compatible color bases
592     template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> }
593         T::T(T2);
594     template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> }
595         bool operator==(const T&, const T2&);
596     template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> }
597         bool operator!=(const T&, const T2&);
598 
599 };
600 \endcode
601 */
602 
603 template <typename ColorBase>
604 struct ColorBaseConcept {
constraintsboost::gil::ColorBaseConcept605     void constraints() {
606         gil_function_requires< CopyConstructible<ColorBase> >();
607         gil_function_requires< EqualityComparable<ColorBase> >();
608 
609         typedef typename ColorBase::layout_t::color_space_t color_space_t;
610         gil_function_requires<ColorSpaceConcept<color_space_t> >();
611 
612         typedef typename ColorBase::layout_t::channel_mapping_t channel_mapping_t;
613         // TODO: channel_mapping_t must be an MPL RandomAccessSequence
614 
615         static const std::size_t num_elements = size<ColorBase>::value;
616 
617         typedef typename kth_element_type<ColorBase,num_elements-1>::type TN;
618         typedef typename kth_element_const_reference_type<ColorBase,num_elements-1>::type CR;
619 
620 #if !defined(_MSC_VER) || _MSC_VER > 1310
621         CR cr=at_c<num_elements-1>(cb);  ignore_unused_variable_warning(cr);
622 #endif
623 
624         // functions that work for every pixel (no need to require them)
625         semantic_at_c<0>(cb);
626         semantic_at_c<num_elements-1>(cb);
627         // also static_max(cb), static_min(cb), static_fill(cb,value), and all variations of static_for_each(), static_generate(), static_transform()
628     }
629 
630     ColorBase cb;
631 };
632 
633 /// \ingroup ColorBaseConcept
634 /// \brief Color base which allows for modifying its elements
635 /**
636 
637 \code
638 concept MutableColorBaseConcept<ColorBaseConcept T> : Assignable<T>, Swappable<T> {
639     template <int K> struct kth_element_reference_type;       where Metafunction<kth_element_reference_type>;
640 
641     template <int K> kth_element_reference_type<kth_element_type<T,K>::type>::type at_c(T);
642 
643     template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> }
644         T& operator=(T&, const T2&);
645 };
646 \endcode
647 */
648 template <typename ColorBase>
649 struct MutableColorBaseConcept {
constraintsboost::gil::MutableColorBaseConcept650     void constraints() {
651         gil_function_requires< ColorBaseConcept<ColorBase> >();
652         gil_function_requires< Assignable<ColorBase> >();
653         gil_function_requires< Swappable<ColorBase> >();
654 
655         typedef typename kth_element_reference_type<ColorBase, 0>::type CR;
656 
657 #if !defined(_MSC_VER) || _MSC_VER > 1310
658         CR r=at_c<0>(cb);
659         at_c<0>(cb)=r;
660 #endif
661     }
662 
663     ColorBase cb;
664 };
665 
666 /// \ingroup ColorBaseConcept
667 /// \brief Color base that also has a default-constructor. Refines Regular
668 /**
669 \code
670 concept ColorBaseValueConcept<typename T> : MutableColorBaseConcept<T>, Regular<T> {
671 };
672 \endcode
673 */
674 template <typename ColorBase>
675 struct ColorBaseValueConcept {
constraintsboost::gil::ColorBaseValueConcept676     void constraints() {
677         gil_function_requires< MutableColorBaseConcept<ColorBase> >();
678         gil_function_requires< Regular<ColorBase> >();
679     }
680 };
681 
682 /// \ingroup ColorBaseConcept
683 /// \brief Color base whose elements all have the same type
684 /**
685 \code
686 concept HomogeneousColorBaseConcept<ColorBaseConcept CB> {
687     // For all K in [0 ... size<C1>::value-1):
688     //     where SameType<kth_element_type<CB,K>::type, kth_element_type<CB,K+1>::type>;
689     kth_element_const_reference_type<CB,0>::type dynamic_at_c(const CB&, std::size_t n) const;
690 };
691 \endcode
692 */
693 
694 template <typename ColorBase>
695 struct HomogeneousColorBaseConcept {
constraintsboost::gil::HomogeneousColorBaseConcept696     void constraints() {
697         gil_function_requires< ColorBaseConcept<ColorBase> >();
698 
699         static const std::size_t num_elements = size<ColorBase>::value;
700 
701         typedef typename kth_element_type<ColorBase,0>::type T0;
702         typedef typename kth_element_type<ColorBase,num_elements-1>::type TN;
703 
704         BOOST_STATIC_ASSERT((is_same<T0,TN>::value));   // better than nothing
705         typedef typename kth_element_const_reference_type<ColorBase,0>::type CRef0;
706         CRef0 e0=dynamic_at_c(cb,0);
707     }
708     ColorBase cb;
709 };
710 
711 /// \ingroup ColorBaseConcept
712 /// \brief Homogeneous color base that allows for modifying its elements
713 /**
714 
715 \code
716 concept MutableHomogeneousColorBaseConcept<ColorBaseConcept CB> : HomogeneousColorBaseConcept<CB> {
717     kth_element_reference_type<CB,0>::type dynamic_at_c(CB&, std::size_t n);
718 };
719 \endcode
720 */
721 
722 template <typename ColorBase>
723 struct MutableHomogeneousColorBaseConcept {
constraintsboost::gil::MutableHomogeneousColorBaseConcept724     void constraints() {
725         gil_function_requires< ColorBaseConcept<ColorBase> >();
726         gil_function_requires< HomogeneousColorBaseConcept<ColorBase> >();
727         typedef typename kth_element_reference_type<ColorBase, 0>::type R0;
728         R0 x=dynamic_at_c(cb,0);
729         dynamic_at_c(cb,0) = dynamic_at_c(cb,0);
730     }
731     ColorBase cb;
732 };
733 
734 /// \ingroup ColorBaseConcept
735 /// \brief Homogeneous color base that also has a default constructor. Refines Regular.
736 /**
737 
738 \code
739 concept HomogeneousColorBaseValueConcept<typename T> : MutableHomogeneousColorBaseConcept<T>, Regular<T> {
740 };
741 \endcode
742 */
743 
744 template <typename ColorBase>
745 struct HomogeneousColorBaseValueConcept {
constraintsboost::gil::HomogeneousColorBaseValueConcept746     void constraints() {
747         gil_function_requires< MutableHomogeneousColorBaseConcept<ColorBase> >();
748         gil_function_requires< Regular<ColorBase> >();
749     }
750 };
751 
752 
753 /// \ingroup ColorBaseConcept
754 /// \brief Two color bases are compatible if they have the same color space and their elements are compatible, semantic-pairwise.
755 /**
756 
757 \code
758 concept ColorBasesCompatibleConcept<ColorBaseConcept C1, ColorBaseConcept C2> {
759     where SameType<C1::layout_t::color_space_t, C2::layout_t::color_space_t>;
760     // also, for all K in [0 ... size<C1>::value):
761     //     where Convertible<kth_semantic_element_type<C1,K>::type, kth_semantic_element_type<C2,K>::type>;
762     //     where Convertible<kth_semantic_element_type<C2,K>::type, kth_semantic_element_type<C1,K>::type>;
763 };
764 \endcode
765 */
766 template <typename ColorBase1, typename ColorBase2>
767 struct ColorBasesCompatibleConcept {
constraintsboost::gil::ColorBasesCompatibleConcept768     void constraints() {
769         BOOST_STATIC_ASSERT((is_same<typename ColorBase1::layout_t::color_space_t,
770                                      typename ColorBase2::layout_t::color_space_t>::value));
771 //        typedef typename kth_semantic_element_type<ColorBase1,0>::type e1;
772 //        typedef typename kth_semantic_element_type<ColorBase2,0>::type e2;
773 //        "e1 is convertible to e2"
774     }
775 };
776 
777 
778 
779 
780 
781 
782 
783 
784 
785 
786 
787 
788 
789 
790 
791 
792 
793 
794 
795 
796 
797 
798 ////////////////////////////////////////////////////////////////////////////////////////
799 ///
800 ///         PIXEL CONCEPTS
801 ///
802 ////////////////////////////////////////////////////////////////////////////////////////
803 
804 /// \brief Concept for all pixel-based GIL constructs, such as pixels, iterators, locators, views and images whose value type is a pixel
805 /// \ingroup PixelBasedConcept
806 /**
807 \code
808 concept PixelBasedConcept<typename T> {
809     typename color_space_type<T>;
810         where Metafunction<color_space_type<T> >;
811         where ColorSpaceConcept<color_space_type<T>::type>;
812     typename channel_mapping_type<T>;
813         where Metafunction<channel_mapping_type<T> >;
814         where ChannelMappingConcept<channel_mapping_type<T>::type>;
815     typename is_planar<T>;
816         where Metafunction<is_planar<T> >;
817         where SameType<is_planar<T>::type, bool>;
818 };
819 \endcode
820 */
821 template <typename P>
822 struct PixelBasedConcept {
constraintsboost::gil::PixelBasedConcept823     void constraints() {
824         typedef typename color_space_type<P>::type color_space_t;
825         gil_function_requires<ColorSpaceConcept<color_space_t> >();
826         typedef typename channel_mapping_type<P>::type channel_mapping_t;
827         gil_function_requires<ChannelMappingConcept<channel_mapping_t> >();
828 
829         static const bool planar = is_planar<P>::type::value;   ignore_unused_variable_warning(planar);
830 
831 
832         // This is not part of the concept, but should still work
833         static const std::size_t nc = num_channels<P>::value;
834         ignore_unused_variable_warning(nc);
835     }
836 };
837 
838 /// \brief Concept for homogeneous pixel-based GIL constructs
839 /// \ingroup PixelBasedConcept
840 /**
841 \code
842 concept HomogeneousPixelBasedConcept<PixelBasedConcept T> {
843     typename channel_type<T>;
844         where Metafunction<channel_type<T> >;
845         where ChannelConcept<channel_type<T>::type>;
846 };
847 \endcode
848 */
849 template <typename P>
850 struct HomogeneousPixelBasedConcept {
constraintsboost::gil::HomogeneousPixelBasedConcept851     void constraints() {
852         gil_function_requires<PixelBasedConcept<P> >();
853         typedef typename channel_type<P>::type channel_t;
854         gil_function_requires<ChannelConcept<channel_t> >();
855     }
856 };
857 
858 
859 /// \brief Pixel concept - A color base whose elements are channels
860 /// \ingroup PixelConcept
861 /**
862 \code
863 concept PixelConcept<typename P> : ColorBaseConcept<P>, PixelBasedConcept<P> {
864     where is_pixel<P>::type::value==true;
865     // where for each K [0..size<P>::value-1]:
866     //      ChannelConcept<kth_element_type<P,K> >;
867 
868     typename P::value_type;       where PixelValueConcept<value_type>;
869     typename P::reference;        where PixelConcept<reference>;
870     typename P::const_reference;  where PixelConcept<const_reference>;
871     static const bool P::is_mutable;
872 
873     template <PixelConcept P2> where { PixelConcept<P,P2> }
874         P::P(P2);
875     template <PixelConcept P2> where { PixelConcept<P,P2> }
876         bool operator==(const P&, const P2&);
877     template <PixelConcept P2> where { PixelConcept<P,P2> }
878         bool operator!=(const P&, const P2&);
879 };
880 \endcode
881 */
882 
883 template <typename P>
884 struct PixelConcept {
constraintsboost::gil::PixelConcept885     void constraints() {
886         gil_function_requires<ColorBaseConcept<P> >();
887         gil_function_requires<PixelBasedConcept<P> >();
888 
889         BOOST_STATIC_ASSERT((is_pixel<P>::value));
890         static const bool is_mutable = P::is_mutable; ignore_unused_variable_warning(is_mutable);
891 
892         typedef typename P::value_type      value_type;
893 //      gil_function_requires<PixelValueConcept<value_type> >();
894 
895         typedef typename P::reference       reference;
896         gil_function_requires<PixelConcept<typename remove_const_and_reference<reference>::type> >();
897 
898         typedef typename P::const_reference const_reference;
899         gil_function_requires<PixelConcept<typename remove_const_and_reference<const_reference>::type> >();
900     }
901 };
902 
903 
904 /// \brief Pixel concept that allows for changing its channels
905 /// \ingroup PixelConcept
906 /**
907 \code
908 concept MutablePixelConcept<PixelConcept P> : MutableColorBaseConcept<P> {
909     where is_mutable==true;
910 };
911 \endcode
912 */
913 template <typename P>
914 struct MutablePixelConcept {
constraintsboost::gil::MutablePixelConcept915     void constraints() {
916         gil_function_requires<PixelConcept<P> >();
917         BOOST_STATIC_ASSERT(P::is_mutable);
918     }
919 };
920 /// \brief Homogeneous pixel concept
921 /// \ingroup PixelConcept
922 /**
923 \code
924 concept HomogeneousPixelConcept<PixelConcept P> : HomogeneousColorBaseConcept<P>, HomogeneousPixelBasedConcept<P> {
925     P::template element_const_reference_type<P>::type operator[](P p, std::size_t i) const { return dynamic_at_c(p,i); }
926 };
927 \endcode
928 */
929 template <typename P>
930 struct HomogeneousPixelConcept {
constraintsboost::gil::HomogeneousPixelConcept931     void constraints() {
932         gil_function_requires<PixelConcept<P> >();
933         gil_function_requires<HomogeneousColorBaseConcept<P> >();
934         gil_function_requires<HomogeneousPixelBasedConcept<P> >();
935         p[0];
936     }
937     P p;
938 };
939 
940 /// \brief Homogeneous pixel concept that allows for changing its channels
941 /// \ingroup PixelConcept
942 /**
943 \code
944 concept MutableHomogeneousPixelConcept<HomogeneousPixelConcept P> : MutableHomogeneousColorBaseConcept<P> {
945     P::template element_reference_type<P>::type operator[](P p, std::size_t i) { return dynamic_at_c(p,i); }
946 };
947 \endcode
948 */
949 template <typename P>
950 struct MutableHomogeneousPixelConcept {
constraintsboost::gil::MutableHomogeneousPixelConcept951     void constraints() {
952         gil_function_requires<HomogeneousPixelConcept<P> >();
953         gil_function_requires<MutableHomogeneousColorBaseConcept<P> >();
954         p[0]=p[0];
955     }
956     P p;
957 };
958 
959 /// \brief Pixel concept that is a Regular type
960 /// \ingroup PixelConcept
961 /**
962 \code
963 concept PixelValueConcept<PixelConcept P> : Regular<P> {
964     where SameType<value_type,P>;
965 };
966 \endcode
967 */
968 template <typename P>
969 struct PixelValueConcept {
constraintsboost::gil::PixelValueConcept970     void constraints() {
971         gil_function_requires<PixelConcept<P> >();
972         gil_function_requires<Regular<P> >();
973     }
974 };
975 
976 /// \brief Homogeneous pixel concept that is a Regular type
977 /// \ingroup PixelConcept
978 /**
979 \code
980 concept HomogeneousPixelValueConcept<HomogeneousPixelConcept P> : Regular<P> {
981     where SameType<value_type,P>;
982 };
983 \endcode
984 */
985 template <typename P>
986 struct HomogeneousPixelValueConcept {
constraintsboost::gil::HomogeneousPixelValueConcept987     void constraints() {
988         gil_function_requires<HomogeneousPixelConcept<P> >();
989         gil_function_requires<Regular<P> >();
990         BOOST_STATIC_ASSERT((is_same<P, typename P::value_type>::value));
991     }
992 };
993 
994 namespace detail {
995     template <typename P1, typename P2, int K>
996     struct channels_are_pairwise_compatible : public
997         mpl::and_<channels_are_pairwise_compatible<P1,P2,K-1>,
998                          channels_are_compatible<typename kth_semantic_element_reference_type<P1,K>::type,
999                                                  typename kth_semantic_element_reference_type<P2,K>::type> > {};
1000 
1001     template <typename P1, typename P2>
1002     struct channels_are_pairwise_compatible<P1,P2,-1> : public mpl::true_ {};
1003 }
1004 
1005 /// \brief Returns whether two pixels are compatible
1006 ///
1007 /// Pixels are compatible if their channels and color space types are compatible. Compatible pixels can be assigned and copy constructed from one another.
1008 /// \ingroup PixelAlgorithm
1009 template <typename P1, typename P2>  // Models GIL Pixel
1010 struct pixels_are_compatible
1011     : public mpl::and_<typename color_spaces_are_compatible<typename color_space_type<P1>::type,
1012                                                             typename color_space_type<P2>::type>::type,
1013                        detail::channels_are_pairwise_compatible<P1,P2,num_channels<P1>::value-1> > {};
1014 
1015 /// \brief  Concept for pixel compatibility
1016 ///    Pixels are compatible if their channels and color space types are compatible. Compatible pixels can be assigned and copy constructed from one another.
1017 /// \ingroup PixelConcept
1018 /**
1019 \code
1020 concept PixelsCompatibleConcept<PixelConcept P1, PixelConcept P2> : ColorBasesCompatibleConcept<P1,P2> {
1021     // where for each K [0..size<P1>::value):
1022     //    ChannelsCompatibleConcept<kth_semantic_element_type<P1,K>::type, kth_semantic_element_type<P2,K>::type>;
1023 };
1024 \endcode
1025 */
1026 template <typename P1, typename P2> // precondition: P1 and P2 model PixelConcept
1027 struct PixelsCompatibleConcept {
constraintsboost::gil::PixelsCompatibleConcept1028     void constraints() {
1029         BOOST_STATIC_ASSERT((pixels_are_compatible<P1,P2>::value));
1030     }
1031 };
1032 
1033 /// \brief Pixel convertible concept
1034 ///
1035 /// Convertibility is non-symmetric and implies that one pixel can be converted to another, approximating the color. Conversion is explicit and sometimes lossy.
1036 /// \ingroup PixelConcept
1037 /**
1038 \code
1039 template <PixelConcept SrcPixel, MutablePixelConcept DstPixel>
1040 concept PixelConvertibleConcept {
1041     void color_convert(const SrcPixel&, DstPixel&);
1042 };
1043 \endcode
1044 */
1045 template <typename SrcP, typename DstP>
1046 struct PixelConvertibleConcept {
constraintsboost::gil::PixelConvertibleConcept1047     void constraints() {
1048         gil_function_requires<PixelConcept<SrcP> >();
1049         gil_function_requires<MutablePixelConcept<DstP> >();
1050         color_convert(src,dst);
1051     }
1052     SrcP src;
1053     DstP dst;
1054 };
1055 
1056 ////////////////////////////////////////////////////////////////////////////////////////
1057 ///
1058 ///         DEREFERENCE ADAPTOR CONCEPTS
1059 ///
1060 ////////////////////////////////////////////////////////////////////////////////////////
1061 
1062 /// \ingroup PixelDereferenceAdaptorConcept
1063 
1064 /// \brief Represents a unary function object that can be invoked upon dereferencing a pixel iterator.
1065 ///
1066 /// This can perform an arbitrary computation, such as color conversion or table lookup
1067 /**
1068 \code
1069 concept PixelDereferenceAdaptorConcept<boost::UnaryFunctionConcept D>
1070   : DefaultConstructibleConcept<D>, CopyConstructibleConcept<D>, AssignableConcept<D>  {
1071     typename const_t;         where PixelDereferenceAdaptorConcept<const_t>;
1072     typename value_type;      where PixelValueConcept<value_type>;
1073     typename reference;         // may be mutable
1074     typename const_reference;   // must not be mutable
1075     static const bool D::is_mutable;
1076 
1077     where Convertible<value_type,result_type>;
1078 };
1079 \endcode
1080 */
1081 
1082 template <typename D>
1083 struct PixelDereferenceAdaptorConcept {
constraintsboost::gil::PixelDereferenceAdaptorConcept1084     void constraints() {
1085         gil_function_requires< boost::UnaryFunctionConcept<D,
1086             typename remove_const_and_reference<typename D::result_type>::type,
1087             typename D::argument_type> >();
1088         gil_function_requires< boost::DefaultConstructibleConcept<D> >();
1089         gil_function_requires< boost::CopyConstructibleConcept<D> >();
1090         gil_function_requires< boost::AssignableConcept<D> >();
1091 
1092         gil_function_requires<PixelConcept<typename remove_const_and_reference<typename D::result_type>::type> >();
1093 
1094         typedef typename D::const_t const_t;
1095         gil_function_requires<PixelDereferenceAdaptorConcept<const_t> >();
1096         typedef typename D::value_type value_type;
1097         gil_function_requires<PixelValueConcept<value_type> >();
1098         typedef typename D::reference reference;                // == PixelConcept (if you remove const and reference)
1099         typedef typename D::const_reference const_reference;    // == PixelConcept (if you remove const and reference)
1100 
1101         const bool is_mutable=D::is_mutable; ignore_unused_variable_warning(is_mutable);
1102     }
1103     D d;
1104 };
1105 
1106 template <typename P>
1107 struct PixelDereferenceAdaptorArchetype : public std::unary_function<P, P> {
1108     typedef PixelDereferenceAdaptorArchetype const_t;
1109     typedef typename remove_reference<P>::type value_type;
1110     typedef typename add_reference<P>::type reference;
1111     typedef reference const_reference;
1112     static const bool is_mutable=false;
operator ()boost::gil::PixelDereferenceAdaptorArchetype1113     P operator()(P x) const { throw; }
1114 };
1115 
1116 ////////////////////////////////////////////////////////////////////////////////////////
1117 ///
1118 ///         Pixel ITERATOR CONCEPTS
1119 ///
1120 ////////////////////////////////////////////////////////////////////////////////////////
1121 
1122 /// \brief Concept for iterators, locators and views that can define a type just like the given iterator/locator/view, except it supports runtime specified step along the X navigation
1123 /// \ingroup PixelIteratorConcept
1124 /**
1125 \code
1126 concept HasDynamicXStepTypeConcept<typename T> {
1127     typename dynamic_x_step_type<T>;
1128         where Metafunction<dynamic_x_step_type<T> >;
1129 };
1130 \endcode
1131 */
1132 template <typename T>
1133 struct HasDynamicXStepTypeConcept {
constraintsboost::gil::HasDynamicXStepTypeConcept1134     void constraints() {
1135         typedef typename dynamic_x_step_type<T>::type type;
1136     }
1137 };
1138 
1139 /// \brief Concept for locators and views that can define a type just like the given locator or view, except it supports runtime specified step along the Y navigation
1140 /// \ingroup PixelLocatorConcept
1141 /**
1142 \code
1143 concept HasDynamicYStepTypeConcept<typename T> {
1144     typename dynamic_y_step_type<T>;
1145         where Metafunction<dynamic_y_step_type<T> >;
1146 };
1147 \endcode
1148 */
1149 template <typename T>
1150 struct HasDynamicYStepTypeConcept {
constraintsboost::gil::HasDynamicYStepTypeConcept1151     void constraints() {
1152         typedef typename dynamic_y_step_type<T>::type type;
1153     }
1154 };
1155 
1156 
1157 /// \brief Concept for locators and views that can define a type just like the given locator or view, except X and Y is swapped
1158 /// \ingroup PixelLocatorConcept
1159 /**
1160 \code
1161 concept HasTransposedTypeConcept<typename T> {
1162     typename transposed_type<T>;
1163         where Metafunction<transposed_type<T> >;
1164 };
1165 \endcode
1166 */
1167 template <typename T>
1168 struct HasTransposedTypeConcept {
constraintsboost::gil::HasTransposedTypeConcept1169     void constraints() {
1170         typedef typename transposed_type<T>::type type;
1171     }
1172 };
1173 
1174 /// \defgroup PixelIteratorConceptPixelIterator PixelIteratorConcept
1175 /// \ingroup PixelIteratorConcept
1176 /// \brief STL iterator over pixels
1177 
1178 /// \ingroup PixelIteratorConceptPixelIterator
1179 /// \brief An STL random access traversal iterator over a model of PixelConcept.
1180 /**
1181 GIL's iterators must also provide the following metafunctions:
1182  - \p const_iterator_type<Iterator>:   Returns a read-only equivalent of \p Iterator
1183  - \p iterator_is_mutable<Iterator>:   Returns whether the given iterator is read-only or mutable
1184  - \p is_iterator_adaptor<Iterator>:   Returns whether the given iterator is an adaptor over another iterator. See IteratorAdaptorConcept for additional requirements of adaptors.
1185 
1186  \code
1187 concept PixelIteratorConcept<typename Iterator> : boost_concepts::RandomAccessTraversalConcept<Iterator>, PixelBasedConcept<Iterator> {
1188     where PixelValueConcept<value_type>;
1189     typename const_iterator_type<It>::type;
1190         where PixelIteratorConcept<const_iterator_type<It>::type>;
1191     static const bool  iterator_is_mutable<It>::type::value;
1192     static const bool  is_iterator_adaptor<It>::type::value;   // is it an iterator adaptor
1193 };
1194 \endcode
1195 */
1196 template <typename Iterator>
1197 struct PixelIteratorConcept {
constraintsboost::gil::PixelIteratorConcept1198     void constraints() {
1199         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<Iterator> >();
1200         gil_function_requires<PixelBasedConcept<Iterator> >();
1201 
1202         typedef typename std::iterator_traits<Iterator>::value_type value_type;
1203         gil_function_requires<PixelValueConcept<value_type> >();
1204 
1205         typedef typename const_iterator_type<Iterator>::type const_t;
1206         static const bool is_mut = iterator_is_mutable<Iterator>::type::value; ignore_unused_variable_warning(is_mut);
1207 
1208         const_t const_it(it);  ignore_unused_variable_warning(const_it);  // immutable iterator must be constructible from (possibly mutable) iterator
1209 
1210         check_base(typename is_iterator_adaptor<Iterator>::type());
1211     }
check_baseboost::gil::PixelIteratorConcept1212     void check_base(mpl::false_) {}
check_baseboost::gil::PixelIteratorConcept1213     void check_base(mpl::true_) {
1214         typedef typename iterator_adaptor_get_base<Iterator>::type base_t;
1215         gil_function_requires<PixelIteratorConcept<base_t> >();
1216     }
1217 
1218     Iterator it;
1219 };
1220 
1221 namespace detail {
1222     template <typename Iterator>  // Preconditions: Iterator Models PixelIteratorConcept
1223     struct PixelIteratorIsMutableConcept {
constraintsboost::gil::detail::PixelIteratorIsMutableConcept1224         void constraints() {
1225             gil_function_requires<detail::RandomAccessIteratorIsMutableConcept<Iterator> >();
1226             typedef typename remove_reference<typename std::iterator_traits<Iterator>::reference>::type ref;
1227             typedef typename element_type<ref>::type channel_t;
1228             gil_function_requires<detail::ChannelIsMutableConcept<channel_t> >();
1229         }
1230     };
1231 }
1232 
1233 /// \brief Pixel iterator that allows for changing its pixel
1234 /// \ingroup PixelIteratorConceptPixelIterator
1235 /**
1236 \code
1237 concept MutablePixelIteratorConcept<PixelIteratorConcept Iterator> : MutableRandomAccessIteratorConcept<Iterator> {};
1238 
1239 \endcode
1240 */
1241 template <typename Iterator>
1242 struct MutablePixelIteratorConcept {
constraintsboost::gil::MutablePixelIteratorConcept1243     void constraints() {
1244         gil_function_requires<PixelIteratorConcept<Iterator> >();
1245         gil_function_requires<detail::PixelIteratorIsMutableConcept<Iterator> >();
1246     }
1247 };
1248 
1249 namespace detail {
1250     // Iterators that can be used as the base of memory_based_step_iterator require some additional functions
1251     template <typename Iterator>  // Preconditions: Iterator Models boost_concepts::RandomAccessTraversalConcept
1252     struct RandomAccessIteratorIsMemoryBasedConcept {
constraintsboost::gil::detail::RandomAccessIteratorIsMemoryBasedConcept1253         void constraints() {
1254             std::ptrdiff_t bs=memunit_step(it);  ignore_unused_variable_warning(bs);
1255             it=memunit_advanced(it,3);
1256             std::ptrdiff_t bd=memunit_distance(it,it);  ignore_unused_variable_warning(bd);
1257             memunit_advance(it,3);
1258             // for performace you may also provide a customized implementation of memunit_advanced_ref
1259         }
1260         Iterator it;
1261     };
1262 }
1263 
1264 /// \defgroup PixelIteratorConceptStepIterator StepIteratorConcept
1265 /// \ingroup PixelIteratorConcept
1266 /// \brief Iterator that advances by a specified step
1267 
1268 /// \brief Concept of a random-access iterator that can be advanced in memory units (bytes or bits)
1269 /// \ingroup PixelIteratorConceptStepIterator
1270 /**
1271 \code
1272 concept MemoryBasedIteratorConcept<boost_concepts::RandomAccessTraversalConcept Iterator> {
1273     typename byte_to_memunit<Iterator>; where metafunction<byte_to_memunit<Iterator> >;
1274     std::ptrdiff_t      memunit_step(const Iterator&);
1275     std::ptrdiff_t      memunit_distance(const Iterator& , const Iterator&);
1276     void                memunit_advance(Iterator&, std::ptrdiff_t diff);
1277     Iterator            memunit_advanced(const Iterator& p, std::ptrdiff_t diff) { Iterator tmp; memunit_advance(tmp,diff); return tmp; }
1278     Iterator::reference memunit_advanced_ref(const Iterator& p, std::ptrdiff_t diff) { return *memunit_advanced(p,diff); }
1279 };
1280 \endcode
1281 */
1282 template <typename Iterator>
1283 struct MemoryBasedIteratorConcept {
constraintsboost::gil::MemoryBasedIteratorConcept1284     void constraints() {
1285         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<Iterator> >();
1286         gil_function_requires<detail::RandomAccessIteratorIsMemoryBasedConcept<Iterator> >();
1287     }
1288 };
1289 
1290 /// \brief Step iterator concept
1291 ///
1292 /// Step iterators are iterators that have a set_step method
1293 /// \ingroup PixelIteratorConceptStepIterator
1294 /**
1295 \code
1296 concept StepIteratorConcept<boost_concepts::ForwardTraversalConcept Iterator> {
1297     template <Integral D> void Iterator::set_step(D step);
1298 };
1299 \endcode
1300 */
1301 template <typename Iterator>
1302 struct StepIteratorConcept {
constraintsboost::gil::StepIteratorConcept1303     void constraints() {
1304         gil_function_requires<boost_concepts::ForwardTraversalConcept<Iterator> >();
1305         it.set_step(0);
1306     }
1307     Iterator it;
1308 };
1309 
1310 
1311 /// \brief Step iterator that allows for modifying its current value
1312 ///
1313 /// \ingroup PixelIteratorConceptStepIterator
1314 /**
1315 \code
1316 concept MutableStepIteratorConcept<Mutable_ForwardIteratorConcept Iterator> : StepIteratorConcept<Iterator> {};
1317 \endcode
1318 */
1319 template <typename Iterator>
1320 struct MutableStepIteratorConcept {
constraintsboost::gil::MutableStepIteratorConcept1321     void constraints() {
1322         gil_function_requires<StepIteratorConcept<Iterator> >();
1323         gil_function_requires<detail::ForwardIteratorIsMutableConcept<Iterator> >();
1324     }
1325 };
1326 
1327 /// \defgroup PixelIteratorConceptIteratorAdaptor IteratorAdaptorConcept
1328 /// \ingroup PixelIteratorConcept
1329 /// \brief Adaptor over another iterator
1330 
1331 /// \ingroup PixelIteratorConceptIteratorAdaptor
1332 /// \brief Iterator adaptor is a forward iterator adapting another forward iterator.
1333 /**
1334 In addition to GIL iterator requirements, GIL iterator adaptors must provide the following metafunctions:
1335  - \p is_iterator_adaptor<Iterator>:             Returns \p mpl::true_
1336  - \p iterator_adaptor_get_base<Iterator>:       Returns the base iterator type
1337  - \p iterator_adaptor_rebind<Iterator,NewBase>: Replaces the base iterator with the new one
1338 
1339 The adaptee can be obtained from the iterator via the "base()" method.
1340 
1341 \code
1342 concept IteratorAdaptorConcept<boost_concepts::ForwardTraversalConcept Iterator> {
1343     where SameType<is_iterator_adaptor<Iterator>::type, mpl::true_>;
1344 
1345     typename iterator_adaptor_get_base<Iterator>;
1346         where Metafunction<iterator_adaptor_get_base<Iterator> >;
1347         where boost_concepts::ForwardTraversalConcept<iterator_adaptor_get_base<Iterator>::type>;
1348 
1349     typename another_iterator;
1350     typename iterator_adaptor_rebind<Iterator,another_iterator>::type;
1351         where boost_concepts::ForwardTraversalConcept<another_iterator>;
1352         where IteratorAdaptorConcept<iterator_adaptor_rebind<Iterator,another_iterator>::type>;
1353 
1354     const iterator_adaptor_get_base<Iterator>::type& Iterator::base() const;
1355 };
1356 \endcode
1357 */
1358 template <typename Iterator>
1359 struct IteratorAdaptorConcept {
constraintsboost::gil::IteratorAdaptorConcept1360     void constraints() {
1361         gil_function_requires<boost_concepts::ForwardTraversalConcept<Iterator> >();
1362 
1363         typedef typename iterator_adaptor_get_base<Iterator>::type base_t;
1364         gil_function_requires<boost_concepts::ForwardTraversalConcept<base_t> >();
1365 
1366         BOOST_STATIC_ASSERT(is_iterator_adaptor<Iterator>::value);
1367         typedef typename iterator_adaptor_rebind<Iterator, void*>::type rebind_t;
1368 
1369         base_t base=it.base();  ignore_unused_variable_warning(base);
1370     }
1371     Iterator it;
1372 };
1373 
1374 /// \brief Iterator adaptor that is mutable
1375 /// \ingroup PixelIteratorConceptIteratorAdaptor
1376 /**
1377 \code
1378 concept MutableIteratorAdaptorConcept<Mutable_ForwardIteratorConcept Iterator> : IteratorAdaptorConcept<Iterator> {};
1379 \endcode
1380 */
1381 template <typename Iterator>
1382 struct MutableIteratorAdaptorConcept {
constraintsboost::gil::MutableIteratorAdaptorConcept1383     void constraints() {
1384         gil_function_requires<IteratorAdaptorConcept<Iterator> >();
1385         gil_function_requires<detail::ForwardIteratorIsMutableConcept<Iterator> >();
1386     }
1387 };
1388 
1389 ////////////////////////////////////////////////////////////////////////////////////////
1390 ///
1391 ///         LOCATOR CONCEPTS
1392 ///
1393 ////////////////////////////////////////////////////////////////////////////////////////
1394 
1395 /// \defgroup LocatorNDConcept RandomAccessNDLocatorConcept
1396 /// \ingroup PixelLocatorConcept
1397 /// \brief N-dimensional locator
1398 
1399 /// \defgroup Locator2DConcept RandomAccess2DLocatorConcept
1400 /// \ingroup PixelLocatorConcept
1401 /// \brief 2-dimensional locator
1402 
1403 /// \defgroup PixelLocator2DConcept PixelLocatorConcept
1404 /// \ingroup PixelLocatorConcept
1405 /// \brief 2-dimensional locator over pixel data
1406 
1407 /// \ingroup LocatorNDConcept
1408 /// \brief N-dimensional locator over immutable values
1409 /**
1410 \code
1411 concept RandomAccessNDLocatorConcept<Regular Loc> {
1412     typename value_type;        // value over which the locator navigates
1413     typename reference;         // result of dereferencing
1414     typename difference_type; where PointNDConcept<difference_type>; // return value of operator-.
1415     typename const_t;           // same as Loc, but operating over immutable values
1416     typename cached_location_t; // type to store relative location (for efficient repeated access)
1417     typename point_t  = difference_type;
1418 
1419     static const size_t num_dimensions; // dimensionality of the locator
1420     where num_dimensions = point_t::num_dimensions;
1421 
1422     // The difference_type and iterator type along each dimension. The iterators may only differ in
1423     // difference_type. Their value_type must be the same as Loc::value_type
1424     template <size_t D> struct axis {
1425         typename coord_t = point_t::axis<D>::coord_t;
1426         typename iterator; where RandomAccessTraversalConcept<iterator>; // iterator along D-th axis.
1427         where iterator::value_type == value_type;
1428     };
1429 
1430     // Defines the type of a locator similar to this type, except it invokes Deref upon dereferencing
1431     template <PixelDereferenceAdaptorConcept Deref> struct add_deref {
1432         typename type;        where RandomAccessNDLocatorConcept<type>;
1433         static type make(const Loc& loc, const Deref& deref);
1434     };
1435 
1436     Loc& operator+=(Loc&, const difference_type&);
1437     Loc& operator-=(Loc&, const difference_type&);
1438     Loc operator+(const Loc&, const difference_type&);
1439     Loc operator-(const Loc&, const difference_type&);
1440 
1441     reference operator*(const Loc&);
1442     reference operator[](const Loc&, const difference_type&);
1443 
1444     // Storing relative location for faster repeated access and accessing it
1445     cached_location_t Loc::cache_location(const difference_type&) const;
1446     reference operator[](const Loc&,const cached_location_t&);
1447 
1448     // Accessing iterators along a given dimension at the current location or at a given offset
1449     template <size_t D> axis<D>::iterator&       Loc::axis_iterator();
1450     template <size_t D> axis<D>::iterator const& Loc::axis_iterator() const;
1451     template <size_t D> axis<D>::iterator        Loc::axis_iterator(const difference_type&) const;
1452 };
1453 \endcode
1454 */
1455 template <typename Loc>
1456 struct RandomAccessNDLocatorConcept {
constraintsboost::gil::RandomAccessNDLocatorConcept1457     void constraints() {
1458         gil_function_requires< Regular<Loc> >();
1459 
1460         typedef typename Loc::value_type        value_type;
1461         typedef typename Loc::reference         reference;          // result of dereferencing
1462         typedef typename Loc::difference_type   difference_type;    // result of operator-(pixel_locator, pixel_locator)
1463         typedef typename Loc::cached_location_t cached_location_t;  // type used to store relative location (to allow for more efficient repeated access)
1464         typedef typename Loc::const_t           const_t;         // same as this type, but over const values
1465         typedef typename Loc::point_t           point_t;         // same as difference_type
1466         static const std::size_t N=Loc::num_dimensions; ignore_unused_variable_warning(N);
1467 
1468         typedef typename Loc::template axis<0>::iterator    first_it_type;
1469         typedef typename Loc::template axis<N-1>::iterator  last_it_type;
1470         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<first_it_type> >();
1471         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<last_it_type> >();
1472 
1473         // point_t must be an N-dimensional point, each dimension of which must have the same type as difference_type of the corresponding iterator
1474         gil_function_requires<PointNDConcept<point_t> >();
1475         BOOST_STATIC_ASSERT(point_t::num_dimensions==N);
1476         BOOST_STATIC_ASSERT((is_same<typename std::iterator_traits<first_it_type>::difference_type, typename point_t::template axis<0>::coord_t>::value));
1477         BOOST_STATIC_ASSERT((is_same<typename std::iterator_traits<last_it_type>::difference_type, typename point_t::template axis<N-1>::coord_t>::value));
1478 
1479         difference_type d;
1480         loc+=d;
1481         loc-=d;
1482         loc=loc+d;
1483         loc=loc-d;
1484         reference r1=loc[d];  ignore_unused_variable_warning(r1);
1485         reference r2=*loc;  ignore_unused_variable_warning(r2);
1486         cached_location_t cl=loc.cache_location(d);  ignore_unused_variable_warning(cl);
1487         reference r3=loc[d];  ignore_unused_variable_warning(r3);
1488 
1489         first_it_type fi=loc.template axis_iterator<0>();
1490         fi=loc.template axis_iterator<0>(d);
1491         last_it_type li=loc.template axis_iterator<N-1>();
1492         li=loc.template axis_iterator<N-1>(d);
1493 
1494         typedef PixelDereferenceAdaptorArchetype<typename Loc::value_type> deref_t;
1495         typedef typename Loc::template add_deref<deref_t>::type dtype;
1496         //gil_function_requires<RandomAccessNDLocatorConcept<dtype> >();    // infinite recursion
1497     }
1498     Loc loc;
1499 };
1500 
1501 /// \ingroup Locator2DConcept
1502 /// \brief 2-dimensional locator over immutable values
1503 /**
1504 \code
1505 concept RandomAccess2DLocatorConcept<RandomAccessNDLocatorConcept Loc> {
1506     where num_dimensions==2;
1507     where Point2DConcept<point_t>;
1508 
1509     typename x_iterator = axis<0>::iterator;
1510     typename y_iterator = axis<1>::iterator;
1511     typename x_coord_t  = axis<0>::coord_t;
1512     typename y_coord_t  = axis<1>::coord_t;
1513 
1514     // Only available to locators that have dynamic step in Y
1515     //Loc::Loc(const Loc& loc, y_coord_t);
1516 
1517     // Only available to locators that have dynamic step in X and Y
1518     //Loc::Loc(const Loc& loc, x_coord_t, y_coord_t, bool transposed=false);
1519 
1520     x_iterator&       Loc::x();
1521     x_iterator const& Loc::x() const;
1522     y_iterator&       Loc::y();
1523     y_iterator const& Loc::y() const;
1524 
1525     x_iterator Loc::x_at(const difference_type&) const;
1526     y_iterator Loc::y_at(const difference_type&) const;
1527     Loc Loc::xy_at(const difference_type&) const;
1528 
1529     // x/y versions of all methods that can take difference type
1530     x_iterator        Loc::x_at(x_coord_t, y_coord_t) const;
1531     y_iterator        Loc::y_at(x_coord_t, y_coord_t) const;
1532     Loc               Loc::xy_at(x_coord_t, y_coord_t) const;
1533     reference         operator()(const Loc&, x_coord_t, y_coord_t);
1534     cached_location_t Loc::cache_location(x_coord_t, y_coord_t) const;
1535 
1536     bool      Loc::is_1d_traversable(x_coord_t width) const;
1537     y_coord_t Loc::y_distance_to(const Loc& loc2, x_coord_t x_diff) const;
1538 };
1539 \endcode
1540 */
1541 template <typename Loc>
1542 struct RandomAccess2DLocatorConcept {
constraintsboost::gil::RandomAccess2DLocatorConcept1543     void constraints() {
1544         gil_function_requires<RandomAccessNDLocatorConcept<Loc> >();
1545         BOOST_STATIC_ASSERT(Loc::num_dimensions==2);
1546 
1547         typedef typename dynamic_x_step_type<Loc>::type dynamic_x_step_t;
1548         typedef typename dynamic_y_step_type<Loc>::type dynamic_y_step_t;
1549         typedef typename transposed_type<Loc>::type     transposed_t;
1550 
1551         typedef typename Loc::cached_location_t   cached_location_t;
1552         gil_function_requires<Point2DConcept<typename Loc::point_t> >();
1553 
1554         typedef typename Loc::x_iterator x_iterator;
1555         typedef typename Loc::y_iterator y_iterator;
1556         typedef typename Loc::x_coord_t  x_coord_t;
1557         typedef typename Loc::y_coord_t  y_coord_t;
1558 
1559         x_coord_t xd=0; ignore_unused_variable_warning(xd);
1560         y_coord_t yd=0; ignore_unused_variable_warning(yd);
1561 
1562         typename Loc::difference_type d;
1563         typename Loc::reference r=loc(xd,yd);  ignore_unused_variable_warning(r);
1564 
1565         dynamic_x_step_t loc2(dynamic_x_step_t(), yd);
1566         dynamic_x_step_t loc3(dynamic_x_step_t(), xd, yd);
1567 
1568         typedef typename dynamic_y_step_type<typename dynamic_x_step_type<transposed_t>::type>::type dynamic_xy_step_transposed_t;
1569         dynamic_xy_step_transposed_t loc4(loc, xd,yd,true);
1570 
1571         bool is_contiguous=loc.is_1d_traversable(xd); ignore_unused_variable_warning(is_contiguous);
1572         loc.y_distance_to(loc, xd);
1573 
1574         loc=loc.xy_at(d);
1575         loc=loc.xy_at(xd,yd);
1576 
1577         x_iterator xit=loc.x_at(d);
1578         xit=loc.x_at(xd,yd);
1579         xit=loc.x();
1580 
1581         y_iterator yit=loc.y_at(d);
1582         yit=loc.y_at(xd,yd);
1583         yit=loc.y();
1584 
1585         cached_location_t cl=loc.cache_location(xd,yd);  ignore_unused_variable_warning(cl);
1586     }
1587     Loc loc;
1588 };
1589 
1590 /// \ingroup PixelLocator2DConcept
1591 /// \brief GIL's 2-dimensional locator over immutable GIL pixels
1592 /**
1593 \code
1594 concept PixelLocatorConcept<RandomAccess2DLocatorConcept Loc> {
1595     where PixelValueConcept<value_type>;
1596     where PixelIteratorConcept<x_iterator>;
1597     where PixelIteratorConcept<y_iterator>;
1598     where x_coord_t == y_coord_t;
1599 
1600     typename coord_t = x_coord_t;
1601 };
1602 \endcode
1603 */
1604 template <typename Loc>
1605 struct PixelLocatorConcept {
constraintsboost::gil::PixelLocatorConcept1606     void constraints() {
1607         gil_function_requires< RandomAccess2DLocatorConcept<Loc> >();
1608         gil_function_requires< PixelIteratorConcept<typename Loc::x_iterator> >();
1609         gil_function_requires< PixelIteratorConcept<typename Loc::y_iterator> >();
1610         typedef typename Loc::coord_t                      coord_t;
1611         BOOST_STATIC_ASSERT((is_same<typename Loc::x_coord_t, typename Loc::y_coord_t>::value));
1612     }
1613     Loc loc;
1614 };
1615 
1616 namespace detail {
1617     template <typename Loc> // preconditions: Loc Models RandomAccessNDLocatorConcept
1618     struct RandomAccessNDLocatorIsMutableConcept {
constraintsboost::gil::detail::RandomAccessNDLocatorIsMutableConcept1619         void constraints() {
1620             gil_function_requires<detail::RandomAccessIteratorIsMutableConcept<typename Loc::template axis<0>::iterator> >();
1621             gil_function_requires<detail::RandomAccessIteratorIsMutableConcept<typename Loc::template axis<Loc::num_dimensions-1>::iterator> >();
1622 
1623             typename Loc::difference_type d; initialize_it(d);
1624             typename Loc::value_type v;initialize_it(v);
1625             typename Loc::cached_location_t cl=loc.cache_location(d);
1626             *loc=v;
1627             loc[d]=v;
1628             loc[cl]=v;
1629         }
1630         Loc loc;
1631     };
1632 
1633     template <typename Loc> // preconditions: Loc Models RandomAccess2DLocatorConcept
1634     struct RandomAccess2DLocatorIsMutableConcept {
constraintsboost::gil::detail::RandomAccess2DLocatorIsMutableConcept1635         void constraints() {
1636             gil_function_requires<detail::RandomAccessNDLocatorIsMutableConcept<Loc> >();
1637             typename Loc::x_coord_t xd=0; ignore_unused_variable_warning(xd);
1638             typename Loc::y_coord_t yd=0; ignore_unused_variable_warning(yd);
1639             typename Loc::value_type v; initialize_it(v);
1640             loc(xd,yd)=v;
1641         }
1642         Loc loc;
1643     };
1644 }
1645 
1646 /// \ingroup LocatorNDConcept
1647 /// \brief N-dimensional locator over mutable pixels
1648 /**
1649 \code
1650 concept MutableRandomAccessNDLocatorConcept<RandomAccessNDLocatorConcept Loc> {
1651     where Mutable<reference>;
1652 };
1653 \endcode
1654 */
1655 template <typename Loc>
1656 struct MutableRandomAccessNDLocatorConcept {
constraintsboost::gil::MutableRandomAccessNDLocatorConcept1657     void constraints() {
1658         gil_function_requires<RandomAccessNDLocatorConcept<Loc> >();
1659         gil_function_requires<detail::RandomAccessNDLocatorIsMutableConcept<Loc> >();
1660     }
1661 };
1662 
1663 /// \ingroup Locator2DConcept
1664 /// \brief 2-dimensional locator over mutable pixels
1665 /**
1666 \code
1667 concept MutableRandomAccess2DLocatorConcept<RandomAccess2DLocatorConcept Loc> : MutableRandomAccessNDLocatorConcept<Loc> {};
1668 \endcode
1669 */
1670 template <typename Loc>
1671 struct MutableRandomAccess2DLocatorConcept {
constraintsboost::gil::MutableRandomAccess2DLocatorConcept1672     void constraints() {
1673         gil_function_requires< RandomAccess2DLocatorConcept<Loc> >();
1674         gil_function_requires<detail::RandomAccess2DLocatorIsMutableConcept<Loc> >();
1675     }
1676 };
1677 
1678 /// \ingroup PixelLocator2DConcept
1679 /// \brief GIL's 2-dimensional locator over mutable GIL pixels
1680 /**
1681 \code
1682 concept MutablePixelLocatorConcept<PixelLocatorConcept Loc> : MutableRandomAccess2DLocatorConcept<Loc> {};
1683 \endcode
1684 */
1685 template <typename Loc>
1686 struct MutablePixelLocatorConcept {
constraintsboost::gil::MutablePixelLocatorConcept1687     void constraints() {
1688         gil_function_requires<PixelLocatorConcept<Loc> >();
1689         gil_function_requires<detail::RandomAccess2DLocatorIsMutableConcept<Loc> >();
1690     }
1691 };
1692 
1693 ////////////////////////////////////////////////////////////////////////////////////////
1694 ///
1695 ///         IMAGE VIEW CONCEPTS
1696 ///
1697 ////////////////////////////////////////////////////////////////////////////////////////
1698 
1699 /// \defgroup ImageViewNDConcept ImageViewNDLocatorConcept
1700 /// \ingroup ImageViewConcept
1701 /// \brief N-dimensional range
1702 
1703 /// \defgroup ImageView2DConcept ImageView2DConcept
1704 /// \ingroup ImageViewConcept
1705 /// \brief 2-dimensional range
1706 
1707 /// \defgroup PixelImageViewConcept ImageViewConcept
1708 /// \ingroup ImageViewConcept
1709 /// \brief 2-dimensional range over pixel data
1710 
1711 /// \ingroup ImageViewNDConcept
1712 /// \brief N-dimensional view over immutable values
1713 /**
1714 \code
1715 concept RandomAccessNDImageViewConcept<Regular View> {
1716     typename value_type;
1717     typename reference;       // result of dereferencing
1718     typename difference_type; // result of operator-(iterator,iterator) (1-dimensional!)
1719     typename const_t;  where RandomAccessNDImageViewConcept<View>; // same as View, but over immutable values
1720     typename point_t;  where PointNDConcept<point_t>; // N-dimensional point
1721     typename locator;  where RandomAccessNDLocatorConcept<locator>; // N-dimensional locator.
1722     typename iterator; where RandomAccessTraversalConcept<iterator>; // 1-dimensional iterator over all values
1723     typename reverse_iterator; where RandomAccessTraversalConcept<reverse_iterator>;
1724     typename size_type;       // the return value of size()
1725 
1726     // Equivalent to RandomAccessNDLocatorConcept::axis
1727     template <size_t D> struct axis {
1728         typename coord_t = point_t::axis<D>::coord_t;
1729         typename iterator; where RandomAccessTraversalConcept<iterator>;   // iterator along D-th axis.
1730         where SameType<coord_t, iterator::difference_type>;
1731         where SameType<iterator::value_type,value_type>;
1732     };
1733 
1734     // Defines the type of a view similar to this type, except it invokes Deref upon dereferencing
1735     template <PixelDereferenceAdaptorConcept Deref> struct add_deref {
1736         typename type;        where RandomAccessNDImageViewConcept<type>;
1737         static type make(const View& v, const Deref& deref);
1738     };
1739 
1740     static const size_t num_dimensions = point_t::num_dimensions;
1741 
1742     // Create from a locator at the top-left corner and dimensions
1743     View::View(const locator&, const point_type&);
1744 
1745     size_type        View::size()       const; // total number of elements
1746     reference        operator[](View, const difference_type&) const; // 1-dimensional reference
1747     iterator         View::begin()      const;
1748     iterator         View::end()        const;
1749     reverse_iterator View::rbegin()     const;
1750     reverse_iterator View::rend()       const;
1751     iterator         View::at(const point_t&);
1752     point_t          View::dimensions() const; // number of elements along each dimension
1753     bool             View::is_1d_traversable() const;   // can an iterator over the first dimension visit each value? I.e. are there gaps between values?
1754 
1755     // iterator along a given dimension starting at a given point
1756     template <size_t D> View::axis<D>::iterator View::axis_iterator(const point_t&) const;
1757 
1758     reference operator()(View,const point_t&) const;
1759 };
1760 \endcode
1761 */
1762 template <typename View>
1763 struct RandomAccessNDImageViewConcept {
constraintsboost::gil::RandomAccessNDImageViewConcept1764     void constraints() {
1765         gil_function_requires< Regular<View> >();
1766 
1767         typedef typename View::value_type       value_type;
1768         typedef typename View::reference        reference;       // result of dereferencing
1769         typedef typename View::difference_type  difference_type; // result of operator-(1d_iterator,1d_iterator)
1770         typedef typename View::const_t          const_t;         // same as this type, but over const values
1771         typedef typename View::point_t          point_t;         // N-dimensional point
1772         typedef typename View::locator          locator;         // N-dimensional locator
1773         typedef typename View::iterator         iterator;
1774         typedef typename View::reverse_iterator reverse_iterator;
1775         typedef typename View::size_type        size_type;
1776         static const std::size_t N=View::num_dimensions;
1777 
1778         gil_function_requires<RandomAccessNDLocatorConcept<locator> >();
1779         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<iterator> >();
1780         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<reverse_iterator> >();
1781 
1782         typedef typename View::template axis<0>::iterator   first_it_type;
1783         typedef typename View::template axis<N-1>::iterator last_it_type;
1784         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<first_it_type> >();
1785         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<last_it_type> >();
1786 
1787 //        BOOST_STATIC_ASSERT((typename std::iterator_traits<first_it_type>::difference_type, typename point_t::template axis<0>::coord_t>::value));
1788 //        BOOST_STATIC_ASSERT((typename std::iterator_traits< last_it_type>::difference_type, typename point_t::template axis<N-1>::coord_t>::value));
1789 
1790         // point_t must be an N-dimensional point, each dimension of which must have the same type as difference_type of the corresponding iterator
1791         gil_function_requires<PointNDConcept<point_t> >();
1792         BOOST_STATIC_ASSERT(point_t::num_dimensions==N);
1793         BOOST_STATIC_ASSERT((is_same<typename std::iterator_traits<first_it_type>::difference_type, typename point_t::template axis<0>::coord_t>::value));
1794         BOOST_STATIC_ASSERT((is_same<typename std::iterator_traits<last_it_type>::difference_type, typename point_t::template axis<N-1>::coord_t>::value));
1795 
1796         point_t p;
1797         locator lc;
1798         iterator it;
1799         reverse_iterator rit;
1800         difference_type d; detail::initialize_it(d); ignore_unused_variable_warning(d);
1801 
1802         View(p,lc); // view must be constructible from a locator and a point
1803 
1804         p=view.dimensions();
1805         lc=view.pixels();
1806         size_type sz=view.size();  ignore_unused_variable_warning(sz);
1807         bool is_contiguous=view.is_1d_traversable(); ignore_unused_variable_warning(is_contiguous);
1808 
1809         it=view.begin();
1810         it=view.end();
1811         rit=view.rbegin();
1812         rit=view.rend();
1813 
1814         reference r1=view[d]; ignore_unused_variable_warning(r1);    // 1D access
1815         reference r2=view(p); ignore_unused_variable_warning(r2);    // 2D access
1816 
1817         // get 1-D iterator of any dimension at a given pixel location
1818         first_it_type fi=view.template axis_iterator<0>(p); ignore_unused_variable_warning(fi);
1819         last_it_type li=view.template axis_iterator<N-1>(p); ignore_unused_variable_warning(li);
1820 
1821         typedef PixelDereferenceAdaptorArchetype<typename View::value_type> deref_t;
1822         typedef typename View::template add_deref<deref_t>::type dtype;
1823     }
1824     View view;
1825 };
1826 
1827 /// \ingroup ImageView2DConcept
1828 /// \brief 2-dimensional view over immutable values
1829 /**
1830 \code
1831 concept RandomAccess2DImageViewConcept<RandomAccessNDImageViewConcept View> {
1832     where num_dimensions==2;
1833 
1834     typename x_iterator = axis<0>::iterator;
1835     typename y_iterator = axis<1>::iterator;
1836     typename x_coord_t  = axis<0>::coord_t;
1837     typename y_coord_t  = axis<1>::coord_t;
1838     typename xy_locator = locator;
1839 
1840     x_coord_t View::width()  const;
1841     y_coord_t View::height() const;
1842 
1843     // X-navigation
1844     x_iterator View::x_at(const point_t&) const;
1845     x_iterator View::row_begin(y_coord_t) const;
1846     x_iterator View::row_end  (y_coord_t) const;
1847 
1848     // Y-navigation
1849     y_iterator View::y_at(const point_t&) const;
1850     y_iterator View::col_begin(x_coord_t) const;
1851     y_iterator View::col_end  (x_coord_t) const;
1852 
1853     // navigating in 2D
1854     xy_locator View::xy_at(const point_t&) const;
1855 
1856     // (x,y) versions of all methods taking point_t
1857     View::View(x_coord_t,y_coord_t,const locator&);
1858     iterator View::at(x_coord_t,y_coord_t) const;
1859     reference operator()(View,x_coord_t,y_coord_t) const;
1860     xy_locator View::xy_at(x_coord_t,y_coord_t) const;
1861     x_iterator View::x_at(x_coord_t,y_coord_t) const;
1862     y_iterator View::y_at(x_coord_t,y_coord_t) const;
1863 };
1864 \endcode
1865 */
1866 template <typename View>
1867 struct RandomAccess2DImageViewConcept {
constraintsboost::gil::RandomAccess2DImageViewConcept1868     void constraints() {
1869         gil_function_requires<RandomAccessNDImageViewConcept<View> >();
1870         BOOST_STATIC_ASSERT(View::num_dimensions==2);
1871 
1872         // TODO: This executes the requirements for RandomAccessNDLocatorConcept again. Fix it to improve compile time
1873         gil_function_requires<RandomAccess2DLocatorConcept<typename View::locator> >();
1874 
1875         typedef typename dynamic_x_step_type<View>::type  dynamic_x_step_t;
1876         typedef typename dynamic_y_step_type<View>::type  dynamic_y_step_t;
1877         typedef typename transposed_type<View>::type      transposed_t;
1878 
1879         typedef typename View::x_iterator x_iterator;
1880         typedef typename View::y_iterator y_iterator;
1881         typedef typename View::x_coord_t  x_coord_t;
1882         typedef typename View::y_coord_t  y_coord_t;
1883         typedef typename View::xy_locator xy_locator;
1884 
1885         x_coord_t xd=0; ignore_unused_variable_warning(xd);
1886         y_coord_t yd=0; ignore_unused_variable_warning(yd);
1887         x_iterator xit;
1888         y_iterator yit;
1889         typename View::point_t d;
1890 
1891         View(xd,yd,xy_locator());       // constructible with width, height, 2d_locator
1892 
1893         xy_locator lc=view.xy_at(xd,yd);
1894         lc=view.xy_at(d);
1895 
1896         typename View::reference r=view(xd,yd);  ignore_unused_variable_warning(r);
1897         xd=view.width();
1898         yd=view.height();
1899 
1900         xit=view.x_at(d);
1901         xit=view.x_at(xd,yd);
1902         xit=view.row_begin(xd);
1903         xit=view.row_end(xd);
1904 
1905         yit=view.y_at(d);
1906         yit=view.y_at(xd,yd);
1907         yit=view.col_begin(xd);
1908         yit=view.col_end(xd);
1909     }
1910     View view;
1911 };
1912 
1913 
1914 /// \ingroup PixelImageViewConcept
1915 /// \brief GIL's 2-dimensional view over immutable GIL pixels
1916 /**
1917 \code
1918 concept ImageViewConcept<RandomAccess2DImageViewConcept View> {
1919     where PixelValueConcept<value_type>;
1920     where PixelIteratorConcept<x_iterator>;
1921     where PixelIteratorConcept<y_iterator>;
1922     where x_coord_t == y_coord_t;
1923 
1924     typename coord_t = x_coord_t;
1925 
1926     std::size_t View::num_channels() const;
1927 };
1928 \endcode
1929 */
1930 template <typename View>
1931 struct ImageViewConcept {
constraintsboost::gil::ImageViewConcept1932     void constraints() {
1933         gil_function_requires<RandomAccess2DImageViewConcept<View> >();
1934 
1935         // TODO: This executes the requirements for RandomAccess2DLocatorConcept again. Fix it to improve compile time
1936         gil_function_requires<PixelLocatorConcept<typename View::xy_locator> >();
1937 
1938         BOOST_STATIC_ASSERT((is_same<typename View::x_coord_t, typename View::y_coord_t>::value));
1939 
1940         typedef typename View::coord_t           coord_t;      // 1D difference type (same for all dimensions)
1941         std::size_t num_chan = view.num_channels(); ignore_unused_variable_warning(num_chan);
1942     }
1943     View view;
1944 };
1945 
1946 
1947 namespace detail {
1948     template <typename View>    // Preconditions: View Models RandomAccessNDImageViewConcept
1949     struct RandomAccessNDImageViewIsMutableConcept {
constraintsboost::gil::detail::RandomAccessNDImageViewIsMutableConcept1950         void constraints() {
1951             gil_function_requires<detail::RandomAccessNDLocatorIsMutableConcept<typename View::locator> >();
1952 
1953             gil_function_requires<detail::RandomAccessIteratorIsMutableConcept<typename View::iterator> >();
1954             gil_function_requires<detail::RandomAccessIteratorIsMutableConcept<typename View::reverse_iterator> >();
1955             gil_function_requires<detail::RandomAccessIteratorIsMutableConcept<typename View::template axis<0>::iterator> >();
1956             gil_function_requires<detail::RandomAccessIteratorIsMutableConcept<typename View::template axis<View::num_dimensions-1>::iterator> >();
1957 
1958             typename View::difference_type diff; initialize_it(diff); ignore_unused_variable_warning(diff);
1959             typename View::point_t pt;
1960             typename View::value_type v; initialize_it(v);
1961 
1962             view[diff]=v;
1963             view(pt)=v;
1964         }
1965         View view;
1966     };
1967 
1968     template <typename View>    // preconditions: View Models RandomAccessNDImageViewConcept
1969     struct RandomAccess2DImageViewIsMutableConcept {
constraintsboost::gil::detail::RandomAccess2DImageViewIsMutableConcept1970         void constraints() {
1971             gil_function_requires<detail::RandomAccessNDImageViewIsMutableConcept<View> >();
1972             typename View::x_coord_t xd=0; ignore_unused_variable_warning(xd);
1973             typename View::y_coord_t yd=0; ignore_unused_variable_warning(yd);
1974             typename View::value_type v; initialize_it(v);
1975             view(xd,yd)=v;
1976         }
1977         View view;
1978     };
1979 
1980     template <typename View>    // preconditions: View Models ImageViewConcept
1981     struct PixelImageViewIsMutableConcept {
constraintsboost::gil::detail::PixelImageViewIsMutableConcept1982         void constraints() {
1983             gil_function_requires<detail::RandomAccess2DImageViewIsMutableConcept<View> >();
1984         }
1985     };
1986 }
1987 
1988 /// \ingroup ImageViewNDConcept
1989 /// \brief N-dimensional view over mutable values
1990 /**
1991 \code
1992 concept MutableRandomAccessNDImageViewConcept<RandomAccessNDImageViewConcept View> {
1993     where Mutable<reference>;
1994 };
1995 \endcode
1996 */
1997 template <typename View>
1998 struct MutableRandomAccessNDImageViewConcept {
constraintsboost::gil::MutableRandomAccessNDImageViewConcept1999     void constraints() {
2000         gil_function_requires<RandomAccessNDImageViewConcept<View> >();
2001         gil_function_requires<detail::RandomAccessNDImageViewIsMutableConcept<View> >();
2002     }
2003 };
2004 
2005 /// \ingroup ImageView2DConcept
2006 /// \brief 2-dimensional view over mutable values
2007 /**
2008 \code
2009 concept MutableRandomAccess2DImageViewConcept<RandomAccess2DImageViewConcept View> : MutableRandomAccessNDImageViewConcept<View> {};
2010 \endcode
2011 */
2012 template <typename View>
2013 struct MutableRandomAccess2DImageViewConcept {
constraintsboost::gil::MutableRandomAccess2DImageViewConcept2014     void constraints() {
2015         gil_function_requires<RandomAccess2DImageViewConcept<View> >();
2016         gil_function_requires<detail::RandomAccess2DImageViewIsMutableConcept<View> >();
2017     }
2018 };
2019 
2020 /// \ingroup PixelImageViewConcept
2021 /// \brief GIL's 2-dimensional view over mutable GIL pixels
2022 /**
2023 \code
2024 concept MutableImageViewConcept<ImageViewConcept View> : MutableRandomAccess2DImageViewConcept<View> {};
2025 \endcode
2026 */
2027 template <typename View>
2028 struct MutableImageViewConcept {
constraintsboost::gil::MutableImageViewConcept2029     void constraints() {
2030         gil_function_requires<ImageViewConcept<View> >();
2031         gil_function_requires<detail::PixelImageViewIsMutableConcept<View> >();
2032     }
2033 };
2034 
2035 /// \brief Returns whether two views are compatible
2036 ///
2037 /// Views are compatible if their pixels are compatible. Compatible views can be assigned and copy constructed from one another.
2038 template <typename V1, typename V2>  // Model ImageViewConcept
2039 struct views_are_compatible : public pixels_are_compatible<typename V1::value_type, typename V2::value_type> {};
2040 
2041 /// \brief Views are compatible if they have the same color spaces and compatible channel values. Constness and layout are not important for compatibility
2042 /// \ingroup ImageViewConcept
2043 /**
2044 \code
2045 concept ViewsCompatibleConcept<ImageViewConcept V1, ImageViewConcept V2> {
2046     where PixelsCompatibleConcept<V1::value_type, P2::value_type>;
2047 };
2048 \endcode
2049 */
2050 template <typename V1, typename V2>
2051 struct ViewsCompatibleConcept {
constraintsboost::gil::ViewsCompatibleConcept2052     void constraints() {
2053         BOOST_STATIC_ASSERT((views_are_compatible<V1,V2>::value));
2054     }
2055 };
2056 
2057 
2058 ////////////////////////////////////////////////////////////////////////////////////////
2059 ///
2060 ///         IMAGE CONCEPTS
2061 ///
2062 ////////////////////////////////////////////////////////////////////////////////////////
2063 
2064 
2065 /// \ingroup ImageConcept
2066 /// \brief N-dimensional container of values
2067 /**
2068 \code
2069 concept RandomAccessNDImageConcept<typename Img> : Regular<Img> {
2070     typename view_t; where MutableRandomAccessNDImageViewConcept<view_t>;
2071     typename const_view_t = view_t::const_t;
2072     typename point_t      = view_t::point_t;
2073     typename value_type   = view_t::value_type;
2074     typename allocator_type;
2075 
2076     Img::Img(point_t dims, std::size_t alignment=1);
2077     Img::Img(point_t dims, value_type fill_value, std::size_t alignment);
2078 
2079     void Img::recreate(point_t new_dims, std::size_t alignment=1);
2080     void Img::recreate(point_t new_dims, value_type fill_value, std::size_t alignment);
2081 
2082     const point_t&        Img::dimensions() const;
2083     const const_view_t&   const_view(const Img&);
2084     const view_t&         view(Img&);
2085 };
2086 \endcode
2087 */
2088 template <typename Img>
2089 struct RandomAccessNDImageConcept {
constraintsboost::gil::RandomAccessNDImageConcept2090     void constraints() {
2091         gil_function_requires<Regular<Img> >();
2092 
2093         typedef typename Img::view_t       view_t;
2094         gil_function_requires<MutableRandomAccessNDImageViewConcept<view_t> >();
2095 
2096         typedef typename Img::const_view_t const_view_t;
2097         typedef typename Img::value_type   pixel_t;
2098 
2099         typedef typename Img::point_t        point_t;
2100         gil_function_requires<PointNDConcept<point_t> >();
2101 
2102         const_view_t cv = const_view(img); ignore_unused_variable_warning(cv);
2103         view_t       v  = view(img);       ignore_unused_variable_warning(v);
2104 
2105         pixel_t fill_value;
2106         point_t pt=img.dimensions();
2107         Img im1(pt);
2108         Img im2(pt,1);
2109         Img im3(pt,fill_value,1);
2110         img.recreate(pt);
2111         img.recreate(pt,1);
2112         img.recreate(pt,fill_value,1);
2113     }
2114     Img img;
2115 };
2116 
2117 
2118 /// \ingroup ImageConcept
2119 /// \brief 2-dimensional container of values
2120 /**
2121 \code
2122 concept RandomAccess2DImageConcept<RandomAccessNDImageConcept Img> {
2123     typename x_coord_t = const_view_t::x_coord_t;
2124     typename y_coord_t = const_view_t::y_coord_t;
2125 
2126     Img::Img(x_coord_t width, y_coord_t height, std::size_t alignment=1);
2127     Img::Img(x_coord_t width, y_coord_t height, value_type fill_value, std::size_t alignment);
2128 
2129     x_coord_t Img::width() const;
2130     y_coord_t Img::height() const;
2131 
2132     void Img::recreate(x_coord_t width, y_coord_t height, std::size_t alignment=1);
2133     void Img::recreate(x_coord_t width, y_coord_t height, value_type fill_value, std::size_t alignment);
2134 };
2135 \endcode
2136 */
2137 template <typename Img>
2138 struct RandomAccess2DImageConcept {
constraintsboost::gil::RandomAccess2DImageConcept2139     void constraints() {
2140         gil_function_requires<RandomAccessNDImageConcept<Img> >();
2141         typedef typename Img::x_coord_t  x_coord_t;
2142         typedef typename Img::y_coord_t  y_coord_t;
2143         typedef typename Img::value_type value_t;
2144 
2145         gil_function_requires<MutableRandomAccess2DImageViewConcept<typename Img::view_t> >();
2146 
2147         x_coord_t w=img.width();
2148         y_coord_t h=img.height();
2149         value_t fill_value;
2150         Img im1(w,h);
2151         Img im2(w,h,1);
2152         Img im3(w,h,fill_value,1);
2153         img.recreate(w,h);
2154         img.recreate(w,h,1);
2155         img.recreate(w,h,fill_value,1);
2156     }
2157     Img img;
2158 };
2159 
2160 /// \ingroup ImageConcept
2161 /// \brief 2-dimensional image whose value type models PixelValueConcept
2162 /**
2163 \code
2164 concept ImageConcept<RandomAccess2DImageConcept Img> {
2165     where MutableImageViewConcept<view_t>;
2166     typename coord_t  = view_t::coord_t;
2167 };
2168 \endcode
2169 */
2170 template <typename Img>
2171 struct ImageConcept {
constraintsboost::gil::ImageConcept2172     void constraints() {
2173         gil_function_requires<RandomAccess2DImageConcept<Img> >();
2174         gil_function_requires<MutableImageViewConcept<typename Img::view_t> >();
2175         typedef typename Img::coord_t        coord_t;
2176         BOOST_STATIC_ASSERT(num_channels<Img>::value == mpl::size<typename color_space_type<Img>::type>::value);
2177 
2178         BOOST_STATIC_ASSERT((is_same<coord_t, typename Img::x_coord_t>::value));
2179         BOOST_STATIC_ASSERT((is_same<coord_t, typename Img::y_coord_t>::value));
2180     }
2181     Img img;
2182 };
2183 
2184 
2185 } }  // namespace boost::gil
2186 
2187 #endif
2188