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 00014 #ifndef GIL_ALGORITHM_HPP 00015 #define GIL_ALGORITHM_HPP 00016 00017 #include <cassert> 00018 #include <cstddef> 00019 #include <algorithm> 00020 #include <iterator> 00021 #include <memory> 00022 #include "gil_config.hpp" 00023 #include "gil_concept.hpp" 00024 #include "color_base_algorithm.hpp" 00025 #include "image_view.hpp" 00026 #include "image_view_factory.hpp" 00027 #include "bit_aligned_pixel_iterator.hpp" 00028 00037 00038 #ifdef _MSC_VER 00039 #pragma warning(push) 00040 #pragma warning(disable : 4244) // conversion from 'gil::image<V,Alloc>::coord_t' to 'int', possible loss of data (visual studio compiler doesn't realize that the two types are the same) 00041 #endif 00042 00043 namespace boost { namespace gil { 00044 00045 //forward declarations 00046 template <typename ChannelPtr, typename ColorSpace> 00047 struct planar_pixel_iterator; 00048 template <typename Iterator> 00049 class memory_based_step_iterator; 00050 template <typename StepIterator> 00051 class memory_based_2d_locator; 00052 00053 // a tag denoting incompatible arguments 00054 struct error_t {}; 00055 00080 00081 00085 00094 template <typename Derived, typename Result=void> 00095 struct binary_operation_obj { 00096 typedef Result result_type; 00097 00098 template <typename V1, typename V2> GIL_FORCEINLINE 00099 result_type operator()(const std::pair<const V1*,const V2*>& p) const { 00100 return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type()); 00101 } 00102 00103 template <typename V1, typename V2> GIL_FORCEINLINE 00104 result_type operator()(const V1& v1, const V2& v2) const { 00105 return apply(v1, v2, typename views_are_compatible<V1,V2>::type()); 00106 } 00107 00108 result_type operator()(const error_t&) const { throw std::bad_cast(); } 00109 private: 00110 00111 // dispatch from apply overload to a function with distinct name 00112 template <typename V1, typename V2> 00113 GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::false_) const { 00114 return ((const Derived*)this)->apply_incompatible(v1,v2); 00115 } 00116 00117 // dispatch from apply overload to a function with distinct name 00118 template <typename V1, typename V2> 00119 GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::true_) const { 00120 return ((const Derived*)this)->apply_compatible(v1,v2); 00121 } 00122 00123 // function with distinct name - it can be overloaded by subclasses 00124 template <typename V1, typename V2> 00125 GIL_FORCEINLINE result_type apply_incompatible(const V1& v1, const V2& v2) const { 00126 throw std::bad_cast(); 00127 } 00128 }; 00129 } } // namespace boost::gil 00130 00136 00140 00141 namespace std { 00142 00145 template<typename T, typename Cs> 00146 GIL_FORCEINLINE boost::gil::pixel<T,Cs>* 00147 copy(boost::gil::pixel<T,Cs>* first, boost::gil::pixel<T,Cs>* last, 00148 boost::gil::pixel<T,Cs>* dst) { 00149 return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst); 00150 } 00151 00154 template<typename T, typename Cs> 00155 GIL_FORCEINLINE boost::gil::pixel<T,Cs>* 00156 copy(const boost::gil::pixel<T,Cs>* first, const boost::gil::pixel<T,Cs>* last, 00157 boost::gil::pixel<T,Cs>* dst) { 00158 return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst); 00159 } 00160 } // namespace std 00161 00162 namespace boost { namespace gil { 00163 namespace detail { 00164 template <typename I, typename O> struct copy_fn { 00165 GIL_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); } 00166 }; 00167 } // namespace detail 00168 } } // namespace boost::gil 00169 00170 namespace std { 00173 template<typename Cs, typename IC1, typename IC2> GIL_FORCEINLINE 00174 boost::gil::planar_pixel_iterator<IC2,Cs> copy(boost::gil::planar_pixel_iterator<IC1,Cs> first, boost::gil::planar_pixel_iterator<IC1,Cs> last, boost::gil::planar_pixel_iterator<IC2,Cs> dst) { 00175 boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type> >(); 00176 static_for_each(first,last,dst,boost::gil::detail::copy_fn<IC1,IC2>()); 00177 return dst+(last-first); 00178 } 00179 } // namespace std 00180 00181 namespace boost { namespace gil { 00182 namespace detail { 00185 template <typename I, typename O> 00186 struct copier_n { 00187 GIL_FORCEINLINE void operator()(I src, typename std::iterator_traits<I>::difference_type n, O dst) const { std::copy(src,src+n, dst); } 00188 }; 00189 00191 template <typename IL, typename O> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept 00192 struct copier_n<iterator_from_2d<IL>,O> { 00193 typedef typename std::iterator_traits<iterator_from_2d<IL> >::difference_type diff_t; 00194 GIL_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, O dst) const { 00195 gil_function_requires<PixelLocatorConcept<IL> >(); 00196 gil_function_requires<MutablePixelIteratorConcept<O> >(); 00197 while (n>0) { 00198 typedef typename iterator_from_2d<IL>::difference_type diff_t; 00199 diff_t l=src.width()-src.x_pos(); 00200 diff_t numToCopy=(n<l ? n:l); 00201 detail::copy_n(src.x(), numToCopy, dst); 00202 dst+=numToCopy; 00203 src+=numToCopy; 00204 n-=numToCopy; 00205 } 00206 } 00207 }; 00208 00210 template <typename I, typename OL> // I Models ConstPixelIteratorConcept, OL Models PixelLocatorConcept 00211 struct copier_n<I,iterator_from_2d<OL> > { 00212 typedef typename std::iterator_traits<I>::difference_type diff_t; 00213 GIL_FORCEINLINE void operator()(I src, diff_t n, iterator_from_2d<OL> dst) const { 00214 gil_function_requires<PixelIteratorConcept<I> >(); 00215 gil_function_requires<MutablePixelLocatorConcept<OL> >(); 00216 while (n>0) { 00217 diff_t l=dst.width()-dst.x_pos(); 00218 diff_t numToCopy=(n<l ? n:l); 00219 detail::copy_n(src, numToCopy, dst.x()); 00220 dst+=numToCopy; 00221 src+=numToCopy; 00222 n-=numToCopy; 00223 } 00224 } 00225 }; 00226 00228 template <typename IL, typename OL> 00229 struct copier_n<iterator_from_2d<IL>,iterator_from_2d<OL> > { 00230 typedef typename iterator_from_2d<IL>::difference_type diff_t; 00231 GIL_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, iterator_from_2d<OL> dst) const { 00232 gil_function_requires<PixelLocatorConcept<IL> >(); 00233 gil_function_requires<MutablePixelLocatorConcept<OL> >(); 00234 if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) { 00235 while(n-->0) { 00236 *dst++=*src++; 00237 } 00238 } 00239 while (n>0) { 00240 diff_t l=dst.width()-dst.x_pos(); 00241 diff_t numToCopy=(n<l ? n : l); 00242 detail::copy_n(src.x(), numToCopy, dst.x()); 00243 dst+=numToCopy; 00244 src+=numToCopy; 00245 n-=numToCopy; 00246 } 00247 } 00248 }; 00249 00250 template <typename SrcIterator, typename DstIterator> 00251 GIL_FORCEINLINE DstIterator copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) { 00252 typedef typename SrcIterator::x_iterator src_x_iterator; 00253 typedef typename DstIterator::x_iterator dst_x_iterator; 00254 00255 typename SrcIterator::difference_type n = last - first; 00256 00257 if (first.is_1d_traversable()) { 00258 if (dst.is_1d_traversable()) 00259 copier_n<src_x_iterator,dst_x_iterator>()(first.x(),n, dst.x()); 00260 else 00261 copier_n<src_x_iterator,DstIterator >()(first.x(),n, dst); 00262 } else { 00263 if (dst.is_1d_traversable()) 00264 copier_n<SrcIterator,dst_x_iterator>()(first,n, dst.x()); 00265 else 00266 copier_n<SrcIterator,DstIterator>()(first,n,dst); 00267 } 00268 return dst+n; 00269 } 00270 00271 } // namespace detail 00272 } } // namespace boost::gil 00273 00274 namespace std { 00277 template <typename IL, typename OL> 00278 GIL_FORCEINLINE boost::gil::iterator_from_2d<OL> copy1(boost::gil::iterator_from_2d<IL> first, boost::gil::iterator_from_2d<IL> last, boost::gil::iterator_from_2d<OL> dst) { 00279 return boost::gil::detail::copy_with_2d_iterators(first,last,dst); 00280 } 00281 00282 } // namespace std 00283 00284 namespace boost { namespace gil { 00285 00286 00289 template <typename View1, typename View2> GIL_FORCEINLINE 00290 void copy_pixels(const View1& src, const View2& dst) { 00291 assert(src.dimensions()==dst.dimensions()); 00292 detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin()); 00293 } 00294 00300 00306 00307 namespace detail { 00308 template <typename CC> 00309 class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC> > { 00310 private: 00311 CC _cc; 00312 public: 00313 typedef typename binary_operation_obj<copy_and_convert_pixels_fn<CC> >::result_type result_type; 00314 copy_and_convert_pixels_fn() {} 00315 copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {} 00316 // when the two color spaces are incompatible, a color conversion is performed 00317 template <typename V1, typename V2> GIL_FORCEINLINE 00318 result_type apply_incompatible(const V1& src, const V2& dst) const { 00319 copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst); 00320 } 00321 00322 // If the two color spaces are compatible, copy_and_convert is just copy 00323 template <typename V1, typename V2> GIL_FORCEINLINE 00324 result_type apply_compatible(const V1& src, const V2& dst) const { 00325 copy_pixels(src,dst); 00326 } 00327 }; 00328 } // namespace detail 00329 00331 template <typename V1, typename V2,typename CC> 00332 GIL_FORCEINLINE 00333 void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) { 00334 detail::copy_and_convert_pixels_fn<CC> ccp(cc); 00335 ccp(src,dst); 00336 } 00337 00338 struct default_color_converter; 00339 00341 template <typename View1, typename View2> 00342 GIL_FORCEINLINE 00343 void copy_and_convert_pixels(const View1& src, const View2& dst) { 00344 detail::copy_and_convert_pixels_fn<default_color_converter> ccp; 00345 ccp(src,dst); 00346 } 00347 00348 } } // namespace boost::gil 00349 00351 // 00352 // std::fill and gil::fill_pixels 00353 // 00355 00359 00360 00361 namespace std { 00370 template <typename IL, typename V> 00371 void fill(boost::gil::iterator_from_2d<IL> first, boost::gil::iterator_from_2d<IL> last, const V& val) { 00372 boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL> >(); 00373 if (first.is_1d_traversable()) { 00374 std::fill(first.x(), last.x(), val); 00375 } else { 00376 // fill row by row 00377 std::ptrdiff_t n=last-first; 00378 while (n>0) { 00379 std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos())); 00380 fill_n(first.x(), numToDo, val); 00381 first+=numToDo; 00382 n-=numToDo; 00383 } 00384 } 00385 } 00386 } // namespace std 00387 00388 namespace boost { namespace gil { 00389 00390 namespace detail { 00392 struct std_fill_t { 00393 template <typename It, typename P> 00394 void operator()(It first, It last, const P& p_in) { 00395 std::fill(first,last,p_in); 00396 } 00397 }; 00399 template <typename It, typename P> 00400 GIL_FORCEINLINE 00401 void fill_aux(It first, It last, const P& p, mpl::true_) { 00402 static_for_each(first,last,p,std_fill_t()); 00403 } 00405 template <typename It, typename P> 00406 GIL_FORCEINLINE 00407 void fill_aux(It first, It last, const P& p,mpl::false_) { 00408 std::fill(first,last,p); 00409 } 00410 } // namespace detail 00411 00414 template <typename View, typename Value> GIL_FORCEINLINE 00415 void fill_pixels(const View& img_view, const Value& val) { 00416 if (img_view.is_1d_traversable()) 00417 detail::fill_aux(img_view.begin().x(), img_view.end().x(), 00418 val,is_planar<View>()); 00419 else 00420 for (std::ptrdiff_t y=0; y<img_view.height(); ++y) 00421 detail::fill_aux(img_view.row_begin(y),img_view.row_end(y), 00422 val,is_planar<View>()); 00423 } 00424 00430 00434 00435 00436 namespace detail { 00437 00438 template <typename It> GIL_FORCEINLINE 00439 void destruct_range_impl(It first, It last, mpl::true_) { 00440 typedef typename std::iterator_traits<It>::value_type value_t; 00441 if (boost::has_trivial_destructor<value_t>::value) 00442 return; 00443 while (first!=last) { 00444 first->~value_t(); 00445 ++first; 00446 } 00447 } 00448 template <typename It> GIL_FORCEINLINE 00449 void destruct_range_impl(It first, It last, mpl::false_) {} 00450 00451 template <typename It> GIL_FORCEINLINE 00452 void destruct_range(It first, It last) { 00453 destruct_range_impl(first,last,typename is_pointer<It>::type()); 00454 } 00455 00456 struct std_destruct_t { 00457 template <typename It> void operator()(It first, It last) const { destruct_range(first,last); } 00458 }; 00459 00461 template <typename It> 00462 GIL_FORCEINLINE 00463 void destruct_aux(It first, It last, mpl::true_) { 00464 static_for_each(first,last,std_destruct_t()); 00465 } 00467 template <typename It> 00468 GIL_FORCEINLINE 00469 void destruct_aux(It first, It last, mpl::false_) { 00470 destruct_range(first,last); 00471 } 00472 00473 } // namespace detail 00474 00477 template <typename View> GIL_FORCEINLINE 00478 void destruct_pixels(const View& img_view) { 00479 if (img_view.is_1d_traversable()) 00480 detail::destruct_aux(img_view.begin().x(), img_view.end().x(), 00481 is_planar<View>()); 00482 else 00483 for (std::ptrdiff_t y=0; y<img_view.height(); ++y) 00484 detail::destruct_aux(img_view.row_begin(y),img_view.row_end(y), 00485 is_planar<View>()); 00486 } 00487 00493 00497 00498 00499 namespace detail { 00500 00503 template <typename It, typename P> 00504 GIL_FORCEINLINE 00505 void uninitialized_fill_aux(It first, It last, 00506 const P& p, mpl::true_) { 00507 int channel=0; 00508 try { 00509 typedef typename std::iterator_traits<It>::value_type pixel_t; 00510 while (channel < num_channels<pixel_t>::value) { 00511 std::uninitialized_fill(dynamic_at_c(first,channel), dynamic_at_c(last,channel), 00512 dynamic_at_c(p,channel)); 00513 ++channel; 00514 } 00515 } catch (...) { 00516 for (int c=0; c<channel; ++c) 00517 destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c)); 00518 throw; 00519 } 00520 } 00521 00524 template <typename It, typename P> 00525 GIL_FORCEINLINE 00526 void uninitialized_fill_aux(It first, It last, 00527 const P& p,mpl::false_) { 00528 std::uninitialized_fill(first,last,p); 00529 } 00530 00531 } // namespace detail 00532 00537 template <typename View, typename Value> 00538 void uninitialized_fill_pixels(const View& img_view, const Value& val) { 00539 if (img_view.is_1d_traversable()) 00540 detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(), 00541 val,is_planar<View>()); 00542 else { 00543 typename View::y_coord_t y; 00544 try { 00545 for (y=0; y<img_view.height(); ++y) 00546 detail::uninitialized_fill_aux(img_view.row_begin(y),img_view.row_end(y), 00547 val,is_planar<View>()); 00548 } catch(...) { 00549 for (typename View::y_coord_t y0=0; y0<y; ++y0) 00550 detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>()); 00551 throw; 00552 } 00553 } 00554 } 00555 00561 00565 00566 namespace detail { 00567 00568 template <typename It> GIL_FORCEINLINE 00569 void default_construct_range_impl(It first, It last, mpl::true_) { 00570 typedef typename std::iterator_traits<It>::value_type value_t; 00571 It first1=first; 00572 try { 00573 while (first!=last) { 00574 new (first) value_t(); 00575 ++first; 00576 } 00577 } catch (...) { 00578 destruct_range(first1,first); 00579 throw; 00580 } 00581 } 00582 00583 template <typename It> GIL_FORCEINLINE 00584 void default_construct_range_impl(It first, It last, mpl::false_) {} 00585 00586 template <typename It> GIL_FORCEINLINE 00587 void default_construct_range(It first, It last) { default_construct_range_impl(first, last, typename is_pointer<It>::type()); } 00588 00590 template <typename It> 00591 GIL_FORCEINLINE 00592 void default_construct_aux(It first, It last, mpl::true_) { 00593 int channel=0; 00594 try { 00595 typedef typename std::iterator_traits<It>::value_type pixel_t; 00596 while (channel < num_channels<pixel_t>::value) { 00597 default_construct_range(dynamic_at_c(first,channel), dynamic_at_c(last,channel)); 00598 ++channel; 00599 } 00600 } catch (...) { 00601 for (int c=0; c<channel; ++c) 00602 destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c)); 00603 throw; 00604 } 00605 } 00606 00608 template <typename It> 00609 GIL_FORCEINLINE 00610 void default_construct_aux(It first, It last, mpl::false_) { 00611 default_construct_range(first,last); 00612 } 00613 00614 template <typename View, bool IsPlanar> 00615 struct has_trivial_pixel_constructor : public boost::has_trivial_constructor<typename View::value_type> {}; 00616 template <typename View> 00617 struct has_trivial_pixel_constructor<View, true> : public boost::has_trivial_constructor<typename channel_type<View>::type> {}; 00618 00619 } // namespace detail 00620 00625 template <typename View> 00626 void default_construct_pixels(const View& img_view) { 00627 if (detail::has_trivial_pixel_constructor<View, is_planar<View>::value>::value) 00628 return; 00629 00630 if (img_view.is_1d_traversable()) 00631 detail::default_construct_aux(img_view.begin().x(), img_view.end().x(), is_planar<View>()); 00632 else { 00633 typename View::y_coord_t y; 00634 try { 00635 for (y=0; y<img_view.height(); ++y) 00636 detail::default_construct_aux(img_view.row_begin(y),img_view.row_end(y), is_planar<View>()); 00637 } catch(...) { 00638 for (typename View::y_coord_t y0=0; y0<y; ++y0) 00639 detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>()); 00640 throw; 00641 } 00642 } 00643 } 00644 00645 00651 00655 00656 namespace detail { 00657 00659 template <typename It1, typename It2> 00660 GIL_FORCEINLINE 00661 void uninitialized_copy_aux(It1 first1, It1 last1, 00662 It2 first2, mpl::true_) { 00663 int channel=0; 00664 try { 00665 typedef typename std::iterator_traits<It1>::value_type pixel_t; 00666 while (channel < num_channels<pixel_t>::value) { 00667 std::uninitialized_copy(dynamic_at_c(first1,channel), dynamic_at_c(last1,channel), dynamic_at_c(first2,channel)); 00668 ++channel; 00669 } 00670 } catch (...) { 00671 It2 last2=first2; 00672 std::advance(last2, std::distance(first1,last1)); 00673 for (int c=0; c<channel; ++c) 00674 destruct_range(dynamic_at_c(first2,c), dynamic_at_c(last2,c)); 00675 throw; 00676 } 00677 } 00679 template <typename It1, typename It2> 00680 GIL_FORCEINLINE 00681 void uninitialized_copy_aux(It1 first1, It1 last1, 00682 It2 first2,mpl::false_) { 00683 std::uninitialized_copy(first1,last1,first2); 00684 } 00685 } // namespace detail 00686 00691 template <typename View1, typename View2> 00692 void uninitialized_copy_pixels(const View1& view1, const View2& view2) { 00693 typedef mpl::bool_<is_planar<View1>::value && is_planar<View2>::value> is_planar; 00694 assert(view1.dimensions()==view2.dimensions()); 00695 if (view1.is_1d_traversable() && view2.is_1d_traversable()) 00696 detail::uninitialized_copy_aux(view1.begin().x(), view1.end().x(), 00697 view2.begin().x(), 00698 is_planar()); 00699 else { 00700 typename View1::y_coord_t y; 00701 try { 00702 for (y=0; y<view1.height(); ++y) 00703 detail::uninitialized_copy_aux(view1.row_begin(y), view1.row_end(y), 00704 view2.row_begin(y), 00705 is_planar()); 00706 } catch(...) { 00707 for (typename View1::y_coord_t y0=0; y0<y; ++y0) 00708 detail::destruct_aux(view2.row_begin(y0),view2.row_end(y0), is_planar()); 00709 throw; 00710 } 00711 } 00712 } 00713 00719 00728 00730 template <typename V, typename F> 00731 F for_each_pixel(const V& img, F fun) { 00732 if (img.is_1d_traversable()) { 00733 return std::for_each(img.begin().x(), img.end().x(), fun); 00734 } else { 00735 for (std::ptrdiff_t y=0; y<img.height(); ++y) 00736 fun = std::for_each(img.row_begin(y),img.row_end(y),fun); 00737 return fun; 00738 } 00739 } 00740 00744 00746 template <typename View, typename F> 00747 F for_each_pixel_position(const View& img, F fun) { 00748 typename View::xy_locator loc=img.xy_at(0,0); 00749 for (std::ptrdiff_t y=0; y<img.height(); ++y) { 00750 for (std::ptrdiff_t x=0; x<img.width(); ++x, ++loc.x()) 00751 fun(loc); 00752 loc.x()-=img.width(); ++loc.y(); 00753 } 00754 return fun; 00755 } 00756 00757 00763 00767 00770 template <typename View, typename F> 00771 void generate_pixels(const View& v, F fun) { 00772 if (v.is_1d_traversable()) { 00773 std::generate(v.begin().x(), v.end().x(), fun); 00774 } else { 00775 for (std::ptrdiff_t y=0; y<v.height(); ++y) 00776 std::generate(v.row_begin(y),v.row_end(y),fun); 00777 } 00778 } 00779 00785 00789 00790 template <typename I1, typename I2> GIL_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2); 00791 00792 namespace detail { 00793 00794 template <typename I1, typename I2> 00795 struct equal_n_fn { 00796 GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); } 00797 }; 00798 00801 template<typename T, typename Cs> 00802 struct equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> { 00803 GIL_FORCEINLINE bool operator()(const pixel<T,Cs>* i1, std::ptrdiff_t n, const pixel<T,Cs>* i2) const { 00804 return memcmp(i1, i2, n*sizeof(pixel<T,Cs>))==0; 00805 } 00806 }; 00807 template<typename T, typename Cs> 00808 struct equal_n_fn<pixel<T,Cs>*, pixel<T,Cs>*> : equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {}; 00809 00813 template<typename IC, typename Cs> 00814 struct equal_n_fn<planar_pixel_iterator<IC,Cs>, planar_pixel_iterator<IC,Cs> > { 00815 GIL_FORCEINLINE bool operator()(const planar_pixel_iterator<IC,Cs> i1, std::ptrdiff_t n, const planar_pixel_iterator<IC,Cs> i2) const { 00816 ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type); 00817 00818 for (std::ptrdiff_t i=0; i<mpl::size<Cs>::value; ++i) 00819 if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0) 00820 return false; 00821 return true; 00822 } 00823 }; 00824 00825 00827 template <typename Loc, typename I2> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept 00828 struct equal_n_fn<boost::gil::iterator_from_2d<Loc>,I2> { 00829 GIL_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, I2 i2) const { 00830 gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >(); 00831 gil_function_requires<boost::gil::PixelIteratorConcept<I2> >(); 00832 while (n>0) { 00833 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos()); 00834 if (!equal_n(i1.x(), num, i2)) 00835 return false; 00836 i1+=num; 00837 i2+=num; 00838 n-=num; 00839 } 00840 return true; 00841 } 00842 }; 00843 00845 template <typename I1, typename Loc> // I Models PixelIteratorConcept, OL Models PixelLocatorConcept 00846 struct equal_n_fn<I1,boost::gil::iterator_from_2d<Loc> > { 00847 GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const { 00848 gil_function_requires<boost::gil::PixelIteratorConcept<I1> >(); 00849 gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >(); 00850 while (n>0) { 00851 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos()); 00852 if (!equal_n(i1, num, i2.x())) 00853 return false; 00854 i1+=num; 00855 i2+=num; 00856 n-=num; 00857 } 00858 return true; 00859 } 00860 }; 00861 00863 template <typename Loc1, typename Loc2> 00864 struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> > { 00865 GIL_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const { 00866 gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >(); 00867 gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >(); 00868 if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) { 00869 while(n-->0) { 00870 if (*i1++!=*i2++) return false; 00871 } 00872 } 00873 while (n>0) { 00874 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos()); 00875 if (!equal_n(i1.x(), num, i2.x())) 00876 return false; 00877 i1+=num; 00878 i2+=num; 00879 n-=num; 00880 } 00881 return true; 00882 } 00883 }; 00884 } // namespace detail 00885 00886 template <typename I1, typename I2> GIL_FORCEINLINE 00887 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) { 00888 return detail::equal_n_fn<I1,I2>()(i1,n,i2); 00889 } 00890 } } // namespace boost::gil 00891 00892 namespace std { 00904 template <typename Loc1, typename Loc2> GIL_FORCEINLINE 00905 bool equal(boost::gil::iterator_from_2d<Loc1> first, boost::gil::iterator_from_2d<Loc1> last, boost::gil::iterator_from_2d<Loc2> first2) { 00906 boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >(); 00907 boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >(); 00908 std::ptrdiff_t n=last-first; 00909 if (first.is_1d_traversable()) { 00910 if (first2.is_1d_traversable()) 00911 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x()); 00912 else 00913 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2> >()(first.x(),n, first2); 00914 } else { 00915 if (first2.is_1d_traversable()) 00916 return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x()); 00917 else 00918 return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> >()(first,n,first2); 00919 } 00920 } 00921 } // namespace std 00922 00923 namespace boost { namespace gil { 00924 00927 template <typename View1, typename View2> GIL_FORCEINLINE 00928 bool equal_pixels(const View1& v1, const View2& v2) { 00929 assert(v1.dimensions()==v2.dimensions()); 00930 return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance 00931 } 00932 00938 00942 00945 template <typename View1, typename View2, typename F> GIL_FORCEINLINE 00946 F transform_pixels(const View1& src,const View2& dst, F fun) { 00947 assert(src.dimensions()==dst.dimensions()); 00948 for (std::ptrdiff_t y=0; y<src.height(); ++y) { 00949 typename View1::x_iterator srcIt=src.row_begin(y); 00950 typename View2::x_iterator dstIt=dst.row_begin(y); 00951 for (std::ptrdiff_t x=0; x<src.width(); ++x) 00952 dstIt[x]=fun(srcIt[x]); 00953 } 00954 return fun; 00955 } 00956 00959 template <typename View1, typename View2, typename View3, typename F> GIL_FORCEINLINE 00960 F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) { 00961 for (std::ptrdiff_t y=0; y<dst.height(); ++y) { 00962 typename View1::x_iterator srcIt1=src1.row_begin(y); 00963 typename View2::x_iterator srcIt2=src2.row_begin(y); 00964 typename View3::x_iterator dstIt=dst.row_begin(y); 00965 for (std::ptrdiff_t x=0; x<dst.width(); ++x) 00966 dstIt[x]=fun(srcIt1[x],srcIt2[x]); 00967 } 00968 return fun; 00969 } 00970 00974 00977 template <typename View1, typename View2, typename F> GIL_FORCEINLINE 00978 F transform_pixel_positions(const View1& src,const View2& dst, F fun) { 00979 assert(src.dimensions()==dst.dimensions()); 00980 typename View1::xy_locator loc=src.xy_at(0,0); 00981 for (std::ptrdiff_t y=0; y<src.height(); ++y) { 00982 typename View2::x_iterator dstIt=dst.row_begin(y); 00983 for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x()) 00984 dstIt[x]=fun(loc); 00985 loc.x()-=src.width(); ++loc.y(); 00986 } 00987 return fun; 00988 } 00989 00992 template <typename View1, typename View2, typename View3, typename F> GIL_FORCEINLINE 00993 F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) { 00994 assert(src1.dimensions()==dst.dimensions()); 00995 assert(src2.dimensions()==dst.dimensions()); 00996 typename View1::xy_locator loc1=src1.xy_at(0,0); 00997 typename View2::xy_locator loc2=src2.xy_at(0,0); 00998 for (std::ptrdiff_t y=0; y<src1.height(); ++y) { 00999 typename View3::x_iterator dstIt=dst.row_begin(y); 01000 for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x()) 01001 dstIt[x]=fun(loc1,loc2); 01002 loc1.x()-=src1.width(); ++loc1.y(); 01003 loc2.x()-=src2.width(); ++loc2.y(); 01004 } 01005 return fun; 01006 } 01007 01008 } } // namespace boost::gil 01009 01010 #ifdef _MSC_VER 01011 #pragma warning(pop) 01012 #endif 01013 01014 #endif Generated on Thu Nov 8 21:53:16 2007 for Generic Image Library by 1.4.4 |