00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef GIL_REDUCE_HPP
00013 #define GIL_REDUCE_HPP
00014
00015 #include <boost/mpl/insert_range.hpp>
00016 #include <boost/mpl/range_c.hpp>
00017 #include <boost/mpl/vector_c.hpp>
00018 #include <boost/mpl/back.hpp>
00019 #include <boost/mpl/vector.hpp>
00020 #include <boost/mpl/long.hpp>
00021 #include <boost/mpl/logical.hpp>
00022 #include <boost/mpl/transform.hpp>
00023 #include <boost/mpl/insert.hpp>
00024 #include <boost/mpl/transform.hpp>
00025
00026 #include "../../metafunctions.hpp"
00027 #include "../../typedefs.hpp"
00028 #include "dynamic_at_c.hpp"
00029
00038
00039
00040 #ifdef GIL_REDUCE_CODE_BLOAT
00041
00042
00043
00044 #define GIL_BINARY_REDUCE_LIMIT 226
00045
00046 namespace boost { namespace mpl {
00047
00056
00057 template <typename SrcTypes, typename DstTypes>
00058 struct mapping_vector {};
00059
00060 template <typename SrcTypes, typename DstTypes, long K>
00061 struct at_c<mapping_vector<SrcTypes,DstTypes>, K> {
00062 static const std::size_t value=size<DstTypes>::value - order<DstTypes, typename at_c<SrcTypes,K>::type>::type::value +1;
00063 typedef size_t<value> type;
00064 };
00065
00066 template <typename SrcTypes, typename DstTypes>
00067 struct size<mapping_vector<SrcTypes,DstTypes> > {
00068 typedef typename size<SrcTypes>::type type;
00069 static const std::size_t value=type::value;
00070 };
00071
00080
00081 namespace detail {
00082 template <typename SFirst, std::size_t NLeft>
00083 struct copy_to_vector_impl {
00084 private:
00085 typedef typename deref<SFirst>::type T;
00086 typedef typename next<SFirst>::type next;
00087 typedef typename copy_to_vector_impl<next, NLeft-1>::type rest;
00088 public:
00089 typedef typename push_front<rest, T>::type type;
00090 };
00091
00092 template <typename SFirst>
00093 struct copy_to_vector_impl<SFirst,1> {
00094 typedef vector<typename deref<SFirst>::type> type;
00095 };
00096 }
00097
00098 template <typename Src>
00099 struct copy_to_vector {
00100 typedef typename detail::copy_to_vector_impl<typename begin<Src>::type, size<Src>::value>::type type;
00101 };
00102
00103 template <>
00104 struct copy_to_vector<set<> > {
00105 typedef vector0<> type;
00106 };
00107
00108 } }
00109
00110 namespace boost { namespace gil {
00111
00112
00120
00121
00122
00123
00133
00134 template <typename Types, typename Op>
00135 struct unary_reduce_impl {
00136 typedef typename mpl::transform<Types, detail::reduce<Op, mpl::_1> >::type reduced_t;
00137 typedef typename mpl::copy<reduced_t, mpl::inserter<mpl::set<>, mpl::insert<mpl::_1,mpl::_2> > >::type unique_t;
00138 static const bool is_single=mpl::size<unique_t>::value==1;
00139 };
00140
00141 template <typename Types, typename Op, bool IsSingle=unary_reduce_impl<Types,Op>::is_single>
00142 struct unary_reduce : public unary_reduce_impl<Types,Op> {
00143 typedef typename unary_reduce_impl<Types,Op>::reduced_t reduced_t;
00144 typedef typename unary_reduce_impl<Types,Op>::unique_t unique_t;
00145
00146 static unsigned short inline map_index(std::size_t index) {
00147 typedef typename mpl::mapping_vector<reduced_t, unique_t> indices_t;
00148 return gil::at_c<indices_t, unsigned short>(index);
00149 }
00150 template <typename Bits> GIL_FORCEINLINE static typename Op::result_type applyc(const Bits& bits, std::size_t index, Op op) {
00151 return apply_operation_basec<unique_t>(bits,map_index(index),op);
00152 }
00153
00154 template <typename Bits> GIL_FORCEINLINE static typename Op::result_type apply(Bits& bits, std::size_t index, Op op) {
00155 return apply_operation_base<unique_t>(bits,map_index(index),op);
00156 }
00157 };
00158
00159 template <typename Types, typename Op>
00160 struct unary_reduce<Types,Op,true> : public unary_reduce_impl<Types,Op> {
00161 typedef typename unary_reduce_impl<Types,Op>::unique_t unique_t;
00162 static unsigned short inline map_index(std::size_t index) { return 0; }
00163
00164 template <typename Bits> GIL_FORCEINLINE static typename Op::result_type applyc(const Bits& bits, std::size_t index, Op op) {
00165 return op(*gil_reinterpret_cast_c<const typename mpl::front<unique_t>::type*>(&bits));
00166 }
00167
00168 template <typename Bits> GIL_FORCEINLINE static typename Op::result_type apply(Bits& bits, std::size_t index, Op op) {
00169 return op(*gil_reinterpret_cast<typename mpl::front<unique_t>::type*>(&bits));
00170 }
00171 };
00172
00173
00186
00187 namespace detail {
00188 struct pair_generator {
00189 template <typename Vec2> struct apply {
00190 typedef std::pair<const typename mpl::at_c<Vec2,0>::type*, const typename mpl::at_c<Vec2,1>::type*> type;
00191 };
00192 };
00193
00194
00195 template <typename Unary1, typename Unary2, typename Op, bool IsComplex>
00196 struct binary_reduce_impl {
00197
00198 typedef typename mpl::copy_to_vector<typename Unary1::unique_t>::type vec1_types;
00199 typedef typename mpl::copy_to_vector<typename Unary2::unique_t>::type vec2_types;
00200
00201 typedef mpl::cross_vector<mpl::vector2<vec1_types, vec2_types>, pair_generator> BIN_TYPES;
00202 typedef unary_reduce<BIN_TYPES,Op> bin_reduced_t;
00203
00204 static unsigned short inline map_index(std::size_t index1, std::size_t index2) {
00205 unsigned short r1=Unary1::map_index(index1);
00206 unsigned short r2=Unary2::map_index(index2);
00207 return bin_reduced_t::map_index(r2*mpl::size<vec1_types>::value + r1);
00208 }
00209 public:
00210 typedef typename bin_reduced_t::unique_t unique_t;
00211
00212 template <typename Bits1, typename Bits2>
00213 static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
00214 std::pair<const void*,const void*> pr(&bits1, &bits2);
00215 return apply_operation_basec<unique_t>(pr, map_index(index1,index2),op);
00216 }
00217 };
00218
00219
00220 template <typename Unary1, typename Unary2, typename Op>
00221 struct binary_reduce_impl<Unary1,Unary2,Op,true> {
00222 template <typename Bits1, typename Bits2>
00223 static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
00224 return apply_operation_base<Unary1::unique_t,Unary2::unique_t>(bits1, index1, bits2, index2, op);
00225 }
00226 };
00227 }
00228
00229
00230 template <typename Types1, typename Types2, typename Op>
00231 struct binary_reduce {
00232
00233 typedef unary_reduce<Types1,Op> unary1_t;
00234 typedef unary_reduce<Types2,Op> unary2_t;
00235
00236 static const std::size_t CROSS_SIZE = mpl::size<typename unary1_t::unique_t>::value *
00237 mpl::size<typename unary2_t::unique_t>::value;
00238
00239 typedef detail::binary_reduce_impl<unary1_t,unary2_t,Op, (CROSS_SIZE>GIL_BINARY_REDUCE_LIMIT)> impl;
00240 public:
00241 template <typename Bits1, typename Bits2>
00242 static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
00243 return impl::apply(bits1,index1,bits2,index2,op);
00244 }
00245 };
00246
00247 template <typename Types, typename UnaryOp>
00248 GIL_FORCEINLINE typename UnaryOp::result_type apply_operation(variant<Types>& arg, UnaryOp op) {
00249 return unary_reduce<Types,UnaryOp>::template apply(arg._bits, arg._index ,op);
00250 }
00251
00252 template <typename Types, typename UnaryOp>
00253 GIL_FORCEINLINE typename UnaryOp::result_type apply_operation(const variant<Types>& arg, UnaryOp op) {
00254 return unary_reduce<Types,UnaryOp>::template applyc(arg._bits, arg._index ,op);
00255 }
00256
00257 template <typename Types1, typename Types2, typename BinaryOp>
00258 GIL_FORCEINLINE typename BinaryOp::result_type apply_operation(const variant<Types1>& arg1, const variant<Types2>& arg2, BinaryOp op) {
00259 return binary_reduce<Types1,Types2,BinaryOp>::template apply(arg1._bits, arg1._index, arg2._bits, arg2._index, op);
00260 }
00261
00262 #undef GIL_BINARY_REDUCE_LIMIT
00263
00264 } }
00265
00266
00267 namespace boost { namespace mpl {
00286
00287 template <typename VecOfVecs, typename TypeGen>
00288 struct cross_vector {};
00289
00292 template <typename VecOfVecs, typename TypeGen, std::size_t K>
00293 struct cross_iterator {
00294 typedef mpl::random_access_iterator_tag category;
00295 };
00296
00300
00306 template <typename VecOfVecs, typename TypeGen, std::size_t K>
00307 struct deref<cross_iterator<VecOfVecs,TypeGen,K> > {
00308 private:
00309 typedef typename detail::select_subvector_c<VecOfVecs, K>::type DerefTypes;
00310 public:
00311 typedef typename TypeGen::template apply<DerefTypes>::type type;
00312 };
00313
00316 template <typename VecOfVecs, typename TypeGen, std::size_t K>
00317 struct next<cross_iterator<VecOfVecs,TypeGen,K> > {
00318 typedef cross_iterator<VecOfVecs,TypeGen,K+1> type;
00319 };
00320
00323 template <typename VecOfVecs, typename TypeGen, std::size_t K>
00324 struct prior<cross_iterator<VecOfVecs,TypeGen,K> > {
00325 typedef cross_iterator<VecOfVecs,TypeGen,K-1> type;
00326 };
00327
00330 template <typename VecOfVecs, typename TypeGen, std::size_t K, typename Distance>
00331 struct advance<cross_iterator<VecOfVecs,TypeGen,K>, Distance > {
00332 typedef cross_iterator<VecOfVecs,TypeGen,K+Distance::value> type;
00333 };
00334
00337
00338 template <typename VecOfVecs, typename TypeGen, std::size_t K1, std::size_t K2>
00339 struct distance<cross_iterator<VecOfVecs,TypeGen,K1>, cross_iterator<VecOfVecs,TypeGen,K2> > {
00340 typedef size_t<K2-K1> type;
00341 };
00342
00348 template <typename VecOfVecs, typename TypeGen>
00349 struct size<cross_vector<VecOfVecs,TypeGen> > {
00350 typedef typename fold<VecOfVecs, size_t<1>, times<_1, size<_2> > >::type type;
00351 static const std::size_t value=type::value;
00352 };
00353
00356 template <typename VecOfVecs, typename TypeGen>
00357 struct empty<cross_vector<VecOfVecs,TypeGen> > {
00358 typedef typename empty<VecOfVecs>::type type;
00359 };
00360
00363 template <typename VecOfVecs, typename TypeGen, typename K>
00364 struct at<cross_vector<VecOfVecs,TypeGen>, K> {
00365 private:
00366 typedef cross_iterator<VecOfVecs,TypeGen,K::value> KthIterator;
00367 public:
00368 typedef typename deref<KthIterator>::type type;
00369 };
00370
00373 template <typename VecOfVecs, typename TypeGen>
00374 struct begin<cross_vector<VecOfVecs,TypeGen> > {
00375 typedef cross_iterator<VecOfVecs,TypeGen,0> type;
00376 };
00377
00380 template <typename VecOfVecs, typename TypeGen>
00381 struct end<cross_vector<VecOfVecs,TypeGen> > {
00382 private:
00383 typedef cross_vector<VecOfVecs,TypeGen> this_t;
00384 public:
00385 typedef cross_iterator<VecOfVecs,TypeGen,size<this_t>::value> type;
00386 };
00387
00390 template <typename VecOfVecs, typename TypeGen>
00391 struct front<cross_vector<VecOfVecs,TypeGen> > {
00392 private:
00393 typedef cross_vector<VecOfVecs,TypeGen> this_t;
00394 public:
00395 typedef typename deref<typename begin<this_t>::type>::type type;
00396 };
00397
00400 template <typename VecOfVecs, typename TypeGen>
00401 struct back<cross_vector<VecOfVecs,TypeGen> > {
00402 private:
00403 typedef cross_vector<VecOfVecs,TypeGen> this_t;
00404 typedef typename size<this_t>::type size;
00405 typedef typename minus<size, size_t<1> >::type last_index;
00406 public:
00407 typedef typename at<this_t, last_index>::type type;
00408 };
00409
00412 template <typename VecOfVecs, typename TypeGen, typename OPP>
00413 struct transform<cross_vector<VecOfVecs,TypeGen>, OPP > {
00414 typedef typename lambda<OPP>::type Op;
00415 struct adapter {
00416 template <typename Elements>
00417 struct apply {
00418 typedef typename TypeGen::template apply<Elements>::type orig_t;
00419 typedef typename Op::template apply<orig_t>::type type;
00420 };
00421 };
00422 typedef cross_vector<VecOfVecs, adapter > type;
00423 };
00424
00425 } }
00426
00427 namespace boost { namespace gil {
00428
00429 template <typename Types, typename T> struct type_to_index;
00430 template <typename V> struct view_is_basic;
00431 struct rgb_t;
00432 struct lab_t;
00433 struct hsb_t;
00434 struct cmyk_t;
00435 struct rgba_t;
00436 struct error_t;
00437
00438
00439 namespace detail {
00445 template <typename Op, typename T>
00446 struct reduce {
00447 typedef T type;
00448 };
00449
00456
00457 template <typename Op, typename View, bool IsBasic>
00458 struct reduce_view_basic {
00459 typedef View type;
00460 };
00461
00462 template <typename Op, typename Loc>
00463 struct reduce<Op, image_view<Loc> >
00464 : public reduce_view_basic<Op,image_view<Loc>,view_is_basic<image_view<Loc> >::value> {};
00465
00472
00473 template <typename Op, typename Img, bool IsBasic>
00474 struct reduce_image_basic {
00475 typedef Img type;
00476 };
00477
00478 template <typename Op, typename V, typename Alloc>
00479 struct reduce<Op, image<V,Alloc> > : public reduce_image_basic<Op,image<V,Alloc>,image_is_basic<image<V,Alloc> >::value > {};
00480
00487
00488 template <typename Op, typename V1, typename V2, bool AreBasic>
00489 struct reduce_views_basic {
00490 typedef std::pair<const V1*, const V2*> type;
00491 };
00492
00493 template <typename Op, typename L1, typename L2>
00494 struct reduce<Op, std::pair<const image_view<L1>*, const image_view<L2>*> >
00495 : public reduce_views_basic<Op,image_view<L1>,image_view<L2>,
00496 mpl::and_<view_is_basic<image_view<L1> >, view_is_basic<image_view<L2> > >::value >
00497 {};
00498
00499
00505
00506 template <typename Cs>
00507 struct reduce_color_space {
00508 typedef Cs type;
00509 };
00510
00511 template <> struct reduce_color_space<lab_t> { typedef rgb_t type; };
00512 template <> struct reduce_color_space<hsb_t> { typedef rgb_t type; };
00513 template <> struct reduce_color_space<cmyk_t> { typedef rgba_t type; };
00514
00515
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 template <typename SrcLayout, typename DstLayout>
00622 struct reduce_color_layouts {
00623 typedef SrcLayout first_t;
00624 typedef DstLayout second_t;
00625 };
00626
00632
00633 struct copy_pixels_fn;
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 template <typename V1, typename V2, bool Compatible>
00648 struct reduce_copy_pixop_compat {
00649 typedef error_t type;
00650 };
00651
00652
00653
00654 template <typename V1, typename V2>
00655 struct reduce_copy_pixop_compat<V1,V2,true> {
00656 typedef layout<typename V1::color_space_t, typename V1::channel_mapping_t> layout1;
00657 typedef layout<typename V2::color_space_t, typename V2::channel_mapping_t> layout2;
00658
00659 typedef typename reduce_color_layouts<layout1,layout2>::first_t L1;
00660 typedef typename reduce_color_layouts<layout1,layout2>::second_t L2;
00661
00662 typedef typename derived_view_type<V1, use_default, L1, use_default, use_default, use_default, mpl::false_>::type DV1;
00663 typedef typename derived_view_type<V2, use_default, L2, use_default, use_default, use_default, mpl::true_ >::type DV2;
00664
00665 typedef std::pair<const DV1*, const DV2*> type;
00666 };
00667
00668
00669 template <typename V1, typename V2>
00670 struct reduce_views_basic<copy_pixels_fn, V1, V2, true>
00671 : public reduce_copy_pixop_compat<V1, V2, mpl::and_<views_are_compatible<V1,V2>, view_is_mutable<V2> >::value > {
00672 };
00673
00679
00680 struct destructor_op;
00681 template <typename View> struct reduce_view_basic<destructor_op,View,true> { typedef gray8_view_t type; };
00682
00688
00689 struct any_type_get_dimensions;
00690 template <typename View> struct reduce_view_basic<any_type_get_dimensions,View,true> { typedef gray8_view_t type; };
00691 template <typename Img> struct reduce_image_basic<any_type_get_dimensions,Img,true> { typedef gray8_image_t type; };
00692
00698
00699 struct any_type_get_num_channels;
00700 template <typename View> struct reduce_view_basic<any_type_get_num_channels,View,true> {
00701 typedef typename View::color_space_t::base Cs;
00702 typedef typename view_type<bits8,typename reduce_color_space<Cs>::type>::type type;
00703 };
00704 template <typename Img> struct reduce_image_basic<any_type_get_num_channels,Img,true> {
00705 typedef typename Img::color_space_t::base Cs;
00706 typedef typename image_type<bits8,typename reduce_color_space<Cs>::type>::type type;
00707 };
00708
00714
00715 template <typename Sampler, typename MapFn> struct resample_pixels_fn;
00716
00717 template <typename S, typename M, typename V, bool IsBasic>
00718 struct reduce_view_basic<resample_pixels_fn<S,M>, V, IsBasic> : public reduce_view_basic<copy_pixels_fn, V, IsBasic> {};
00719
00720 template <typename S, typename M, typename V1, typename V2, bool IsBasic>
00721 struct reduce_views_basic<resample_pixels_fn<S,M>, V1, V2, IsBasic> : public reduce_views_basic<copy_pixels_fn, V1, V2, IsBasic> {};
00722
00729
00730
00731 template <typename CC> class copy_and_convert_pixels_fn;
00732
00733
00734 template <typename CC, typename View, bool IsBasic>
00735 struct reduce_view_basic<copy_and_convert_pixels_fn<CC>, View, IsBasic>
00736 : public derived_view_type<View, use_default, use_default, use_default, use_default, mpl::true_> {
00737 };
00738
00739
00740
00741 template <typename CC, typename V1, typename V2, bool AreBasic>
00742 struct reduce_views_basic<copy_and_convert_pixels_fn<CC>, V1, V2, AreBasic> {
00743 typedef is_same<typename V1::pixel_t, typename V2::pixel_t> Same;
00744
00745 typedef reduce_color_space<typename V1::color_space_t::base> CsR;
00746 typedef typename mpl::if_<Same, typename CsR::type, typename V1::color_space_t>::type Cs1;
00747 typedef typename mpl::if_<Same, typename CsR::type, typename V2::color_space_t>::type Cs2;
00748
00749 typedef typename derived_view_type<V1, use_default, layout<Cs1, typename V1::channel_mapping_t>, use_default, use_default, mpl::false_>::type DV1;
00750 typedef typename derived_view_type<V2, use_default, layout<Cs2, typename V2::channel_mapping_t>, use_default, use_default, mpl::true_ >::type DV2;
00751
00752 typedef std::pair<const DV1*, const DV2*> type;
00753 };
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782 }
00783
00784 } }
00785
00786 #endif // GIL_REDUCE_CODE_BLOAT
00787
00788
00789 #endif