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 <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  doxygen 1.5.6