2 // Copyright 2005-2007 Adobe Systems Incorporated
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
8 #ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_GIL_REDUCE_HPP
9 #define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_GIL_REDUCE_HPP
11 #ifdef BOOST_GIL_DOXYGEN_ONLY
12 #undef BOOST_GIL_REDUCE_CODE_BLOAT
15 #ifdef BOOST_GIL_REDUCE_CODE_BLOAT
17 #include <boost/gil/extension/dynamic_image/dynamic_at_c.hpp>
19 #include <boost/gil/metafunctions.hpp>
20 #include <boost/gil/typedefs.hpp>
22 #include <boost/mpl/back.hpp>
23 #include <boost/mpl/insert.hpp>
24 #include <boost/mpl/insert_range.hpp>
25 #include <boost/mpl/long.hpp>
26 #include <boost/mpl/logical.hpp>
27 #include <boost/mpl/range_c.hpp>
28 #include <boost/mpl/vector.hpp>
29 #include <boost/mpl/vector_c.hpp>
30 #include <boost/mpl/transform.hpp>
32 #include <type_traits>
34 // Max number of cases in the cross-expension of binary operation for it to be reduced as unary
35 #define GIL_BINARY_REDUCE_LIMIT 226
37 namespace boost { namespace mpl {
39 // Constructs for static-to-dynamic integer convesion
41 ///////////////////////////////////////////////////////
42 /// Mapping vector - represents the mapping of one type vector to another
43 /// It is not a full-blown Boost.MP11-compatible list; just has at_c and size implemented
45 /// SrcTypes, DstTypes: Boost.MP11-compatible list
47 /// Implements size and at_c to behave as if this is an Boost.MP11-compatible list of integers
48 ///////////////////////////////////////////////////////
50 template <typename SrcTypes, typename DstTypes>
51 struct mapping_vector {};
53 template <typename SrcTypes, typename DstTypes, long K>
54 struct at_c<mapping_vector<SrcTypes,DstTypes>, K>
56 static const std::size_t value=size<DstTypes>::value - order<DstTypes, typename gil::at_c<SrcTypes,K>::type>::value +1;
57 using type = size_t<value>;
60 template <typename SrcTypes, typename DstTypes>
61 struct size<mapping_vector<SrcTypes,DstTypes>>
63 using type = typename size<SrcTypes>::type;
64 static const std::size_t value=type::value;
67 ///////////////////////////////////////////////////////
68 /// copy_to_vector - copies a sequence (mpl::set) to vector.
70 /// Temporary solution because I couldn't get mpl::copy to do this.
71 /// This is what I tried:
72 /// mpl::copy<SET, mpl::back_inserter<mpl::vector<>>>::type;
73 /// It works when SET is mpl::vector, but not when SET is mpl::set...
74 ///////////////////////////////////////////////////////
77 template <typename SFirst, std::size_t NLeft>
78 struct copy_to_vector_impl {
80 using T = typename deref<SFirst>::type;
81 using next = typename next<SFirst>::type;
82 using rest = typename copy_to_vector_impl<next, NLeft-1>::type;
84 using type = typename push_front<rest, T>::type;
87 template <typename SFirst>
88 struct copy_to_vector_impl<SFirst,1>
90 using type = vector<typename deref<SFirst>::type>;
94 template <typename Src>
97 using type = typename detail::copy_to_vector_impl<typename begin<Src>::type, size<Src>::value>::type;
101 struct copy_to_vector<set<>>
103 using type = vector0<>;
108 namespace boost { namespace gil {
111 ///////////////////////////////////////////////////////
113 /// unary_reduce, binary_reduce - given an MPL Random Access Sequence,
114 /// dynamically specified index to that container, the bits of an instance of the corresponding type and
115 /// a generic operation, invokes the operation on the given type
117 ///////////////////////////////////////////////////////
122 ///////////////////////////////////////////////////////
124 /// \brief Unary reduce.
126 /// Given a set of types and an operation, reduces each type in the set (to reduced_t), then removes duplicates (to unique_t)
127 /// To apply the operation, first constructs a lookup table that maps each element from Types to its place in unique_t and uses it to map
128 /// the index to anther index (in map_index). Then invokes apply_operation_base on the unique types with the new index.
130 ///////////////////////////////////////////////////////
132 template <typename Types, typename Op>
133 struct unary_reduce_impl {
134 using reduced_t = typename mpl::transform<Types, detail::reduce<Op, mpl::_1> >::type;
135 using unique_t = typename mpl::copy<reduced_t, mpl::inserter<mpl::set<>, mpl::insert<mpl::_1,mpl::_2>>>::type;
136 static const bool is_single=mpl::size<unique_t>::value==1;
139 template <typename Types, typename Op, bool IsSingle=unary_reduce_impl<Types,Op>::is_single>
140 struct unary_reduce : public unary_reduce_impl<Types,Op>
142 using reduced_t = typename unary_reduce_impl<Types,Op>::reduced_t;
143 using unique_t = typename unary_reduce_impl<Types,Op>::unique_t;
145 static unsigned short inline map_index(std::size_t index)
147 using indices_t = typename mpl::mapping_vector<reduced_t, unique_t>;
148 return gil::at_c<indices_t, unsigned short>(index);
150 template <typename Bits> BOOST_FORCEINLINE static typename Op::result_type applyc(const Bits& bits, std::size_t index, Op op) {
151 return apply_operation_basec<unique_t>(bits,map_index(index),op);
154 template <typename Bits> BOOST_FORCEINLINE static typename Op::result_type apply(Bits& bits, std::size_t index, Op op) {
155 return apply_operation_base<unique_t>(bits,map_index(index),op);
159 template <typename Types, typename Op>
160 struct unary_reduce<Types,Op,true> : public unary_reduce_impl<Types,Op> {
161 using unique_t = typename unary_reduce_impl<Types,Op>::unique_t;
162 static unsigned short inline map_index(std::size_t index) { return 0; }
164 template <typename Bits> BOOST_FORCEINLINE static typename Op::result_type applyc(const Bits& bits, std::size_t index, Op op) {
165 return op(*gil_reinterpret_cast_c<const typename mpl::front<unique_t>::type*>(&bits));
168 template <typename Bits> BOOST_FORCEINLINE static typename Op::result_type apply(Bits& bits, std::size_t index, Op op) {
169 return op(*gil_reinterpret_cast<typename mpl::front<unique_t>::type*>(&bits));
174 ///////////////////////////////////////////////////////
176 /// \brief Binary reduce.
178 /// Given two sets of types, Types1 and Types2, first performs unary reduction on each. Then checks if the product of their sizes is above
179 /// the GIL_BINARY_REDUCE_LIMIT limit. If so, the operation is too complex to be binary-reduced and uses a specialization of binary_reduce_impl
180 /// to simply call the binary apply_operation_base (which performs two nested 1D apply operations)
181 /// If the operation is not too complex, uses the other specialization of binary_reduce_impl to create a cross-product of the input types
182 /// and performs unary reduction on the result (bin_reduced_t). To apply the binary operation, it simply invokes a unary apply_operation_base
183 /// on the reduced cross-product types
185 ///////////////////////////////////////////////////////
188 struct pair_generator {
189 template <typename Vec2> struct apply
191 using type = std::pair<const typename mpl::at_c<Vec2,0>::type*, const typename mpl::at_c<Vec2,1>::type*>;
195 // When the types are not too large, applies reduce on their cross product
196 template <typename Unary1, typename Unary2, typename Op, bool IsComplex>
197 struct binary_reduce_impl
200 using vec1_types = typename mpl::copy_to_vector<typename Unary1::unique_t>::type;
201 using vec2_types = typename mpl::copy_to_vector<typename Unary2::unique_t>::type;
203 using BIN_TYPES = mpl::cross_vector<mpl::vector2<vec1_types, vec2_types>, pair_generator>;
204 using bin_reduced_t = unary_reduce<BIN_TYPES,Op>;
206 static unsigned short inline map_index(std::size_t index1, std::size_t index2) {
207 unsigned short r1=Unary1::map_index(index1);
208 unsigned short r2=Unary2::map_index(index2);
209 return bin_reduced_t::map_index(r2*mpl::size<vec1_types>::value + r1);
212 using unique_t = typename bin_reduced_t::unique_t
214 template <typename Bits1, typename Bits2>
215 static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
216 std::pair<const void*,const void*> pr(&bits1, &bits2);
217 return apply_operation_basec<unique_t>(pr, map_index(index1,index2),op);
221 // When the types are large performs a double-dispatch. Binary reduction is not done.
222 template <typename Unary1, typename Unary2, typename Op>
223 struct binary_reduce_impl<Unary1,Unary2,Op,true> {
224 template <typename Bits1, typename Bits2>
225 static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
226 return apply_operation_base<Unary1::unique_t,Unary2::unique_t>(bits1, index1, bits2, index2, op);
232 template <typename Types1, typename Types2, typename Op>
236 using unary1_t = unary_reduce<Types1,Op>;
237 using unary2_t = unary_reduce<Types2,Op>;
239 static const std::size_t CROSS_SIZE = mpl::size<typename unary1_t::unique_t>::value *
240 mpl::size<typename unary2_t::unique_t>::value;
242 using impl = detail::binary_reduce_impl<unary1_t,unary2_t,Op, (CROSS_SIZE>GIL_BINARY_REDUCE_LIMIT)>;
244 template <typename Bits1, typename Bits2>
245 static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
246 return impl::apply(bits1,index1,bits2,index2,op);
250 template <typename Types, typename UnaryOp>
251 BOOST_FORCEINLINE typename UnaryOp::result_type apply_operation(variant<Types>& arg, UnaryOp op) {
252 return unary_reduce<Types,UnaryOp>::template apply(arg._bits, arg._index ,op);
255 template <typename Types, typename UnaryOp>
256 BOOST_FORCEINLINE typename UnaryOp::result_type apply_operation(const variant<Types>& arg, UnaryOp op) {
257 return unary_reduce<Types,UnaryOp>::template applyc(arg._bits, arg._index ,op);
260 template <typename Types1, typename Types2, typename BinaryOp>
261 BOOST_FORCEINLINE typename BinaryOp::result_type apply_operation(const variant<Types1>& arg1, const variant<Types2>& arg2, BinaryOp op) {
262 return binary_reduce<Types1,Types2,BinaryOp>::template apply(arg1._bits, arg1._index, arg2._bits, arg2._index, op);
265 #undef GIL_BINARY_REDUCE_LIMIT
270 namespace boost { namespace mpl {
271 ///////////////////////////////////////////////////////
272 /// \brief Represents the virtual cross-product of the types generated from VecOfVecs.
273 /// \ingroup CrossVector
275 /// VecOfVecs - a vector of vector types. For example [ [A1,A2,A3], [B1,B2], [C1,C2,C3,C4] ]
276 /// Each element must be a non-empty mpl vector
277 /// TypeGen - a metafunction that generates a type from a vector of types, each of which can be
278 /// selected from the corresponding vector in VecOfVecs. For example, [A1, B2, C4]
280 /// Represents the virtual cross-product of the types generated from VecOfVecs.
281 /// For example, [ TypeGen[A1,B1,C1], TypeGen[A2,B1,C1], TypeGen[A3,B1,C1],
282 /// TypeGen[A1,B2,C1], TypeGen[A2,B2,C1], TypeGen[A3,B2,C1],
283 /// TypeGen[A1,B1,C2], TypeGen[A2,B1,C2], TypeGen[A3,B1,C2], ... ]
285 /// Models an immutable MPL Random Access Sequence
286 /// Traversal, random-access, etc, is defined, but mutable operations,
287 /// such as push_back and pop_front are not supported
288 ///////////////////////////////////////////////////////
290 template <typename VecOfVecs, typename TypeGen>
291 struct cross_vector {};
293 /// \brief Iterator of cross_vector
294 /// \ingroup CrossVectorIterator
295 template <typename VecOfVecs, typename TypeGen, std::size_t K>
296 struct cross_iterator
298 using category = mpl::random_access_iterator_tag;
301 ///////////////////////////////////////////////////////
302 /// Implementation of the iterator functions of cross vector
303 ///////////////////////////////////////////////////////
305 /// \brief Dereferences a cross-vector iterator
306 /// \ingroup CrossVectorIterator
307 /// Creates a vector of the sizes of each type vector in VecOfVecs, then uses it as a basis
308 /// to represent the iterator's position K as a vector of indices. Extracts the corresponding type of
309 /// each input vector and passes the element types to the type generation function, which returns the dereferenced type
310 template <typename VecOfVecs, typename TypeGen, std::size_t K>
311 struct deref<cross_iterator<VecOfVecs,TypeGen,K>>
314 using DerefTypes = typename detail::select_subvector_c<VecOfVecs, K>::type;
316 using type = typename TypeGen::template apply<DerefTypes>::type;
319 /// \brief Increments a cross-vector iterator.
320 /// \ingroup CrossVectorIterator
321 template <typename VecOfVecs, typename TypeGen, std::size_t K>
322 struct next<cross_iterator<VecOfVecs,TypeGen,K>>
324 using type = cross_iterator<VecOfVecs,TypeGen,K+1>;
327 /// \brief Decrements a cross-vector iterator.
328 /// \ingroup CrossVectorIterator
329 template <typename VecOfVecs, typename TypeGen, std::size_t K>
330 struct prior<cross_iterator<VecOfVecs,TypeGen,K>>
332 using type = cross_iterator<VecOfVecs,TypeGen,K-1>;
335 /// \brief Advances a cross-vector iterator.
336 /// \ingroup CrossVectorIterator
337 template <typename VecOfVecs, typename TypeGen, std::size_t K, typename Distance>
338 struct advance<cross_iterator<VecOfVecs,TypeGen,K>, Distance>
340 using type = cross_iterator<VecOfVecs,TypeGen,K+Distance::value>;
343 /// \brief Computes the distance between two cross-vector iterator-s.
344 /// \ingroup CrossVectorIterator
345 // (shortened the names of the template arguments - otherwise doxygen cannot parse this...)
346 template <typename VecOfVecs, typename TypeGen, std::size_t K1, std::size_t K2>
347 struct distance<cross_iterator<VecOfVecs,TypeGen,K1>, cross_iterator<VecOfVecs,TypeGen,K2>>
349 using type = size_t<K2-K1>;
352 ///////////////////////////////////////////////////////
353 /// Implementation of cross vector
354 ///////////////////////////////////////////////////////
355 /// \brief Computes the size of a cross vector as the product of the sizes of all vectors in VecOfVecs
356 /// \ingroup CrossVector
357 template <typename VecOfVecs, typename TypeGen>
358 struct size<cross_vector<VecOfVecs,TypeGen>>
360 using type = typename fold<VecOfVecs, size_t<1>, times<_1, size<_2>>>::type;
361 static const std::size_t value=type::value;
364 /// \brief Determines whether a cross vector is empty
365 /// \ingroup CrossVector
366 template <typename VecOfVecs, typename TypeGen>
367 struct empty<cross_vector<VecOfVecs,TypeGen>> {
368 using type = typename empty<VecOfVecs>::type;
371 /// \brief Returns the K-th element of a cross vector
372 /// \ingroup CrossVector
373 template <typename VecOfVecs, typename TypeGen, typename K>
374 struct at<cross_vector<VecOfVecs,TypeGen>, K>
377 using KthIterator = cross_iterator<VecOfVecs,TypeGen,K::value>;
379 using type = typename deref<KthIterator>::type;
382 /// \brief Returns an iterator to the first element of a cross vector
383 /// \ingroup CrossVector
384 template <typename VecOfVecs, typename TypeGen>
385 struct begin<cross_vector<VecOfVecs,TypeGen>>
387 using type = cross_iterator<VecOfVecs,TypeGen,0>;
390 /// \brief Returns an iterator to the last element of a cross vector
391 /// \ingroup CrossVector
392 template <typename VecOfVecs, typename TypeGen>
393 struct end<cross_vector<VecOfVecs,TypeGen>>
396 using this_t = cross_vector<VecOfVecs,TypeGen>;
398 using type = cross_iterator<VecOfVecs,TypeGen,size<this_t>::value>;
401 /// \brief Returns the first element of a cross vector
402 /// \ingroup CrossVector
403 template <typename VecOfVecs, typename TypeGen>
404 struct front<cross_vector<VecOfVecs,TypeGen>> {
406 using this_t = cross_vector<VecOfVecs,TypeGen>;
408 using type = typename deref<typename begin<this_t>::type>::type;
411 /// \brief Returns the last element of a cross vector
412 /// \ingroup CrossVector
413 template <typename VecOfVecs, typename TypeGen>
414 struct back<cross_vector<VecOfVecs,TypeGen>>
417 using this_t = cross_vector<VecOfVecs,TypeGen>;
418 using size = typename size<this_t>::type;
419 using last_index = typename minus<size, size_t<1>>::type;
421 using type = typename at<this_t, last_index>::type;
424 /// \brief Transforms the elements of a cross vector
425 /// \ingroup CrossVector
426 template <typename VecOfVecs, typename TypeGen, typename OPP>
427 struct transform<cross_vector<VecOfVecs,TypeGen>, OPP>
429 using Op = typename lambda<OPP>::type;
432 template <typename Elements>
435 using orig_t = typename TypeGen::template apply<Elements>::type;
436 using type = typename Op::template apply<orig_t>::type;
439 using type = cross_vector<VecOfVecs, adapter>;
444 namespace boost { namespace gil {
446 template <typename Types, typename T> struct type_to_index;
447 template <typename V> struct view_is_basic;
457 ////////////////////////////////////////////////////////
459 //// Generic reduce operation
461 ////////////////////////////////////////////////////////
462 template <typename Op, typename T>
468 ////////////////////////////////////////////////////////
470 //// Unary reduce_view operation. Splits into basic and non-basic views.
471 //// Algorithm-specific reduce should specialize for basic views
473 ////////////////////////////////////////////////////////
475 template <typename Op, typename View, bool IsBasic>
476 struct reduce_view_basic
481 template <typename Op, typename Loc>
482 struct reduce<Op, image_view<Loc>>
483 : public reduce_view_basic<Op,image_view<Loc>,view_is_basic<image_view<Loc>>::value> {};
485 ////////////////////////////////////////////////////////
487 //// Unary reduce_image operation. Splits into basic and non-basic images.
488 //// Algorithm-specific reduce should specialize for basic images
490 ////////////////////////////////////////////////////////
492 template <typename Op, typename Img, bool IsBasic>
493 struct reduce_image_basic
498 template <typename Op, typename V, typename Alloc>
499 struct reduce<Op, image<V,Alloc>> : public reduce_image_basic<Op,image<V,Alloc>,image_is_basic<image<V,Alloc>>::value > {};
501 ////////////////////////////////////////////////////////
503 //// Binary reduce_view operation. Splits into basic and non-basic views.
504 //// Algorithm-specific reduce should specialize for basic views
506 ////////////////////////////////////////////////////////
508 template <typename Op, typename V1, typename V2, bool AreBasic>
509 struct reduce_views_basic
511 using type = std::pair<const V1*, const V2*>;
514 template <typename Op, typename L1, typename L2>
515 struct reduce<Op, std::pair<const image_view<L1>*, const image_view<L2>*>>
516 : public reduce_views_basic<Op,image_view<L1>,image_view<L2>,
517 mpl::and_<view_is_basic<image_view<L1>>, view_is_basic<image_view<L2>>>::value >
521 ////////////////////////////////////////////////////////
523 //// Color space unary reduce operation. Reduce a color space to a base with the same number of channels
525 ////////////////////////////////////////////////////////
527 template <typename CS>
528 struct reduce_color_space
533 template <> struct reduce_color_space<lab_t> { using type = rgb_t; };
534 template <> struct reduce_color_space<hsb_t> { using type = rgb_t; };
535 template <> struct reduce_color_space<cmyk_t> { using type = rgba_t; };
538 ////////////////////////////////////////////////////////
540 //// Color space binary reduce operation. Given a source and destination color spaces,
541 //// returns a reduced source and destination color spaces that have the same mapping of channels
543 //// Precondition: The two color spaces must be compatible (i.e. must have the same set of channels)
544 ////////////////////////////////////////////////////////
546 template <typename Vec, int Basis, int VecSize>
547 struct type_vec_to_integer_impl {
548 using last = typename mpl::back<Vec>::type;
549 using rest = typename mpl::pop_back<Vec>::type;
550 static const int value = type_vec_to_integer_impl<rest, Basis, VecSize-1>::value * Basis + last::value;
553 template <typename Vec, int Basis>
554 struct type_vec_to_integer_impl<Vec,Basis,0> {
555 static const int value=0;
558 template <typename Vec, int Basis=10>
559 struct type_vec_to_integer {
560 static const int value = type_vec_to_integer_impl<Vec,Basis, mpl::size<Vec>::value>::value;
563 // Given two color spaces and the mapping of the channels between them, returns the reduced pair of color spaces
564 // The default version performs no reduction
565 template <typename SrcColorSpace, typename DstColorSpace, int Mapping>
566 struct reduce_color_spaces_impl {
567 using first_t = SrcColorSpace;
568 using second_t = DstColorSpace;
571 // 012: RGB-RGB, bgr-bgr, lab-lab, hsb-hsb
572 template <typename SrcColorSpace, typename DstColorSpace>
573 struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,12> {
574 using first_t = rgb_t;
575 using second_t = rgb_t;
578 // 210: RGB-bgr, bgr-RGB
579 template <typename SrcColorSpace, typename DstColorSpace>
580 struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,210> {
581 using first_t = rgb_t;
582 using second_t = bgr_t;
585 // 0123: RGBA-RGBA, bgra-bgra, argb-argb, abgr-abgr cmyk-cmyk
586 template <typename SrcColorSpace, typename DstColorSpace>
587 struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,123> {
588 using first_t = rgba_t;
589 using second_t = rgba_t;
592 // 3210: RGBA-abgr, bgra-argb, argb-bgra, abgr-RGBA
593 template <typename SrcColorSpace, typename DstColorSpace>
594 struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,3210> {
595 using first_t = rgba_t;
596 using second_t = abgr_t;
599 // 1230: RGBA-argb, bgra-abgr
600 template <typename SrcColorSpace, typename DstColorSpace>
601 struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,1230> {
602 using first_t = rgba_t;
603 using second_t = argb_t;
606 // 2103: RGBA-bgra, bgra-RGBA (uses subclass to ensure that base color space is not reduced to derived)
607 template <typename SrcColorSpace, typename DstColorSpace>
608 struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,2103> {
609 using first_t = rgba_t;
610 using second_t = bgra_t;
613 // 3012: argb-RGBA, abgr-bgra
614 template <typename SrcColorSpace, typename DstColorSpace>
615 struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,3012> {
616 using first_t = argb_t;
617 using second_t = rgba_t;
620 // 0321: argb-abgr, abgr-argb
621 template <typename SrcColorSpace, typename DstColorSpace>
622 struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,321> {
623 using first_t = argb_t;
624 using second_t = abgr_t;
627 template <typename SrcColorSpace, typename DstColorSpace>
628 struct reduce_color_spaces {
629 using src_order_t = typename channel_order<SrcColorSpace>::type;
630 using dst_order_t = typename channel_order<DstColorSpace>::type;
631 using mapping = typename mpl::transform<src_order_t, type_to_index<dst_order_t,mpl::_1>>::type;
632 static const int mapping_val = type_vec_to_integer<mapping>::value;
634 using _first_t = typename reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,mapping_val>::first_t;
635 using _second_t = typename reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,mapping_val>::second_t;
636 using swap_t = typename mpl::and_<color_space_is_base<DstColorSpace>, mpl::not_< color_space_is_base<_second_t>>>;
638 using first_t = typename mpl::if_<swap_t, _second_t, _first_t>::type;
639 using second_t = typename mpl::if_<swap_t, _first_t, _second_t>::type;
642 // TODO: Use the old code for reduce_color_spaces above to do color layout reduction
643 template <typename SrcLayout, typename DstLayout>
644 struct reduce_color_layouts
646 using first_t = SrcLayout;
647 using second_t = DstLayout;
650 ////////////////////////////////////////////////////////
652 //// Reduce for copy_pixels
654 ////////////////////////////////////////////////////////
656 struct copy_pixels_fn;
659 // 1D reduce for copy_pixels reduces the channel to mutable and the color space to its base with same dimensions
660 template <typename View>
661 struct reduce_view_basic<copy_pixels_fn,View,true> {
663 using color_space_t = typename reduce_color_space<typename View::color_space_t>::type color_space_t; // reduce the color space
664 using layout_t = layout<color_space_t, typename View::channel_mapping_t>;
666 using type = typename derived_view_type<View, use_default, layout_t, use_default, use_default, mpl::true_>::type;
669 // Incompatible views cannot be used in copy_pixels - will throw std::bad_cast
670 template <typename V1, typename V2, bool Compatible>
671 struct reduce_copy_pixop_compat
673 using type = error_t;
676 // For compatible basic views, reduce their color spaces based on their channel mapping.
677 // Make the source immutable and the destination mutable (they should already be that way)
678 template <typename V1, typename V2>
679 struct reduce_copy_pixop_compat<V1,V2,true>
681 using layout1 = layout<typename V1::color_space_t, typename V1::channel_mapping_t>;
682 using layout2 = layout<typename V2::color_space_t, typename V2::channel_mapping_t>;
684 using L1 = typename reduce_color_layouts<layout1,layout2>::first_t;
685 using L2 = typename reduce_color_layouts<layout1,layout2>::second_t;
687 using DV1 = typename derived_view_type<V1, use_default, L1, use_default, use_default, use_default, mpl::false_>::type;
688 using DV2 = typename derived_view_type<V2, use_default, L2, use_default, use_default, use_default, mpl::true_ >::type;
690 using type = std::pair<const DV1*, const DV2*>;
693 // The general 2D version branches into compatible and incompatible views
694 template <typename V1, typename V2>
695 struct reduce_views_basic<copy_pixels_fn, V1, V2, true>
696 : public reduce_copy_pixop_compat<V1, V2, mpl::and_<views_are_compatible<V1,V2>, view_is_mutable<V2>>::value > {
699 ////////////////////////////////////////////////////////
701 //// Reduce for variant destructor (basic views have no destructor)
703 ////////////////////////////////////////////////////////
705 struct destructor_op;
706 template <typename View>
707 struct reduce_view_basic<destructor_op,View,true>
709 using type = gray8_view_t;
712 ////////////////////////////////////////////////////////
714 //// Reduce for get_dimensions (basic views and images have the same structure and the dimensions are contained at the beginning)
716 ////////////////////////////////////////////////////////
718 struct any_type_get_dimensions;
720 template <typename View>
721 struct reduce_view_basic<any_type_get_dimensions,View,true>
723 using type = gray8_view_t;
726 template <typename Img>
727 struct reduce_image_basic<any_type_get_dimensions,Img,true>
729 using type = gray8_image_t;
732 ////////////////////////////////////////////////////////
734 //// Reduce for get_num_channels (only color space matters)
736 ////////////////////////////////////////////////////////
738 struct any_type_get_num_channels;
740 template <typename View>
741 struct reduce_view_basic<any_type_get_num_channels,View,true>
743 using color_space_t = typename View::color_space_t::base;
744 using type = typename view_type<uint8_t,typename reduce_color_space<color_space_t>::type>::type;
747 template <typename Img>
748 struct reduce_image_basic<any_type_get_num_channels,Img,true>
750 using color_space_t = typename Img::color_space_t::base;
751 using type = typename image_type<uint8_t,typename reduce_color_space<color_space_t>::type>::type;
754 ////////////////////////////////////////////////////////
756 //// Reduce for resample_pixels (same as copy_pixels)
758 ////////////////////////////////////////////////////////
760 template <typename Sampler, typename MapFn> struct resample_pixels_fn;
762 template <typename S, typename M, typename V, bool IsBasic>
763 struct reduce_view_basic<resample_pixels_fn<S,M>, V, IsBasic> : public reduce_view_basic<copy_pixels_fn, V, IsBasic> {};
765 template <typename S, typename M, typename V1, typename V2, bool IsBasic>
766 struct reduce_views_basic<resample_pixels_fn<S,M>, V1, V2, IsBasic> : public reduce_views_basic<copy_pixels_fn, V1, V2, IsBasic> {};
768 ////////////////////////////////////////////////////////
770 //// Reduce for copy_and_convert_pixels
771 //// (the only reduction could be made when views are compatible and have the same mapping, planarity and stepness)
773 ////////////////////////////////////////////////////////
776 template <typename CC> class copy_and_convert_pixels_fn;
778 // the only thing for 1D reduce is making them all mutable...
779 template <typename CC, typename View, bool IsBasic>
780 struct reduce_view_basic<copy_and_convert_pixels_fn<CC>, View, IsBasic>
781 : public derived_view_type<View, use_default, use_default, use_default, use_default, mpl::true_> {
784 // For 2D reduce, if they have the same channels and color spaces (i.e. the same pixels) then copy_and_convert is just copy.
785 // In this case, reduce their common color space. In general make the first immutable and the second mutable
786 template <typename CC, typename V1, typename V2, bool AreBasic>
787 struct reduce_views_basic<copy_and_convert_pixels_fn<CC>, V1, V2, AreBasic>
789 using Same = std::is_same<typename V1::pixel_t, typename V2::pixel_t>;
791 using CsR = reduce_color_space<typename V1::color_space_t::base>;
792 using Cs1 = typename mpl::if_<Same, typename CsR::type, typename V1::color_space_t>::type;
793 using Cs2 = typename mpl::if_<Same, typename CsR::type, typename V2::color_space_t>::type;
795 using DV1 = typename derived_view_type<V1, use_default, layout<Cs1, typename V1::channel_mapping_t>, use_default, use_default, mpl::false_>::type;
796 using DV2 = typename derived_view_type<V2, use_default, layout<Cs2, typename V2::channel_mapping_t>, use_default, use_default, mpl::true_ >::type;
798 using type = std::pair<const DV1*, const DV2*>;
802 //integral_image_generator
803 //resize_clobber_image_fnobj
804 //image_default_construct_fnobj
805 //fill_converted_pixels_fn
806 //std::bind(gil::detail::copy_pixels_fn(), std::placeholders::_1, dst)
807 //std::bind(gil::detail::copy_pixels_fn(), src, std::placeholders::_1)
809 //std::bind(detail::copy_and_convert_pixels_fn(), std::placeholders::_1, dst)
810 //std::bind(detail::copy_and_convert_pixels_fn(), src, std::placeholders::_1)
811 //gil::detail::fill_pixels_fn<Value>(val)
813 //detail::copy_construct_in_place_fn<base_t>
814 //detail::equal_to_fn<typename variant<Types>::base_t>
816 //detail::any_image_get_view<typename any_image<Types>::view_t>
817 //detail::any_image_get_const_view<typename any_image<Types>::view_t>
818 //detail::flipped_up_down_view_fn<any_image_view<ViewTypes>>
819 //detail::flipped_left_right_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
820 //detail::tranposed_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
821 //detail::rotated90cw_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
822 //detail::rotated90ccw_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
823 //detail::rotated180_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
824 //detail::subimage_view_fn<any_image_view<ViewTypes>>
825 //detail::subsampled_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
826 //detail::nth_channel_view_fn<typename nth_channel_view_type<any_image_view<ViewTypes>>
827 //detail::color_converted_view_fn<DstP,typename color_convert_view_type<any_image_view<ViewTypes>, DstP>::type >
830 }} // namespace boost::gil
832 #endif // defined(BOOST_GIL_REDUCE_CODE_BLOAT)