Boost GIL


algorithm.hpp
1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 #ifndef BOOST_GIL_ALGORITHM_HPP
9 #define BOOST_GIL_ALGORITHM_HPP
10 
11 #include <boost/gil/bit_aligned_pixel_iterator.hpp>
12 #include <boost/gil/color_base_algorithm.hpp>
13 #include <boost/gil/concepts.hpp>
14 #include <boost/gil/image_view.hpp>
15 #include <boost/gil/image_view_factory.hpp>
16 
17 #include <boost/config.hpp>
18 #include <boost/utility/enable_if.hpp>
19 #include <boost/mpl/and.hpp>
20 #include <boost/mpl/or.hpp>
21 
22 #include <algorithm>
23 #include <cassert>
24 #include <cstddef>
25 #include <cstring>
26 #include <iterator>
27 #include <memory>
28 #include <typeinfo>
29 
30 namespace boost { namespace gil {
31 
32 //forward declarations
33 template <typename ChannelPtr, typename ColorSpace>
35 template <typename Iterator>
37 template <typename StepIterator>
39 
40 // a tag denoting incompatible arguments
41 struct error_t {};
42 
67 
71 
80 template <typename Derived, typename Result=void>
82  typedef Result result_type;
83 
84  template <typename V1, typename V2> BOOST_FORCEINLINE
85  result_type operator()(const std::pair<const V1*,const V2*>& p) const {
86  return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type());
87  }
88 
89  template <typename V1, typename V2> BOOST_FORCEINLINE
90  result_type operator()(const V1& v1, const V2& v2) const {
91  return apply(v1, v2, typename views_are_compatible<V1,V2>::type());
92  }
93 
94  result_type operator()(const error_t&) const { throw std::bad_cast(); }
95 private:
96 
97  // dispatch from apply overload to a function with distinct name
98  template <typename V1, typename V2>
99  BOOST_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::false_) const {
100  return ((const Derived*)this)->apply_incompatible(v1,v2);
101  }
102 
103  // dispatch from apply overload to a function with distinct name
104  template <typename V1, typename V2>
105  BOOST_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::true_) const {
106  return ((const Derived*)this)->apply_compatible(v1,v2);
107  }
108 
109  // function with distinct name - it can be overloaded by subclasses
110  template <typename V1, typename V2>
111  BOOST_FORCEINLINE result_type apply_incompatible(const V1&, const V2&) const {
112  throw std::bad_cast();
113  }
114 };
115 } } // namespace boost::gil
116 
122 
126 
127 namespace std {
130 template<typename T, typename Cs>
131 BOOST_FORCEINLINE boost::gil::pixel<T,Cs>*
134  return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
135 }
136 
139 template<typename T, typename Cs>
140 BOOST_FORCEINLINE boost::gil::pixel<T,Cs>*
143  return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
144 }
145 } // namespace std
146 
147 namespace boost { namespace gil {
148 namespace detail {
149 template <typename I, typename O> struct copy_fn {
150  BOOST_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); }
151 };
152 } // namespace detail
153 } } // namespace boost::gil
154 
155 namespace std {
158 template<typename Cs, typename IC1, typename IC2> BOOST_FORCEINLINE
160  boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type> >();
161  static_for_each(first,last,dst,boost::gil::detail::copy_fn<IC1,IC2>());
162  return dst+(last-first);
163 }
164 } // namespace std
165 
166 namespace boost { namespace gil {
167 namespace detail {
170 template <typename I, typename O>
171 struct copier_n {
172  BOOST_FORCEINLINE void operator()(I src, typename std::iterator_traits<I>::difference_type n, O dst) const { std::copy(src,src+n, dst); }
173 };
174 
176 template <typename IL, typename O> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
177 struct copier_n<iterator_from_2d<IL>,O> {
178  typedef typename std::iterator_traits<iterator_from_2d<IL> >::difference_type diff_t;
179  BOOST_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, O dst) const {
180  gil_function_requires<PixelLocatorConcept<IL> >();
181  gil_function_requires<MutablePixelIteratorConcept<O> >();
182  while (n>0) {
183  diff_t l=src.width()-src.x_pos();
184  diff_t numToCopy=(n<l ? n:l);
185  detail::copy_n(src.x(), numToCopy, dst);
186  dst+=numToCopy;
187  src+=numToCopy;
188  n-=numToCopy;
189  }
190  }
191 };
192 
194 template <typename I, typename OL> // I Models ConstPixelIteratorConcept, OL Models PixelLocatorConcept
195 struct copier_n<I,iterator_from_2d<OL> > {
196  typedef typename std::iterator_traits<I>::difference_type diff_t;
197  BOOST_FORCEINLINE void operator()(I src, diff_t n, iterator_from_2d<OL> dst) const {
198  gil_function_requires<PixelIteratorConcept<I> >();
199  gil_function_requires<MutablePixelLocatorConcept<OL> >();
200  while (n>0) {
201  diff_t l=dst.width()-dst.x_pos();
202  diff_t numToCopy=(n<l ? n:l);
203  detail::copy_n(src, numToCopy, dst.x());
204  dst+=numToCopy;
205  src+=numToCopy;
206  n-=numToCopy;
207  }
208  }
209 };
210 
212 template <typename IL, typename OL>
214  typedef typename iterator_from_2d<IL>::difference_type diff_t;
215  BOOST_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, iterator_from_2d<OL> dst) const {
216  gil_function_requires<PixelLocatorConcept<IL> >();
217  gil_function_requires<MutablePixelLocatorConcept<OL> >();
218  if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
219  while(n-->0) {
220  *dst++=*src++;
221  }
222  }
223  while (n>0) {
224  diff_t l=dst.width()-dst.x_pos();
225  diff_t numToCopy=(n<l ? n : l);
226  detail::copy_n(src.x(), numToCopy, dst.x());
227  dst+=numToCopy;
228  src+=numToCopy;
229  n-=numToCopy;
230  }
231  }
232 };
233 
234 template <typename SrcIterator, typename DstIterator>
235 BOOST_FORCEINLINE DstIterator copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) {
236  typedef typename SrcIterator::x_iterator src_x_iterator;
237  typedef typename DstIterator::x_iterator dst_x_iterator;
238 
239  typename SrcIterator::difference_type n = last - first;
240 
241  if (first.is_1d_traversable()) {
242  if (dst.is_1d_traversable())
243  copier_n<src_x_iterator,dst_x_iterator>()(first.x(),n, dst.x());
244  else
245  copier_n<src_x_iterator,DstIterator >()(first.x(),n, dst);
246  } else {
247  if (dst.is_1d_traversable())
248  copier_n<SrcIterator,dst_x_iterator>()(first,n, dst.x());
249  else
250  copier_n<SrcIterator,DstIterator>()(first,n,dst);
251  }
252  return dst+n;
253 }
254 } // namespace detail
255 } } // namespace boost::gil
256 
257 namespace std {
260 template <typename IL, typename OL>
262  return boost::gil::detail::copy_with_2d_iterators(first,last,dst);
263 }
264 } // namespace std
265 
266 namespace boost { namespace gil {
269 template <typename View1, typename View2> BOOST_FORCEINLINE
270 void copy_pixels(const View1& src, const View2& dst) {
271  assert(src.dimensions()==dst.dimensions());
272  detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
273 }
274 
280 
286 
287 namespace detail {
288 template <typename CC>
289 class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC> > {
290 private:
291  CC _cc;
292 public:
293  typedef typename binary_operation_obj<copy_and_convert_pixels_fn<CC> >::result_type result_type;
294  copy_and_convert_pixels_fn() {}
295  copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {}
296  // when the two color spaces are incompatible, a color conversion is performed
297  template <typename V1, typename V2> BOOST_FORCEINLINE
298  result_type apply_incompatible(const V1& src, const V2& dst) const {
299  copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst);
300  }
301 
302  // If the two color spaces are compatible, copy_and_convert is just copy
303  template <typename V1, typename V2> BOOST_FORCEINLINE
304  result_type apply_compatible(const V1& src, const V2& dst) const {
305  copy_pixels(src,dst);
306  }
307 };
308 } // namespace detail
309 
311 template <typename V1, typename V2,typename CC>
312 BOOST_FORCEINLINE
313 void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) {
314  detail::copy_and_convert_pixels_fn<CC> ccp(cc);
315  ccp(src,dst);
316 }
317 
318 struct default_color_converter;
319 
321 template <typename View1, typename View2>
322 BOOST_FORCEINLINE
323 void copy_and_convert_pixels(const View1& src, const View2& dst) {
324  detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
325  ccp(src,dst);
326 }
327 } } // namespace boost::gil
328 
330 //
331 // std::fill and gil::fill_pixels
332 //
334 
338 
339 namespace std {
348 template <typename IL, typename V>
350  boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL> >();
351  if (first.is_1d_traversable()) {
352  std::fill(first.x(), last.x(), val);
353  } else {
354  // fill row by row
355  std::ptrdiff_t n=last-first;
356  while (n>0) {
357  std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
358  std::fill_n(first.x(), numToDo, val);
359  first+=numToDo;
360  n-=numToDo;
361  }
362  }
363 }
364 } // namespace std
365 
366 namespace boost { namespace gil {
367 namespace detail {
369 struct std_fill_t {
370  template <typename It, typename P>
371  void operator()(It first, It last, const P& p_in) {
372  std::fill(first,last,p_in);
373  }
374 };
376 template <typename It, typename P>
377 BOOST_FORCEINLINE
378 void fill_aux(It first, It last, const P& p, mpl::true_) {
379  static_for_each(first,last,p,std_fill_t());
380 }
382 template <typename It, typename P>
383 BOOST_FORCEINLINE
384 void fill_aux(It first, It last, const P& p,mpl::false_) {
385  std::fill(first,last,p);
386 }
387 } // namespace detail
388 
391 template <typename View, typename Value> BOOST_FORCEINLINE
392 void fill_pixels(const View& img_view, const Value& val) {
393  if (img_view.is_1d_traversable())
394  detail::fill_aux(img_view.begin().x(), img_view.end().x(),
395  val,is_planar<View>());
396  else
397  for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
398  detail::fill_aux(img_view.row_begin(y),img_view.row_end(y),
399  val,is_planar<View>());
400 }
401 
407 
411 
412 namespace detail {
413 template <typename It> BOOST_FORCEINLINE
414 void destruct_range_impl( It first
415  , It last
416  , typename enable_if< mpl::and_< is_pointer< It >
417  , mpl::not_< boost::has_trivial_destructor< typename std::iterator_traits<It>::value_type > >
418  >
419  >::type* /*ptr*/ = 0
420  )
421 {
422  while (first!=last) {
423  first->~value_t();
424  ++first;
425  }
426 }
427 
428 template <typename It> BOOST_FORCEINLINE
429 void destruct_range_impl( It
430  , It
431  , typename enable_if< mpl::or_< mpl::not_< is_pointer< It > >
432  , boost::has_trivial_destructor< typename std::iterator_traits< It >::value_type >
433  >
434  >::type* /* ptr */ = 0)
435 {}
436 
437 template <typename It> BOOST_FORCEINLINE
438 void destruct_range(It first, It last) {
439  destruct_range_impl( first
440  , last
441  );
442 }
443 
444 struct std_destruct_t {
445  template <typename It> void operator()(It first, It last) const { destruct_range(first,last); }
446 };
447 
449 template <typename It>
450 BOOST_FORCEINLINE
451 void destruct_aux(It first, It last, mpl::true_) {
452  static_for_each(first,last,std_destruct_t());
453 }
455 template <typename It>
456 BOOST_FORCEINLINE
457 void destruct_aux(It first, It last, mpl::false_) {
458  destruct_range(first,last);
459 }
460 } // namespace detail
461 
464 template <typename View> BOOST_FORCEINLINE
465 void destruct_pixels(const View& img_view) {
466  if (img_view.is_1d_traversable())
467  detail::destruct_aux(img_view.begin().x(), img_view.end().x(),
468  is_planar<View>());
469  else
470  for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
471  detail::destruct_aux(img_view.row_begin(y),img_view.row_end(y),
472  is_planar<View>());
473 }
474 
480 
484 
485 namespace detail {
488 template <typename It, typename P>
489 BOOST_FORCEINLINE
490 void uninitialized_fill_aux(It first, It last,
491  const P& p, mpl::true_) {
492  int channel=0;
493  try {
494  typedef typename std::iterator_traits<It>::value_type pixel_t;
495  while (channel < num_channels<pixel_t>::value) {
496  std::uninitialized_fill(dynamic_at_c(first,channel), dynamic_at_c(last,channel),
497  dynamic_at_c(p,channel));
498  ++channel;
499  }
500  } catch (...) {
501  for (int c=0; c<channel; ++c)
502  destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
503  throw;
504  }
505 }
506 
509 template <typename It, typename P>
510 BOOST_FORCEINLINE
511 void uninitialized_fill_aux(It first, It last,
512  const P& p,mpl::false_) {
513  std::uninitialized_fill(first,last,p);
514 }
515 } // namespace detail
516 
521 template <typename View, typename Value>
522 void uninitialized_fill_pixels(const View& img_view, const Value& val) {
523  if (img_view.is_1d_traversable())
524  detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(),
525  val,is_planar<View>());
526  else {
527  typename View::y_coord_t y = 0;
528  try {
529  for (y=0; y<img_view.height(); ++y)
530  detail::uninitialized_fill_aux(img_view.row_begin(y),img_view.row_end(y),
531  val,is_planar<View>());
532  } catch(...) {
533  for (typename View::y_coord_t y0=0; y0<y; ++y0)
534  detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>());
535  throw;
536  }
537  }
538 }
539 
545 
549 
550 namespace detail {
551 template <typename It> BOOST_FORCEINLINE
552 void default_construct_range_impl(It first, It last, mpl::true_) {
553  typedef typename std::iterator_traits<It>::value_type value_t;
554  It first1=first;
555  try {
556  while (first!=last) {
557  new (first) value_t();
558  ++first;
559  }
560  } catch (...) {
561  destruct_range(first1,first);
562  throw;
563  }
564 }
565 
566 template <typename It> BOOST_FORCEINLINE
567 void default_construct_range_impl(It, It, mpl::false_) {}
568 
569 template <typename It> BOOST_FORCEINLINE
570 void default_construct_range(It first, It last) { default_construct_range_impl(first, last, typename is_pointer<It>::type()); }
571 
573 template <typename It>
574 BOOST_FORCEINLINE
575 void default_construct_aux(It first, It last, mpl::true_) {
576  int channel=0;
577  try {
578  typedef typename std::iterator_traits<It>::value_type pixel_t;
579  while (channel < num_channels<pixel_t>::value) {
580  default_construct_range(dynamic_at_c(first,channel), dynamic_at_c(last,channel));
581  ++channel;
582  }
583  } catch (...) {
584  for (int c=0; c<channel; ++c)
585  destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
586  throw;
587  }
588 }
589 
591 template <typename It>
592 BOOST_FORCEINLINE
593 void default_construct_aux(It first, It last, mpl::false_) {
594  default_construct_range(first,last);
595 }
596 
597 template <typename View, bool IsPlanar>
598 struct has_trivial_pixel_constructor : public boost::has_trivial_constructor<typename View::value_type> {};
599 template <typename View>
600 struct has_trivial_pixel_constructor<View, true> : public boost::has_trivial_constructor<typename channel_type<View>::type> {};
601 } // namespace detail
602 
603 namespace detail {
604 template< typename View, bool B > BOOST_FORCEINLINE
605 void default_construct_pixels_impl( const View& img_view
606  , boost::enable_if< is_same< mpl::bool_< B >
607  , mpl::false_
608  >
609  >* /* ptr */ = 0
610  )
611 {
612  if( img_view.is_1d_traversable() )
613  {
614  detail::default_construct_aux( img_view.begin().x()
615  , img_view.end().x()
616  , is_planar<View>()
617  );
618  }
619  else
620  {
621  typename View::y_coord_t y = 0;
622  try
623  {
624  for( y = 0; y < img_view.height(); ++y )
625  {
626  detail::default_construct_aux( img_view.row_begin( y )
627  ,img_view.row_end( y )
628  , is_planar<View>()
629  );
630  }
631  } catch(...)
632  {
633  for (typename View::y_coord_t y0 = 0; y0 < y; ++y0 )
634  {
635  detail::destruct_aux( img_view.row_begin(y0)
636  , img_view.row_end(y0)
637  , is_planar<View>()
638  );
639  }
640 
641  throw;
642  }
643  }
644 }
645 } // namespace detail
646 
651 template <typename View>
652 void default_construct_pixels(const View& img_view) {
653  detail::default_construct_pixels_impl< View
654  , detail::has_trivial_pixel_constructor< View
655  , is_planar< View >::value
656  >::value
657  >( img_view );
658 }
659 
665 
669 
670 namespace detail {
672 template <typename It1, typename It2>
673 BOOST_FORCEINLINE
674 void uninitialized_copy_aux(It1 first1, It1 last1,
675  It2 first2, mpl::true_) {
676  int channel=0;
677  try {
678  typedef typename std::iterator_traits<It1>::value_type pixel_t;
679  while (channel < num_channels<pixel_t>::value) {
680  std::uninitialized_copy(dynamic_at_c(first1,channel), dynamic_at_c(last1,channel), dynamic_at_c(first2,channel));
681  ++channel;
682  }
683  } catch (...) {
684  It2 last2=first2;
685  std::advance(last2, std::distance(first1,last1));
686  for (int c=0; c<channel; ++c)
687  destruct_range(dynamic_at_c(first2,c), dynamic_at_c(last2,c));
688  throw;
689  }
690 }
692 template <typename It1, typename It2>
693 BOOST_FORCEINLINE
694 void uninitialized_copy_aux(It1 first1, It1 last1,
695  It2 first2,mpl::false_) {
696  std::uninitialized_copy(first1,last1,first2);
697 }
698 } // namespace detail
699 
704 template <typename View1, typename View2>
705 void uninitialized_copy_pixels(const View1& view1, const View2& view2) {
706  typedef mpl::bool_<is_planar<View1>::value && is_planar<View2>::value> is_planar;
707  assert(view1.dimensions()==view2.dimensions());
708  if (view1.is_1d_traversable() && view2.is_1d_traversable())
709  detail::uninitialized_copy_aux(view1.begin().x(), view1.end().x(),
710  view2.begin().x(),
711  is_planar());
712  else {
713  typename View1::y_coord_t y = 0;
714  try {
715  for (y=0; y<view1.height(); ++y)
716  detail::uninitialized_copy_aux(view1.row_begin(y), view1.row_end(y),
717  view2.row_begin(y),
718  is_planar());
719  } catch(...) {
720  for (typename View1::y_coord_t y0=0; y0<y; ++y0)
721  detail::destruct_aux(view2.row_begin(y0),view2.row_end(y0), is_planar());
722  throw;
723  }
724  }
725 }
726 
732 
741 
743 template <typename V, typename F>
744 F for_each_pixel(const V& img, F fun) {
745  if (img.is_1d_traversable()) {
746  return std::for_each(img.begin().x(), img.end().x(), fun);
747  } else {
748  for (std::ptrdiff_t y=0; y<img.height(); ++y)
749  std::for_each(img.row_begin(y),img.row_end(y),fun);
750  return fun;
751  }
752 }
753 
757 
759 template <typename View, typename F>
760 F for_each_pixel_position(const View& img, F fun) {
761  typename View::xy_locator loc=img.xy_at(0,0);
762  for (std::ptrdiff_t y=0; y<img.height(); ++y) {
763  for (std::ptrdiff_t x=0; x<img.width(); ++x, ++loc.x())
764  fun(loc);
765  loc.x()-=img.width(); ++loc.y();
766  }
767  return fun;
768 }
769 
775 
779 
782 template <typename View, typename F>
783 void generate_pixels(const View& v, F fun) {
784  if (v.is_1d_traversable()) {
785  std::generate(v.begin().x(), v.end().x(), fun);
786  } else {
787  for (std::ptrdiff_t y=0; y<v.height(); ++y)
788  std::generate(v.row_begin(y),v.row_end(y),fun);
789  }
790 }
791 
797 
801 
802 template <typename I1, typename I2> BOOST_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
803 
804 namespace detail {
805 template <typename I1, typename I2>
806 struct equal_n_fn {
807  BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); }
808 };
809 
812 template<typename T, typename Cs>
813 struct equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {
814  BOOST_FORCEINLINE bool operator()(const pixel<T,Cs>* i1, std::ptrdiff_t n, const pixel<T,Cs>* i2) const {
815  return memcmp(i1, i2, n*sizeof(pixel<T,Cs>))==0;
816  }
817 };
818 template<typename T, typename Cs>
819 struct equal_n_fn<pixel<T,Cs>*, pixel<T,Cs>*> : equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {};
820 
824 template<typename IC, typename Cs>
825 struct equal_n_fn<planar_pixel_iterator<IC,Cs>, planar_pixel_iterator<IC,Cs> > {
826  BOOST_FORCEINLINE bool operator()(const planar_pixel_iterator<IC,Cs> i1, std::ptrdiff_t n, const planar_pixel_iterator<IC,Cs> i2) const {
827  std::ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type);
828 
829  for (std::ptrdiff_t i=0; i<mpl::size<Cs>::value; ++i)
830  if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0)
831  return false;
832  return true;
833  }
834 };
835 
837 template <typename Loc, typename I2> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
838 struct equal_n_fn<boost::gil::iterator_from_2d<Loc>,I2> {
839  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, I2 i2) const {
840  gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
841  gil_function_requires<boost::gil::PixelIteratorConcept<I2> >();
842  while (n>0) {
843  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
844  if (!equal_n(i1.x(), num, i2))
845  return false;
846  i1+=num;
847  i2+=num;
848  n-=num;
849  }
850  return true;
851  }
852 };
853 
855 template <typename I1, typename Loc> // I Models PixelIteratorConcept, OL Models PixelLocatorConcept
856 struct equal_n_fn<I1,boost::gil::iterator_from_2d<Loc> > {
857  BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const {
858  gil_function_requires<boost::gil::PixelIteratorConcept<I1> >();
859  gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
860  while (n>0) {
861  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
862  if (!equal_n(i1, num, i2.x()))
863  return false;
864  i1+=num;
865  i2+=num;
866  n-=num;
867  }
868  return true;
869  }
870 };
871 
873 template <typename Loc1, typename Loc2>
874 struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> > {
875  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const {
876  gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
877  gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
878  if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
879  while(n-->0) {
880  if (*i1++!=*i2++) return false;
881  }
882  }
883  while (n>0) {
884  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
885  if (!equal_n(i1.x(), num, i2.x()))
886  return false;
887  i1+=num;
888  i2+=num;
889  n-=num;
890  }
891  return true;
892  }
893 };
894 } // namespace detail
895 
896 template <typename I1, typename I2> BOOST_FORCEINLINE
897 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
898  return detail::equal_n_fn<I1,I2>()(i1,n,i2);
899 }
900 } } // namespace boost::gil
901 
902 namespace std {
914 template <typename Loc1, typename Loc2> BOOST_FORCEINLINE
916  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
917  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
918  std::ptrdiff_t n=last-first;
919  if (first.is_1d_traversable()) {
920  if (first2.is_1d_traversable())
921  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
922  else
923  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2> >()(first.x(),n, first2);
924  } else {
925  if (first2.is_1d_traversable())
926  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
927  else
928  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> >()(first,n,first2);
929  }
930 }
931 } // namespace std
932 
933 namespace boost { namespace gil {
936 template <typename View1, typename View2> BOOST_FORCEINLINE
937 bool equal_pixels(const View1& v1, const View2& v2) {
938  assert(v1.dimensions()==v2.dimensions());
939  return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance
940 }
941 
947 
951 
954 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
955 F transform_pixels(const View1& src,const View2& dst, F fun) {
956  assert(src.dimensions()==dst.dimensions());
957  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
958  typename View1::x_iterator srcIt=src.row_begin(y);
959  typename View2::x_iterator dstIt=dst.row_begin(y);
960  for (std::ptrdiff_t x=0; x<src.width(); ++x)
961  dstIt[x]=fun(srcIt[x]);
962  }
963  return fun;
964 }
965 
968 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
969 F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) {
970  for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
971  typename View1::x_iterator srcIt1=src1.row_begin(y);
972  typename View2::x_iterator srcIt2=src2.row_begin(y);
973  typename View3::x_iterator dstIt=dst.row_begin(y);
974  for (std::ptrdiff_t x=0; x<dst.width(); ++x)
975  dstIt[x]=fun(srcIt1[x],srcIt2[x]);
976  }
977  return fun;
978 }
979 
983 
986 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
987 F transform_pixel_positions(const View1& src,const View2& dst, F fun) {
988  assert(src.dimensions()==dst.dimensions());
989  typename View1::xy_locator loc=src.xy_at(0,0);
990  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
991  typename View2::x_iterator dstIt=dst.row_begin(y);
992  for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
993  dstIt[x]=fun(loc);
994  loc.x()-=src.width(); ++loc.y();
995  }
996  return fun;
997 }
998 
1001 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
1002 F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) {
1003  assert(src1.dimensions()==dst.dimensions());
1004  assert(src2.dimensions()==dst.dimensions());
1005  typename View1::xy_locator loc1=src1.xy_at(0,0);
1006  typename View2::xy_locator loc2=src2.xy_at(0,0);
1007  for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
1008  typename View3::x_iterator dstIt=dst.row_begin(y);
1009  for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
1010  dstIt[x]=fun(loc1,loc2);
1011  loc1.x()-=src1.width(); ++loc1.y();
1012  loc2.x()-=src2.width(); ++loc2.y();
1013  }
1014  return fun;
1015 }
1016 } } // namespace boost::gil
1017 
1018 #endif
void uninitialized_fill_pixels(const View &img_view, const Value &val)
std::uninitialized_fill for image views. Does not support planar heterogeneous views. If an exception is thrown destructs any in-place copy-constructed pixels
Definition: algorithm.hpp:522
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept, PixelValueConcept, HomogeneousPixelBasedConcept.
Definition: metafunctions.hpp:30
void generate_pixels(const View &v, F fun)
std::generate for image views
Definition: algorithm.hpp:783
BOOST_FORCEINLINE F transform_pixels(const View1 &src1, const View2 &src2, const View3 &dst, F fun)
transform_pixels with two sources
Definition: algorithm.hpp:969
An iterator over planar pixels. Models HomogeneousColorBaseConcept, PixelIteratorConcept, HomogeneousPixelBasedConcept, MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept.
Definition: algorithm.hpp:34
Definition: algorithm.hpp:171
Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept.
Definition: iterator_from_2d.hpp:43
Memory-based pixel locator. Models: PixelLocatorConcept,HasDynamicXStepTypeConcept,HasDynamicYStepTypeConcept,HasTransposedTypeConceptThe class takes a step iterator as a parameter. The step iterator provides navigation along the vertical axis while its base iterator provides horizontal navigation.
Definition: algorithm.hpp:38
BOOST_FORCEINLINE bool equal_pixels(const View1 &v1, const View2 &v2)
std::equal for image views
Definition: algorithm.hpp:937
void fill(boost::gil::iterator_from_2d< IL > first, boost::gil::iterator_from_2d< IL > last, const V &val)
std::fill(I,I,V) with I being a iterator_from_2d
Definition: algorithm.hpp:349
Returns whether two views are compatible.
Definition: concepts.hpp:2128
BOOST_FORCEINLINE void copy_pixels(const View1 &src, const View2 &dst)
std::copy for image views
Definition: algorithm.hpp:270
BOOST_FORCEINLINE void fill_pixels(const View &img_view, const Value &val)
std::fill for image views
Definition: algorithm.hpp:392
void default_construct_pixels(const View &img_view)
Invokes the in-place default constructor on every pixel of the (uninitialized) view. Does not support planar heterogeneous views. If an exception is thrown destructs any in-place default-constructed pixels.
Definition: algorithm.hpp:652
BOOST_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)
std::copy(I1,I1,I2) with I1 and I2 being a iterator_from_2d
Definition: algorithm.hpp:261
BOOST_FORCEINLINE 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)
Copy when both src and dst are planar pointers is copy for each channel.
Definition: algorithm.hpp:159
BOOST_FORCEINLINE bool equal(boost::gil::iterator_from_2d< Loc1 > first, boost::gil::iterator_from_2d< Loc1 > last, boost::gil::iterator_from_2d< Loc2 > first2)
std::equal(I1,I1,I2) with I1 and I2 being a iterator_from_2d
Definition: algorithm.hpp:915
A generic binary operation on viewsUse this class as a convenience superclass when defining an operat...
Definition: algorithm.hpp:81
struct to do std::fill
Definition: algorithm.hpp:369
BOOST_FORCEINLINE F transform_pixel_positions(const View1 &src1, const View2 &src2, const View3 &dst, F fun)
transform_pixel_positions with two sources
Definition: algorithm.hpp:1002
void uninitialized_copy_pixels(const View1 &view1, const View2 &view2)
std::uninitialized_copy for image views. Does not support planar heterogeneous views. If an exception is thrown destructs any in-place copy-constructed objects
Definition: algorithm.hpp:705
BOOST_FORCEINLINE void destruct_pixels(const View &img_view)
Invokes the in-place destructor on every pixel of the view.
Definition: algorithm.hpp:465
MEMORY-BASED STEP ITERATOR.
Definition: algorithm.hpp:36