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 
22 #include <algorithm>
23 #include <cstddef>
24 #include <cstring>
25 #include <iterator>
26 #include <memory>
27 #include <type_traits>
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 
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 Iterator>
415 BOOST_FORCEINLINE
416 void destruct_range_impl(Iterator first, Iterator last,
417  typename std::enable_if
418  <
419  mpl::and_
420  <
421  is_pointer<Iterator>,
422  mpl::not_<std::is_trivially_destructible<typename std::iterator_traits<Iterator>::value_type>>
423  >::value
424  >::type* /*ptr*/ = 0)
425 {
426  while (first != last)
427  {
428  first->~value_t();
429  ++first;
430  }
431 }
432 
433 template <typename Iterator>
434 BOOST_FORCEINLINE
435 void destruct_range_impl(Iterator /*first*/, Iterator /*last*/,
436  typename std::enable_if
437  <
438  mpl::or_
439  <
440  mpl::not_<is_pointer<Iterator>>,
441  std::is_trivially_destructible<typename std::iterator_traits<Iterator>::value_type>
442  >::value
443  >::type* /* ptr */ = nullptr)
444 {
445 }
446 
447 template <typename Iterator>
448 BOOST_FORCEINLINE
449 void destruct_range(Iterator first, Iterator last)
450 {
451  destruct_range_impl(first, last);
452 }
453 
454 struct std_destruct_t
455 {
456  template <typename Iterator>
457  void operator()(Iterator first, Iterator last) const
458  {
459  destruct_range(first,last);
460  }
461 };
462 
464 template <typename It>
465 BOOST_FORCEINLINE
466 void destruct_aux(It first, It last, mpl::true_) {
467  static_for_each(first,last,std_destruct_t());
468 }
470 template <typename It>
471 BOOST_FORCEINLINE
472 void destruct_aux(It first, It last, mpl::false_) {
473  destruct_range(first,last);
474 }
475 } // namespace detail
476 
479 template <typename View> BOOST_FORCEINLINE
480 void destruct_pixels(const View& img_view) {
481  if (img_view.is_1d_traversable())
482  detail::destruct_aux(img_view.begin().x(), img_view.end().x(),
483  is_planar<View>());
484  else
485  for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
486  detail::destruct_aux(img_view.row_begin(y),img_view.row_end(y),
487  is_planar<View>());
488 }
489 
495 
499 
500 namespace detail {
503 template <typename It, typename P>
504 BOOST_FORCEINLINE
505 void uninitialized_fill_aux(It first, It last,
506  const P& p, mpl::true_) {
507  int channel=0;
508  try {
509  using pixel_t = typename std::iterator_traits<It>::value_type;
510  while (channel < num_channels<pixel_t>::value) {
511  std::uninitialized_fill(dynamic_at_c(first,channel), dynamic_at_c(last,channel),
512  dynamic_at_c(p,channel));
513  ++channel;
514  }
515  } catch (...) {
516  for (int c=0; c<channel; ++c)
517  destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
518  throw;
519  }
520 }
521 
524 template <typename It, typename P>
525 BOOST_FORCEINLINE
526 void uninitialized_fill_aux(It first, It last,
527  const P& p,mpl::false_) {
528  std::uninitialized_fill(first,last,p);
529 }
530 } // namespace detail
531 
536 template <typename View, typename Value>
537 void uninitialized_fill_pixels(const View& img_view, const Value& val) {
538  if (img_view.is_1d_traversable())
539  detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(),
540  val,is_planar<View>());
541  else {
542  typename View::y_coord_t y = 0;
543  try {
544  for (y=0; y<img_view.height(); ++y)
545  detail::uninitialized_fill_aux(img_view.row_begin(y),img_view.row_end(y),
546  val,is_planar<View>());
547  } catch(...) {
548  for (typename View::y_coord_t y0=0; y0<y; ++y0)
549  detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>());
550  throw;
551  }
552  }
553 }
554 
560 
564 
565 namespace detail {
566 template <typename It> BOOST_FORCEINLINE
567 void default_construct_range_impl(It first, It last, mpl::true_) {
568  using value_t = typename std::iterator_traits<It>::value_type;
569  It first1=first;
570  try {
571  while (first!=last) {
572  new (first) value_t();
573  ++first;
574  }
575  } catch (...) {
576  destruct_range(first1,first);
577  throw;
578  }
579 }
580 
581 template <typename It> BOOST_FORCEINLINE
582 void default_construct_range_impl(It, It, mpl::false_) {}
583 
584 template <typename It> BOOST_FORCEINLINE
585 void default_construct_range(It first, It last) { default_construct_range_impl(first, last, typename is_pointer<It>::type()); }
586 
588 template <typename It>
589 BOOST_FORCEINLINE
590 void default_construct_aux(It first, It last, mpl::true_) {
591  int channel=0;
592  try {
593  using pixel_t = typename std::iterator_traits<It>::value_type;
594  while (channel < num_channels<pixel_t>::value) {
595  default_construct_range(dynamic_at_c(first,channel), dynamic_at_c(last,channel));
596  ++channel;
597  }
598  } catch (...) {
599  for (int c=0; c<channel; ++c)
600  destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
601  throw;
602  }
603 }
604 
606 template <typename It>
607 BOOST_FORCEINLINE
608 void default_construct_aux(It first, It last, mpl::false_) {
609  default_construct_range(first,last);
610 }
611 
612 template <typename View, bool IsPlanar>
613 struct has_trivial_pixel_constructor : public boost::has_trivial_constructor<typename View::value_type> {};
614 template <typename View>
615 struct has_trivial_pixel_constructor<View, true> : public boost::has_trivial_constructor<typename channel_type<View>::type> {};
616 } // namespace detail
617 
618 namespace detail {
619 
620 template<typename View, bool IsTriviallyConstructible>
621 BOOST_FORCEINLINE
622 void default_construct_pixels_impl(
623  View const& img_view,
624  std::enable_if<!IsTriviallyConstructible>* /* ptr */ = nullptr)
625 {
626  if( img_view.is_1d_traversable() )
627  {
628  detail::default_construct_aux( img_view.begin().x()
629  , img_view.end().x()
630  , is_planar<View>()
631  );
632  }
633  else
634  {
635  typename View::y_coord_t y = 0;
636  try
637  {
638  for( y = 0; y < img_view.height(); ++y )
639  {
640  detail::default_construct_aux( img_view.row_begin( y )
641  ,img_view.row_end( y )
642  , is_planar<View>()
643  );
644  }
645  } catch(...)
646  {
647  for (typename View::y_coord_t y0 = 0; y0 < y; ++y0 )
648  {
649  detail::destruct_aux( img_view.row_begin(y0)
650  , img_view.row_end(y0)
651  , is_planar<View>()
652  );
653  }
654 
655  throw;
656  }
657  }
658 }
659 } // namespace detail
660 
665 template <typename View>
666 void default_construct_pixels(const View& img_view) {
667  detail::default_construct_pixels_impl< View
668  , detail::has_trivial_pixel_constructor< View
669  , is_planar< View >::value
670  >::value
671  >( img_view );
672 }
673 
679 
683 
684 namespace detail {
686 template <typename It1, typename It2>
687 BOOST_FORCEINLINE
688 void uninitialized_copy_aux(It1 first1, It1 last1,
689  It2 first2, mpl::true_) {
690  int channel=0;
691  try {
692  using pixel_t = typename std::iterator_traits<It1>::value_type;
693  while (channel < num_channels<pixel_t>::value) {
694  std::uninitialized_copy(dynamic_at_c(first1,channel), dynamic_at_c(last1,channel), dynamic_at_c(first2,channel));
695  ++channel;
696  }
697  } catch (...) {
698  It2 last2=first2;
699  std::advance(last2, std::distance(first1,last1));
700  for (int c=0; c<channel; ++c)
701  destruct_range(dynamic_at_c(first2,c), dynamic_at_c(last2,c));
702  throw;
703  }
704 }
706 template <typename It1, typename It2>
707 BOOST_FORCEINLINE
708 void uninitialized_copy_aux(It1 first1, It1 last1,
709  It2 first2,mpl::false_) {
710  std::uninitialized_copy(first1,last1,first2);
711 }
712 } // namespace detail
713 
718 template <typename View1, typename View2>
719 void uninitialized_copy_pixels(const View1& view1, const View2& view2) {
720  using is_planar = mpl::bool_<is_planar<View1>::value && is_planar<View2>::value>;
721  BOOST_ASSERT(view1.dimensions() == view2.dimensions());
722  if (view1.is_1d_traversable() && view2.is_1d_traversable())
723  detail::uninitialized_copy_aux(view1.begin().x(), view1.end().x(),
724  view2.begin().x(),
725  is_planar());
726  else {
727  typename View1::y_coord_t y = 0;
728  try {
729  for (y=0; y<view1.height(); ++y)
730  detail::uninitialized_copy_aux(view1.row_begin(y), view1.row_end(y),
731  view2.row_begin(y),
732  is_planar());
733  } catch(...) {
734  for (typename View1::y_coord_t y0=0; y0<y; ++y0)
735  detail::destruct_aux(view2.row_begin(y0),view2.row_end(y0), is_planar());
736  throw;
737  }
738  }
739 }
740 
746 
755 
757 template <typename V, typename F>
758 F for_each_pixel(const V& img, F fun) {
759  if (img.is_1d_traversable()) {
760  return std::for_each(img.begin().x(), img.end().x(), fun);
761  } else {
762  for (std::ptrdiff_t y=0; y<img.height(); ++y)
763  std::for_each(img.row_begin(y),img.row_end(y),fun);
764  return fun;
765  }
766 }
767 
771 
773 template <typename View, typename F>
774 F for_each_pixel_position(const View& img, F fun) {
775  typename View::xy_locator loc=img.xy_at(0,0);
776  for (std::ptrdiff_t y=0; y<img.height(); ++y) {
777  for (std::ptrdiff_t x=0; x<img.width(); ++x, ++loc.x())
778  fun(loc);
779  loc.x()-=img.width(); ++loc.y();
780  }
781  return fun;
782 }
783 
789 
793 
796 template <typename View, typename F>
797 void generate_pixels(const View& v, F fun) {
798  if (v.is_1d_traversable()) {
799  std::generate(v.begin().x(), v.end().x(), fun);
800  } else {
801  for (std::ptrdiff_t y=0; y<v.height(); ++y)
802  std::generate(v.row_begin(y),v.row_end(y),fun);
803  }
804 }
805 
811 
815 
816 template <typename I1, typename I2> BOOST_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
817 
818 namespace detail {
819 template <typename I1, typename I2>
820 struct equal_n_fn {
821  BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); }
822 };
823 
826 template<typename T, typename Cs>
827 struct equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {
828  BOOST_FORCEINLINE bool operator()(const pixel<T,Cs>* i1, std::ptrdiff_t n, const pixel<T,Cs>* i2) const {
829  return memcmp(i1, i2, n*sizeof(pixel<T,Cs>))==0;
830  }
831 };
832 template<typename T, typename Cs>
833 struct equal_n_fn<pixel<T,Cs>*, pixel<T,Cs>*> : equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {};
834 
838 template<typename IC, typename Cs>
839 struct equal_n_fn<planar_pixel_iterator<IC,Cs>, planar_pixel_iterator<IC,Cs> > {
840  BOOST_FORCEINLINE bool operator()(const planar_pixel_iterator<IC,Cs> i1, std::ptrdiff_t n, const planar_pixel_iterator<IC,Cs> i2) const {
841  std::ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type);
842 
843  for (std::ptrdiff_t i=0; i<mpl::size<Cs>::value; ++i)
844  if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0)
845  return false;
846  return true;
847  }
848 };
849 
851 template <typename Loc, typename I2> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
852 struct equal_n_fn<boost::gil::iterator_from_2d<Loc>,I2> {
853  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, I2 i2) const {
854  gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
855  gil_function_requires<boost::gil::PixelIteratorConcept<I2> >();
856  while (n>0) {
857  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
858  if (!equal_n(i1.x(), num, i2))
859  return false;
860  i1+=num;
861  i2+=num;
862  n-=num;
863  }
864  return true;
865  }
866 };
867 
869 template <typename I1, typename Loc> // I Models PixelIteratorConcept, OL Models PixelLocatorConcept
870 struct equal_n_fn<I1,boost::gil::iterator_from_2d<Loc> > {
871  BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const {
872  gil_function_requires<boost::gil::PixelIteratorConcept<I1> >();
873  gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
874  while (n>0) {
875  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
876  if (!equal_n(i1, num, i2.x()))
877  return false;
878  i1+=num;
879  i2+=num;
880  n-=num;
881  }
882  return true;
883  }
884 };
885 
887 template <typename Loc1, typename Loc2>
888 struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> > {
889  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const {
890  gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
891  gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
892  if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
893  while(n-->0) {
894  if (*i1++!=*i2++) return false;
895  }
896  }
897  while (n>0) {
898  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
899  if (!equal_n(i1.x(), num, i2.x()))
900  return false;
901  i1+=num;
902  i2+=num;
903  n-=num;
904  }
905  return true;
906  }
907 };
908 } // namespace detail
909 
910 template <typename I1, typename I2> BOOST_FORCEINLINE
911 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
912  return detail::equal_n_fn<I1,I2>()(i1,n,i2);
913 }
914 } } // namespace boost::gil
915 
916 namespace std {
928 template <typename Loc1, typename Loc2> BOOST_FORCEINLINE
930  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
931  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
932  std::ptrdiff_t n=last-first;
933  if (first.is_1d_traversable()) {
934  if (first2.is_1d_traversable())
935  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
936  else
937  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2> >()(first.x(),n, first2);
938  } else {
939  if (first2.is_1d_traversable())
940  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
941  else
942  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> >()(first,n,first2);
943  }
944 }
945 } // namespace std
946 
947 namespace boost { namespace gil {
950 template <typename View1, typename View2> BOOST_FORCEINLINE
951 bool equal_pixels(const View1& v1, const View2& v2) {
952  BOOST_ASSERT(v1.dimensions() == v2.dimensions());
953  return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance
954 }
955 
961 
965 
968 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
969 F transform_pixels(const View1& src,const View2& dst, F fun) {
970  BOOST_ASSERT(src.dimensions() == dst.dimensions());
971  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
972  typename View1::x_iterator srcIt=src.row_begin(y);
973  typename View2::x_iterator dstIt=dst.row_begin(y);
974  for (std::ptrdiff_t x=0; x<src.width(); ++x)
975  dstIt[x]=fun(srcIt[x]);
976  }
977  return fun;
978 }
979 
982 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
983 F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) {
984  for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
985  typename View1::x_iterator srcIt1=src1.row_begin(y);
986  typename View2::x_iterator srcIt2=src2.row_begin(y);
987  typename View3::x_iterator dstIt=dst.row_begin(y);
988  for (std::ptrdiff_t x=0; x<dst.width(); ++x)
989  dstIt[x]=fun(srcIt1[x],srcIt2[x]);
990  }
991  return fun;
992 }
993 
997 
1000 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
1001 F transform_pixel_positions(const View1& src,const View2& dst, F fun) {
1002  BOOST_ASSERT(src.dimensions() == dst.dimensions());
1003  typename View1::xy_locator loc=src.xy_at(0,0);
1004  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1005  typename View2::x_iterator dstIt=dst.row_begin(y);
1006  for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
1007  dstIt[x]=fun(loc);
1008  loc.x()-=src.width(); ++loc.y();
1009  }
1010  return fun;
1011 }
1012 
1015 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
1016 F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) {
1017  BOOST_ASSERT(src1.dimensions() == dst.dimensions());
1018  BOOST_ASSERT(src2.dimensions() == dst.dimensions());
1019  typename View1::xy_locator loc1=src1.xy_at(0,0);
1020  typename View2::xy_locator loc2=src2.xy_at(0,0);
1021  for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
1022  typename View3::x_iterator dstIt=dst.row_begin(y);
1023  for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
1024  dstIt[x]=fun(loc1,loc2);
1025  loc1.x()-=src1.width(); ++loc1.y();
1026  loc2.x()-=src2.width(); ++loc2.y();
1027  }
1028  return fun;
1029 }
1030 } } // namespace boost::gil
1031 
1032 #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:537
Definition: algorithm.hpp:30
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept, PixelValueConcept, HomogeneousPixelBasedConcept.
Definition: metafunctions.hpp:31
void generate_pixels(const View &v, F fun)
std::generate for image views
Definition: algorithm.hpp:797
BOOST_FORCEINLINE F transform_pixels(const View1 &src1, const View2 &src2, const View3 &dst, F fun)
transform_pixels with two sources
Definition: algorithm.hpp:983
Definition: algorithm.hpp:127
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:951
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
Returns whether two views are compatible.
Definition: concepts/image_view.hpp:520
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:666
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:929
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:1016
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:719
class for color-converting one pixel to another
Definition: color_convert.hpp:282
Returns the number of channels of a pixel-based GIL construct.
Definition: locator.hpp:38
BOOST_FORCEINLINE void destruct_pixels(const View &img_view)
Invokes the in-place destructor on every pixel of the view.
Definition: algorithm.hpp:480
MEMORY-BASED STEP ITERATOR.
Definition: algorithm.hpp:36