color_base_algorithm.hppGo 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 1.5.6 |