Generic Image Library: algorithm.hpp Source File

Modules | Alphabetical List | Class List | Directories | File List | GIL Home Page # 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