Boost GIL


algorithm.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2005-2007 Adobe Systems Incorporated
3 
4  Use, modification and distribution are subject to the Boost Software License,
5  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6  http://www.boost.org/LICENSE_1_0.txt).
7 
8  See http://opensource.adobe.com/gil for most recent version including documentation.
9 */
10 
11 /*************************************************************************************************/
12 
13 #ifndef GIL_ALGORITHM_HPP
14 #define GIL_ALGORITHM_HPP
15 
16 #include <cassert>
17 #include <cstddef>
18 #include <cstring>
19 #include <algorithm>
20 #include <iterator>
21 #include <memory>
22 #include <typeinfo>
23 
24 #include <boost/config.hpp>
25 #include <boost/utility/enable_if.hpp>
26 #include <boost/mpl/and.hpp>
27 #include <boost/mpl/or.hpp>
28 
29 #include "gil_concept.hpp"
30 #include "color_base_algorithm.hpp"
31 #include "image_view.hpp"
32 #include "image_view_factory.hpp"
34 
43 
44 //#ifdef _MSC_VER
45 //#pragma warning(push)
46 //#pragma warning(disable : 4244) // conversion from 'gil::image<V,Alloc>::coord_t' to 'int', possible loss of data (visual studio compiler doesn't realize that the two types are the same)
47 //#endif
48 
49 namespace boost { namespace gil {
50 //forward declarations
51 template <typename ChannelPtr, typename ColorSpace>
53 template <typename Iterator>
55 template <typename StepIterator>
57 
58 // a tag denoting incompatible arguments
59 struct error_t {};
60 
85 
89 
98 template <typename Derived, typename Result=void>
100  typedef Result result_type;
101 
102  template <typename V1, typename V2> BOOST_FORCEINLINE
103  result_type operator()(const std::pair<const V1*,const V2*>& p) const {
104  return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type());
105  }
106 
107  template <typename V1, typename V2> BOOST_FORCEINLINE
108  result_type operator()(const V1& v1, const V2& v2) const {
109  return apply(v1, v2, typename views_are_compatible<V1,V2>::type());
110  }
111 
112  result_type operator()(const error_t&) const { throw std::bad_cast(); }
113 private:
114 
115  // dispatch from apply overload to a function with distinct name
116  template <typename V1, typename V2>
117  BOOST_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::false_) const {
118  return ((const Derived*)this)->apply_incompatible(v1,v2);
119  }
120 
121  // dispatch from apply overload to a function with distinct name
122  template <typename V1, typename V2>
123  BOOST_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::true_) const {
124  return ((const Derived*)this)->apply_compatible(v1,v2);
125  }
126 
127  // function with distinct name - it can be overloaded by subclasses
128  template <typename V1, typename V2>
129  BOOST_FORCEINLINE result_type apply_incompatible(const V1&, const V2&) const {
130  throw std::bad_cast();
131  }
132 };
133 } } // namespace boost::gil
134 
140 
144 
145 namespace std {
148 template<typename T, typename Cs>
149 BOOST_FORCEINLINE boost::gil::pixel<T,Cs>*
152  return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
153 }
154 
157 template<typename T, typename Cs>
158 BOOST_FORCEINLINE boost::gil::pixel<T,Cs>*
161  return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
162 }
163 } // namespace std
164 
165 namespace boost { namespace gil {
166 namespace detail {
167 template <typename I, typename O> struct copy_fn {
168  BOOST_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); }
169 };
170 } // namespace detail
171 } } // namespace boost::gil
172 
173 namespace std {
176 template<typename Cs, typename IC1, typename IC2> BOOST_FORCEINLINE
178  boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type> >();
179  static_for_each(first,last,dst,boost::gil::detail::copy_fn<IC1,IC2>());
180  return dst+(last-first);
181 }
182 } // namespace std
183 
184 namespace boost { namespace gil {
185 namespace detail {
188 template <typename I, typename O>
189 struct copier_n {
190  BOOST_FORCEINLINE void operator()(I src, typename std::iterator_traits<I>::difference_type n, O dst) const { std::copy(src,src+n, dst); }
191 };
192 
194 template <typename IL, typename O> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
195 struct copier_n<iterator_from_2d<IL>,O> {
196  typedef typename std::iterator_traits<iterator_from_2d<IL> >::difference_type diff_t;
197  BOOST_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, O dst) const {
198  gil_function_requires<PixelLocatorConcept<IL> >();
199  gil_function_requires<MutablePixelIteratorConcept<O> >();
200  while (n>0) {
201  diff_t l=src.width()-src.x_pos();
202  diff_t numToCopy=(n<l ? n:l);
203  detail::copy_n(src.x(), numToCopy, dst);
204  dst+=numToCopy;
205  src+=numToCopy;
206  n-=numToCopy;
207  }
208  }
209 };
210 
212 template <typename I, typename OL> // I Models ConstPixelIteratorConcept, OL Models PixelLocatorConcept
213 struct copier_n<I,iterator_from_2d<OL> > {
214  typedef typename std::iterator_traits<I>::difference_type diff_t;
215  BOOST_FORCEINLINE void operator()(I src, diff_t n, iterator_from_2d<OL> dst) const {
216  gil_function_requires<PixelIteratorConcept<I> >();
217  gil_function_requires<MutablePixelLocatorConcept<OL> >();
218  while (n>0) {
219  diff_t l=dst.width()-dst.x_pos();
220  diff_t numToCopy=(n<l ? n:l);
221  detail::copy_n(src, numToCopy, dst.x());
222  dst+=numToCopy;
223  src+=numToCopy;
224  n-=numToCopy;
225  }
226  }
227 };
228 
230 template <typename IL, typename OL>
232  typedef typename iterator_from_2d<IL>::difference_type diff_t;
233  BOOST_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, iterator_from_2d<OL> dst) const {
234  gil_function_requires<PixelLocatorConcept<IL> >();
235  gil_function_requires<MutablePixelLocatorConcept<OL> >();
236  if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
237  while(n-->0) {
238  *dst++=*src++;
239  }
240  }
241  while (n>0) {
242  diff_t l=dst.width()-dst.x_pos();
243  diff_t numToCopy=(n<l ? n : l);
244  detail::copy_n(src.x(), numToCopy, dst.x());
245  dst+=numToCopy;
246  src+=numToCopy;
247  n-=numToCopy;
248  }
249  }
250 };
251 
252 template <typename SrcIterator, typename DstIterator>
253 BOOST_FORCEINLINE DstIterator copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) {
254  typedef typename SrcIterator::x_iterator src_x_iterator;
255  typedef typename DstIterator::x_iterator dst_x_iterator;
256 
257  typename SrcIterator::difference_type n = last - first;
258 
259  if (first.is_1d_traversable()) {
260  if (dst.is_1d_traversable())
261  copier_n<src_x_iterator,dst_x_iterator>()(first.x(),n, dst.x());
262  else
263  copier_n<src_x_iterator,DstIterator >()(first.x(),n, dst);
264  } else {
265  if (dst.is_1d_traversable())
266  copier_n<SrcIterator,dst_x_iterator>()(first,n, dst.x());
267  else
268  copier_n<SrcIterator,DstIterator>()(first,n,dst);
269  }
270  return dst+n;
271 }
272 } // namespace detail
273 } } // namespace boost::gil
274 
275 namespace std {
278 template <typename IL, typename OL>
280  return boost::gil::detail::copy_with_2d_iterators(first,last,dst);
281 }
282 } // namespace std
283 
284 namespace boost { namespace gil {
287 template <typename View1, typename View2> BOOST_FORCEINLINE
288 void copy_pixels(const View1& src, const View2& dst) {
289  assert(src.dimensions()==dst.dimensions());
290  detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
291 }
292 
298 
304 
305 namespace detail {
306 template <typename CC>
307 class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC> > {
308 private:
309  CC _cc;
310 public:
311  typedef typename binary_operation_obj<copy_and_convert_pixels_fn<CC> >::result_type result_type;
312  copy_and_convert_pixels_fn() {}
313  copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {}
314  // when the two color spaces are incompatible, a color conversion is performed
315  template <typename V1, typename V2> BOOST_FORCEINLINE
316  result_type apply_incompatible(const V1& src, const V2& dst) const {
317  copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst);
318  }
319 
320  // If the two color spaces are compatible, copy_and_convert is just copy
321  template <typename V1, typename V2> BOOST_FORCEINLINE
322  result_type apply_compatible(const V1& src, const V2& dst) const {
323  copy_pixels(src,dst);
324  }
325 };
326 } // namespace detail
327 
329 template <typename V1, typename V2,typename CC>
330 BOOST_FORCEINLINE
331 void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) {
332  detail::copy_and_convert_pixels_fn<CC> ccp(cc);
333  ccp(src,dst);
334 }
335 
336 struct default_color_converter;
337 
339 template <typename View1, typename View2>
340 BOOST_FORCEINLINE
341 void copy_and_convert_pixels(const View1& src, const View2& dst) {
342  detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
343  ccp(src,dst);
344 }
345 } } // namespace boost::gil
346 
348 //
349 // std::fill and gil::fill_pixels
350 //
352 
356 
357 namespace std {
366 template <typename IL, typename V>
368  boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL> >();
369  if (first.is_1d_traversable()) {
370  std::fill(first.x(), last.x(), val);
371  } else {
372  // fill row by row
373  std::ptrdiff_t n=last-first;
374  while (n>0) {
375  std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
376  fill_n(first.x(), numToDo, val);
377  first+=numToDo;
378  n-=numToDo;
379  }
380  }
381 }
382 } // namespace std
383 
384 namespace boost { namespace gil {
385 namespace detail {
387 struct std_fill_t {
388  template <typename It, typename P>
389  void operator()(It first, It last, const P& p_in) {
390  std::fill(first,last,p_in);
391  }
392 };
394 template <typename It, typename P>
395 BOOST_FORCEINLINE
396 void fill_aux(It first, It last, const P& p, mpl::true_) {
397  static_for_each(first,last,p,std_fill_t());
398 }
400 template <typename It, typename P>
401 BOOST_FORCEINLINE
402 void fill_aux(It first, It last, const P& p,mpl::false_) {
403  std::fill(first,last,p);
404 }
405 } // namespace detail
406 
409 template <typename View, typename Value> BOOST_FORCEINLINE
410 void fill_pixels(const View& img_view, const Value& val) {
411  if (img_view.is_1d_traversable())
412  detail::fill_aux(img_view.begin().x(), img_view.end().x(),
413  val,is_planar<View>());
414  else
415  for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
416  detail::fill_aux(img_view.row_begin(y),img_view.row_end(y),
417  val,is_planar<View>());
418 }
419 
425 
429 
430 namespace detail {
431 template <typename It> BOOST_FORCEINLINE
432 void destruct_range_impl( It first
433  , It last
434  , typename enable_if< mpl::and_< is_pointer< It >
435  , mpl::not_< boost::has_trivial_destructor< typename std::iterator_traits<It>::value_type > >
436  >
437  >::type* /*ptr*/ = 0
438  )
439 {
440  while (first!=last) {
441  first->~value_t();
442  ++first;
443  }
444 }
445 
446 template <typename It> BOOST_FORCEINLINE
447 void destruct_range_impl( It
448  , It
449  , typename enable_if< mpl::or_< mpl::not_< is_pointer< It > >
450  , boost::has_trivial_destructor< typename std::iterator_traits< It >::value_type >
451  >
452  >::type* /* ptr */ = 0)
453 {}
454 
455 template <typename It> BOOST_FORCEINLINE
456 void destruct_range(It first, It last) {
457  destruct_range_impl( first
458  , last
459  );
460 }
461 
462 struct std_destruct_t {
463  template <typename It> void operator()(It first, It last) const { destruct_range(first,last); }
464 };
465 
467 template <typename It>
468 BOOST_FORCEINLINE
469 void destruct_aux(It first, It last, mpl::true_) {
470  static_for_each(first,last,std_destruct_t());
471 }
473 template <typename It>
474 BOOST_FORCEINLINE
475 void destruct_aux(It first, It last, mpl::false_) {
476  destruct_range(first,last);
477 }
478 } // namespace detail
479 
482 template <typename View> BOOST_FORCEINLINE
483 void destruct_pixels(const View& img_view) {
484  if (img_view.is_1d_traversable())
485  detail::destruct_aux(img_view.begin().x(), img_view.end().x(),
486  is_planar<View>());
487  else
488  for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
489  detail::destruct_aux(img_view.row_begin(y),img_view.row_end(y),
490  is_planar<View>());
491 }
492 
498 
502 
503 namespace detail {
506 template <typename It, typename P>
507 BOOST_FORCEINLINE
508 void uninitialized_fill_aux(It first, It last,
509  const P& p, mpl::true_) {
510  int channel=0;
511  try {
512  typedef typename std::iterator_traits<It>::value_type pixel_t;
513  while (channel < num_channels<pixel_t>::value) {
514  std::uninitialized_fill(dynamic_at_c(first,channel), dynamic_at_c(last,channel),
515  dynamic_at_c(p,channel));
516  ++channel;
517  }
518  } catch (...) {
519  for (int c=0; c<channel; ++c)
520  destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
521  throw;
522  }
523 }
524 
527 template <typename It, typename P>
528 BOOST_FORCEINLINE
529 void uninitialized_fill_aux(It first, It last,
530  const P& p,mpl::false_) {
531  std::uninitialized_fill(first,last,p);
532 }
533 } // namespace detail
534 
539 template <typename View, typename Value>
540 void uninitialized_fill_pixels(const View& img_view, const Value& val) {
541  if (img_view.is_1d_traversable())
542  detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(),
543  val,is_planar<View>());
544  else {
545  typename View::y_coord_t y = 0;
546  try {
547  for (y=0; y<img_view.height(); ++y)
548  detail::uninitialized_fill_aux(img_view.row_begin(y),img_view.row_end(y),
549  val,is_planar<View>());
550  } catch(...) {
551  for (typename View::y_coord_t y0=0; y0<y; ++y0)
552  detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>());
553  throw;
554  }
555  }
556 }
557 
563 
567 
568 namespace detail {
569 template <typename It> BOOST_FORCEINLINE
570 void default_construct_range_impl(It first, It last, mpl::true_) {
571  typedef typename std::iterator_traits<It>::value_type value_t;
572  It first1=first;
573  try {
574  while (first!=last) {
575  new (first) value_t();
576  ++first;
577  }
578  } catch (...) {
579  destruct_range(first1,first);
580  throw;
581  }
582 }
583 
584 template <typename It> BOOST_FORCEINLINE
585 void default_construct_range_impl(It, It, mpl::false_) {}
586 
587 template <typename It> BOOST_FORCEINLINE
588 void default_construct_range(It first, It last) { default_construct_range_impl(first, last, typename is_pointer<It>::type()); }
589 
591 template <typename It>
592 BOOST_FORCEINLINE
593 void default_construct_aux(It first, It last, mpl::true_) {
594  int channel=0;
595  try {
596  typedef typename std::iterator_traits<It>::value_type pixel_t;
597  while (channel < num_channels<pixel_t>::value) {
598  default_construct_range(dynamic_at_c(first,channel), dynamic_at_c(last,channel));
599  ++channel;
600  }
601  } catch (...) {
602  for (int c=0; c<channel; ++c)
603  destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
604  throw;
605  }
606 }
607 
609 template <typename It>
610 BOOST_FORCEINLINE
611 void default_construct_aux(It first, It last, mpl::false_) {
612  default_construct_range(first,last);
613 }
614 
615 template <typename View, bool IsPlanar>
616 struct has_trivial_pixel_constructor : public boost::has_trivial_constructor<typename View::value_type> {};
617 template <typename View>
618 struct has_trivial_pixel_constructor<View, true> : public boost::has_trivial_constructor<typename channel_type<View>::type> {};
619 } // namespace detail
620 
621 namespace detail {
622 template< typename View, bool B > BOOST_FORCEINLINE
623 void default_construct_pixels_impl( const View& img_view
624  , boost::enable_if< is_same< mpl::bool_< B >
625  , mpl::false_
626  >
627  >* /* ptr */ = 0
628  )
629 {
630  if( img_view.is_1d_traversable() )
631  {
632  detail::default_construct_aux( img_view.begin().x()
633  , img_view.end().x()
634  , is_planar<View>()
635  );
636  }
637  else
638  {
639  typename View::y_coord_t y = 0;
640  try
641  {
642  for( y = 0; y < img_view.height(); ++y )
643  {
644  detail::default_construct_aux( img_view.row_begin( y )
645  ,img_view.row_end( y )
646  , is_planar<View>()
647  );
648  }
649  } catch(...)
650  {
651  for (typename View::y_coord_t y0 = 0; y0 < y; ++y0 )
652  {
653  detail::destruct_aux( img_view.row_begin(y0)
654  , img_view.row_end(y0)
655  , is_planar<View>()
656  );
657  }
658 
659  throw;
660  }
661  }
662 }
663 } // namespace detail
664 
669 template <typename View>
670 void default_construct_pixels(const View& img_view) {
671  detail::default_construct_pixels_impl< View
672  , detail::has_trivial_pixel_constructor< View
673  , is_planar< View >::value
674  >::value
675  >( img_view );
676 }
677 
683 
687 
688 namespace detail {
690 template <typename It1, typename It2>
691 BOOST_FORCEINLINE
692 void uninitialized_copy_aux(It1 first1, It1 last1,
693  It2 first2, mpl::true_) {
694  int channel=0;
695  try {
696  typedef typename std::iterator_traits<It1>::value_type pixel_t;
697  while (channel < num_channels<pixel_t>::value) {
698  std::uninitialized_copy(dynamic_at_c(first1,channel), dynamic_at_c(last1,channel), dynamic_at_c(first2,channel));
699  ++channel;
700  }
701  } catch (...) {
702  It2 last2=first2;
703  std::advance(last2, std::distance(first1,last1));
704  for (int c=0; c<channel; ++c)
705  destruct_range(dynamic_at_c(first2,c), dynamic_at_c(last2,c));
706  throw;
707  }
708 }
710 template <typename It1, typename It2>
711 BOOST_FORCEINLINE
712 void uninitialized_copy_aux(It1 first1, It1 last1,
713  It2 first2,mpl::false_) {
714  std::uninitialized_copy(first1,last1,first2);
715 }
716 } // namespace detail
717 
722 template <typename View1, typename View2>
723 void uninitialized_copy_pixels(const View1& view1, const View2& view2) {
724  typedef mpl::bool_<is_planar<View1>::value && is_planar<View2>::value> is_planar;
725  assert(view1.dimensions()==view2.dimensions());
726  if (view1.is_1d_traversable() && view2.is_1d_traversable())
727  detail::uninitialized_copy_aux(view1.begin().x(), view1.end().x(),
728  view2.begin().x(),
729  is_planar());
730  else {
731  typename View1::y_coord_t y = 0;
732  try {
733  for (y=0; y<view1.height(); ++y)
734  detail::uninitialized_copy_aux(view1.row_begin(y), view1.row_end(y),
735  view2.row_begin(y),
736  is_planar());
737  } catch(...) {
738  for (typename View1::y_coord_t y0=0; y0<y; ++y0)
739  detail::destruct_aux(view2.row_begin(y0),view2.row_end(y0), is_planar());
740  throw;
741  }
742  }
743 }
744 
750 
759 
761 template <typename V, typename F>
762 F for_each_pixel(const V& img, F fun) {
763  if (img.is_1d_traversable()) {
764  return std::for_each(img.begin().x(), img.end().x(), fun);
765  } else {
766  for (std::ptrdiff_t y=0; y<img.height(); ++y)
767  std::for_each(img.row_begin(y),img.row_end(y),fun);
768  return fun;
769  }
770 }
771 
775 
777 template <typename View, typename F>
778 F for_each_pixel_position(const View& img, F fun) {
779  typename View::xy_locator loc=img.xy_at(0,0);
780  for (std::ptrdiff_t y=0; y<img.height(); ++y) {
781  for (std::ptrdiff_t x=0; x<img.width(); ++x, ++loc.x())
782  fun(loc);
783  loc.x()-=img.width(); ++loc.y();
784  }
785  return fun;
786 }
787 
793 
797 
800 template <typename View, typename F>
801 void generate_pixels(const View& v, F fun) {
802  if (v.is_1d_traversable()) {
803  std::generate(v.begin().x(), v.end().x(), fun);
804  } else {
805  for (std::ptrdiff_t y=0; y<v.height(); ++y)
806  std::generate(v.row_begin(y),v.row_end(y),fun);
807  }
808 }
809 
815 
819 
820 template <typename I1, typename I2> BOOST_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
821 
822 namespace detail {
823 template <typename I1, typename I2>
824 struct equal_n_fn {
825  BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); }
826 };
827 
830 template<typename T, typename Cs>
831 struct equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {
832  BOOST_FORCEINLINE bool operator()(const pixel<T,Cs>* i1, std::ptrdiff_t n, const pixel<T,Cs>* i2) const {
833  return memcmp(i1, i2, n*sizeof(pixel<T,Cs>))==0;
834  }
835 };
836 template<typename T, typename Cs>
837 struct equal_n_fn<pixel<T,Cs>*, pixel<T,Cs>*> : equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {};
838 
842 template<typename IC, typename Cs>
843 struct equal_n_fn<planar_pixel_iterator<IC,Cs>, planar_pixel_iterator<IC,Cs> > {
844  BOOST_FORCEINLINE bool operator()(const planar_pixel_iterator<IC,Cs> i1, std::ptrdiff_t n, const planar_pixel_iterator<IC,Cs> i2) const {
845  std::ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type);
846 
847  for (std::ptrdiff_t i=0; i<mpl::size<Cs>::value; ++i)
848  if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0)
849  return false;
850  return true;
851  }
852 };
853 
855 template <typename Loc, typename I2> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
856 struct equal_n_fn<boost::gil::iterator_from_2d<Loc>,I2> {
857  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, I2 i2) const {
858  gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
859  gil_function_requires<boost::gil::PixelIteratorConcept<I2> >();
860  while (n>0) {
861  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
862  if (!equal_n(i1.x(), num, i2))
863  return false;
864  i1+=num;
865  i2+=num;
866  n-=num;
867  }
868  return true;
869  }
870 };
871 
873 template <typename I1, typename Loc> // I Models PixelIteratorConcept, OL Models PixelLocatorConcept
874 struct equal_n_fn<I1,boost::gil::iterator_from_2d<Loc> > {
875  BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const {
876  gil_function_requires<boost::gil::PixelIteratorConcept<I1> >();
877  gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
878  while (n>0) {
879  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
880  if (!equal_n(i1, num, i2.x()))
881  return false;
882  i1+=num;
883  i2+=num;
884  n-=num;
885  }
886  return true;
887  }
888 };
889 
891 template <typename Loc1, typename Loc2>
892 struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> > {
893  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const {
894  gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
895  gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
896  if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
897  while(n-->0) {
898  if (*i1++!=*i2++) return false;
899  }
900  }
901  while (n>0) {
902  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
903  if (!equal_n(i1.x(), num, i2.x()))
904  return false;
905  i1+=num;
906  i2+=num;
907  n-=num;
908  }
909  return true;
910  }
911 };
912 } // namespace detail
913 
914 template <typename I1, typename I2> BOOST_FORCEINLINE
915 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
916  return detail::equal_n_fn<I1,I2>()(i1,n,i2);
917 }
918 } } // namespace boost::gil
919 
920 namespace std {
932 template <typename Loc1, typename Loc2> BOOST_FORCEINLINE
934  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
935  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
936  std::ptrdiff_t n=last-first;
937  if (first.is_1d_traversable()) {
938  if (first2.is_1d_traversable())
939  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
940  else
941  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2> >()(first.x(),n, first2);
942  } else {
943  if (first2.is_1d_traversable())
944  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
945  else
946  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> >()(first,n,first2);
947  }
948 }
949 } // namespace std
950 
951 namespace boost { namespace gil {
954 template <typename View1, typename View2> BOOST_FORCEINLINE
955 bool equal_pixels(const View1& v1, const View2& v2) {
956  assert(v1.dimensions()==v2.dimensions());
957  return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance
958 }
959 
965 
969 
972 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
973 F transform_pixels(const View1& src,const View2& dst, F fun) {
974  assert(src.dimensions()==dst.dimensions());
975  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
976  typename View1::x_iterator srcIt=src.row_begin(y);
977  typename View2::x_iterator dstIt=dst.row_begin(y);
978  for (std::ptrdiff_t x=0; x<src.width(); ++x)
979  dstIt[x]=fun(srcIt[x]);
980  }
981  return fun;
982 }
983 
986 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
987 F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) {
988  for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
989  typename View1::x_iterator srcIt1=src1.row_begin(y);
990  typename View2::x_iterator srcIt2=src2.row_begin(y);
991  typename View3::x_iterator dstIt=dst.row_begin(y);
992  for (std::ptrdiff_t x=0; x<dst.width(); ++x)
993  dstIt[x]=fun(srcIt1[x],srcIt2[x]);
994  }
995  return fun;
996 }
997 
1001 
1004 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
1005 F transform_pixel_positions(const View1& src,const View2& dst, F fun) {
1006  assert(src.dimensions()==dst.dimensions());
1007  typename View1::xy_locator loc=src.xy_at(0,0);
1008  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1009  typename View2::x_iterator dstIt=dst.row_begin(y);
1010  for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
1011  dstIt[x]=fun(loc);
1012  loc.x()-=src.width(); ++loc.y();
1013  }
1014  return fun;
1015 }
1016 
1019 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
1020 F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) {
1021  assert(src1.dimensions()==dst.dimensions());
1022  assert(src2.dimensions()==dst.dimensions());
1023  typename View1::xy_locator loc1=src1.xy_at(0,0);
1024  typename View2::xy_locator loc2=src2.xy_at(0,0);
1025  for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
1026  typename View3::x_iterator dstIt=dst.row_begin(y);
1027  for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
1028  dstIt[x]=fun(loc1,loc2);
1029  loc1.x()-=src1.width(); ++loc1.y();
1030  loc2.x()-=src2.width(); ++loc2.y();
1031  }
1032  return fun;
1033 }
1034 } } // namespace boost::gil
1035 
1036 //#ifdef _MSC_VER
1037 //#pragma warning(pop)
1038 //#endif
1039 
1040 #endif
image view class
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:540
pixel related algorithms
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept, PixelValueConcept, HomogeneousPixelBasedConcept.
Definition: metafunctions.hpp:43
void generate_pixels(const View &v, F fun)
std::generate for image views
Definition: algorithm.hpp:801
BOOST_FORCEINLINE F transform_pixels(const View1 &src1, const View2 &src2, const View3 &dst, F fun)
transform_pixels with two sources
Definition: algorithm.hpp:987
An iterator over planar pixels. Models HomogeneousColorBaseConcept, PixelIteratorConcept, HomogeneousPixelBasedConcept, MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept.
Definition: algorithm.hpp:52
Concept check classes for GIL concepts.
Definition: algorithm.hpp:189
Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept.
Definition: iterator_from_2d.hpp:51
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:56
BOOST_FORCEINLINE bool equal_pixels(const View1 &v1, const View2 &v2)
std::equal for image views
Definition: algorithm.hpp:955
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:367
Returns whether two views are compatible.
Definition: gil_concept.hpp:2141
BOOST_FORCEINLINE void copy_pixels(const View1 &src, const View2 &dst)
std::copy for image views
Definition: algorithm.hpp:288
BOOST_FORCEINLINE void fill_pixels(const View &img_view, const Value &val)
std::fill for image views
Definition: algorithm.hpp:410
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:670
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:279
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:177
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:933
A generic binary operation on viewsUse this class as a convenience superclass when defining an operat...
Definition: algorithm.hpp:99
struct to do std::fill
Definition: algorithm.hpp:387
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:1020
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:723
Methods for constructing image views from raw data or other image views /.
BOOST_FORCEINLINE void destruct_pixels(const View &img_view)
Invokes the in-place destructor on every pixel of the view.
Definition: algorithm.hpp:483
MEMORY-BASED STEP ITERATOR.
Definition: algorithm.hpp:54
A model of a heterogeneous pixel that is not byte aligned. Examples are bitmap (1-bit pixels) or 6-bi...