algorithm.hpp

Go 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  doxygen 1.4.4