color_base_algorithm.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2007 Adobe Systems Incorporated
00003    
00004     Use, modification and distribution are subject to the Boost Software License,
00005     Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
00006     http://www.boost.org/LICENSE_1_0.txt).
00007 
00008     See http://opensource.adobe.com/gil for most recent version including documentation.
00009 */
00010 
00011 /*************************************************************************************************/
00012 
00013 #ifndef GIL_COLOR_BASE_ALGORITHM_HPP
00014 #define GIL_COLOR_BASE_ALGORITHM_HPP
00015 
00024 
00025 #include <algorithm>
00026 #include <boost/type_traits.hpp>
00027 #include <boost/utility/enable_if.hpp>
00028 #include <boost/mpl/contains.hpp>
00029 #include <boost/mpl/at.hpp>
00030 #include "gil_config.hpp"
00031 #include "gil_concept.hpp"
00032 #include "utilities.hpp"
00033 
00034 namespace boost { namespace gil {
00035 
00036 
00042 
00055 
00056 
00057 template <typename ColorBase>
00058 struct size : public mpl::size<typename ColorBase::layout_t::color_space_t> {};
00059 
00065 
00092 
00093 
00094 template <typename ColorBase, int K> struct kth_semantic_element_type {
00095     BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c<typename ColorBase::layout_t::channel_mapping_t,K>::type::value));
00096     typedef typename kth_element_type<ColorBase, semantic_index>::type type;
00097 };
00098 
00101 template <typename ColorBase, int K> struct kth_semantic_element_reference_type {
00102     BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c<typename ColorBase::layout_t::channel_mapping_t,K>::type::value));
00103     typedef typename kth_element_reference_type<ColorBase,semantic_index>::type type;
00104     static type       get(ColorBase& cb) { return at_c<semantic_index>(cb); }
00105 };
00106 
00109 template <typename ColorBase, int K> struct kth_semantic_element_const_reference_type {
00110     BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c<typename ColorBase::layout_t::channel_mapping_t,K>::type::value));
00111     typedef typename kth_element_const_reference_type<ColorBase,semantic_index>::type type;
00112     static type       get(const ColorBase& cb) { return at_c<semantic_index>(cb); }
00113 };
00114 
00117 template <int K, typename ColorBase> inline
00118 typename disable_if<is_const<ColorBase>,typename kth_semantic_element_reference_type<ColorBase,K>::type>::type
00119 semantic_at_c(ColorBase& p) { 
00120     return kth_semantic_element_reference_type<ColorBase,K>::get(p); 
00121 }
00122 
00125 template <int K, typename ColorBase> inline
00126 typename kth_semantic_element_const_reference_type<ColorBase,K>::type
00127 semantic_at_c(const ColorBase& p) { 
00128     return kth_semantic_element_const_reference_type<ColorBase,K>::get(p); 
00129 }
00130 
00136 
00156 
00157 
00158 template <typename ColorBase, typename Color>
00159 struct contains_color : public mpl::contains<typename ColorBase::layout_t::color_space_t,Color> {};
00160 
00161 template <typename ColorBase, typename Color>
00162 struct color_index_type : public detail::type_to_index<typename ColorBase::layout_t::color_space_t,Color> {};
00163 
00166 template <typename ColorBase, typename Color>
00167 struct color_element_type : public kth_semantic_element_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
00168 
00171 template <typename ColorBase, typename Color>
00172 struct color_element_reference_type : public kth_semantic_element_reference_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
00173 
00176 template <typename ColorBase, typename Color>
00177 struct color_element_const_reference_type : public kth_semantic_element_const_reference_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
00178 
00181 template <typename ColorBase, typename Color> 
00182 typename color_element_reference_type<ColorBase,Color>::type get_color(ColorBase& cb, Color=Color()) {
00183     return color_element_reference_type<ColorBase,Color>::get(cb);
00184 }
00185 
00188 template <typename ColorBase, typename Color> 
00189 typename color_element_const_reference_type<ColorBase,Color>::type get_color(const ColorBase& cb, Color=Color()) {
00190     return color_element_const_reference_type<ColorBase,Color>::get(cb);
00191 }
00192 
00198 
00210 
00211 
00212 template <typename ColorBase>
00213 struct element_type : public kth_element_type<ColorBase, 0> {};
00214 
00217 template <typename ColorBase>
00218 struct element_reference_type : public kth_element_reference_type<ColorBase, 0> {};
00219 
00222 template <typename ColorBase>
00223 struct element_const_reference_type : public kth_element_const_reference_type<ColorBase, 0> {};
00224 
00225 
00226 namespace detail {
00227 
00228 // compile-time recursion for per-element operations on color bases
00229 template <int N>
00230 struct element_recursion {
00231     //static_equal
00232     template <typename P1,typename P2>
00233     static bool static_equal(const P1& p1, const P2& p2) { 
00234         return element_recursion<N-1>::static_equal(p1,p2) &&
00235                semantic_at_c<N-1>(p1)==semantic_at_c<N-1>(p2); 
00236     }
00237     //static_copy
00238     template <typename P1,typename P2>
00239     static void static_copy(const P1& p1, P2& p2) {
00240         element_recursion<N-1>::static_copy(p1,p2);
00241         semantic_at_c<N-1>(p2)=semantic_at_c<N-1>(p1);
00242     }
00243     //static_fill
00244     template <typename P,typename T2>
00245     static void static_fill(P& p, T2 v) {
00246         element_recursion<N-1>::static_fill(p,v);
00247         semantic_at_c<N-1>(p)=v;
00248     }
00249     //static_generate
00250     template <typename Dst,typename Op> 
00251     static void static_generate(Dst& dst, Op op) {
00252         element_recursion<N-1>::static_generate(dst,op);
00253         semantic_at_c<N-1>(dst)=op();
00254     }
00255     //static_for_each with one source
00256     template <typename P1,typename Op> 
00257     static Op static_for_each(P1& p1, Op op) {
00258         Op op2(element_recursion<N-1>::static_for_each(p1,op));
00259         op2(semantic_at_c<N-1>(p1));
00260         return op2;
00261     }
00262     template <typename P1,typename Op> 
00263     static Op static_for_each(const P1& p1, Op op) {
00264         Op op2(element_recursion<N-1>::static_for_each(p1,op));
00265         op2(semantic_at_c<N-1>(p1));
00266         return op2;
00267     }
00268     //static_for_each with two sources
00269     template <typename P1,typename P2,typename Op> 
00270     static Op static_for_each(P1& p1, P2& p2, Op op) {
00271         Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
00272         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
00273         return op2;
00274     }
00275     template <typename P1,typename P2,typename Op> 
00276     static Op static_for_each(P1& p1, const P2& p2, Op op) {
00277         Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
00278         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
00279         return op2;
00280     }
00281     template <typename P1,typename P2,typename Op> 
00282     static Op static_for_each(const P1& p1, P2& p2, Op op) {
00283         Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
00284         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
00285         return op2;
00286     }
00287     template <typename P1,typename P2,typename Op> 
00288     static Op static_for_each(const P1& p1, const P2& p2, Op op) {
00289         Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
00290         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
00291         return op2;
00292     }
00293     //static_for_each with three sources
00294     template <typename P1,typename P2,typename P3,typename Op>
00295     static Op static_for_each(P1& p1, P2& p2, P3& p3, Op op) {
00296         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00297         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
00298         return op2;
00299     }
00300     template <typename P1,typename P2,typename P3,typename Op>
00301     static Op static_for_each(P1& p1, P2& p2, const P3& p3, Op op) {
00302         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00303         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
00304         return op2;
00305     }
00306     template <typename P1,typename P2,typename P3,typename Op>
00307     static Op static_for_each(P1& p1, const P2& p2, P3& p3, Op op) {
00308         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00309         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
00310         return op2;
00311     }
00312     template <typename P1,typename P2,typename P3,typename Op>
00313     static Op static_for_each(P1& p1, const P2& p2, const P3& p3, Op op) {
00314         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00315         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
00316         return op2;
00317     }
00318     template <typename P1,typename P2,typename P3,typename Op>
00319     static Op static_for_each(const P1& p1, P2& p2, P3& p3, Op op) {
00320         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00321         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
00322         return op2;
00323     }
00324     template <typename P1,typename P2,typename P3,typename Op>
00325     static Op static_for_each(const P1& p1, P2& p2, const P3& p3, Op op) {
00326         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00327         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
00328         return op2;
00329     }
00330     template <typename P1,typename P2,typename P3,typename Op>
00331     static Op static_for_each(const P1& p1, const P2& p2, P3& p3, Op op) {
00332         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00333         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
00334         return op2;
00335     }
00336     template <typename P1,typename P2,typename P3,typename Op>
00337     static Op static_for_each(const P1& p1, const P2& p2, const P3& p3, Op op) {
00338         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
00339         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
00340         return op2;
00341     }
00342     //static_transform with one source
00343     template <typename P1,typename Dst,typename Op> 
00344     static Op static_transform(P1& src, Dst& dst, Op op) {
00345         Op op2(element_recursion<N-1>::static_transform(src,dst,op));
00346         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src));
00347         return op2;
00348     }
00349     template <typename P1,typename Dst,typename Op> 
00350     static Op static_transform(const P1& src, Dst& dst, Op op) {
00351         Op op2(element_recursion<N-1>::static_transform(src,dst,op));
00352         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src));
00353         return op2;
00354     }
00355     //static_transform with two sources
00356     template <typename P1,typename P2,typename Dst,typename Op>
00357     static Op static_transform(P1& src1, P2& src2, Dst& dst, Op op) {
00358         Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
00359         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2));
00360         return op2;
00361     }
00362     template <typename P1,typename P2,typename Dst,typename Op>
00363     static Op static_transform(P1& src1, const P2& src2, Dst& dst, Op op) {
00364         Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
00365         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2));
00366         return op2;
00367     }
00368     template <typename P1,typename P2,typename Dst,typename Op>
00369     static Op static_transform(const P1& src1, P2& src2, Dst& dst, Op op) {
00370         Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
00371         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2));
00372         return op2;
00373     }
00374     template <typename P1,typename P2,typename Dst,typename Op>
00375     static Op static_transform(const P1& src1, const P2& src2, Dst& dst, Op op) {
00376         Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
00377         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2));
00378         return op2;
00379     }
00380 };
00381 
00382 // Termination condition of the compile-time recursion for element operations on a color base
00383 template<> struct element_recursion<0> {
00384     //static_equal
00385     template <typename P1,typename P2>
00386     static bool static_equal(const P1&, const P2&) { return true; }
00387     //static_copy
00388     template <typename P1,typename P2>
00389     static void static_copy(const P1&, const P2&) {}
00390     //static_fill
00391     template <typename P, typename T2>
00392     static void static_fill(const P&, T2) {}
00393     //static_generate
00394     template <typename Dst,typename Op>
00395     static void static_generate(const Dst&,Op){}
00396     //static_for_each with one source
00397     template <typename P1,typename Op>
00398     static Op static_for_each(const P1&,Op op){return op;}
00399     //static_for_each with two sources
00400     template <typename P1,typename P2,typename Op>
00401     static Op static_for_each(const P1&,const P2&,Op op){return op;}
00402     //static_for_each with three sources
00403     template <typename P1,typename P2,typename P3,typename Op>
00404     static Op static_for_each(const P1&,const P2&,const P3&,Op op){return op;}
00405     //static_transform with one source
00406     template <typename P1,typename Dst,typename Op>
00407     static Op static_transform(const P1&,const Dst&,Op op){return op;}
00408     //static_transform with two sources
00409     template <typename P1,typename P2,typename Dst,typename Op>
00410     static Op static_transform(const P1&,const P2&,const Dst&,Op op){return op;}
00411 };
00412 
00413 // std::min and std::max don't have the mutable overloads...
00414 template <typename Q> inline const Q& mutable_min(const Q& x, const Q& y) { return x<y ? x : y; }
00415 template <typename Q> inline       Q& mutable_min(      Q& x,       Q& y) { return x<y ? x : y; }
00416 template <typename Q> inline const Q& mutable_max(const Q& x, const Q& y) { return x<y ? y : x; }
00417 template <typename Q> inline       Q& mutable_max(      Q& x,       Q& y) { return x<y ? y : x; }
00418 
00419 
00420 // compile-time recursion for min/max element
00421 template <int N>
00422 struct min_max_recur {
00423     template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) {
00424         return mutable_max(min_max_recur<N-1>::max_(p),semantic_at_c<N-1>(p));
00425     }    
00426     template <typename P> static typename element_reference_type<P>::type       max_(      P& p) {
00427         return mutable_max(min_max_recur<N-1>::max_(p),semantic_at_c<N-1>(p));
00428     }    
00429     template <typename P> static typename element_const_reference_type<P>::type min_(const P& p) {
00430         return mutable_min(min_max_recur<N-1>::min_(p),semantic_at_c<N-1>(p));
00431     }    
00432     template <typename P> static typename element_reference_type<P>::type       min_(      P& p) {
00433         return mutable_min(min_max_recur<N-1>::min_(p),semantic_at_c<N-1>(p));
00434     }    
00435 };
00436 
00437 // termination condition of the compile-time recursion for min/max element
00438 template <>
00439 struct min_max_recur<1> {
00440     template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) { return semantic_at_c<0>(p); }
00441     template <typename P> static typename element_reference_type<P>::type       max_(      P& p) { return semantic_at_c<0>(p); }
00442     template <typename P> static typename element_const_reference_type<P>::type min_(const P& p) { return semantic_at_c<0>(p); }
00443     template <typename P> static typename element_reference_type<P>::type       min_(      P& p) { return semantic_at_c<0>(p); }
00444 };
00445 }  // namespace detail
00446 
00447 
00463 template <typename P>
00464 GIL_FORCEINLINE
00465 typename element_const_reference_type<P>::type static_max(const P& p) { return detail::min_max_recur<size<P>::value>::max_(p); }
00466 
00467 template <typename P>
00468 GIL_FORCEINLINE
00469 typename element_reference_type<P>::type       static_max(      P& p) { return detail::min_max_recur<size<P>::value>::max_(p); }
00470 
00471 template <typename P>
00472 GIL_FORCEINLINE
00473 typename element_const_reference_type<P>::type static_min(const P& p) { return detail::min_max_recur<size<P>::value>::min_(p); }
00474 
00475 template <typename P>
00476 GIL_FORCEINLINE
00477 typename element_reference_type<P>::type       static_min(      P& p) { return detail::min_max_recur<size<P>::value>::min_(p); }
00479 
00497 template <typename P1,typename P2>
00498 GIL_FORCEINLINE
00499 bool static_equal(const P1& p1, const P2& p2) { return detail::element_recursion<size<P1>::value>::static_equal(p1,p2); }
00500 
00502 
00520 template <typename Src,typename Dst>
00521 GIL_FORCEINLINE
00522 void static_copy(const Src& src, Dst& dst) {  detail::element_recursion<size<Dst>::value>::static_copy(src,dst); }
00523 
00525 
00539 template <typename P,typename V>
00540 GIL_FORCEINLINE
00541 void static_fill(P& p, const V& v) {  detail::element_recursion<size<P>::value>::static_fill(p,v); }
00543 
00565 template <typename P1,typename Op>
00566 GIL_FORCEINLINE
00567 void static_generate(P1& dst,Op op)                      { detail::element_recursion<size<P1>::value>::static_generate(dst,op); }
00569 
00598 //static_transform with one source
00599 template <typename Src,typename Dst,typename Op>
00600 GIL_FORCEINLINE
00601 Op static_transform(Src& src,Dst& dst,Op op)              { return detail::element_recursion<size<Dst>::value>::static_transform(src,dst,op); }
00602 template <typename Src,typename Dst,typename Op>
00603 GIL_FORCEINLINE
00604 Op static_transform(const Src& src,Dst& dst,Op op)              { return detail::element_recursion<size<Dst>::value>::static_transform(src,dst,op); }
00605 //static_transform with two sources
00606 template <typename P2,typename P3,typename Dst,typename Op>
00607 GIL_FORCEINLINE
00608 Op static_transform(P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
00609 template <typename P2,typename P3,typename Dst,typename Op>
00610 GIL_FORCEINLINE
00611 Op static_transform(P2& p2,const P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
00612 template <typename P2,typename P3,typename Dst,typename Op>
00613 GIL_FORCEINLINE
00614 Op static_transform(const P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
00615 template <typename P2,typename P3,typename Dst,typename Op>
00616 GIL_FORCEINLINE
00617 Op static_transform(const P2& p2,const P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
00619 
00647 //static_for_each with one source
00648 template <typename P1,typename Op>
00649 GIL_FORCEINLINE
00650 Op static_for_each(      P1& p1, Op op)                          { return detail::element_recursion<size<P1>::value>::static_for_each(p1,op); }
00651 template <typename P1,typename Op>
00652 GIL_FORCEINLINE
00653 Op static_for_each(const P1& p1, Op op)                          { return detail::element_recursion<size<P1>::value>::static_for_each(p1,op); }
00654 //static_for_each with two sources
00655 template <typename P1,typename P2,typename Op>
00656 GIL_FORCEINLINE
00657 Op static_for_each(P1& p1,      P2& p2, Op op)             { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
00658 template <typename P1,typename P2,typename Op>
00659 GIL_FORCEINLINE
00660 Op static_for_each(P1& p1,const P2& p2, Op op)             { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
00661 template <typename P1,typename P2,typename Op>
00662 GIL_FORCEINLINE
00663 Op static_for_each(const P1& p1,      P2& p2, Op op)             { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
00664 template <typename P1,typename P2,typename Op>
00665 GIL_FORCEINLINE
00666 Op static_for_each(const P1& p1,const P2& p2, Op op)             { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
00667 //static_for_each with three sources
00668 template <typename P1,typename P2,typename P3,typename Op>
00669 GIL_FORCEINLINE
00670 Op static_for_each(P1& p1,P2& p2,P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
00671 template <typename P1,typename P2,typename P3,typename Op>
00672 GIL_FORCEINLINE
00673 Op static_for_each(P1& p1,P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
00674 template <typename P1,typename P2,typename P3,typename Op>
00675 GIL_FORCEINLINE
00676 Op static_for_each(P1& p1,const P2& p2,P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
00677 template <typename P1,typename P2,typename P3,typename Op>
00678 GIL_FORCEINLINE
00679 Op static_for_each(P1& p1,const P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
00680 template <typename P1,typename P2,typename P3,typename Op>
00681 GIL_FORCEINLINE
00682 Op static_for_each(const P1& p1,P2& p2,P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
00683 template <typename P1,typename P2,typename P3,typename Op>
00684 GIL_FORCEINLINE
00685 Op static_for_each(const P1& p1,P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
00686 template <typename P1,typename P2,typename P3,typename Op>
00687 GIL_FORCEINLINE
00688 Op static_for_each(const P1& p1,const P2& p2,P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
00689 template <typename P1,typename P2,typename P3,typename Op>
00690 GIL_FORCEINLINE
00691 Op static_for_each(const P1& p1,const P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
00693 
00694 } }  // namespace boost::gil
00695 
00696 #endif

Generated on Sat May 2 13:50:13 2009 for Generic Image Library by  doxygen 1.5.6