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_config.hpp"
30 #include "gil_concept.hpp"
31 #include "color_base_algorithm.hpp"
32 #include "image_view.hpp"
33 #include "image_view_factory.hpp"
35 
44 
45 //#ifdef _MSC_VER
46 //#pragma warning(push)
47 //#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)
48 //#endif
49 
50 namespace boost { namespace gil {
51 //forward declarations
52 template <typename ChannelPtr, typename ColorSpace>
54 template <typename Iterator>
56 template <typename StepIterator>
58 
59 // a tag denoting incompatible arguments
60 struct error_t {};
61 
86 
90 
99 template <typename Derived, typename Result=void>
101  typedef Result result_type;
102 
103  template <typename V1, typename V2> BOOST_FORCEINLINE
104  result_type operator()(const std::pair<const V1*,const V2*>& p) const {
105  return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type());
106  }
107 
108  template <typename V1, typename V2> BOOST_FORCEINLINE
109  result_type operator()(const V1& v1, const V2& v2) const {
110  return apply(v1, v2, typename views_are_compatible<V1,V2>::type());
111  }
112 
113  result_type operator()(const error_t&) const { throw std::bad_cast(); }
114 private:
115 
116  // dispatch from apply overload to a function with distinct name
117  template <typename V1, typename V2>
118  BOOST_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::false_) const {
119  return ((const Derived*)this)->apply_incompatible(v1,v2);
120  }
121 
122  // dispatch from apply overload to a function with distinct name
123  template <typename V1, typename V2>
124  BOOST_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::true_) const {
125  return ((const Derived*)this)->apply_compatible(v1,v2);
126  }
127 
128  // function with distinct name - it can be overloaded by subclasses
129  template <typename V1, typename V2>
130  BOOST_FORCEINLINE result_type apply_incompatible(const V1& v1, const V2& v2) const {
131  throw std::bad_cast();
132  }
133 };
134 } } // namespace boost::gil
135 
141 
145 
146 namespace std {
149 template<typename T, typename Cs>
150 BOOST_FORCEINLINE boost::gil::pixel<T,Cs>*
153  return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
154 }
155 
158 template<typename T, typename Cs>
159 BOOST_FORCEINLINE boost::gil::pixel<T,Cs>*
162  return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
163 }
164 } // namespace std
165 
166 namespace boost { namespace gil {
167 namespace detail {
168 template <typename I, typename O> struct copy_fn {
169  BOOST_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); }
170 };
171 } // namespace detail
172 } } // namespace boost::gil
173 
174 namespace std {
177 template<typename Cs, typename IC1, typename IC2> BOOST_FORCEINLINE
179  boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type> >();
180  static_for_each(first,last,dst,boost::gil::detail::copy_fn<IC1,IC2>());
181  return dst+(last-first);
182 }
183 } // namespace std
184 
185 namespace boost { namespace gil {
186 namespace detail {
189 template <typename I, typename O>
190 struct copier_n {
191  BOOST_FORCEINLINE void operator()(I src, typename std::iterator_traits<I>::difference_type n, O dst) const { std::copy(src,src+n, dst); }
192 };
193 
195 template <typename IL, typename O> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
196 struct copier_n<iterator_from_2d<IL>,O> {
197  typedef typename std::iterator_traits<iterator_from_2d<IL> >::difference_type diff_t;
198  BOOST_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, O dst) const {
199  gil_function_requires<PixelLocatorConcept<IL> >();
200  gil_function_requires<MutablePixelIteratorConcept<O> >();
201  while (n>0) {
202  typedef typename iterator_from_2d<IL>::difference_type diff_t;
203  diff_t l=src.width()-src.x_pos();
204  diff_t numToCopy=(n<l ? n:l);
205  detail::copy_n(src.x(), numToCopy, dst);
206  dst+=numToCopy;
207  src+=numToCopy;
208  n-=numToCopy;
209  }
210  }
211 };
212 
214 template <typename I, typename OL> // I Models ConstPixelIteratorConcept, OL Models PixelLocatorConcept
215 struct copier_n<I,iterator_from_2d<OL> > {
216  typedef typename std::iterator_traits<I>::difference_type diff_t;
217  BOOST_FORCEINLINE void operator()(I src, diff_t n, iterator_from_2d<OL> dst) const {
218  gil_function_requires<PixelIteratorConcept<I> >();
219  gil_function_requires<MutablePixelLocatorConcept<OL> >();
220  while (n>0) {
221  diff_t l=dst.width()-dst.x_pos();
222  diff_t numToCopy=(n<l ? n:l);
223  detail::copy_n(src, numToCopy, dst.x());
224  dst+=numToCopy;
225  src+=numToCopy;
226  n-=numToCopy;
227  }
228  }
229 };
230 
232 template <typename IL, typename OL>
234  typedef typename iterator_from_2d<IL>::difference_type diff_t;
235  BOOST_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, iterator_from_2d<OL> dst) const {
236  gil_function_requires<PixelLocatorConcept<IL> >();
237  gil_function_requires<MutablePixelLocatorConcept<OL> >();
238  if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
239  while(n-->0) {
240  *dst++=*src++;
241  }
242  }
243  while (n>0) {
244  diff_t l=dst.width()-dst.x_pos();
245  diff_t numToCopy=(n<l ? n : l);
246  detail::copy_n(src.x(), numToCopy, dst.x());
247  dst+=numToCopy;
248  src+=numToCopy;
249  n-=numToCopy;
250  }
251  }
252 };
253 
254 template <typename SrcIterator, typename DstIterator>
255 BOOST_FORCEINLINE DstIterator copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) {
256  typedef typename SrcIterator::x_iterator src_x_iterator;
257  typedef typename DstIterator::x_iterator dst_x_iterator;
258 
259  typename SrcIterator::difference_type n = last - first;
260 
261  if (first.is_1d_traversable()) {
262  if (dst.is_1d_traversable())
263  copier_n<src_x_iterator,dst_x_iterator>()(first.x(),n, dst.x());
264  else
265  copier_n<src_x_iterator,DstIterator >()(first.x(),n, dst);
266  } else {
267  if (dst.is_1d_traversable())
268  copier_n<SrcIterator,dst_x_iterator>()(first,n, dst.x());
269  else
270  copier_n<SrcIterator,DstIterator>()(first,n,dst);
271  }
272  return dst+n;
273 }
274 } // namespace detail
275 } } // namespace boost::gil
276 
277 namespace std {
280 template <typename IL, typename OL>
282  return boost::gil::detail::copy_with_2d_iterators(first,last,dst);
283 }
284 } // namespace std
285 
286 namespace boost { namespace gil {
289 template <typename View1, typename View2> BOOST_FORCEINLINE
290 void copy_pixels(const View1& src, const View2& dst) {
291  assert(src.dimensions()==dst.dimensions());
292  detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
293 }
294 
300 
306 
307 namespace detail {
308 template <typename CC>
309 class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC> > {
310 private:
311  CC _cc;
312 public:
313  typedef typename binary_operation_obj<copy_and_convert_pixels_fn<CC> >::result_type result_type;
314  copy_and_convert_pixels_fn() {}
315  copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {}
316  // when the two color spaces are incompatible, a color conversion is performed
317  template <typename V1, typename V2> BOOST_FORCEINLINE
318  result_type apply_incompatible(const V1& src, const V2& dst) const {
319  copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst);
320  }
321 
322  // If the two color spaces are compatible, copy_and_convert is just copy
323  template <typename V1, typename V2> BOOST_FORCEINLINE
324  result_type apply_compatible(const V1& src, const V2& dst) const {
325  copy_pixels(src,dst);
326  }
327 };
328 } // namespace detail
329 
331 template <typename V1, typename V2,typename CC>
332 BOOST_FORCEINLINE
333 void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) {
334  detail::copy_and_convert_pixels_fn<CC> ccp(cc);
335  ccp(src,dst);
336 }
337 
338 struct default_color_converter;
339 
341 template <typename View1, typename View2>
342 BOOST_FORCEINLINE
343 void copy_and_convert_pixels(const View1& src, const View2& dst) {
344  detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
345  ccp(src,dst);
346 }
347 } } // namespace boost::gil
348 
350 //
351 // std::fill and gil::fill_pixels
352 //
354 
358 
359 namespace std {
368 template <typename IL, typename V>
370  boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL> >();
371  if (first.is_1d_traversable()) {
372  std::fill(first.x(), last.x(), val);
373  } else {
374  // fill row by row
375  std::ptrdiff_t n=last-first;
376  while (n>0) {
377  std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
378  fill_n(first.x(), numToDo, val);
379  first+=numToDo;
380  n-=numToDo;
381  }
382  }
383 }
384 } // namespace std
385 
386 namespace boost { namespace gil {
387 namespace detail {
389 struct std_fill_t {
390  template <typename It, typename P>
391  void operator()(It first, It last, const P& p_in) {
392  std::fill(first,last,p_in);
393  }
394 };
396 template <typename It, typename P>
397 BOOST_FORCEINLINE
398 void fill_aux(It first, It last, const P& p, mpl::true_) {
399  static_for_each(first,last,p,std_fill_t());
400 }
402 template <typename It, typename P>
403 BOOST_FORCEINLINE
404 void fill_aux(It first, It last, const P& p,mpl::false_) {
405  std::fill(first,last,p);
406 }
407 } // namespace detail
408 
411 template <typename View, typename Value> BOOST_FORCEINLINE
412 void fill_pixels(const View& img_view, const Value& val) {
413  if (img_view.is_1d_traversable())
414  detail::fill_aux(img_view.begin().x(), img_view.end().x(),
415  val,is_planar<View>());
416  else
417  for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
418  detail::fill_aux(img_view.row_begin(y),img_view.row_end(y),
419  val,is_planar<View>());
420 }
421 
427 
431 
432 namespace detail {
433 template <typename It> BOOST_FORCEINLINE
434 void destruct_range_impl( It first
435  , It last
436  , typename enable_if< mpl::and_< is_pointer< It >
437  , mpl::not_< boost::has_trivial_destructor< typename std::iterator_traits<It>::value_type > >
438  >
439  >::type* /*ptr*/ = 0
440  )
441 {
442  while (first!=last) {
443  first->~value_t();
444  ++first;
445  }
446 }
447 
448 template <typename It> BOOST_FORCEINLINE
449 void destruct_range_impl( It
450  , It
451  , typename enable_if< mpl::or_< mpl::not_< is_pointer< It > >
452  , boost::has_trivial_destructor< typename std::iterator_traits< It >::value_type >
453  >
454  >::type* /* ptr */ = 0)
455 {}
456 
457 template <typename It> BOOST_FORCEINLINE
458 void destruct_range(It first, It last) {
459  destruct_range_impl( first
460  , last
461  );
462 }
463 
464 struct std_destruct_t {
465  template <typename It> void operator()(It first, It last) const { destruct_range(first,last); }
466 };
467 
469 template <typename It>
470 BOOST_FORCEINLINE
471 void destruct_aux(It first, It last, mpl::true_) {
472  static_for_each(first,last,std_destruct_t());
473 }
475 template <typename It>
476 BOOST_FORCEINLINE
477 void destruct_aux(It first, It last, mpl::false_) {
478  destruct_range(first,last);
479 }
480 } // namespace detail
481 
484 template <typename View> BOOST_FORCEINLINE
485 void destruct_pixels(const View& img_view) {
486  if (img_view.is_1d_traversable())
487  detail::destruct_aux(img_view.begin().x(), img_view.end().x(),
488  is_planar<View>());
489  else
490  for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
491  detail::destruct_aux(img_view.row_begin(y),img_view.row_end(y),
492  is_planar<View>());
493 }
494 
500 
504 
505 namespace detail {
508 template <typename It, typename P>
509 BOOST_FORCEINLINE
510 void uninitialized_fill_aux(It first, It last,
511  const P& p, mpl::true_) {
512  int channel=0;
513  try {
514  typedef typename std::iterator_traits<It>::value_type pixel_t;
515  while (channel < num_channels<pixel_t>::value) {
516  std::uninitialized_fill(dynamic_at_c(first,channel), dynamic_at_c(last,channel),
517  dynamic_at_c(p,channel));
518  ++channel;
519  }
520  } catch (...) {
521  for (int c=0; c<channel; ++c)
522  destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
523  throw;
524  }
525 }
526 
529 template <typename It, typename P>
530 BOOST_FORCEINLINE
531 void uninitialized_fill_aux(It first, It last,
532  const P& p,mpl::false_) {
533  std::uninitialized_fill(first,last,p);
534 }
535 } // namespace detail
536 
541 template <typename View, typename Value>
542 void uninitialized_fill_pixels(const View& img_view, const Value& val) {
543  if (img_view.is_1d_traversable())
544  detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(),
545  val,is_planar<View>());
546  else {
547  typename View::y_coord_t y;
548  try {
549  for (y=0; y<img_view.height(); ++y)
550  detail::uninitialized_fill_aux(img_view.row_begin(y),img_view.row_end(y),
551  val,is_planar<View>());
552  } catch(...) {
553  for (typename View::y_coord_t y0=0; y0<y; ++y0)
554  detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>());
555  throw;
556  }
557  }
558 }
559 
565 
569 
570 namespace detail {
571 template <typename It> BOOST_FORCEINLINE
572 void default_construct_range_impl(It first, It last, mpl::true_) {
573  typedef typename std::iterator_traits<It>::value_type value_t;
574  It first1=first;
575  try {
576  while (first!=last) {
577  new (first) value_t();
578  ++first;
579  }
580  } catch (...) {
581  destruct_range(first1,first);
582  throw;
583  }
584 }
585 
586 template <typename It> BOOST_FORCEINLINE
587 void default_construct_range_impl(It, It, mpl::false_) {}
588 
589 template <typename It> BOOST_FORCEINLINE
590 void default_construct_range(It first, It last) { default_construct_range_impl(first, last, typename is_pointer<It>::type()); }
591 
593 template <typename It>
594 BOOST_FORCEINLINE
595 void default_construct_aux(It first, It last, mpl::true_) {
596  int channel=0;
597  try {
598  typedef typename std::iterator_traits<It>::value_type pixel_t;
599  while (channel < num_channels<pixel_t>::value) {
600  default_construct_range(dynamic_at_c(first,channel), dynamic_at_c(last,channel));
601  ++channel;
602  }
603  } catch (...) {
604  for (int c=0; c<channel; ++c)
605  destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
606  throw;
607  }
608 }
609 
611 template <typename It>
612 BOOST_FORCEINLINE
613 void default_construct_aux(It first, It last, mpl::false_) {
614  default_construct_range(first,last);
615 }
616 
617 template <typename View, bool IsPlanar>
618 struct has_trivial_pixel_constructor : public boost::has_trivial_constructor<typename View::value_type> {};
619 template <typename View>
620 struct has_trivial_pixel_constructor<View, true> : public boost::has_trivial_constructor<typename channel_type<View>::type> {};
621 } // namespace detail
622 
623 namespace detail {
624 template< typename View, bool B > BOOST_FORCEINLINE
625 void default_construct_pixels_impl( const View& img_view
626  , boost::enable_if< is_same< mpl::bool_< B >
627  , mpl::false_
628  >
629  >* /* ptr */ = 0
630  )
631 {
632  if( img_view.is_1d_traversable() )
633  {
634  detail::default_construct_aux( img_view.begin().x()
635  , img_view.end().x()
636  , is_planar<View>()
637  );
638  }
639  else
640  {
641  typename View::y_coord_t y;
642  try
643  {
644  for( y = 0; y < img_view.height(); ++y )
645  {
646  detail::default_construct_aux( img_view.row_begin( y )
647  ,img_view.row_end( y )
648  , is_planar<View>()
649  );
650  }
651  } catch(...)
652  {
653  for (typename View::y_coord_t y0 = 0; y0 < y; ++y0 )
654  {
655  detail::destruct_aux( img_view.row_begin(y0)
656  , img_view.row_end(y0)
657  , is_planar<View>()
658  );
659  }
660 
661  throw;
662  }
663  }
664 }
665 } // namespace detail
666 
671 template <typename View>
672 void default_construct_pixels(const View& img_view) {
673  detail::default_construct_pixels_impl< View
674  , detail::has_trivial_pixel_constructor< View
675  , is_planar< View >::value
676  >::value
677  >( img_view );
678 }
679 
685 
689 
690 namespace detail {
692 template <typename It1, typename It2>
693 BOOST_FORCEINLINE
694 void uninitialized_copy_aux(It1 first1, It1 last1,
695  It2 first2, mpl::true_) {
696  int channel=0;
697  try {
698  typedef typename std::iterator_traits<It1>::value_type pixel_t;
699  while (channel < num_channels<pixel_t>::value) {
700  std::uninitialized_copy(dynamic_at_c(first1,channel), dynamic_at_c(last1,channel), dynamic_at_c(first2,channel));
701  ++channel;
702  }
703  } catch (...) {
704  It2 last2=first2;
705  std::advance(last2, std::distance(first1,last1));
706  for (int c=0; c<channel; ++c)
707  destruct_range(dynamic_at_c(first2,c), dynamic_at_c(last2,c));
708  throw;
709  }
710 }
712 template <typename It1, typename It2>
713 BOOST_FORCEINLINE
714 void uninitialized_copy_aux(It1 first1, It1 last1,
715  It2 first2,mpl::false_) {
716  std::uninitialized_copy(first1,last1,first2);
717 }
718 } // namespace detail
719 
724 template <typename View1, typename View2>
725 void uninitialized_copy_pixels(const View1& view1, const View2& view2) {
726  typedef mpl::bool_<is_planar<View1>::value && is_planar<View2>::value> is_planar;
727  assert(view1.dimensions()==view2.dimensions());
728  if (view1.is_1d_traversable() && view2.is_1d_traversable())
729  detail::uninitialized_copy_aux(view1.begin().x(), view1.end().x(),
730  view2.begin().x(),
731  is_planar());
732  else {
733  typename View1::y_coord_t y;
734  try {
735  for (y=0; y<view1.height(); ++y)
736  detail::uninitialized_copy_aux(view1.row_begin(y), view1.row_end(y),
737  view2.row_begin(y),
738  is_planar());
739  } catch(...) {
740  for (typename View1::y_coord_t y0=0; y0<y; ++y0)
741  detail::destruct_aux(view2.row_begin(y0),view2.row_end(y0), is_planar());
742  throw;
743  }
744  }
745 }
746 
752 
761 
763 template <typename V, typename F>
764 F for_each_pixel(const V& img, F fun) {
765  if (img.is_1d_traversable()) {
766  return std::for_each(img.begin().x(), img.end().x(), fun);
767  } else {
768  for (std::ptrdiff_t y=0; y<img.height(); ++y)
769  fun = std::for_each(img.row_begin(y),img.row_end(y),fun);
770  return fun;
771  }
772 }
773 
777 
779 template <typename View, typename F>
780 F for_each_pixel_position(const View& img, F fun) {
781  typename View::xy_locator loc=img.xy_at(0,0);
782  for (std::ptrdiff_t y=0; y<img.height(); ++y) {
783  for (std::ptrdiff_t x=0; x<img.width(); ++x, ++loc.x())
784  fun(loc);
785  loc.x()-=img.width(); ++loc.y();
786  }
787  return fun;
788 }
789 
795 
799 
802 template <typename View, typename F>
803 void generate_pixels(const View& v, F fun) {
804  if (v.is_1d_traversable()) {
805  std::generate(v.begin().x(), v.end().x(), fun);
806  } else {
807  for (std::ptrdiff_t y=0; y<v.height(); ++y)
808  std::generate(v.row_begin(y),v.row_end(y),fun);
809  }
810 }
811 
817 
821 
822 template <typename I1, typename I2> BOOST_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
823 
824 namespace detail {
825 template <typename I1, typename I2>
826 struct equal_n_fn {
827  BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); }
828 };
829 
832 template<typename T, typename Cs>
833 struct equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {
834  BOOST_FORCEINLINE bool operator()(const pixel<T,Cs>* i1, std::ptrdiff_t n, const pixel<T,Cs>* i2) const {
835  return memcmp(i1, i2, n*sizeof(pixel<T,Cs>))==0;
836  }
837 };
838 template<typename T, typename Cs>
839 struct equal_n_fn<pixel<T,Cs>*, pixel<T,Cs>*> : equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {};
840 
844 template<typename IC, typename Cs>
845 struct equal_n_fn<planar_pixel_iterator<IC,Cs>, planar_pixel_iterator<IC,Cs> > {
846  BOOST_FORCEINLINE bool operator()(const planar_pixel_iterator<IC,Cs> i1, std::ptrdiff_t n, const planar_pixel_iterator<IC,Cs> i2) const {
847  std::ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type);
848 
849  for (std::ptrdiff_t i=0; i<mpl::size<Cs>::value; ++i)
850  if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0)
851  return false;
852  return true;
853  }
854 };
855 
857 template <typename Loc, typename I2> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
858 struct equal_n_fn<boost::gil::iterator_from_2d<Loc>,I2> {
859  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, I2 i2) const {
860  gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
861  gil_function_requires<boost::gil::PixelIteratorConcept<I2> >();
862  while (n>0) {
863  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
864  if (!equal_n(i1.x(), num, i2))
865  return false;
866  i1+=num;
867  i2+=num;
868  n-=num;
869  }
870  return true;
871  }
872 };
873 
875 template <typename I1, typename Loc> // I Models PixelIteratorConcept, OL Models PixelLocatorConcept
876 struct equal_n_fn<I1,boost::gil::iterator_from_2d<Loc> > {
877  BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const {
878  gil_function_requires<boost::gil::PixelIteratorConcept<I1> >();
879  gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
880  while (n>0) {
881  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
882  if (!equal_n(i1, num, i2.x()))
883  return false;
884  i1+=num;
885  i2+=num;
886  n-=num;
887  }
888  return true;
889  }
890 };
891 
893 template <typename Loc1, typename Loc2>
894 struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> > {
895  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const {
896  gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
897  gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
898  if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
899  while(n-->0) {
900  if (*i1++!=*i2++) return false;
901  }
902  }
903  while (n>0) {
904  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
905  if (!equal_n(i1.x(), num, i2.x()))
906  return false;
907  i1+=num;
908  i2+=num;
909  n-=num;
910  }
911  return true;
912  }
913 };
914 } // namespace detail
915 
916 template <typename I1, typename I2> BOOST_FORCEINLINE
917 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
918  return detail::equal_n_fn<I1,I2>()(i1,n,i2);
919 }
920 } } // namespace boost::gil
921 
922 namespace std {
934 template <typename Loc1, typename Loc2> BOOST_FORCEINLINE
936  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
937  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
938  std::ptrdiff_t n=last-first;
939  if (first.is_1d_traversable()) {
940  if (first2.is_1d_traversable())
941  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
942  else
943  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2> >()(first.x(),n, first2);
944  } else {
945  if (first2.is_1d_traversable())
946  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
947  else
948  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> >()(first,n,first2);
949  }
950 }
951 } // namespace std
952 
953 namespace boost { namespace gil {
956 template <typename View1, typename View2> BOOST_FORCEINLINE
957 bool equal_pixels(const View1& v1, const View2& v2) {
958  assert(v1.dimensions()==v2.dimensions());
959  return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance
960 }
961 
967 
971 
974 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
975 F transform_pixels(const View1& src,const View2& dst, F fun) {
976  assert(src.dimensions()==dst.dimensions());
977  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
978  typename View1::x_iterator srcIt=src.row_begin(y);
979  typename View2::x_iterator dstIt=dst.row_begin(y);
980  for (std::ptrdiff_t x=0; x<src.width(); ++x)
981  dstIt[x]=fun(srcIt[x]);
982  }
983  return fun;
984 }
985 
988 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
989 F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) {
990  for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
991  typename View1::x_iterator srcIt1=src1.row_begin(y);
992  typename View2::x_iterator srcIt2=src2.row_begin(y);
993  typename View3::x_iterator dstIt=dst.row_begin(y);
994  for (std::ptrdiff_t x=0; x<dst.width(); ++x)
995  dstIt[x]=fun(srcIt1[x],srcIt2[x]);
996  }
997  return fun;
998 }
999 
1003 
1006 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
1007 F transform_pixel_positions(const View1& src,const View2& dst, F fun) {
1008  assert(src.dimensions()==dst.dimensions());
1009  typename View1::xy_locator loc=src.xy_at(0,0);
1010  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1011  typename View2::x_iterator dstIt=dst.row_begin(y);
1012  for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
1013  dstIt[x]=fun(loc);
1014  loc.x()-=src.width(); ++loc.y();
1015  }
1016  return fun;
1017 }
1018 
1021 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
1022 F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) {
1023  assert(src1.dimensions()==dst.dimensions());
1024  assert(src2.dimensions()==dst.dimensions());
1025  typename View1::xy_locator loc1=src1.xy_at(0,0);
1026  typename View2::xy_locator loc2=src2.xy_at(0,0);
1027  for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
1028  typename View3::x_iterator dstIt=dst.row_begin(y);
1029  for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
1030  dstIt[x]=fun(loc1,loc2);
1031  loc1.x()-=src1.width(); ++loc1.y();
1032  loc2.x()-=src2.width(); ++loc2.y();
1033  }
1034  return fun;
1035 }
1036 } } // namespace boost::gil
1037 
1038 //#ifdef _MSC_VER
1039 //#pragma warning(pop)
1040 //#endif
1041 
1042 #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:542
pixel related algorithms
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept, PixelValueConcept, HomogeneousPixelBasedConcept.
Definition: metafunctions.hpp:44
void generate_pixels(const View &v, F fun)
std::generate for image views
Definition: algorithm.hpp:803
BOOST_FORCEINLINE F transform_pixels(const View1 &src1, const View2 &src2, const View3 &dst, F fun)
transform_pixels with two sources
Definition: algorithm.hpp:989
An iterator over planar pixels. Models HomogeneousColorBaseConcept, PixelIteratorConcept, HomogeneousPixelBasedConcept, MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept.
Definition: algorithm.hpp:53
Concept check classes for GIL concepts.
Definition: algorithm.hpp:190
Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept.
Definition: iterator_from_2d.hpp:52
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:57
BOOST_FORCEINLINE bool equal_pixels(const View1 &v1, const View2 &v2)
std::equal for image views
Definition: algorithm.hpp:957
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:369
Returns whether two views are compatible.
Definition: gil_concept.hpp:2049
BOOST_FORCEINLINE void copy_pixels(const View1 &src, const View2 &dst)
std::copy for image views
Definition: algorithm.hpp:290
BOOST_FORCEINLINE void fill_pixels(const View &img_view, const Value &val)
std::fill for image views
Definition: algorithm.hpp:412
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:672
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:281
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:178
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:935
A generic binary operation on viewsUse this class as a convenience superclass when defining an operat...
Definition: algorithm.hpp:100
struct to do std::fill
Definition: algorithm.hpp:389
GIL configuration file.
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:1022
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:725
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:485
MEMORY-BASED STEP ITERATOR.
Definition: algorithm.hpp:55
A model of a heterogeneous pixel that is not byte aligned. Examples are bitmap (1-bit pixels) or 6-bi...