00001
00002
00003
00004
00005
00006
00007
00008
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
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
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
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
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
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 } }
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 }
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 }
00168 } }
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 }
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>
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>
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 }
00272 } }
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 }
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
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
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 }
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 } }
00349
00351
00352
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
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 }
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 }
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 }
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 }
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 }
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 }
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>
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>
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 }
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 } }
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 }
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());
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 } }
01009
01010 #ifdef _MSC_VER
01011 #pragma warning(pop)
01012 #endif
01013
01014 #endif