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> |
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); |
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 |
116 | auto concept DefaultConstructible<typename T> { |
117 | T::T(); |
118 | }; |
119 | \endcode |
120 | */ |
121 | template <typename T> |
122 | struct 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 | */ |
136 | template <typename T> |
137 | struct CopyConstructible { |
138 | 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 { |
154 | 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 { |
169 | 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 { |
183 | 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 { |
198 | 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 { |
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 |
227 | auto concept Metafunction<typename T> { |
228 | typename type; |
229 | }; |
230 | \endcode |
231 | */ |
232 | template <typename T> |
233 | struct 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 |
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 { |
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 |
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 { |
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 | |
318 | namespace 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 |
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 { |
364 | 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 { |
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 |
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 { |
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 | /** |
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 { |
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 | |
454 | namespace 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 |
471 | concept MutableChannelConcept<ChannelConcept T> : Assignable<T>, Swappable<T> {}; |
472 | \endcode |
473 | */ |
474 | template <typename T> |
475 | struct 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 |
486 | concept ChannelValueConcept<ChannelConcept T> : Regular<T> {}; |
487 | \endcode |
488 | */ |
489 | template <typename T> |
490 | struct 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 | /** |
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 { |
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 |
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 { |
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 | /** |
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 { |
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 |
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 { |
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 |
670 | concept ColorBaseValueConcept<typename T> : MutableColorBaseConcept<T>, Regular<T> { |
671 | }; |
672 | \endcode |
673 | */ |
674 | template <typename ColorBase> |
675 | struct 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 |
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 { |
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 |
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 { |
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 |
739 | concept HomogeneousColorBaseValueConcept<typename T> : MutableHomogeneousColorBaseConcept<T>, Regular<T> { |
740 | }; |
741 | \endcode |
742 | */ |
743 | |
744 | template <typename ColorBase> |
745 | struct 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 |
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 { |
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 |
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 { |
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 |
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 { |
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 |
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 { |
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 |
908 | concept MutablePixelConcept<PixelConcept P> : MutableColorBaseConcept<P> { |
909 | where is_mutable==true; |
910 | }; |
911 | \endcode |
912 | */ |
913 | template <typename P> |
914 | struct 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 |
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 { |
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 |
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 { |
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 |
963 | concept PixelValueConcept<PixelConcept P> : Regular<P> { |
964 | where SameType<value_type,P>; |
965 | }; |
966 | \endcode |
967 | */ |
968 | template <typename P> |
969 | struct 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 |
980 | concept HomogeneousPixelValueConcept<HomogeneousPixelConcept P> : Regular<P> { |
981 | where SameType<value_type,P>; |
982 | }; |
983 | \endcode |
984 | */ |
985 | template <typename P> |
986 | struct 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 | |
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 { |
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 |
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 { |
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 |
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 { |
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 | |
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; |
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 |
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 { |
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 |
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 { |
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 |
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 { |
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 | /** |
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 { |
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 | |
1221 | namespace 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 |
1237 | concept MutablePixelIteratorConcept<PixelIteratorConcept Iterator> : MutableRandomAccessIteratorConcept<Iterator> {}; |
1238 | |
1239 | \endcode |
1240 | */ |
1241 | template <typename Iterator> |
1242 | struct MutablePixelIteratorConcept { |
1243 | 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 { |
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 |
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 { |
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 |
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 { |
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 |
1316 | concept MutableStepIteratorConcept<Mutable_ForwardIteratorConcept Iterator> : StepIteratorConcept<Iterator> {}; |
1317 | \endcode |
1318 | */ |
1319 | template <typename Iterator> |
1320 | struct 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 | /** |
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 { |
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 |
1378 | concept MutableIteratorAdaptorConcept<Mutable_ForwardIteratorConcept Iterator> : IteratorAdaptorConcept<Iterator> {}; |
1379 | \endcode |
1380 | */ |
1381 | template <typename Iterator> |
1382 | struct 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 |
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 { |
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 |
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 { |
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 |
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 { |
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 | |
1616 | namespace 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 |
1650 | concept MutableRandomAccessNDLocatorConcept<RandomAccessNDLocatorConcept Loc> { |
1651 | where Mutable<reference>; |
1652 | }; |
1653 | \endcode |
1654 | */ |
1655 | template <typename Loc> |
1656 | struct 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 |
1667 | concept MutableRandomAccess2DLocatorConcept<RandomAccess2DLocatorConcept Loc> : MutableRandomAccessNDLocatorConcept<Loc> {}; |
1668 | \endcode |
1669 | */ |
1670 | template <typename Loc> |
1671 | struct 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 |
1682 | concept MutablePixelLocatorConcept<PixelLocatorConcept Loc> : MutableRandomAccess2DLocatorConcept<Loc> {}; |
1683 | \endcode |
1684 | */ |
1685 | template <typename Loc> |
1686 | struct 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 |
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 { |
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 |
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 { |
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 |
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 { |
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 | |
1947 | namespace 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 |
1992 | concept MutableRandomAccessNDImageViewConcept<RandomAccessNDImageViewConcept View> { |
1993 | where Mutable<reference>; |
1994 | }; |
1995 | \endcode |
1996 | */ |
1997 | template <typename View> |
1998 | struct 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 |
2009 | concept MutableRandomAccess2DImageViewConcept<RandomAccess2DImageViewConcept View> : MutableRandomAccessNDImageViewConcept<View> {}; |
2010 | \endcode |
2011 | */ |
2012 | template <typename View> |
2013 | struct 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 |
2024 | concept MutableImageViewConcept<ImageViewConcept View> : MutableRandomAccess2DImageViewConcept<View> {}; |
2025 | \endcode |
2026 | */ |
2027 | template <typename View> |
2028 | struct 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. |
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 { |
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 |
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 { |
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 |
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 { |
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 |
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 { |
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 | |