Boost GIL


algorithm.hpp
1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 // Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
4 //
5 // Distributed under the Boost Software License, Version 1.0
6 // See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt
8 //
9 #ifndef BOOST_GIL_ALGORITHM_HPP
10 #define BOOST_GIL_ALGORITHM_HPP
11 
12 #include <boost/gil/metafunctions.hpp>
13 #include <boost/gil/pixel_iterator.hpp>
14 #include <boost/gil/pixel_numeric_operations.hpp>
15 #include <boost/gil/image.hpp>
16 #include <boost/gil/bit_aligned_pixel_iterator.hpp>
17 #include <boost/gil/color_base_algorithm.hpp>
18 #include <boost/gil/concepts.hpp>
19 #include <boost/gil/image_view.hpp>
20 #include <boost/gil/image_view_factory.hpp>
21 #include <boost/gil/detail/mp11.hpp>
22 #include <boost/gil/detail/type_traits.hpp>
23 
24 #include <boost/assert.hpp>
25 #include <boost/config.hpp>
26 
27 #include <algorithm>
28 #include <cstddef>
29 #include <cstring>
30 #include <iterator>
31 #include <memory>
32 #include <type_traits>
33 #include <typeinfo>
34 #include <numeric>
35 
36 namespace boost { namespace gil {
37 
38 //forward declarations
39 template <typename ChannelPtr, typename ColorSpace>
41 template <typename Iterator>
43 template <typename StepIterator>
45 
46 // a tag denoting incompatible arguments
47 struct error_t {};
48 
73 
77 
86 template <typename Derived, typename Result=void>
88 {
89  using result_type = Result;
90 
91  template <typename V1, typename V2> BOOST_FORCEINLINE
92  result_type operator()(const std::pair<const V1*,const V2*>& p) const {
93  return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type());
94  }
95 
96  template <typename V1, typename V2> BOOST_FORCEINLINE
97  result_type operator()(const V1& v1, const V2& v2) const {
98  return apply(v1, v2, typename views_are_compatible<V1,V2>::type());
99  }
100 
101  result_type operator()(const error_t&) const { throw std::bad_cast(); }
102 private:
103 
104  // dispatch from apply overload to a function with distinct name
105  template <typename V1, typename V2>
106  BOOST_FORCEINLINE
107  result_type apply(V1 const& v1, V2 const& v2, std::false_type) const
108  {
109  return ((const Derived*)this)->apply_incompatible(v1, v2);
110  }
111 
112  // dispatch from apply overload to a function with distinct name
113  template <typename V1, typename V2>
114  BOOST_FORCEINLINE
115  result_type apply(V1 const& v1, V2 const& v2, std::true_type) const
116  {
117  return ((const Derived*)this)->apply_compatible(v1, v2);
118  }
119 
120  // function with distinct name - it can be overloaded by subclasses
121  template <typename V1, typename V2>
122  BOOST_FORCEINLINE
123  result_type apply_incompatible(V1 const& /*v1*/, V2 const& /*v2*/) const
124  {
125  throw std::bad_cast();
126  }
127 };
128 
129 }} // namespace boost::gil
130 
132 // std::copy and gil::copy_pixels
134 
138 
139 namespace std {
140 
143 template<typename T, typename CS>
144 BOOST_FORCEINLINE
145 auto copy(
150 {
151  auto p = std::copy((unsigned char*)first, (unsigned char*)last, (unsigned char*)dst);
152  return reinterpret_cast<boost::gil::pixel<T, CS>*>(p);
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  using diff_t = typename std::iterator_traits<iterator_from_2d<IL>>::difference_type;
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  using diff_t = typename std::iterator_traits<I>::difference_type;
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  using diff_t = typename iterator_from_2d<IL>::difference_type;
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  using src_x_iterator = typename SrcIterator::x_iterator;
255  using dst_x_iterator = typename DstIterator::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 {
290  BOOST_ASSERT(src.dimensions() == dst.dimensions());
291  detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
292 }
293 
295 // copy_and_convert_pixels
297 
303 
304 namespace detail {
305 template <typename CC>
306 class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC>>
307 {
308 private:
309  CC _cc;
310 public:
311  using result_type = typename binary_operation_obj<copy_and_convert_pixels_fn<default_color_converter>>::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 // std::fill and gil::fill_pixels
350 
354 
355 namespace std {
364 template <typename IL, typename V>
366  boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL>>();
367  if (first.is_1d_traversable()) {
368  std::fill(first.x(), last.x(), val);
369  } else {
370  // fill row by row
371  std::ptrdiff_t n=last-first;
372  while (n>0) {
373  std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
374  std::fill_n(first.x(), numToDo, val);
375  first+=numToDo;
376  n-=numToDo;
377  }
378  }
379 }
380 } // namespace std
381 
382 namespace boost { namespace gil {
383 
384 namespace detail {
385 
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 };
393 
395 template <typename It, typename P>
396 BOOST_FORCEINLINE
397 void fill_aux(It first, It last, P const& p, std::true_type)
398 {
399  static_for_each(first, last, p, std_fill_t());
400 }
401 
403 template <typename It, typename P>
404 BOOST_FORCEINLINE
405 void fill_aux(It first, It last, P const& p, std::false_type)
406 {
407  std::fill(first, last, p);
408 }
409 
410 } // namespace detail
411 
414 template <typename View, typename Value>
415 BOOST_FORCEINLINE
416 void fill_pixels(View const& view, Value const& value)
417 {
418  if (view.is_1d_traversable())
419  {
420  detail::fill_aux(
421  view.begin().x(), view.end().x(), value, is_planar<View>());
422  }
423  else
424  {
425  for (std::ptrdiff_t y = 0; y < view.height(); ++y)
426  detail::fill_aux(
427  view.row_begin(y), view.row_end(y), value, is_planar<View>());
428  }
429 }
430 
432 // destruct_pixels
434 
438 
439 namespace detail {
440 template <typename Iterator>
441 BOOST_FORCEINLINE
442 void destruct_range_impl(Iterator first, Iterator last,
443  typename std::enable_if
444  <
445  mp11::mp_and
446  <
447  std::is_pointer<Iterator>,
448  mp11::mp_not
449  <
450  detail::is_trivially_destructible<typename std::iterator_traits<Iterator>::value_type>
451  >
452  >::value
453  >::type* /*ptr*/ = 0)
454 {
455  while (first != last)
456  {
457  first->~value_t();
458  ++first;
459  }
460 }
461 
462 template <typename Iterator>
463 BOOST_FORCEINLINE
464 void destruct_range_impl(Iterator /*first*/, Iterator /*last*/,
465  typename std::enable_if
466  <
467  mp11::mp_or
468  <
469  mp11::mp_not<std::is_pointer<Iterator>>,
470  detail::is_trivially_destructible<typename std::iterator_traits<Iterator>::value_type>
471  >::value
472  >::type* /* ptr */ = nullptr)
473 {
474 }
475 
476 template <typename Iterator>
477 BOOST_FORCEINLINE
478 void destruct_range(Iterator first, Iterator last)
479 {
480  destruct_range_impl(first, last);
481 }
482 
483 struct std_destruct_t
484 {
485  template <typename Iterator>
486  void operator()(Iterator first, Iterator last) const
487  {
488  destruct_range(first,last);
489  }
490 };
491 
493 template <typename It>
494 BOOST_FORCEINLINE
495 void destruct_aux(It first, It last, std::true_type)
496 {
497  static_for_each(first,last,std_destruct_t());
498 }
499 
501 template <typename It>
502 BOOST_FORCEINLINE
503 void destruct_aux(It first, It last, std::false_type)
504 {
505  destruct_range(first,last);
506 }
507 
508 } // namespace detail
509 
512 template <typename View>
513 BOOST_FORCEINLINE
514 void destruct_pixels(View const& view)
515 {
516  if (view.is_1d_traversable())
517  {
518  detail::destruct_aux(
519  view.begin().x(), view.end().x(), is_planar<View>());
520  }
521  else
522  {
523  for (std::ptrdiff_t y = 0; y < view.height(); ++y)
524  detail::destruct_aux(
525  view.row_begin(y), view.row_end(y), is_planar<View>());
526  }
527 }
528 
530 // uninitialized_fill_pixels
532 
536 
537 namespace detail {
538 
541 template <typename It, typename P>
542 BOOST_FORCEINLINE
543 void uninitialized_fill_aux(It first, It last, P const& p, std::true_type)
544 {
545  std::size_t channel = 0;
546  try
547  {
548  using pixel_t = typename std::iterator_traits<It>::value_type;
549  while (channel < num_channels<pixel_t>::value)
550  {
551  std::uninitialized_fill(
552  dynamic_at_c(first,channel),
553  dynamic_at_c(last,channel),
554  dynamic_at_c(p,channel));
555 
556  ++channel;
557  }
558  }
559  catch (...)
560  {
561  for (std::size_t c = 0; c < channel; ++c)
562  destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
563  throw;
564  }
565 }
566 
569 template <typename It, typename P>
570 BOOST_FORCEINLINE
571 void uninitialized_fill_aux(It first, It last, P const& p, std::false_type)
572 {
573  std::uninitialized_fill(first,last,p);
574 }
575 
576 } // namespace detail
577 
582 template <typename View, typename Value>
583 void uninitialized_fill_pixels(const View& view, const Value& val) {
584  if (view.is_1d_traversable())
585  detail::uninitialized_fill_aux(view.begin().x(), view.end().x(),
586  val,is_planar<View>());
587  else {
588  typename View::y_coord_t y = 0;
589  try {
590  for (y=0; y<view.height(); ++y)
591  detail::uninitialized_fill_aux(view.row_begin(y),view.row_end(y),
592  val,is_planar<View>());
593  } catch(...) {
594  for (typename View::y_coord_t y0=0; y0<y; ++y0)
595  detail::destruct_aux(view.row_begin(y0),view.row_end(y0), is_planar<View>());
596  throw;
597  }
598  }
599 }
600 
602 // default_construct_pixels
604 
608 
609 namespace detail {
610 template <typename It> BOOST_FORCEINLINE
611 void default_construct_range_impl(It first, It last, std::true_type)
612 {
613  It first1 = first;
614  try
615  {
616  using value_t = typename std::iterator_traits<It>::value_type;
617  while (first != last)
618  {
619  new (first) value_t();
620  ++first;
621  }
622  }
623  catch (...)
624  {
625  destruct_range(first1, first);
626  throw;
627  }
628 }
629 
630 template <typename It>
631 BOOST_FORCEINLINE
632 void default_construct_range_impl(It, It, std::false_type) {}
633 
634 template <typename It>
635 BOOST_FORCEINLINE
636 void default_construct_range(It first, It last)
637 {
638  default_construct_range_impl(first, last, typename std::is_pointer<It>::type());
639 }
640 
642 template <typename It>
643 BOOST_FORCEINLINE
644 void default_construct_aux(It first, It last, std::true_type)
645 {
646  std::size_t channel = 0;
647  try
648  {
649  using pixel_t = typename std::iterator_traits<It>::value_type;
650  while (channel < num_channels<pixel_t>::value)
651  {
652  default_construct_range(dynamic_at_c(first, channel), dynamic_at_c(last, channel));
653  ++channel;
654  }
655  }
656  catch (...)
657  {
658  for (std::size_t c = 0; c < channel; ++c)
659  destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
660  throw;
661  }
662 }
663 
665 template <typename It>
666 BOOST_FORCEINLINE
667 void default_construct_aux(It first, It last, std::false_type)
668 {
669  default_construct_range(first, last);
670 }
671 
672 template <typename View, bool IsPlanar>
673 struct has_trivial_pixel_constructor
674  : detail::is_trivially_default_constructible<typename View::value_type>
675 {};
676 
677 template <typename View>
678 struct has_trivial_pixel_constructor<View, true>
679  : detail::is_trivially_default_constructible<typename channel_type<View>::type>
680 {};
681 
682 template<typename View, bool IsTriviallyConstructible>
683 BOOST_FORCEINLINE
684 void default_construct_pixels_impl(
685  View const& view,
686  std::enable_if<!IsTriviallyConstructible>* /*ptr*/ = nullptr)
687 {
688  if (view.is_1d_traversable())
689  {
690  detail::default_construct_aux(
691  view.begin().x(), view.end().x(), is_planar<View>());
692  }
693  else
694  {
695  typename View::y_coord_t y = 0;
696  try
697  {
698  for( y = 0; y < view.height(); ++y )
699  detail::default_construct_aux(
700  view.row_begin(y), view.row_end(y), is_planar<View>());
701  }
702  catch(...)
703  {
704  for (typename View::y_coord_t y0 = 0; y0 < y; ++y0 )
705  detail::destruct_aux(
706  view.row_begin(y0), view.row_end(y0), is_planar<View>());
707 
708  throw;
709  }
710  }
711 }
712 
713 } // namespace detail
714 
719 template <typename View>
721 {
722  detail::default_construct_pixels_impl
723  <
724  View,
725  detail::has_trivial_pixel_constructor
726  <
727  View,
728  is_planar<View>::value
729  >::value
730  >(view);
731 }
732 
734 // uninitialized_copy_pixels
736 
740 
741 namespace detail {
742 
743 enum class copy_planarity_condition
744 {
745  planar_to_planar,
746  interleaved_to_planar,
747  mixed_to_interleaved
748 };
749 
750 using planar_to_planar_type =
751  std::integral_constant
752  <
753  copy_planarity_condition, copy_planarity_condition::planar_to_planar
754  >;
755 using interleaved_to_planar_type =
756  std::integral_constant
757  <
758  copy_planarity_condition, copy_planarity_condition::interleaved_to_planar
759  >;
760 using mixed_to_interleaved_type =
761  std::integral_constant
762  <
763  copy_planarity_condition, copy_planarity_condition::mixed_to_interleaved
764  >;
765 
767 template <typename It1, typename It2>
768 BOOST_FORCEINLINE
769 void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2 last2, planar_to_planar_type)
770 {
771  std::size_t channel=0;
772  try {
773  using pixel_t = typename std::iterator_traits<It1>::value_type;
774  while (channel < num_channels<pixel_t>::value)
775  {
776  std::uninitialized_copy(
777  dynamic_at_c(first1, channel),
778  dynamic_at_c(last1, channel),
779  dynamic_at_c(first2, channel));
780  ++channel;
781  }
782  }
783  catch (...)
784  {
785  It2 last2 = first2;
786  std::advance(last2, std::distance(first1, last1));
787  for (std::size_t c = 0; c < channel; ++c)
788  destruct_range(dynamic_at_c(first2, c), dynamic_at_c(last2, c));
789  throw;
790  }
791 }
792 
794 template <typename It1, typename It2>
795 BOOST_FORCEINLINE
796 void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2 last2, mixed_to_interleaved_type)
797 {
798  std::uninitialized_copy(first1, last1, first2);
799 }
800 
802 template <typename It1, typename It2>
803 BOOST_FORCEINLINE
804 void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2 last2,
805 interleaved_to_planar_type)
806 {
807  default_construct_aux(first2, last2, std::true_type());
808 
809  typename It2::difference_type n = last2 - first2;
810  copier_n<It1,It2>()(first1, n, first2);
811 }
812 } // namespace detail
813 
818 template <typename View1, typename View2>
819 void uninitialized_copy_pixels(View1 const& view1, View2 const& view2)
820 {
821  using copy_planarity_condition = detail::copy_planarity_condition;
822  using copy_planarity_condition_type =
823  std::integral_constant
824  <
825  copy_planarity_condition,
826  !is_planar<View2>::value
827  ? copy_planarity_condition::mixed_to_interleaved
828  : (is_planar<View1>::value
829  ? copy_planarity_condition::planar_to_planar
830  : copy_planarity_condition::interleaved_to_planar)
831  >;
832  BOOST_ASSERT(view1.dimensions() == view2.dimensions());
833 
834  if (view1.is_1d_traversable() && view2.is_1d_traversable())
835  {
836  detail::uninitialized_copy_aux(
837  view1.begin().x(), view1.end().x(), view2.begin().x(), view2.end().x(),
838  copy_planarity_condition_type());
839  }
840  else
841  {
842  typename View1::y_coord_t y = 0;
843  try
844  {
845  for (y = 0; y < view1.height(); ++y)
846  detail::uninitialized_copy_aux(
847  view1.row_begin(y), view1.row_end(y), view2.row_begin(y), view2.row_end(y),
848  copy_planarity_condition_type());
849  }
850  catch(...)
851  {
852  for (typename View1::y_coord_t y0 = 0; y0 < y; ++y0)
853  detail::destruct_aux(view2.row_begin(y0), view2.row_end(y0), is_planar<View2>());
854  throw;
855  }
856  }
857 }
858 
860 // for_each_pixel
862 
871 
873 template <typename View, typename F>
874 F for_each_pixel(View const& view, F fun)
875 {
876  if (view.is_1d_traversable())
877  {
878  return std::for_each(view.begin().x(), view.end().x(), fun);
879  }
880  else
881  {
882  for (std::ptrdiff_t y = 0; y < view.height(); ++y)
883  for (auto begin = view.row_begin(y), end = view.row_end(y); begin != end; ++begin)
884  fun(*begin);
885  return fun;
886  }
887 }
888 
892 
894 template <typename View, typename F>
895 F for_each_pixel_position(View const& view, F fun)
896 {
897  typename View::xy_locator loc = view.xy_at(0, 0);
898  for (std::ptrdiff_t y = 0; y < view.height(); ++y)
899  {
900  for (std::ptrdiff_t x = 0; x < view.width(); ++x, ++loc.x())
901  fun(loc);
902  loc.x() -= view.width(); ++loc.y();
903  }
904  return fun;
905 }
906 
908 // generate_pixels
910 
914 
917 template <typename View, typename F>
918 void generate_pixels(View const& view, F fun)
919 {
920  if (view.is_1d_traversable())
921  {
922  std::generate(view.begin().x(), view.end().x(), fun);
923  }
924  else
925  {
926  for (std::ptrdiff_t y = 0; y < view.height(); ++y)
927  std::generate(view.row_begin(y), view.row_end(y), fun);
928  }
929 }
930 
932 // std::equal and gil::equal_pixels for GIL constructs
934 
938 
939 template <typename I1, typename I2>
940 BOOST_FORCEINLINE
941 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
942 
943 namespace detail {
944 
945 template <typename I1, typename I2>
946 struct equal_n_fn
947 {
948  BOOST_FORCEINLINE
949  bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const
950  {
951  return std::equal(i1, i1 + n, i2);
952  }
953 };
954 
957 template<typename T, typename CS>
958 struct equal_n_fn<pixel<T, CS> const*, pixel<T, CS> const*>
959 {
960  BOOST_FORCEINLINE
961  bool operator()(pixel<T, CS> const* i1, std::ptrdiff_t n, pixel<T, CS> const* i2) const
962  {
963  return memcmp(i1, i2, n * sizeof(pixel<T, CS>)) == 0;
964  }
965 };
966 
967 template<typename T, typename CS>
968 struct equal_n_fn<pixel<T, CS>*, pixel<T, CS>*>
969  : equal_n_fn<pixel<T, CS> const*, pixel<T, CS> const*>
970 {};
971 
975 template<typename IC, typename CS>
976 struct equal_n_fn<planar_pixel_iterator<IC, CS>, planar_pixel_iterator<IC, CS>>
977 {
978  BOOST_FORCEINLINE
979  bool operator()(planar_pixel_iterator<IC, CS> const i1, std::ptrdiff_t n, planar_pixel_iterator<IC, CS> const i2) const
980  {
981  // FIXME: ptrdiff_t vs size_t
982  constexpr std::ptrdiff_t byte_size = n * sizeof(typename std::iterator_traits<IC>::value_type);
983  for (std::ptrdiff_t i = 0; i < mp11::mp_size<CS>::value; ++i)
984  {
985  if (memcmp(dynamic_at_c(i1, i), dynamic_at_c(i2, i), byte_size) != 0)
986  return false;
987  }
988  return true;
989  }
990 };
991 
995 template <typename Loc, typename It>
996 struct equal_n_fn<boost::gil::iterator_from_2d<Loc>, It>
997 {
998  BOOST_FORCEINLINE
999  bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, It i2) const
1000  {
1001  gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
1002  gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
1003  while (n > 0)
1004  {
1005  std::ptrdiff_t const num = std::min<std::ptrdiff_t>(n, i1.width() - i1.x_pos());
1006  if (!equal_n(i1.x(), num, i2))
1007  return false;
1008  i1 += num;
1009  i2 += num;
1010  n -= num;
1011  }
1012  return true;
1013  }
1014 };
1015 
1019 template <typename It, typename Loc>
1020 struct equal_n_fn<It, boost::gil::iterator_from_2d<Loc>>
1021 {
1022  BOOST_FORCEINLINE
1023  bool operator()(It i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const
1024  {
1025  gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
1026  gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
1027  while (n > 0)
1028  {
1029  std::ptrdiff_t const num = std::min<std::ptrdiff_t>(n, i2.width() - i2.x_pos());
1030  if (!equal_n(i1, num, i2.x()))
1031  return false;
1032  i1 += num;
1033  i2 += num;
1034  n -= num;
1035  }
1036  return true;
1037  }
1038 };
1039 
1041 template <typename Loc1, typename Loc2>
1042 struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2>> {
1043  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const {
1044  gil_function_requires<boost::gil::PixelLocatorConcept<Loc1>>();
1045  gil_function_requires<boost::gil::PixelLocatorConcept<Loc2>>();
1046  if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
1047  while(n-->0) {
1048  if (*i1++!=*i2++) return false;
1049  }
1050  }
1051  while (n>0) {
1052  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
1053  if (!equal_n(i1.x(), num, i2.x()))
1054  return false;
1055  i1+=num;
1056  i2+=num;
1057  n-=num;
1058  }
1059  return true;
1060  }
1061 };
1062 } // namespace detail
1063 
1064 template <typename I1, typename I2> BOOST_FORCEINLINE
1065 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
1066  return detail::equal_n_fn<I1,I2>()(i1,n,i2);
1067 }
1068 } } // namespace boost::gil
1069 
1070 namespace std {
1082 template <typename Loc1, typename Loc2> BOOST_FORCEINLINE
1084  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1>>();
1085  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2>>();
1086  std::ptrdiff_t n=last-first;
1087  if (first.is_1d_traversable()) {
1088  if (first2.is_1d_traversable())
1089  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
1090  else
1091  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2>>()(first.x(),n, first2);
1092  } else {
1093  if (first2.is_1d_traversable())
1094  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
1095  else
1096  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2>>()(first,n,first2);
1097  }
1098 }
1099 } // namespace std
1100 
1101 namespace boost { namespace gil {
1104 template <typename View1, typename View2> BOOST_FORCEINLINE
1105 bool equal_pixels(const View1& v1, const View2& v2) {
1106  BOOST_ASSERT(v1.dimensions() == v2.dimensions());
1107  return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance
1108 }
1109 
1115 
1119 
1122 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
1123 F transform_pixels(const View1& src,const View2& dst, F fun) {
1124  BOOST_ASSERT(src.dimensions() == dst.dimensions());
1125  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1126  typename View1::x_iterator srcIt=src.row_begin(y);
1127  typename View2::x_iterator dstIt=dst.row_begin(y);
1128  for (std::ptrdiff_t x=0; x<src.width(); ++x)
1129  dstIt[x]=fun(srcIt[x]);
1130  }
1131  return fun;
1132 }
1133 
1136 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
1137 F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) {
1138  for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
1139  typename View1::x_iterator srcIt1=src1.row_begin(y);
1140  typename View2::x_iterator srcIt2=src2.row_begin(y);
1141  typename View3::x_iterator dstIt=dst.row_begin(y);
1142  for (std::ptrdiff_t x=0; x<dst.width(); ++x)
1143  dstIt[x]=fun(srcIt1[x],srcIt2[x]);
1144  }
1145  return fun;
1146 }
1147 
1151 
1154 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
1155 F transform_pixel_positions(const View1& src,const View2& dst, F fun) {
1156  BOOST_ASSERT(src.dimensions() == dst.dimensions());
1157  typename View1::xy_locator loc=src.xy_at(0,0);
1158  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1159  typename View2::x_iterator dstIt=dst.row_begin(y);
1160  for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
1161  dstIt[x]=fun(loc);
1162  loc.x()-=src.width(); ++loc.y();
1163  }
1164  return fun;
1165 }
1166 
1169 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
1170 F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) {
1171  BOOST_ASSERT(src1.dimensions() == dst.dimensions());
1172  BOOST_ASSERT(src2.dimensions() == dst.dimensions());
1173  typename View1::xy_locator loc1=src1.xy_at(0,0);
1174  typename View2::xy_locator loc2=src2.xy_at(0,0);
1175  for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
1176  typename View3::x_iterator dstIt=dst.row_begin(y);
1177  for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
1178  dstIt[x]=fun(loc1,loc2);
1179  loc1.x()-=src1.width(); ++loc1.y();
1180  loc2.x()-=src2.width(); ++loc2.y();
1181  }
1182  return fun;
1183 }
1184 
1185 
1186 // Code below this line is moved here from <boost/gil/extension/numeric/algorithm.hpp>
1187 
1192 template <typename T>
1193 struct pixel_proxy : std::remove_reference<typename T::reference> {};
1194 
1196 template <typename Iterator1, typename Iterator2, typename BinaryFunction>
1197 BinaryFunction for_each(Iterator1 first1, Iterator1 last1, Iterator2 first2, BinaryFunction f)
1198 {
1199  while (first1 != last1)
1200  f(*first1++, *first2++);
1201  return f;
1202 }
1203 
1204 template <typename SrcIterator, typename DstIterator>
1205 inline
1206 auto assign_pixels(SrcIterator src, SrcIterator src_end, DstIterator dst) -> DstIterator
1207 {
1208  for_each(src, src_end, dst,
1209  pixel_assigns_t
1210  <
1211  typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type,
1212  typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type
1213  >());
1214  return dst + (src_end - src);
1215 }
1216 
1217 namespace detail {
1218 
1219 template <std::size_t Size>
1220 struct inner_product_k_t
1221 {
1222  template
1223  <
1224  class InputIterator1,
1225  class InputIterator2,
1226  class T,
1227  class BinaryOperation1,
1228  class BinaryOperation2
1229  >
1230  static T apply(
1231  InputIterator1 first1,
1232  InputIterator2 first2, T init,
1233  BinaryOperation1 binary_op1,
1234  BinaryOperation2 binary_op2)
1235  {
1236  init = binary_op1(init, binary_op2(*first1, *first2));
1237  return inner_product_k_t<Size - 1>::template apply(
1238  first1 + 1, first2 + 1, init, binary_op1, binary_op2);
1239  }
1240 };
1241 
1242 template <>
1243 struct inner_product_k_t<0>
1244 {
1245  template
1246  <
1247  class InputIterator1,
1248  class InputIterator2,
1249  class T,
1250  class BinaryOperation1,
1251  class BinaryOperation2
1252  >
1253  static T apply(
1254  InputIterator1 first1,
1255  InputIterator2 first2,
1256  T init,
1257  BinaryOperation1 binary_op1,
1258  BinaryOperation2 binary_op2)
1259  {
1260  return init;
1261  }
1262 };
1263 
1264 } // namespace detail
1265 
1267 template
1268 <
1269  std::size_t Size,
1270  class InputIterator1,
1271  class InputIterator2,
1272  class T,
1273  class BinaryOperation1,
1274  class BinaryOperation2
1275 >
1276 BOOST_FORCEINLINE
1277 T inner_product_k(
1278  InputIterator1 first1,
1279  InputIterator2 first2,
1280  T init,
1281  BinaryOperation1 binary_op1,
1282  BinaryOperation2 binary_op2)
1283 {
1284  return detail::inner_product_k_t<Size>::template apply(
1285  first1, first2, init, binary_op1, binary_op2);
1286 }
1287 
1289 template
1290 <
1291  typename PixelAccum,
1292  typename SrcIterator,
1293  typename KernelIterator,
1294  typename Size,
1295  typename DstIterator
1296 >
1297 inline
1298 auto correlate_pixels_n(
1299  SrcIterator src_begin,
1300  SrcIterator src_end,
1301  KernelIterator kernel_begin,
1302  Size kernel_size,
1303  DstIterator dst_begin)
1304  -> DstIterator
1305 {
1306  using src_pixel_ref_t = typename pixel_proxy
1307  <
1308  typename std::iterator_traits<SrcIterator>::value_type
1309  >::type;
1310  using dst_pixel_ref_t = typename pixel_proxy
1311  <
1312  typename std::iterator_traits<DstIterator>::value_type
1313  >::type;
1314  using kernel_value_t = typename std::iterator_traits<KernelIterator>::value_type;
1315 
1316  PixelAccum accum_zero;
1317  pixel_zeros_t<PixelAccum>()(accum_zero);
1318  while (src_begin != src_end)
1319  {
1320  pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1321  std::inner_product(
1322  src_begin,
1323  src_begin + kernel_size,
1324  kernel_begin,
1325  accum_zero,
1326  pixel_plus_t<PixelAccum, PixelAccum, PixelAccum>(),
1327  pixel_multiplies_scalar_t<src_pixel_ref_t, kernel_value_t, PixelAccum>()),
1328  *dst_begin);
1329 
1330  ++src_begin;
1331  ++dst_begin;
1332  }
1333  return dst_begin;
1334 }
1335 
1337 template
1338 <
1339  std::size_t Size,
1340  typename PixelAccum,
1341  typename SrcIterator,
1342  typename KernelIterator,
1343  typename DstIterator
1344 >
1345 inline
1346 auto correlate_pixels_k(
1347  SrcIterator src_begin,
1348  SrcIterator src_end,
1349  KernelIterator kernel_begin,
1350  DstIterator dst_begin)
1351  -> DstIterator
1352 {
1353  using src_pixel_ref_t = typename pixel_proxy
1354  <
1355  typename std::iterator_traits<SrcIterator>::value_type
1356  >::type;
1357  using dst_pixel_ref_t = typename pixel_proxy
1358  <
1359  typename std::iterator_traits<DstIterator>::value_type
1360  >::type;
1361  using kernel_type = typename std::iterator_traits<KernelIterator>::value_type;
1362 
1363  PixelAccum accum_zero;
1364  pixel_zeros_t<PixelAccum>()(accum_zero);
1365  while (src_begin != src_end)
1366  {
1367  pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1368  inner_product_k<Size>(
1369  src_begin,
1370  kernel_begin,
1371  accum_zero,
1372  pixel_plus_t<PixelAccum, PixelAccum, PixelAccum>(),
1373  pixel_multiplies_scalar_t<src_pixel_ref_t, kernel_type, PixelAccum>()),
1374  *dst_begin);
1375 
1376  ++src_begin;
1377  ++dst_begin;
1378  }
1379  return dst_begin;
1380 }
1381 
1386 template <typename PixelAccum, typename SrcView, typename Scalar, typename DstView>
1387 inline
1388 void view_multiplies_scalar(SrcView const& src_view, Scalar const& scalar, DstView const& dst_view)
1389 {
1390  static_assert(std::is_scalar<Scalar>::value, "Scalar is not scalar");
1391  BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions());
1392  using src_pixel_ref_t = typename pixel_proxy<typename SrcView::value_type>::type;
1393  using dst_pixel_ref_t = typename pixel_proxy<typename DstView::value_type>::type;
1394  using y_coord_t = typename SrcView::y_coord_t;
1395 
1396  y_coord_t const height = src_view.height();
1397  for (y_coord_t y = 0; y < height; ++y)
1398  {
1399  typename SrcView::x_iterator it_src = src_view.row_begin(y);
1400  typename DstView::x_iterator it_dst = dst_view.row_begin(y);
1401  typename SrcView::x_iterator it_src_end = src_view.row_end(y);
1402  while (it_src != it_src_end)
1403  {
1404  pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1405  pixel_multiplies_scalar_t<src_pixel_ref_t, Scalar, PixelAccum>()(*it_src, scalar),
1406  *it_dst);
1407 
1408  ++it_src;
1409  ++it_dst;
1410  }
1411  }
1412 }
1413 
1414 
1417 enum class boundary_option
1418 {
1419  output_ignore,
1420  output_zero,
1421  extend_padded,
1422  extend_zero,
1423  extend_constant
1424 };
1425 
1426 namespace detail
1427 {
1428 
1429 template <typename SrcView, typename RltView>
1430 void extend_row_impl(
1431  SrcView const& src_view,
1432  RltView result_view,
1433  std::size_t extend_count,
1434  boundary_option option)
1435 {
1436  std::ptrdiff_t extend_count_ = static_cast<std::ptrdiff_t>(extend_count);
1437 
1438  if (option == boundary_option::extend_constant)
1439  {
1440  for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1441  {
1442  if(i >= extend_count_ && i < extend_count_ + src_view.height())
1443  {
1444  assign_pixels(
1445  src_view.row_begin(i - extend_count_),
1446  src_view.row_end(i - extend_count_),
1447  result_view.row_begin(i)
1448  );
1449  }
1450  else if(i < extend_count_)
1451  {
1452  assign_pixels(src_view.row_begin(0), src_view.row_end(0), result_view.row_begin(i));
1453  }
1454  else
1455  {
1456  assign_pixels(
1457  src_view.row_begin(src_view.height() - 1),
1458  src_view.row_end(src_view.height() - 1),
1459  result_view.row_begin(i)
1460  );
1461  }
1462 
1463  }
1464  }
1465  else if (option == boundary_option::extend_zero)
1466  {
1467  typename SrcView::value_type acc_zero;
1468  pixel_zeros_t<typename SrcView::value_type>()(acc_zero);
1469 
1470  for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1471  {
1472  if (i >= extend_count_ && i < extend_count_ + src_view.height())
1473  {
1474  assign_pixels(
1475  src_view.row_begin(i - extend_count_),
1476  src_view.row_end(i - extend_count_),
1477  result_view.row_begin(i)
1478  );
1479  }
1480  else
1481  {
1482  std::fill_n(result_view.row_begin(i), result_view.width(), acc_zero);
1483  }
1484  }
1485  }
1486  else if (option == boundary_option::extend_padded)
1487  {
1488  auto original_view = subimage_view(
1489  src_view,
1490  0,
1491  -extend_count,
1492  src_view.width(),
1493  src_view.height() + (2 * extend_count)
1494  );
1495  for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1496  {
1497  assign_pixels(
1498  original_view.row_begin(i),
1499  original_view.row_end(i),
1500  result_view.row_begin(i)
1501  );
1502  }
1503  }
1504  else
1505  {
1506  BOOST_ASSERT_MSG(false, "Invalid boundary option");
1507  }
1508 }
1509 
1510 } //namespace detail
1511 
1512 
1519 template <typename SrcView>
1520 auto extend_row(
1521  SrcView const& src_view,
1522  std::size_t extend_count,
1523  boundary_option option
1524 ) -> typename gil::image<typename SrcView::value_type>
1525 {
1526  typename gil::image<typename SrcView::value_type>
1527  result_img(src_view.width(), src_view.height() + (2 * extend_count));
1528 
1529  auto result_view = view(result_img);
1530  detail::extend_row_impl(src_view, result_view, extend_count, option);
1531  return result_img;
1532 }
1533 
1534 
1541 template <typename SrcView>
1542 auto extend_col(
1543  SrcView const& src_view,
1544  std::size_t extend_count,
1545  boundary_option option
1546 ) -> typename gil::image<typename SrcView::value_type>
1547 {
1548  auto src_view_rotate = rotated90cw_view(src_view);
1549 
1550  typename gil::image<typename SrcView::value_type>
1551  result_img(src_view.width() + (2 * extend_count), src_view.height());
1552 
1553  auto result_view = rotated90cw_view(view(result_img));
1554  detail::extend_row_impl(src_view_rotate, result_view, extend_count, option);
1555  return result_img;
1556 }
1557 
1564 template <typename SrcView>
1565 auto extend_boundary(
1566  SrcView const& src_view,
1567  std::size_t extend_count,
1568  boundary_option option
1569 ) -> typename gil::image<typename SrcView::value_type>
1570 {
1571  if (option == boundary_option::extend_padded)
1572  {
1573  typename gil::image<typename SrcView::value_type>
1574  result_img(src_view.width()+(2 * extend_count), src_view.height()+(2 * extend_count));
1575  typename gil::image<typename SrcView::value_type>::view_t result_view = view(result_img);
1576 
1577  auto original_view = subimage_view(
1578  src_view,
1579  -extend_count,
1580  -extend_count,
1581  src_view.width() + (2 * extend_count),
1582  src_view.height() + (2 * extend_count)
1583  );
1584 
1585  for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1586  {
1587  assign_pixels(
1588  original_view.row_begin(i),
1589  original_view.row_end(i),
1590  result_view.row_begin(i)
1591  );
1592  }
1593 
1594  return result_img;
1595  }
1596 
1597  auto auxilary_img = extend_col(src_view, extend_count, option);
1598  return extend_row(view(auxilary_img), extend_count, option);
1599 }
1600 
1601 } } // namespace boost::gil
1602 
1603 #endif
boost::gil::memory_based_step_iterator
MEMORY-BASED STEP ITERATOR.
Definition: algorithm.hpp:42
boost::gil::detail::copier_n
Definition: algorithm.hpp:189
boost::gil::copy_and_convert_pixels
BOOST_FORCEINLINE void copy_and_convert_pixels(const View1 &src, const View2 &dst)
Definition: algorithm.hpp:341
boost::gil::fill_pixels
BOOST_FORCEINLINE void fill_pixels(View const &view, Value const &value)
std::fill for image views
Definition: algorithm.hpp:416
boost::gil::pixel_proxy
Reference proxy associated with a type that has a "reference" member type alias.
Definition: algorithm.hpp:1193
boost::gil::equal_pixels
BOOST_FORCEINLINE bool equal_pixels(const View1 &v1, const View2 &v2)
std::equal for image views
Definition: algorithm.hpp:1105
boost::gil::pixel
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept,...
Definition: metafunctions.hpp:24
boost::gil::binary_operation_obj
A generic binary operation on views.
Definition: algorithm.hpp:87
boost::gil::generate_pixels
void generate_pixels(View const &view, F fun)
std::generate for image views
Definition: algorithm.hpp:918
boost::gil::uninitialized_copy_pixels
void uninitialized_copy_pixels(View1 const &view1, View2 const &view2)
std::uninitialized_copy for image views. Does not support planar heterogeneous views....
Definition: algorithm.hpp:819
boost::gil::iterator_from_2d
Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept,...
Definition: iterator_from_2d.hpp:42
std::fill
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:365
boost::gil::transform_pixels
BOOST_FORCEINLINE F transform_pixels(const View1 &src1, const View2 &src2, const View3 &dst, F fun)
transform_pixels with two sources
Definition: algorithm.hpp:1137
boost::gil::views_are_compatible
Returns whether two views are compatible.
Definition: concepts/image_view.hpp:522
boost::gil::transform_pixel_positions
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:1170
boost::gil::copy_pixels
BOOST_FORCEINLINE void copy_pixels(const View1 &src, const View2 &dst)
std::copy for image views
Definition: algorithm.hpp:288
std::copy1
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::gil::view
const image< Pixel, IsPlanar, Alloc >::view_t & view(image< Pixel, IsPlanar, Alloc > &img)
Returns the non-constant-pixel view of an image.
Definition: image.hpp:549
boost::gil::destruct_pixels
BOOST_FORCEINLINE void destruct_pixels(View const &view)
Invokes the in-place destructor on every pixel of the view.
Definition: algorithm.hpp:514
boost::gil::for_each_pixel_position
F for_each_pixel_position(View const &view, F fun)
Definition: algorithm.hpp:895
boost::gil::uninitialized_fill_pixels
void uninitialized_fill_pixels(const View &view, const Value &val)
std::uninitialized_fill for image views. Does not support planar heterogeneous views....
Definition: algorithm.hpp:583
boost::gil::default_construct_pixels
void default_construct_pixels(View const &view)
Invokes the in-place default constructor on every pixel of the (uninitialized) view....
Definition: algorithm.hpp:720
std::copy
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::gil::rotated90cw_view
dynamic_xy_step_transposed_type< View >::type rotated90cw_view(const View &src)
Definition: image_view_factory.hpp:221
boost::gil::detail::std_fill_t
struct to do std::fill
Definition: algorithm.hpp:387
boost::gil::for_each_pixel
F for_each_pixel(View const &view, F fun)
Definition: algorithm.hpp:874
std::equal
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:1083
boost::gil::memory_based_2d_locator
Memory-based pixel locator. Models: PixelLocatorConcept,HasDynamicXStepTypeConcept,...
Definition: algorithm.hpp:44
boost::gil::planar_pixel_iterator
An iterator over planar pixels. Models HomogeneousColorBaseConcept, PixelIteratorConcept,...
Definition: algorithm.hpp:40
boost::gil::subimage_view
View subimage_view(View const &src, typename View::point_t const &topleft, typename View::point_t const &dimensions)
Definition: image_view_factory.hpp:254