00001
00002
00003
00004
00005
00006
00007
00008
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
00229 template <int N>
00230 struct element_recursion {
00231
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
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
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
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
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
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
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
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
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
00383 template<> struct element_recursion<0> {
00384
00385 template <typename P1,typename P2>
00386 static bool static_equal(const P1&, const P2&) { return true; }
00387
00388 template <typename P1,typename P2>
00389 static void static_copy(const P1&, const P2&) {}
00390
00391 template <typename P, typename T2>
00392 static void static_fill(const P&, T2) {}
00393
00394 template <typename Dst,typename Op>
00395 static void static_generate(const Dst&,Op){}
00396
00397 template <typename P1,typename Op>
00398 static Op static_for_each(const P1&,Op op){return op;}
00399
00400 template <typename P1,typename P2,typename Op>
00401 static Op static_for_each(const P1&,const P2&,Op op){return op;}
00402
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
00406 template <typename P1,typename Dst,typename Op>
00407 static Op static_transform(const P1&,const Dst&,Op op){return op;}
00408
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
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
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
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 }
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
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
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
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
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
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 } }
00695
00696 #endif