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
34namespace boost { namespace gil {
35template <typename T> struct channel_traits;
36template <typename P> struct is_pixel;
37template <typename dstT, typename srcT>
38typename channel_traits<dstT>::value_type channel_convert(const srcT& val);
39template <typename T> class point2;
40template <std::size_t K, typename T> const T& axis_value(const point2<T>& p);
41template <std::size_t K, typename T> T& axis_value( point2<T>& p);
42template <typename ColorBase, int K> struct kth_element_type;
43template <typename ColorBase, int K> struct kth_element_reference_type;
44template <typename ColorBase, int K> struct kth_element_const_reference_type;
45template <typename ColorBase, int K> struct kth_semantic_element_reference_type;
46template <typename ColorBase, int K> struct kth_semantic_element_const_reference_type;
47template <typename ColorBase> struct size;
48template <typename ColorBase> struct element_type;
49template <typename T> struct channel_type;
50template <typename T> struct color_space_type;
51template <typename T> struct channel_mapping_type;
52template <typename T> struct is_planar;
53template <typename T> struct num_channels;
54
55template <typename It> struct const_iterator_type;
56template <typename It> struct iterator_is_mutable;
57template <typename It> struct is_iterator_adaptor;
58template <typename It, typename NewBaseIt> struct iterator_adaptor_rebind;
59template <typename It> struct iterator_adaptor_get_base;
60
61
62// forward-declare at_c
63namespace detail { template <typename Element, typename Layout, int K> struct homogeneous_color_base; }
64template <int K, typename E, typename L, int N>
65typename add_reference<E>::type at_c( detail::homogeneous_color_base<E,L,N>& p);
66
67template <int K, typename E, typename L, int N>
68typename 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
71template <typename P, typename C, typename L> struct packed_pixel;
72template <int K, typename P, typename C, typename L>
73typename kth_element_reference_type<packed_pixel<P,C,L>, K>::type
74at_c(packed_pixel<P,C,L>& p);
75
76template <int K, typename P, typename C, typename L>
77typename kth_element_const_reference_type<packed_pixel<P,C,L>,K>::type
78at_c(const packed_pixel<P,C,L>& p);
79
80template <typename B, typename C, typename L, bool M> struct bit_aligned_pixel_reference;
81
82template <int K, typename B, typename C, typename L, bool M> inline
83typename kth_element_reference_type<bit_aligned_pixel_reference<B,C,L,M>, K>::type
84at_c(const bit_aligned_pixel_reference<B,C,L,M>& p);
85#endif
86
87// Forward-declare semantic_at_c
88template <int K, typename ColorBase>
89typename disable_if<is_const<ColorBase>,typename kth_semantic_element_reference_type<ColorBase,K>::type>::type semantic_at_c(ColorBase& p);
90template <int K, typename ColorBase>
91typename kth_semantic_element_const_reference_type<ColorBase,K>::type semantic_at_c(const ColorBase& p);
92
93template <typename T> struct dynamic_x_step_type;
94template <typename T> struct dynamic_y_step_type;
95template <typename T> struct transposed_type;
96
97namespace detail {
98template <typename T>
99void initialize_it(T& x) {}
100} // namespace detail
101
102template <typename T>
103struct 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);
107 template <typename C> void gil_function_requires() { function_requires<C>(); }
108#else
109 #define GIL_CLASS_REQUIRE(T,NS,C)
110 template <typename C> void gil_function_requires() {}
111#endif
112
113/// \ingroup BasicConcepts
114/**
115\code
116auto concept DefaultConstructible<typename T> {
117 T::T();
118};
119\endcode
120*/
121template <typename T>
122struct DefaultConstructible {
123 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*/
136template <typename T>
137struct CopyConstructible {
138 void constraints() {
139 function_requires<boost::CopyConstructibleConcept<T> >();
140 }
141};
142
143/// \ingroup BasicConcepts
144/**
145\code
146auto concept Assignable<typename T, typename U = T> {
147 typename result_type;
148 result_type operator=(T&, U);
149};
150\endcode
151*/
152template <typename T>
153struct Assignable {
154 void constraints() {
155 function_requires<boost::AssignableConcept<T> >();
156 }
157};
158/// \ingroup BasicConcepts
159/**
160\code
161auto 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*/
167template <typename T>
168struct EqualityComparable {
169 void constraints() {
170 function_requires<boost::EqualityComparableConcept<T> >();
171 }
172};
173
174/// \ingroup BasicConcepts
175/**
176\code
177concept SameType<typename T, typename U>;// unspecified
178\endcode
179*/
180
181template <typename T, typename U>
182struct SameType {
183 void constraints() {
184 BOOST_STATIC_ASSERT((boost::is_same<T,U>::value_core));
185 }
186};
187
188/// \ingroup BasicConcepts
189/**
190\code
191auto concept Swappable<typename T> {
192 void swap(T&,T&);
193};
194\endcode
195*/
196template <typename T>
197struct Swappable {
198 void constraints() {
199 using std::swap;
200 swap(x,y);
201 }
202 T x,y;
203};
204
205/// \ingroup BasicConcepts
206/**
207\code
208auto concept Regular<typename T> : DefaultConstructible<T>, CopyConstructible<T>, EqualityComparable<T>,
209 Assignable<T>, Swappable<T> {};
210\endcode
211*/
212
213template <typename T>
214struct Regular {
215 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
227auto concept Metafunction<typename T> {
228 typename type;
229};
230\endcode
231*/
232template <typename T>
233struct Metafunction {
234 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
248concept 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
261template <typename P>
262struct PointNDConcept {
263 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
285concept 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
299template <typename P>
300struct Point2DConcept {
301 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
318namespace detail {
319 template <class TT> // Preconditions: TT Models boost_concepts::ForwardTraversalConcept
320 struct ForwardIteratorIsMutableConcept {
321 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 {
329 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 {
338 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
357concept ColorSpaceConcept<MPLRandomAccessSequence Cs> {
358 // An MPL Random Access Sequence, whose elements are color tags
359};
360\endcode
361*/
362template <typename Cs>
363struct ColorSpaceConcept {
364 void constraints() {
365 // An MPL Random Access Sequence, whose elements are color tags
366 }
367};
368
369template <typename ColorSpace1, typename ColorSpace2> // Models ColorSpaceConcept
370struct 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
376concept ColorSpacesCompatibleConcept<ColorSpaceConcept Cs1, ColorSpaceConcept Cs2> {
377 where SameType<Cs1,Cs2>;
378};
379\endcode
380*/
381template <typename Cs1, typename Cs2>
382struct ColorSpacesCompatibleConcept {
383 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
392concept ChannelMappingConcept<MPLRandomAccessSequence CM> {
393 // An MPL Random Access Sequence, whose elements model MPLIntegralConstant representing a permutation
394};
395\endcode
396*/
397template <typename CM>
398struct ChannelMappingConcept {
399 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/**
415For 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
417Built-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.
418In such cases special classes are needed to represent the value and reference to a channel.
419
420Channels have a traits class, \p channel_traits, which defines their associated types as well as their operating ranges.
421
422\code
423concept 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*/
436template <typename T>
437struct ChannelConcept {
438 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
454namespace detail {
455 // Preconditions: T models ChannelConcept
456 template <typename T>
457 struct ChannelIsMutableConcept {
458 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
471concept MutableChannelConcept<ChannelConcept T> : Assignable<T>, Swappable<T> {};
472\endcode
473*/
474template <typename T>
475struct MutableChannelConcept {
476 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
486concept ChannelValueConcept<ChannelConcept T> : Regular<T> {};
487\endcode
488*/
489template <typename T>
490struct ChannelValueConcept {
491 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/**
503Example:
504
505\code
506BOOST_STATIC_ASSERT((channels_are_compatible<bits8, const bits8&>::value));
507\endcode
508*/
509template <typename T1, typename T2> // Models GIL Pixel
510struct 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
517concept ChannelsCompatibleConcept<ChannelConcept T1, ChannelConcept T2> {
518 where SameType<T1::value_type, T2::value_type>;
519};
520\endcode
521*/
522template <typename T1, typename T2>
523struct ChannelsCompatibleConcept {
524 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
535concept ChannelConvertibleConcept<ChannelConcept SrcChannel, ChannelValueConcept DstChannel> {
536 DstChannel channel_convert(const SrcChannel&);
537};
538\endcode
539*/
540template <typename SrcChannel, typename DstChannel>
541struct ChannelConvertibleConcept {
542 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/**
564The most common use of color base is in the implementation of a pixel, in which case the color
565elements are channel values. The color base concept, however, can be used in other scenarios. For example, a planar pixel has channels that are not
566contiguous in memory. Its reference is a proxy class that uses a color base whose elements are channel references. Its iterator uses a color base
567whose elements are channel iterators.
568
569A color base must have an associated layout (which consists of a color space, as well as an ordering of the channels).
570There are two ways to index the elements of a color base: A physical index corresponds to the way they are ordered in memory, and
571a semantic index corresponds to the way the elements are ordered in their color space.
572For 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
573in physical ordering is the blue element, whereas the first semantic element is the red one.
574Models of \p ColorBaseConcept are required to provide the \p at_c<K>(ColorBase) function, which allows for accessing the elements based on their
575physical order. GIL provides a \p semantic_at_c<K>(ColorBase) function (described later) which can operate on any model of ColorBaseConcept and returns
576the corresponding semantic element.
577
578\code
579concept 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
603template <typename ColorBase>
604struct ColorBaseConcept {
605 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
638concept 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*/
648template <typename ColorBase>
649struct MutableColorBaseConcept {
650 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
670concept ColorBaseValueConcept<typename T> : MutableColorBaseConcept<T>, Regular<T> {
671};
672\endcode
673*/
674template <typename ColorBase>
675struct ColorBaseValueConcept {
676 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
686concept 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
694template <typename ColorBase>
695struct HomogeneousColorBaseConcept {
696 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
716concept 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
722template <typename ColorBase>
723struct MutableHomogeneousColorBaseConcept {
724 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
739concept HomogeneousColorBaseValueConcept<typename T> : MutableHomogeneousColorBaseConcept<T>, Regular<T> {
740};
741\endcode
742*/
743
744template <typename ColorBase>
745struct HomogeneousColorBaseValueConcept {
746 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
758concept 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*/
766template <typename ColorBase1, typename ColorBase2>
767struct ColorBasesCompatibleConcept {
768 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
808concept 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*/
821template <typename P>
822struct PixelBasedConcept {
823 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
842concept 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*/
849template <typename P>
850struct HomogeneousPixelBasedConcept {
851 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
863concept 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
883template <typename P>
884struct PixelConcept {
885 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
908concept MutablePixelConcept<PixelConcept P> : MutableColorBaseConcept<P> {
909 where is_mutable==true;
910};
911\endcode
912*/
913template <typename P>
914struct MutablePixelConcept {
915 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
924concept 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*/
929template <typename P>
930struct HomogeneousPixelConcept {
931 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
944concept 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*/
949template <typename P>
950struct MutableHomogeneousPixelConcept {
951 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
963concept PixelValueConcept<PixelConcept P> : Regular<P> {
964 where SameType<value_type,P>;
965};
966\endcode
967*/
968template <typename P>
969struct PixelValueConcept {
970 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
980concept HomogeneousPixelValueConcept<HomogeneousPixelConcept P> : Regular<P> {
981 where SameType<value_type,P>;
982};
983\endcode
984*/
985template <typename P>
986struct HomogeneousPixelValueConcept {
987 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
994namespace 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
1009template <typename P1, typename P2> // Models GIL Pixel
1010struct 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
1020concept 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*/
1026template <typename P1, typename P2> // precondition: P1 and P2 model PixelConcept
1027struct PixelsCompatibleConcept {
1028 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
1039template <PixelConcept SrcPixel, MutablePixelConcept DstPixel>
1040concept PixelConvertibleConcept {
1041 void color_convert(const SrcPixel&, DstPixel&);
1042};
1043\endcode
1044*/
1045template <typename SrcP, typename DstP>
1046struct PixelConvertibleConcept {
1047 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
1069concept 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
1082template <typename D>
1083struct PixelDereferenceAdaptorConcept {
1084 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
1106template <typename P>
1107struct 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;
1113 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
1126concept HasDynamicXStepTypeConcept<typename T> {
1127 typename dynamic_x_step_type<T>;
1128 where Metafunction<dynamic_x_step_type<T> >;
1129};
1130\endcode
1131*/
1132template <typename T>
1133struct HasDynamicXStepTypeConcept {
1134 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
1143concept HasDynamicYStepTypeConcept<typename T> {
1144 typename dynamic_y_step_type<T>;
1145 where Metafunction<dynamic_y_step_type<T> >;
1146};
1147\endcode
1148*/
1149template <typename T>
1150struct HasDynamicYStepTypeConcept {
1151 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
1161concept HasTransposedTypeConcept<typename T> {
1162 typename transposed_type<T>;
1163 where Metafunction<transposed_type<T> >;
1164};
1165\endcode
1166*/
1167template <typename T>
1168struct HasTransposedTypeConcept {
1169 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/**
1181GIL'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
1187concept 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*/
1196template <typename Iterator>
1197struct PixelIteratorConcept {
1198 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 }
1212 void check_base(mpl::false_) {}
1213 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
1221namespace detail {
1222 template <typename Iterator> // Preconditions: Iterator Models PixelIteratorConcept
1223 struct PixelIteratorIsMutableConcept {
1224 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
1237concept MutablePixelIteratorConcept<PixelIteratorConcept Iterator> : MutableRandomAccessIteratorConcept<Iterator> {};
1238
1239\endcode
1240*/
1241template <typename Iterator>
1242struct MutablePixelIteratorConcept {
1243 void constraints() {
1244 gil_function_requires<PixelIteratorConcept<Iterator> >();
1245 gil_function_requires<detail::PixelIteratorIsMutableConcept<Iterator> >();
1246 }
1247};
1248
1249namespace 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 {
1253 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
1272concept 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*/
1282template <typename Iterator>
1283struct MemoryBasedIteratorConcept {
1284 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
1296concept StepIteratorConcept<boost_concepts::ForwardTraversalConcept Iterator> {
1297 template <Integral D> void Iterator::set_step(D step);
1298};
1299\endcode
1300*/
1301template <typename Iterator>
1302struct StepIteratorConcept {
1303 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
1316concept MutableStepIteratorConcept<Mutable_ForwardIteratorConcept Iterator> : StepIteratorConcept<Iterator> {};
1317\endcode
1318*/
1319template <typename Iterator>
1320struct MutableStepIteratorConcept {
1321 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/**
1334In 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
1339The adaptee can be obtained from the iterator via the "base()" method.
1340
1341\code
1342concept 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*/
1358template <typename Iterator>
1359struct IteratorAdaptorConcept {
1360 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
1378concept MutableIteratorAdaptorConcept<Mutable_ForwardIteratorConcept Iterator> : IteratorAdaptorConcept<Iterator> {};
1379\endcode
1380*/
1381template <typename Iterator>
1382struct MutableIteratorAdaptorConcept {
1383 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
1411concept 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*/
1455template <typename Loc>
1456struct RandomAccessNDLocatorConcept {
1457 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
1505concept 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*/
1541template <typename Loc>
1542struct RandomAccess2DLocatorConcept {
1543 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
1594concept 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*/
1604template <typename Loc>
1605struct PixelLocatorConcept {
1606 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
1616namespace detail {
1617 template <typename Loc> // preconditions: Loc Models RandomAccessNDLocatorConcept
1618 struct RandomAccessNDLocatorIsMutableConcept {
1619 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 {
1635 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
1650concept MutableRandomAccessNDLocatorConcept<RandomAccessNDLocatorConcept Loc> {
1651 where Mutable<reference>;
1652};
1653\endcode
1654*/
1655template <typename Loc>
1656struct MutableRandomAccessNDLocatorConcept {
1657 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
1667concept MutableRandomAccess2DLocatorConcept<RandomAccess2DLocatorConcept Loc> : MutableRandomAccessNDLocatorConcept<Loc> {};
1668\endcode
1669*/
1670template <typename Loc>
1671struct MutableRandomAccess2DLocatorConcept {
1672 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
1682concept MutablePixelLocatorConcept<PixelLocatorConcept Loc> : MutableRandomAccess2DLocatorConcept<Loc> {};
1683\endcode
1684*/
1685template <typename Loc>
1686struct MutablePixelLocatorConcept {
1687 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
1715concept 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*/
1762template <typename View>
1763struct RandomAccessNDImageViewConcept {
1764 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
1831concept 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*/
1866template <typename View>
1867struct RandomAccess2DImageViewConcept {
1868 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
1918concept 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*/
1930template <typename View>
1931struct ImageViewConcept {
1932 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
1947namespace detail {
1948 template <typename View> // Preconditions: View Models RandomAccessNDImageViewConcept
1949 struct RandomAccessNDImageViewIsMutableConcept {
1950 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 {
1970 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 {
1982 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
1992concept MutableRandomAccessNDImageViewConcept<RandomAccessNDImageViewConcept View> {
1993 where Mutable<reference>;
1994};
1995\endcode
1996*/
1997template <typename View>
1998struct MutableRandomAccessNDImageViewConcept {
1999 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
2009concept MutableRandomAccess2DImageViewConcept<RandomAccess2DImageViewConcept View> : MutableRandomAccessNDImageViewConcept<View> {};
2010\endcode
2011*/
2012template <typename View>
2013struct MutableRandomAccess2DImageViewConcept {
2014 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
2024concept MutableImageViewConcept<ImageViewConcept View> : MutableRandomAccess2DImageViewConcept<View> {};
2025\endcode
2026*/
2027template <typename View>
2028struct MutableImageViewConcept {
2029 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.
2038template <typename V1, typename V2> // Model ImageViewConcept
2039struct 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
2045concept ViewsCompatibleConcept<ImageViewConcept V1, ImageViewConcept V2> {
2046 where PixelsCompatibleConcept<V1::value_type, P2::value_type>;
2047};
2048\endcode
2049*/
2050template <typename V1, typename V2>
2051struct ViewsCompatibleConcept {
2052 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
2069concept 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*/
2088template <typename Img>
2089struct RandomAccessNDImageConcept {
2090 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
2122concept 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*/
2137template <typename Img>
2138struct RandomAccess2DImageConcept {
2139 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
2164concept ImageConcept<RandomAccess2DImageConcept Img> {
2165 where MutableImageViewConcept<view_t>;
2166 typename coord_t = view_t::coord_t;
2167};
2168\endcode
2169*/
2170template <typename Img>
2171struct ImageConcept {
2172 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

source code of boost/boost/gil/gil_concept.hpp