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/assert.hpp>
18 #include <boost/config.hpp>
19 #include <boost/mpl/and.hpp>
20 #include <boost/mpl/or.hpp>
21 #include <boost/utility/enable_if.hpp>
22 
23 #include <algorithm>
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  using result_type = Result;
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  using diff_t = typename std::iterator_traits<iterator_from_2d<IL> >::difference_type;
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  using diff_t = typename std::iterator_traits<I>::difference_type;
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  using diff_t = typename iterator_from_2d<IL>::difference_type;
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  using src_x_iterator = typename SrcIterator::x_iterator;
237  using dst_x_iterator = typename DstIterator::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 {
272  BOOST_ASSERT(src.dimensions() == dst.dimensions());
273  detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
274 }
275 
281 
287 
288 namespace detail {
289 template <typename CC>
290 class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC> > {
291 private:
292  CC _cc;
293 public:
294  using result_type = typename binary_operation_obj<copy_and_convert_pixels_fn<default_color_converter> >::result_type;
295  copy_and_convert_pixels_fn() {}
296  copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {}
297  // when the two color spaces are incompatible, a color conversion is performed
298  template <typename V1, typename V2> BOOST_FORCEINLINE
299  result_type apply_incompatible(const V1& src, const V2& dst) const {
300  copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst);
301  }
302 
303  // If the two color spaces are compatible, copy_and_convert is just copy
304  template <typename V1, typename V2> BOOST_FORCEINLINE
305  result_type apply_compatible(const V1& src, const V2& dst) const {
306  copy_pixels(src,dst);
307  }
308 };
309 } // namespace detail
310 
312 template <typename V1, typename V2,typename CC>
313 BOOST_FORCEINLINE
314 void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) {
315  detail::copy_and_convert_pixels_fn<CC> ccp(cc);
316  ccp(src,dst);
317 }
318 
319 struct default_color_converter;
320 
322 template <typename View1, typename View2>
323 BOOST_FORCEINLINE
324 void copy_and_convert_pixels(const View1& src, const View2& dst) {
325  detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
326  ccp(src,dst);
327 }
328 } } // namespace boost::gil
329 
331 //
332 // std::fill and gil::fill_pixels
333 //
335 
339 
340 namespace std {
349 template <typename IL, typename V>
351  boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL> >();
352  if (first.is_1d_traversable()) {
353  std::fill(first.x(), last.x(), val);
354  } else {
355  // fill row by row
356  std::ptrdiff_t n=last-first;
357  while (n>0) {
358  std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
359  std::fill_n(first.x(), numToDo, val);
360  first+=numToDo;
361  n-=numToDo;
362  }
363  }
364 }
365 } // namespace std
366 
367 namespace boost { namespace gil {
368 namespace detail {
370 struct std_fill_t {
371  template <typename It, typename P>
372  void operator()(It first, It last, const P& p_in) {
373  std::fill(first,last,p_in);
374  }
375 };
377 template <typename It, typename P>
378 BOOST_FORCEINLINE
379 void fill_aux(It first, It last, const P& p, mpl::true_) {
380  static_for_each(first,last,p,std_fill_t());
381 }
383 template <typename It, typename P>
384 BOOST_FORCEINLINE
385 void fill_aux(It first, It last, const P& p,mpl::false_) {
386  std::fill(first,last,p);
387 }
388 } // namespace detail
389 
392 template <typename View, typename Value> BOOST_FORCEINLINE
393 void fill_pixels(const View& img_view, const Value& val) {
394  if (img_view.is_1d_traversable())
395  detail::fill_aux(img_view.begin().x(), img_view.end().x(),
396  val,is_planar<View>());
397  else
398  for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
399  detail::fill_aux(img_view.row_begin(y),img_view.row_end(y),
400  val,is_planar<View>());
401 }
402 
408 
412 
413 namespace detail {
414 template <typename It> BOOST_FORCEINLINE
415 void destruct_range_impl( It first
416  , It last
417  , typename enable_if< mpl::and_< is_pointer< It >
418  , mpl::not_< boost::has_trivial_destructor< typename std::iterator_traits<It>::value_type > >
419  >
420  >::type* /*ptr*/ = 0
421  )
422 {
423  while (first!=last) {
424  first->~value_t();
425  ++first;
426  }
427 }
428 
429 template <typename It> BOOST_FORCEINLINE
430 void destruct_range_impl( It
431  , It
432  , typename enable_if< mpl::or_< mpl::not_< is_pointer< It > >
433  , boost::has_trivial_destructor< typename std::iterator_traits< It >::value_type >
434  >
435  >::type* /* ptr */ = nullptr)
436 {}
437 
438 template <typename It> BOOST_FORCEINLINE
439 void destruct_range(It first, It last) {
440  destruct_range_impl( first
441  , last
442  );
443 }
444 
445 struct std_destruct_t {
446  template <typename It> void operator()(It first, It last) const { destruct_range(first,last); }
447 };
448 
450 template <typename It>
451 BOOST_FORCEINLINE
452 void destruct_aux(It first, It last, mpl::true_) {
453  static_for_each(first,last,std_destruct_t());
454 }
456 template <typename It>
457 BOOST_FORCEINLINE
458 void destruct_aux(It first, It last, mpl::false_) {
459  destruct_range(first,last);
460 }
461 } // namespace detail
462 
465 template <typename View> BOOST_FORCEINLINE
466 void destruct_pixels(const View& img_view) {
467  if (img_view.is_1d_traversable())
468  detail::destruct_aux(img_view.begin().x(), img_view.end().x(),
469  is_planar<View>());
470  else
471  for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
472  detail::destruct_aux(img_view.row_begin(y),img_view.row_end(y),
473  is_planar<View>());
474 }
475 
481 
485 
486 namespace detail {
489 template <typename It, typename P>
490 BOOST_FORCEINLINE
491 void uninitialized_fill_aux(It first, It last,
492  const P& p, mpl::true_) {
493  int channel=0;
494  try {
495  using pixel_t = typename std::iterator_traits<It>::value_type;
496  while (channel < num_channels<pixel_t>::value) {
497  std::uninitialized_fill(dynamic_at_c(first,channel), dynamic_at_c(last,channel),
498  dynamic_at_c(p,channel));
499  ++channel;
500  }
501  } catch (...) {
502  for (int c=0; c<channel; ++c)
503  destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
504  throw;
505  }
506 }
507 
510 template <typename It, typename P>
511 BOOST_FORCEINLINE
512 void uninitialized_fill_aux(It first, It last,
513  const P& p,mpl::false_) {
514  std::uninitialized_fill(first,last,p);
515 }
516 } // namespace detail
517 
522 template <typename View, typename Value>
523 void uninitialized_fill_pixels(const View& img_view, const Value& val) {
524  if (img_view.is_1d_traversable())
525  detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(),
526  val,is_planar<View>());
527  else {
528  typename View::y_coord_t y = 0;
529  try {
530  for (y=0; y<img_view.height(); ++y)
531  detail::uninitialized_fill_aux(img_view.row_begin(y),img_view.row_end(y),
532  val,is_planar<View>());
533  } catch(...) {
534  for (typename View::y_coord_t y0=0; y0<y; ++y0)
535  detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>());
536  throw;
537  }
538  }
539 }
540 
546 
550 
551 namespace detail {
552 template <typename It> BOOST_FORCEINLINE
553 void default_construct_range_impl(It first, It last, mpl::true_) {
554  using value_t = typename std::iterator_traits<It>::value_type;
555  It first1=first;
556  try {
557  while (first!=last) {
558  new (first) value_t();
559  ++first;
560  }
561  } catch (...) {
562  destruct_range(first1,first);
563  throw;
564  }
565 }
566 
567 template <typename It> BOOST_FORCEINLINE
568 void default_construct_range_impl(It, It, mpl::false_) {}
569 
570 template <typename It> BOOST_FORCEINLINE
571 void default_construct_range(It first, It last) { default_construct_range_impl(first, last, typename is_pointer<It>::type()); }
572 
574 template <typename It>
575 BOOST_FORCEINLINE
576 void default_construct_aux(It first, It last, mpl::true_) {
577  int channel=0;
578  try {
579  using pixel_t = typename std::iterator_traits<It>::value_type;
580  while (channel < num_channels<pixel_t>::value) {
581  default_construct_range(dynamic_at_c(first,channel), dynamic_at_c(last,channel));
582  ++channel;
583  }
584  } catch (...) {
585  for (int c=0; c<channel; ++c)
586  destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
587  throw;
588  }
589 }
590 
592 template <typename It>
593 BOOST_FORCEINLINE
594 void default_construct_aux(It first, It last, mpl::false_) {
595  default_construct_range(first,last);
596 }
597 
598 template <typename View, bool IsPlanar>
599 struct has_trivial_pixel_constructor : public boost::has_trivial_constructor<typename View::value_type> {};
600 template <typename View>
601 struct has_trivial_pixel_constructor<View, true> : public boost::has_trivial_constructor<typename channel_type<View>::type> {};
602 } // namespace detail
603 
604 namespace detail {
605 template< typename View, bool B > BOOST_FORCEINLINE
606 void default_construct_pixels_impl( const View& img_view
607  , boost::enable_if< is_same< mpl::bool_< B >
608  , mpl::false_
609  >
610  >* /* ptr */ = nullptr
611  )
612 {
613  if( img_view.is_1d_traversable() )
614  {
615  detail::default_construct_aux( img_view.begin().x()
616  , img_view.end().x()
617  , is_planar<View>()
618  );
619  }
620  else
621  {
622  typename View::y_coord_t y = 0;
623  try
624  {
625  for( y = 0; y < img_view.height(); ++y )
626  {
627  detail::default_construct_aux( img_view.row_begin( y )
628  ,img_view.row_end( y )
629  , is_planar<View>()
630  );
631  }
632  } catch(...)
633  {
634  for (typename View::y_coord_t y0 = 0; y0 < y; ++y0 )
635  {
636  detail::destruct_aux( img_view.row_begin(y0)
637  , img_view.row_end(y0)
638  , is_planar<View>()
639  );
640  }
641 
642  throw;
643  }
644  }
645 }
646 } // namespace detail
647 
652 template <typename View>
653 void default_construct_pixels(const View& img_view) {
654  detail::default_construct_pixels_impl< View
655  , detail::has_trivial_pixel_constructor< View
656  , is_planar< View >::value
657  >::value
658  >( img_view );
659 }
660 
666 
670 
671 namespace detail {
673 template <typename It1, typename It2>
674 BOOST_FORCEINLINE
675 void uninitialized_copy_aux(It1 first1, It1 last1,
676  It2 first2, mpl::true_) {
677  int channel=0;
678  try {
679  using pixel_t = typename std::iterator_traits<It1>::value_type;
680  while (channel < num_channels<pixel_t>::value) {
681  std::uninitialized_copy(dynamic_at_c(first1,channel), dynamic_at_c(last1,channel), dynamic_at_c(first2,channel));
682  ++channel;
683  }
684  } catch (...) {
685  It2 last2=first2;
686  std::advance(last2, std::distance(first1,last1));
687  for (int c=0; c<channel; ++c)
688  destruct_range(dynamic_at_c(first2,c), dynamic_at_c(last2,c));
689  throw;
690  }
691 }
693 template <typename It1, typename It2>
694 BOOST_FORCEINLINE
695 void uninitialized_copy_aux(It1 first1, It1 last1,
696  It2 first2,mpl::false_) {
697  std::uninitialized_copy(first1,last1,first2);
698 }
699 } // namespace detail
700 
705 template <typename View1, typename View2>
706 void uninitialized_copy_pixels(const View1& view1, const View2& view2) {
707  using is_planar = mpl::bool_<is_planar<View1>::value && is_planar<View2>::value>;
708  BOOST_ASSERT(view1.dimensions() == view2.dimensions());
709  if (view1.is_1d_traversable() && view2.is_1d_traversable())
710  detail::uninitialized_copy_aux(view1.begin().x(), view1.end().x(),
711  view2.begin().x(),
712  is_planar());
713  else {
714  typename View1::y_coord_t y = 0;
715  try {
716  for (y=0; y<view1.height(); ++y)
717  detail::uninitialized_copy_aux(view1.row_begin(y), view1.row_end(y),
718  view2.row_begin(y),
719  is_planar());
720  } catch(...) {
721  for (typename View1::y_coord_t y0=0; y0<y; ++y0)
722  detail::destruct_aux(view2.row_begin(y0),view2.row_end(y0), is_planar());
723  throw;
724  }
725  }
726 }
727 
733 
742 
744 template <typename V, typename F>
745 F for_each_pixel(const V& img, F fun) {
746  if (img.is_1d_traversable()) {
747  return std::for_each(img.begin().x(), img.end().x(), fun);
748  } else {
749  for (std::ptrdiff_t y=0; y<img.height(); ++y)
750  std::for_each(img.row_begin(y),img.row_end(y),fun);
751  return fun;
752  }
753 }
754 
758 
760 template <typename View, typename F>
761 F for_each_pixel_position(const View& img, F fun) {
762  typename View::xy_locator loc=img.xy_at(0,0);
763  for (std::ptrdiff_t y=0; y<img.height(); ++y) {
764  for (std::ptrdiff_t x=0; x<img.width(); ++x, ++loc.x())
765  fun(loc);
766  loc.x()-=img.width(); ++loc.y();
767  }
768  return fun;
769 }
770 
776 
780 
783 template <typename View, typename F>
784 void generate_pixels(const View& v, F fun) {
785  if (v.is_1d_traversable()) {
786  std::generate(v.begin().x(), v.end().x(), fun);
787  } else {
788  for (std::ptrdiff_t y=0; y<v.height(); ++y)
789  std::generate(v.row_begin(y),v.row_end(y),fun);
790  }
791 }
792 
798 
802 
803 template <typename I1, typename I2> BOOST_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
804 
805 namespace detail {
806 template <typename I1, typename I2>
807 struct equal_n_fn {
808  BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); }
809 };
810 
813 template<typename T, typename Cs>
814 struct equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {
815  BOOST_FORCEINLINE bool operator()(const pixel<T,Cs>* i1, std::ptrdiff_t n, const pixel<T,Cs>* i2) const {
816  return memcmp(i1, i2, n*sizeof(pixel<T,Cs>))==0;
817  }
818 };
819 template<typename T, typename Cs>
820 struct equal_n_fn<pixel<T,Cs>*, pixel<T,Cs>*> : equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {};
821 
825 template<typename IC, typename Cs>
826 struct equal_n_fn<planar_pixel_iterator<IC,Cs>, planar_pixel_iterator<IC,Cs> > {
827  BOOST_FORCEINLINE bool operator()(const planar_pixel_iterator<IC,Cs> i1, std::ptrdiff_t n, const planar_pixel_iterator<IC,Cs> i2) const {
828  std::ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type);
829 
830  for (std::ptrdiff_t i=0; i<mpl::size<Cs>::value; ++i)
831  if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0)
832  return false;
833  return true;
834  }
835 };
836 
838 template <typename Loc, typename I2> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
839 struct equal_n_fn<boost::gil::iterator_from_2d<Loc>,I2> {
840  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, I2 i2) const {
841  gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
842  gil_function_requires<boost::gil::PixelIteratorConcept<I2> >();
843  while (n>0) {
844  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
845  if (!equal_n(i1.x(), num, i2))
846  return false;
847  i1+=num;
848  i2+=num;
849  n-=num;
850  }
851  return true;
852  }
853 };
854 
856 template <typename I1, typename Loc> // I Models PixelIteratorConcept, OL Models PixelLocatorConcept
857 struct equal_n_fn<I1,boost::gil::iterator_from_2d<Loc> > {
858  BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const {
859  gil_function_requires<boost::gil::PixelIteratorConcept<I1> >();
860  gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
861  while (n>0) {
862  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
863  if (!equal_n(i1, num, i2.x()))
864  return false;
865  i1+=num;
866  i2+=num;
867  n-=num;
868  }
869  return true;
870  }
871 };
872 
874 template <typename Loc1, typename Loc2>
875 struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> > {
876  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const {
877  gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
878  gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
879  if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
880  while(n-->0) {
881  if (*i1++!=*i2++) return false;
882  }
883  }
884  while (n>0) {
885  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
886  if (!equal_n(i1.x(), num, i2.x()))
887  return false;
888  i1+=num;
889  i2+=num;
890  n-=num;
891  }
892  return true;
893  }
894 };
895 } // namespace detail
896 
897 template <typename I1, typename I2> BOOST_FORCEINLINE
898 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
899  return detail::equal_n_fn<I1,I2>()(i1,n,i2);
900 }
901 } } // namespace boost::gil
902 
903 namespace std {
915 template <typename Loc1, typename Loc2> BOOST_FORCEINLINE
917  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
918  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
919  std::ptrdiff_t n=last-first;
920  if (first.is_1d_traversable()) {
921  if (first2.is_1d_traversable())
922  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
923  else
924  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2> >()(first.x(),n, first2);
925  } else {
926  if (first2.is_1d_traversable())
927  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
928  else
929  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> >()(first,n,first2);
930  }
931 }
932 } // namespace std
933 
934 namespace boost { namespace gil {
937 template <typename View1, typename View2> BOOST_FORCEINLINE
938 bool equal_pixels(const View1& v1, const View2& v2) {
939  BOOST_ASSERT(v1.dimensions() == v2.dimensions());
940  return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance
941 }
942 
948 
952 
955 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
956 F transform_pixels(const View1& src,const View2& dst, F fun) {
957  BOOST_ASSERT(src.dimensions() == dst.dimensions());
958  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
959  typename View1::x_iterator srcIt=src.row_begin(y);
960  typename View2::x_iterator dstIt=dst.row_begin(y);
961  for (std::ptrdiff_t x=0; x<src.width(); ++x)
962  dstIt[x]=fun(srcIt[x]);
963  }
964  return fun;
965 }
966 
969 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
970 F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) {
971  for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
972  typename View1::x_iterator srcIt1=src1.row_begin(y);
973  typename View2::x_iterator srcIt2=src2.row_begin(y);
974  typename View3::x_iterator dstIt=dst.row_begin(y);
975  for (std::ptrdiff_t x=0; x<dst.width(); ++x)
976  dstIt[x]=fun(srcIt1[x],srcIt2[x]);
977  }
978  return fun;
979 }
980 
984 
987 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
988 F transform_pixel_positions(const View1& src,const View2& dst, F fun) {
989  BOOST_ASSERT(src.dimensions() == dst.dimensions());
990  typename View1::xy_locator loc=src.xy_at(0,0);
991  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
992  typename View2::x_iterator dstIt=dst.row_begin(y);
993  for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
994  dstIt[x]=fun(loc);
995  loc.x()-=src.width(); ++loc.y();
996  }
997  return fun;
998 }
999 
1002 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
1003 F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) {
1004  BOOST_ASSERT(src1.dimensions() == dst.dimensions());
1005  BOOST_ASSERT(src2.dimensions() == dst.dimensions());
1006  typename View1::xy_locator loc1=src1.xy_at(0,0);
1007  typename View2::xy_locator loc2=src2.xy_at(0,0);
1008  for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
1009  typename View3::x_iterator dstIt=dst.row_begin(y);
1010  for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
1011  dstIt[x]=fun(loc1,loc2);
1012  loc1.x()-=src1.width(); ++loc1.y();
1013  loc2.x()-=src2.width(); ++loc2.y();
1014  }
1015  return fun;
1016 }
1017 } } // namespace boost::gil
1018 
1019 #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:523
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:784
BOOST_FORCEINLINE F transform_pixels(const View1 &src1, const View2 &src2, const View3 &dst, F fun)
transform_pixels with two sources
Definition: algorithm.hpp:970
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:42
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:938
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:350
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:393
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:653
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:916
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:370
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:1003
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:706
BOOST_FORCEINLINE void destruct_pixels(const View &img_view)
Invokes the in-place destructor on every pixel of the view.
Definition: algorithm.hpp:466
MEMORY-BASED STEP ITERATOR.
Definition: algorithm.hpp:36