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 <cstring> 00020 #include <algorithm> 00021 #include <iterator> 00022 #include <memory> 00023 #include <typeinfo> 00024 #include "gil_config.hpp" 00025 #include "gil_concept.hpp" 00026 #include "color_base_algorithm.hpp" 00027 #include "image_view.hpp" 00028 #include "image_view_factory.hpp" 00029 #include "bit_aligned_pixel_iterator.hpp" 00030 00039 00040 //#ifdef _MSC_VER 00041 //#pragma warning(push) 00042 //#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) 00043 //#endif 00044 00045 namespace boost { namespace gil { 00046 00047 //forward declarations 00048 template <typename ChannelPtr, typename ColorSpace> 00049 struct planar_pixel_iterator; 00050 template <typename Iterator> 00051 class memory_based_step_iterator; 00052 template <typename StepIterator> 00053 class memory_based_2d_locator; 00054 00055 // a tag denoting incompatible arguments 00056 struct error_t {}; 00057 00082 00083 00087 00096 template <typename Derived, typename Result=void> 00097 struct binary_operation_obj { 00098 typedef Result result_type; 00099 00100 template <typename V1, typename V2> GIL_FORCEINLINE 00101 result_type operator()(const std::pair<const V1*,const V2*>& p) const { 00102 return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type()); 00103 } 00104 00105 template <typename V1, typename V2> GIL_FORCEINLINE 00106 result_type operator()(const V1& v1, const V2& v2) const { 00107 return apply(v1, v2, typename views_are_compatible<V1,V2>::type()); 00108 } 00109 00110 result_type operator()(const error_t&) const { throw std::bad_cast(); } 00111 private: 00112 00113 // dispatch from apply overload to a function with distinct name 00114 template <typename V1, typename V2> 00115 GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::false_) const { 00116 return ((const Derived*)this)->apply_incompatible(v1,v2); 00117 } 00118 00119 // dispatch from apply overload to a function with distinct name 00120 template <typename V1, typename V2> 00121 GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::true_) const { 00122 return ((const Derived*)this)->apply_compatible(v1,v2); 00123 } 00124 00125 // function with distinct name - it can be overloaded by subclasses 00126 template <typename V1, typename V2> 00127 GIL_FORCEINLINE result_type apply_incompatible(const V1& v1, const V2& v2) const { 00128 throw std::bad_cast(); 00129 } 00130 }; 00131 } } // namespace boost::gil 00132 00138 00142 00143 namespace std { 00144 00147 template<typename T, typename Cs> 00148 GIL_FORCEINLINE boost::gil::pixel<T,Cs>* 00149 copy(boost::gil::pixel<T,Cs>* first, boost::gil::pixel<T,Cs>* last, 00150 boost::gil::pixel<T,Cs>* dst) { 00151 return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst); 00152 } 00153 00156 template<typename T, typename Cs> 00157 GIL_FORCEINLINE boost::gil::pixel<T,Cs>* 00158 copy(const boost::gil::pixel<T,Cs>* first, const boost::gil::pixel<T,Cs>* last, 00159 boost::gil::pixel<T,Cs>* dst) { 00160 return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst); 00161 } 00162 } // namespace std 00163 00164 namespace boost { namespace gil { 00165 namespace detail { 00166 template <typename I, typename O> struct copy_fn { 00167 GIL_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); } 00168 }; 00169 } // namespace detail 00170 } } // namespace boost::gil 00171 00172 namespace std { 00175 template<typename Cs, typename IC1, typename IC2> GIL_FORCEINLINE 00176 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) { 00177 boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type> >(); 00178 static_for_each(first,last,dst,boost::gil::detail::copy_fn<IC1,IC2>()); 00179 return dst+(last-first); 00180 } 00181 } // namespace std 00182 00183 namespace boost { namespace gil { 00184 namespace detail { 00187 template <typename I, typename O> 00188 struct copier_n { 00189 GIL_FORCEINLINE void operator()(I src, typename std::iterator_traits<I>::difference_type n, O dst) const { std::copy(src,src+n, dst); } 00190 }; 00191 00193 template <typename IL, typename O> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept 00194 struct copier_n<iterator_from_2d<IL>,O> { 00195 typedef typename std::iterator_traits<iterator_from_2d<IL> >::difference_type diff_t; 00196 GIL_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, O dst) const { 00197 gil_function_requires<PixelLocatorConcept<IL> >(); 00198 gil_function_requires<MutablePixelIteratorConcept<O> >(); 00199 while (n>0) { 00200 typedef typename iterator_from_2d<IL>::difference_type diff_t; 00201 diff_t l=src.width()-src.x_pos(); 00202 diff_t numToCopy=(n<l ? n:l); 00203 detail::copy_n(src.x(), numToCopy, dst); 00204 dst+=numToCopy; 00205 src+=numToCopy; 00206 n-=numToCopy; 00207 } 00208 } 00209 }; 00210 00212 template <typename I, typename OL> // I Models ConstPixelIteratorConcept, OL Models PixelLocatorConcept 00213 struct copier_n<I,iterator_from_2d<OL> > { 00214 typedef typename std::iterator_traits<I>::difference_type diff_t; 00215 GIL_FORCEINLINE void operator()(I src, diff_t n, iterator_from_2d<OL> dst) const { 00216 gil_function_requires<PixelIteratorConcept<I> >(); 00217 gil_function_requires<MutablePixelLocatorConcept<OL> >(); 00218 while (n>0) { 00219 diff_t l=dst.width()-dst.x_pos(); 00220 diff_t numToCopy=(n<l ? n:l); 00221 detail::copy_n(src, numToCopy, dst.x()); 00222 dst+=numToCopy; 00223 src+=numToCopy; 00224 n-=numToCopy; 00225 } 00226 } 00227 }; 00228 00230 template <typename IL, typename OL> 00231 struct copier_n<iterator_from_2d<IL>,iterator_from_2d<OL> > { 00232 typedef typename iterator_from_2d<IL>::difference_type diff_t; 00233 GIL_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, iterator_from_2d<OL> dst) const { 00234 gil_function_requires<PixelLocatorConcept<IL> >(); 00235 gil_function_requires<MutablePixelLocatorConcept<OL> >(); 00236 if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) { 00237 while(n-->0) { 00238 *dst++=*src++; 00239 } 00240 } 00241 while (n>0) { 00242 diff_t l=dst.width()-dst.x_pos(); 00243 diff_t numToCopy=(n<l ? n : l); 00244 detail::copy_n(src.x(), numToCopy, dst.x()); 00245 dst+=numToCopy; 00246 src+=numToCopy; 00247 n-=numToCopy; 00248 } 00249 } 00250 }; 00251 00252 template <typename SrcIterator, typename DstIterator> 00253 GIL_FORCEINLINE DstIterator copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) { 00254 typedef typename SrcIterator::x_iterator src_x_iterator; 00255 typedef typename DstIterator::x_iterator dst_x_iterator; 00256 00257 typename SrcIterator::difference_type n = last - first; 00258 00259 if (first.is_1d_traversable()) { 00260 if (dst.is_1d_traversable()) 00261 copier_n<src_x_iterator,dst_x_iterator>()(first.x(),n, dst.x()); 00262 else 00263 copier_n<src_x_iterator,DstIterator >()(first.x(),n, dst); 00264 } else { 00265 if (dst.is_1d_traversable()) 00266 copier_n<SrcIterator,dst_x_iterator>()(first,n, dst.x()); 00267 else 00268 copier_n<SrcIterator,DstIterator>()(first,n,dst); 00269 } 00270 return dst+n; 00271 } 00272 00273 } // namespace detail 00274 } } // namespace boost::gil 00275 00276 namespace std { 00279 template <typename IL, typename OL> 00280 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) { 00281 return boost::gil::detail::copy_with_2d_iterators(first,last,dst); 00282 } 00283 00284 } // namespace std 00285 00286 namespace boost { namespace gil { 00287 00288 00291 template <typename View1, typename View2> GIL_FORCEINLINE 00292 void copy_pixels(const View1& src, const View2& dst) { 00293 assert(src.dimensions()==dst.dimensions()); 00294 detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin()); 00295 } 00296 00302 00308 00309 namespace detail { 00310 template <typename CC> 00311 class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC> > { 00312 private: 00313 CC _cc; 00314 public: 00315 typedef typename binary_operation_obj<copy_and_convert_pixels_fn<CC> >::result_type result_type; 00316 copy_and_convert_pixels_fn() {} 00317 copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {} 00318 // when the two color spaces are incompatible, a color conversion is performed 00319 template <typename V1, typename V2> GIL_FORCEINLINE 00320 result_type apply_incompatible(const V1& src, const V2& dst) const { 00321 copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst); 00322 } 00323 00324 // If the two color spaces are compatible, copy_and_convert is just copy 00325 template <typename V1, typename V2> GIL_FORCEINLINE 00326 result_type apply_compatible(const V1& src, const V2& dst) const { 00327 copy_pixels(src,dst); 00328 } 00329 }; 00330 } // namespace detail 00331 00333 template <typename V1, typename V2,typename CC> 00334 GIL_FORCEINLINE 00335 void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) { 00336 detail::copy_and_convert_pixels_fn<CC> ccp(cc); 00337 ccp(src,dst); 00338 } 00339 00340 struct default_color_converter; 00341 00343 template <typename View1, typename View2> 00344 GIL_FORCEINLINE 00345 void copy_and_convert_pixels(const View1& src, const View2& dst) { 00346 detail::copy_and_convert_pixels_fn<default_color_converter> ccp; 00347 ccp(src,dst); 00348 } 00349 00350 } } // namespace boost::gil 00351 00353 // 00354 // std::fill and gil::fill_pixels 00355 // 00357 00361 00362 00363 namespace std { 00372 template <typename IL, typename V> 00373 void fill(boost::gil::iterator_from_2d<IL> first, boost::gil::iterator_from_2d<IL> last, const V& val) { 00374 boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL> >(); 00375 if (first.is_1d_traversable()) { 00376 std::fill(first.x(), last.x(), val); 00377 } else { 00378 // fill row by row 00379 std::ptrdiff_t n=last-first; 00380 while (n>0) { 00381 std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos())); 00382 fill_n(first.x(), numToDo, val); 00383 first+=numToDo; 00384 n-=numToDo; 00385 } 00386 } 00387 } 00388 } // namespace std 00389 00390 namespace boost { namespace gil { 00391 00392 namespace detail { 00394 struct std_fill_t { 00395 template <typename It, typename P> 00396 void operator()(It first, It last, const P& p_in) { 00397 std::fill(first,last,p_in); 00398 } 00399 }; 00401 template <typename It, typename P> 00402 GIL_FORCEINLINE 00403 void fill_aux(It first, It last, const P& p, mpl::true_) { 00404 static_for_each(first,last,p,std_fill_t()); 00405 } 00407 template <typename It, typename P> 00408 GIL_FORCEINLINE 00409 void fill_aux(It first, It last, const P& p,mpl::false_) { 00410 std::fill(first,last,p); 00411 } 00412 } // namespace detail 00413 00416 template <typename View, typename Value> GIL_FORCEINLINE 00417 void fill_pixels(const View& img_view, const Value& val) { 00418 if (img_view.is_1d_traversable()) 00419 detail::fill_aux(img_view.begin().x(), img_view.end().x(), 00420 val,is_planar<View>()); 00421 else 00422 for (std::ptrdiff_t y=0; y<img_view.height(); ++y) 00423 detail::fill_aux(img_view.row_begin(y),img_view.row_end(y), 00424 val,is_planar<View>()); 00425 } 00426 00432 00436 00437 00438 namespace detail { 00439 00440 template <typename It> GIL_FORCEINLINE 00441 void destruct_range_impl(It first, It last, mpl::true_) { 00442 typedef typename std::iterator_traits<It>::value_type value_t; 00443 if (boost::has_trivial_destructor<value_t>::value) 00444 return; 00445 while (first!=last) { 00446 first->~value_t(); 00447 ++first; 00448 } 00449 } 00450 template <typename It> GIL_FORCEINLINE 00451 void destruct_range_impl(It first, It last, mpl::false_) {} 00452 00453 template <typename It> GIL_FORCEINLINE 00454 void destruct_range(It first, It last) { 00455 destruct_range_impl(first,last,typename is_pointer<It>::type()); 00456 } 00457 00458 struct std_destruct_t { 00459 template <typename It> void operator()(It first, It last) const { destruct_range(first,last); } 00460 }; 00461 00463 template <typename It> 00464 GIL_FORCEINLINE 00465 void destruct_aux(It first, It last, mpl::true_) { 00466 static_for_each(first,last,std_destruct_t()); 00467 } 00469 template <typename It> 00470 GIL_FORCEINLINE 00471 void destruct_aux(It first, It last, mpl::false_) { 00472 destruct_range(first,last); 00473 } 00474 00475 } // namespace detail 00476 00479 template <typename View> GIL_FORCEINLINE 00480 void destruct_pixels(const View& img_view) { 00481 if (img_view.is_1d_traversable()) 00482 detail::destruct_aux(img_view.begin().x(), img_view.end().x(), 00483 is_planar<View>()); 00484 else 00485 for (std::ptrdiff_t y=0; y<img_view.height(); ++y) 00486 detail::destruct_aux(img_view.row_begin(y),img_view.row_end(y), 00487 is_planar<View>()); 00488 } 00489 00495 00499 00500 00501 namespace detail { 00502 00505 template <typename It, typename P> 00506 GIL_FORCEINLINE 00507 void uninitialized_fill_aux(It first, It last, 00508 const P& p, mpl::true_) { 00509 int channel=0; 00510 try { 00511 typedef typename std::iterator_traits<It>::value_type pixel_t; 00512 while (channel < num_channels<pixel_t>::value) { 00513 std::uninitialized_fill(dynamic_at_c(first,channel), dynamic_at_c(last,channel), 00514 dynamic_at_c(p,channel)); 00515 ++channel; 00516 } 00517 } catch (...) { 00518 for (int c=0; c<channel; ++c) 00519 destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c)); 00520 throw; 00521 } 00522 } 00523 00526 template <typename It, typename P> 00527 GIL_FORCEINLINE 00528 void uninitialized_fill_aux(It first, It last, 00529 const P& p,mpl::false_) { 00530 std::uninitialized_fill(first,last,p); 00531 } 00532 00533 } // namespace detail 00534 00539 template <typename View, typename Value> 00540 void uninitialized_fill_pixels(const View& img_view, const Value& val) { 00541 if (img_view.is_1d_traversable()) 00542 detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(), 00543 val,is_planar<View>()); 00544 else { 00545 typename View::y_coord_t y; 00546 try { 00547 for (y=0; y<img_view.height(); ++y) 00548 detail::uninitialized_fill_aux(img_view.row_begin(y),img_view.row_end(y), 00549 val,is_planar<View>()); 00550 } catch(...) { 00551 for (typename View::y_coord_t y0=0; y0<y; ++y0) 00552 detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>()); 00553 throw; 00554 } 00555 } 00556 } 00557 00563 00567 00568 namespace detail { 00569 00570 template <typename It> GIL_FORCEINLINE 00571 void default_construct_range_impl(It first, It last, mpl::true_) { 00572 typedef typename std::iterator_traits<It>::value_type value_t; 00573 It first1=first; 00574 try { 00575 while (first!=last) { 00576 new (first) value_t(); 00577 ++first; 00578 } 00579 } catch (...) { 00580 destruct_range(first1,first); 00581 throw; 00582 } 00583 } 00584 00585 template <typename It> GIL_FORCEINLINE 00586 void default_construct_range_impl(It first, It last, mpl::false_) {} 00587 00588 template <typename It> GIL_FORCEINLINE 00589 void default_construct_range(It first, It last) { default_construct_range_impl(first, last, typename is_pointer<It>::type()); } 00590 00592 template <typename It> 00593 GIL_FORCEINLINE 00594 void default_construct_aux(It first, It last, mpl::true_) { 00595 int channel=0; 00596 try { 00597 typedef typename std::iterator_traits<It>::value_type pixel_t; 00598 while (channel < num_channels<pixel_t>::value) { 00599 default_construct_range(dynamic_at_c(first,channel), dynamic_at_c(last,channel)); 00600 ++channel; 00601 } 00602 } catch (...) { 00603 for (int c=0; c<channel; ++c) 00604 destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c)); 00605 throw; 00606 } 00607 } 00608 00610 template <typename It> 00611 GIL_FORCEINLINE 00612 void default_construct_aux(It first, It last, mpl::false_) { 00613 default_construct_range(first,last); 00614 } 00615 00616 template <typename View, bool IsPlanar> 00617 struct has_trivial_pixel_constructor : public boost::has_trivial_constructor<typename View::value_type> {}; 00618 template <typename View> 00619 struct has_trivial_pixel_constructor<View, true> : public boost::has_trivial_constructor<typename channel_type<View>::type> {}; 00620 00621 } // namespace detail 00622 00627 template <typename View> 00628 void default_construct_pixels(const View& img_view) { 00629 if (detail::has_trivial_pixel_constructor<View, is_planar<View>::value>::value) 00630 return; 00631 00632 if (img_view.is_1d_traversable()) 00633 detail::default_construct_aux(img_view.begin().x(), img_view.end().x(), is_planar<View>()); 00634 else { 00635 typename View::y_coord_t y; 00636 try { 00637 for (y=0; y<img_view.height(); ++y) 00638 detail::default_construct_aux(img_view.row_begin(y),img_view.row_end(y), is_planar<View>()); 00639 } catch(...) { 00640 for (typename View::y_coord_t y0=0; y0<y; ++y0) 00641 detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>()); 00642 throw; 00643 } 00644 } 00645 } 00646 00647 00653 00657 00658 namespace detail { 00659 00661 template <typename It1, typename It2> 00662 GIL_FORCEINLINE 00663 void uninitialized_copy_aux(It1 first1, It1 last1, 00664 It2 first2, mpl::true_) { 00665 int channel=0; 00666 try { 00667 typedef typename std::iterator_traits<It1>::value_type pixel_t; 00668 while (channel < num_channels<pixel_t>::value) { 00669 std::uninitialized_copy(dynamic_at_c(first1,channel), dynamic_at_c(last1,channel), dynamic_at_c(first2,channel)); 00670 ++channel; 00671 } 00672 } catch (...) { 00673 It2 last2=first2; 00674 std::advance(last2, std::distance(first1,last1)); 00675 for (int c=0; c<channel; ++c) 00676 destruct_range(dynamic_at_c(first2,c), dynamic_at_c(last2,c)); 00677 throw; 00678 } 00679 } 00681 template <typename It1, typename It2> 00682 GIL_FORCEINLINE 00683 void uninitialized_copy_aux(It1 first1, It1 last1, 00684 It2 first2,mpl::false_) { 00685 std::uninitialized_copy(first1,last1,first2); 00686 } 00687 } // namespace detail 00688 00693 template <typename View1, typename View2> 00694 void uninitialized_copy_pixels(const View1& view1, const View2& view2) { 00695 typedef mpl::bool_<is_planar<View1>::value && is_planar<View2>::value> is_planar; 00696 assert(view1.dimensions()==view2.dimensions()); 00697 if (view1.is_1d_traversable() && view2.is_1d_traversable()) 00698 detail::uninitialized_copy_aux(view1.begin().x(), view1.end().x(), 00699 view2.begin().x(), 00700 is_planar()); 00701 else { 00702 typename View1::y_coord_t y; 00703 try { 00704 for (y=0; y<view1.height(); ++y) 00705 detail::uninitialized_copy_aux(view1.row_begin(y), view1.row_end(y), 00706 view2.row_begin(y), 00707 is_planar()); 00708 } catch(...) { 00709 for (typename View1::y_coord_t y0=0; y0<y; ++y0) 00710 detail::destruct_aux(view2.row_begin(y0),view2.row_end(y0), is_planar()); 00711 throw; 00712 } 00713 } 00714 } 00715 00721 00730 00732 template <typename V, typename F> 00733 F for_each_pixel(const V& img, F fun) { 00734 if (img.is_1d_traversable()) { 00735 return std::for_each(img.begin().x(), img.end().x(), fun); 00736 } else { 00737 for (std::ptrdiff_t y=0; y<img.height(); ++y) 00738 fun = std::for_each(img.row_begin(y),img.row_end(y),fun); 00739 return fun; 00740 } 00741 } 00742 00746 00748 template <typename View, typename F> 00749 F for_each_pixel_position(const View& img, F fun) { 00750 typename View::xy_locator loc=img.xy_at(0,0); 00751 for (std::ptrdiff_t y=0; y<img.height(); ++y) { 00752 for (std::ptrdiff_t x=0; x<img.width(); ++x, ++loc.x()) 00753 fun(loc); 00754 loc.x()-=img.width(); ++loc.y(); 00755 } 00756 return fun; 00757 } 00758 00759 00765 00769 00772 template <typename View, typename F> 00773 void generate_pixels(const View& v, F fun) { 00774 if (v.is_1d_traversable()) { 00775 std::generate(v.begin().x(), v.end().x(), fun); 00776 } else { 00777 for (std::ptrdiff_t y=0; y<v.height(); ++y) 00778 std::generate(v.row_begin(y),v.row_end(y),fun); 00779 } 00780 } 00781 00787 00791 00792 template <typename I1, typename I2> GIL_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2); 00793 00794 namespace detail { 00795 00796 template <typename I1, typename I2> 00797 struct equal_n_fn { 00798 GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); } 00799 }; 00800 00803 template<typename T, typename Cs> 00804 struct equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> { 00805 GIL_FORCEINLINE bool operator()(const pixel<T,Cs>* i1, std::ptrdiff_t n, const pixel<T,Cs>* i2) const { 00806 return memcmp(i1, i2, n*sizeof(pixel<T,Cs>))==0; 00807 } 00808 }; 00809 template<typename T, typename Cs> 00810 struct equal_n_fn<pixel<T,Cs>*, pixel<T,Cs>*> : equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {}; 00811 00815 template<typename IC, typename Cs> 00816 struct equal_n_fn<planar_pixel_iterator<IC,Cs>, planar_pixel_iterator<IC,Cs> > { 00817 GIL_FORCEINLINE bool operator()(const planar_pixel_iterator<IC,Cs> i1, std::ptrdiff_t n, const planar_pixel_iterator<IC,Cs> i2) const { 00818 ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type); 00819 00820 for (std::ptrdiff_t i=0; i<mpl::size<Cs>::value; ++i) 00821 if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0) 00822 return false; 00823 return true; 00824 } 00825 }; 00826 00827 00829 template <typename Loc, typename I2> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept 00830 struct equal_n_fn<boost::gil::iterator_from_2d<Loc>,I2> { 00831 GIL_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, I2 i2) const { 00832 gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >(); 00833 gil_function_requires<boost::gil::PixelIteratorConcept<I2> >(); 00834 while (n>0) { 00835 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos()); 00836 if (!equal_n(i1.x(), num, i2)) 00837 return false; 00838 i1+=num; 00839 i2+=num; 00840 n-=num; 00841 } 00842 return true; 00843 } 00844 }; 00845 00847 template <typename I1, typename Loc> // I Models PixelIteratorConcept, OL Models PixelLocatorConcept 00848 struct equal_n_fn<I1,boost::gil::iterator_from_2d<Loc> > { 00849 GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const { 00850 gil_function_requires<boost::gil::PixelIteratorConcept<I1> >(); 00851 gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >(); 00852 while (n>0) { 00853 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos()); 00854 if (!equal_n(i1, num, i2.x())) 00855 return false; 00856 i1+=num; 00857 i2+=num; 00858 n-=num; 00859 } 00860 return true; 00861 } 00862 }; 00863 00865 template <typename Loc1, typename Loc2> 00866 struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> > { 00867 GIL_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const { 00868 gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >(); 00869 gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >(); 00870 if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) { 00871 while(n-->0) { 00872 if (*i1++!=*i2++) return false; 00873 } 00874 } 00875 while (n>0) { 00876 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos()); 00877 if (!equal_n(i1.x(), num, i2.x())) 00878 return false; 00879 i1+=num; 00880 i2+=num; 00881 n-=num; 00882 } 00883 return true; 00884 } 00885 }; 00886 } // namespace detail 00887 00888 template <typename I1, typename I2> GIL_FORCEINLINE 00889 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) { 00890 return detail::equal_n_fn<I1,I2>()(i1,n,i2); 00891 } 00892 } } // namespace boost::gil 00893 00894 namespace std { 00906 template <typename Loc1, typename Loc2> GIL_FORCEINLINE 00907 bool equal(boost::gil::iterator_from_2d<Loc1> first, boost::gil::iterator_from_2d<Loc1> last, boost::gil::iterator_from_2d<Loc2> first2) { 00908 boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >(); 00909 boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >(); 00910 std::ptrdiff_t n=last-first; 00911 if (first.is_1d_traversable()) { 00912 if (first2.is_1d_traversable()) 00913 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x()); 00914 else 00915 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2> >()(first.x(),n, first2); 00916 } else { 00917 if (first2.is_1d_traversable()) 00918 return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x()); 00919 else 00920 return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> >()(first,n,first2); 00921 } 00922 } 00923 } // namespace std 00924 00925 namespace boost { namespace gil { 00926 00929 template <typename View1, typename View2> GIL_FORCEINLINE 00930 bool equal_pixels(const View1& v1, const View2& v2) { 00931 assert(v1.dimensions()==v2.dimensions()); 00932 return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance 00933 } 00934 00940 00944 00947 template <typename View1, typename View2, typename F> GIL_FORCEINLINE 00948 F transform_pixels(const View1& src,const View2& dst, F fun) { 00949 assert(src.dimensions()==dst.dimensions()); 00950 for (std::ptrdiff_t y=0; y<src.height(); ++y) { 00951 typename View1::x_iterator srcIt=src.row_begin(y); 00952 typename View2::x_iterator dstIt=dst.row_begin(y); 00953 for (std::ptrdiff_t x=0; x<src.width(); ++x) 00954 dstIt[x]=fun(srcIt[x]); 00955 } 00956 return fun; 00957 } 00958 00961 template <typename View1, typename View2, typename View3, typename F> GIL_FORCEINLINE 00962 F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) { 00963 for (std::ptrdiff_t y=0; y<dst.height(); ++y) { 00964 typename View1::x_iterator srcIt1=src1.row_begin(y); 00965 typename View2::x_iterator srcIt2=src2.row_begin(y); 00966 typename View3::x_iterator dstIt=dst.row_begin(y); 00967 for (std::ptrdiff_t x=0; x<dst.width(); ++x) 00968 dstIt[x]=fun(srcIt1[x],srcIt2[x]); 00969 } 00970 return fun; 00971 } 00972 00976 00979 template <typename View1, typename View2, typename F> GIL_FORCEINLINE 00980 F transform_pixel_positions(const View1& src,const View2& dst, F fun) { 00981 assert(src.dimensions()==dst.dimensions()); 00982 typename View1::xy_locator loc=src.xy_at(0,0); 00983 for (std::ptrdiff_t y=0; y<src.height(); ++y) { 00984 typename View2::x_iterator dstIt=dst.row_begin(y); 00985 for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x()) 00986 dstIt[x]=fun(loc); 00987 loc.x()-=src.width(); ++loc.y(); 00988 } 00989 return fun; 00990 } 00991 00994 template <typename View1, typename View2, typename View3, typename F> GIL_FORCEINLINE 00995 F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) { 00996 assert(src1.dimensions()==dst.dimensions()); 00997 assert(src2.dimensions()==dst.dimensions()); 00998 typename View1::xy_locator loc1=src1.xy_at(0,0); 00999 typename View2::xy_locator loc2=src2.xy_at(0,0); 01000 for (std::ptrdiff_t y=0; y<src1.height(); ++y) { 01001 typename View3::x_iterator dstIt=dst.row_begin(y); 01002 for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x()) 01003 dstIt[x]=fun(loc1,loc2); 01004 loc1.x()-=src1.width(); ++loc1.y(); 01005 loc2.x()-=src2.width(); ++loc2.y(); 01006 } 01007 return fun; 01008 } 01009 01010 } } // namespace boost::gil 01011 01012 //#ifdef _MSC_VER 01013 //#pragma warning(pop) 01014 //#endif 01015 01016 #endif Generated on Sat May 2 13:50:13 2009 for Generic Image Library by 1.5.6 |