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  std::for_each(view.row_begin(y), view.row_end(y), fun);
884  return fun;
885  }
886 }
887 
891 
893 template <typename View, typename F>
894 F for_each_pixel_position(View const& view, F fun)
895 {
896  typename View::xy_locator loc = view.xy_at(0, 0);
897  for (std::ptrdiff_t y = 0; y < view.height(); ++y)
898  {
899  for (std::ptrdiff_t x = 0; x < view.width(); ++x, ++loc.x())
900  fun(loc);
901  loc.x() -= view.width(); ++loc.y();
902  }
903  return fun;
904 }
905 
907 // generate_pixels
909 
913 
916 template <typename View, typename F>
917 void generate_pixels(View const& view, F fun)
918 {
919  if (view.is_1d_traversable())
920  {
921  std::generate(view.begin().x(), view.end().x(), fun);
922  }
923  else
924  {
925  for (std::ptrdiff_t y = 0; y < view.height(); ++y)
926  std::generate(view.row_begin(y), view.row_end(y), fun);
927  }
928 }
929 
931 // std::equal and gil::equal_pixels for GIL constructs
933 
937 
938 template <typename I1, typename I2>
939 BOOST_FORCEINLINE
940 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
941 
942 namespace detail {
943 
944 template <typename I1, typename I2>
945 struct equal_n_fn
946 {
947  BOOST_FORCEINLINE
948  bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const
949  {
950  return std::equal(i1, i1 + n, i2);
951  }
952 };
953 
956 template<typename T, typename CS>
957 struct equal_n_fn<pixel<T, CS> const*, pixel<T, CS> const*>
958 {
959  BOOST_FORCEINLINE
960  bool operator()(pixel<T, CS> const* i1, std::ptrdiff_t n, pixel<T, CS> const* i2) const
961  {
962  return memcmp(i1, i2, n * sizeof(pixel<T, CS>)) == 0;
963  }
964 };
965 
966 template<typename T, typename CS>
967 struct equal_n_fn<pixel<T, CS>*, pixel<T, CS>*>
968  : equal_n_fn<pixel<T, CS> const*, pixel<T, CS> const*>
969 {};
970 
974 template<typename IC, typename CS>
975 struct equal_n_fn<planar_pixel_iterator<IC, CS>, planar_pixel_iterator<IC, CS>>
976 {
977  BOOST_FORCEINLINE
978  bool operator()(planar_pixel_iterator<IC, CS> const i1, std::ptrdiff_t n, planar_pixel_iterator<IC, CS> const i2) const
979  {
980  // FIXME: ptrdiff_t vs size_t
981  constexpr std::ptrdiff_t byte_size = n * sizeof(typename std::iterator_traits<IC>::value_type);
982  for (std::ptrdiff_t i = 0; i < mp11::mp_size<CS>::value; ++i)
983  {
984  if (memcmp(dynamic_at_c(i1, i), dynamic_at_c(i2, i), byte_size) != 0)
985  return false;
986  }
987  return true;
988  }
989 };
990 
994 template <typename Loc, typename It>
995 struct equal_n_fn<boost::gil::iterator_from_2d<Loc>, It>
996 {
997  BOOST_FORCEINLINE
998  bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, It i2) const
999  {
1000  gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
1001  gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
1002  while (n > 0)
1003  {
1004  std::ptrdiff_t const num = std::min<std::ptrdiff_t>(n, i1.width() - i1.x_pos());
1005  if (!equal_n(i1.x(), num, i2))
1006  return false;
1007  i1 += num;
1008  i2 += num;
1009  n -= num;
1010  }
1011  return true;
1012  }
1013 };
1014 
1018 template <typename It, typename Loc>
1019 struct equal_n_fn<It, boost::gil::iterator_from_2d<Loc>>
1020 {
1021  BOOST_FORCEINLINE
1022  bool operator()(It i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const
1023  {
1024  gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
1025  gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
1026  while (n > 0)
1027  {
1028  std::ptrdiff_t const num = std::min<std::ptrdiff_t>(n, i2.width() - i2.x_pos());
1029  if (!equal_n(i1, num, i2.x()))
1030  return false;
1031  i1 += num;
1032  i2 += num;
1033  n -= num;
1034  }
1035  return true;
1036  }
1037 };
1038 
1040 template <typename Loc1, typename Loc2>
1041 struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2>> {
1042  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const {
1043  gil_function_requires<boost::gil::PixelLocatorConcept<Loc1>>();
1044  gil_function_requires<boost::gil::PixelLocatorConcept<Loc2>>();
1045  if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
1046  while(n-->0) {
1047  if (*i1++!=*i2++) return false;
1048  }
1049  }
1050  while (n>0) {
1051  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
1052  if (!equal_n(i1.x(), num, i2.x()))
1053  return false;
1054  i1+=num;
1055  i2+=num;
1056  n-=num;
1057  }
1058  return true;
1059  }
1060 };
1061 } // namespace detail
1062 
1063 template <typename I1, typename I2> BOOST_FORCEINLINE
1064 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
1065  return detail::equal_n_fn<I1,I2>()(i1,n,i2);
1066 }
1067 } } // namespace boost::gil
1068 
1069 namespace std {
1081 template <typename Loc1, typename Loc2> BOOST_FORCEINLINE
1083  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1>>();
1084  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2>>();
1085  std::ptrdiff_t n=last-first;
1086  if (first.is_1d_traversable()) {
1087  if (first2.is_1d_traversable())
1088  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
1089  else
1090  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2>>()(first.x(),n, first2);
1091  } else {
1092  if (first2.is_1d_traversable())
1093  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
1094  else
1095  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2>>()(first,n,first2);
1096  }
1097 }
1098 } // namespace std
1099 
1100 namespace boost { namespace gil {
1103 template <typename View1, typename View2> BOOST_FORCEINLINE
1104 bool equal_pixels(const View1& v1, const View2& v2) {
1105  BOOST_ASSERT(v1.dimensions() == v2.dimensions());
1106  return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance
1107 }
1108 
1114 
1118 
1121 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
1122 F transform_pixels(const View1& src,const View2& dst, F fun) {
1123  BOOST_ASSERT(src.dimensions() == dst.dimensions());
1124  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1125  typename View1::x_iterator srcIt=src.row_begin(y);
1126  typename View2::x_iterator dstIt=dst.row_begin(y);
1127  for (std::ptrdiff_t x=0; x<src.width(); ++x)
1128  dstIt[x]=fun(srcIt[x]);
1129  }
1130  return fun;
1131 }
1132 
1135 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
1136 F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) {
1137  for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
1138  typename View1::x_iterator srcIt1=src1.row_begin(y);
1139  typename View2::x_iterator srcIt2=src2.row_begin(y);
1140  typename View3::x_iterator dstIt=dst.row_begin(y);
1141  for (std::ptrdiff_t x=0; x<dst.width(); ++x)
1142  dstIt[x]=fun(srcIt1[x],srcIt2[x]);
1143  }
1144  return fun;
1145 }
1146 
1150 
1153 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
1154 F transform_pixel_positions(const View1& src,const View2& dst, F fun) {
1155  BOOST_ASSERT(src.dimensions() == dst.dimensions());
1156  typename View1::xy_locator loc=src.xy_at(0,0);
1157  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1158  typename View2::x_iterator dstIt=dst.row_begin(y);
1159  for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
1160  dstIt[x]=fun(loc);
1161  loc.x()-=src.width(); ++loc.y();
1162  }
1163  return fun;
1164 }
1165 
1168 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
1169 F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) {
1170  BOOST_ASSERT(src1.dimensions() == dst.dimensions());
1171  BOOST_ASSERT(src2.dimensions() == dst.dimensions());
1172  typename View1::xy_locator loc1=src1.xy_at(0,0);
1173  typename View2::xy_locator loc2=src2.xy_at(0,0);
1174  for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
1175  typename View3::x_iterator dstIt=dst.row_begin(y);
1176  for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
1177  dstIt[x]=fun(loc1,loc2);
1178  loc1.x()-=src1.width(); ++loc1.y();
1179  loc2.x()-=src2.width(); ++loc2.y();
1180  }
1181  return fun;
1182 }
1183 
1184 
1185 // Code below this line is moved here from <boost/gil/extension/numeric/algorithm.hpp>
1186 
1191 template <typename T>
1192 struct pixel_proxy : std::remove_reference<typename T::reference> {};
1193 
1195 template <typename Iterator1, typename Iterator2, typename BinaryFunction>
1196 BinaryFunction for_each(Iterator1 first1, Iterator1 last1, Iterator2 first2, BinaryFunction f)
1197 {
1198  while (first1 != last1)
1199  f(*first1++, *first2++);
1200  return f;
1201 }
1202 
1203 template <typename SrcIterator, typename DstIterator>
1204 inline
1205 auto assign_pixels(SrcIterator src, SrcIterator src_end, DstIterator dst) -> DstIterator
1206 {
1207  for_each(src, src_end, dst,
1208  pixel_assigns_t
1209  <
1210  typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type,
1211  typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type
1212  >());
1213  return dst + (src_end - src);
1214 }
1215 
1216 namespace detail {
1217 
1218 template <std::size_t Size>
1219 struct inner_product_k_t
1220 {
1221  template
1222  <
1223  class InputIterator1,
1224  class InputIterator2,
1225  class T,
1226  class BinaryOperation1,
1227  class BinaryOperation2
1228  >
1229  static T apply(
1230  InputIterator1 first1,
1231  InputIterator2 first2, T init,
1232  BinaryOperation1 binary_op1,
1233  BinaryOperation2 binary_op2)
1234  {
1235  init = binary_op1(init, binary_op2(*first1, *first2));
1236  return inner_product_k_t<Size - 1>::template apply(
1237  first1 + 1, first2 + 1, init, binary_op1, binary_op2);
1238  }
1239 };
1240 
1241 template <>
1242 struct inner_product_k_t<0>
1243 {
1244  template
1245  <
1246  class InputIterator1,
1247  class InputIterator2,
1248  class T,
1249  class BinaryOperation1,
1250  class BinaryOperation2
1251  >
1252  static T apply(
1253  InputIterator1 first1,
1254  InputIterator2 first2,
1255  T init,
1256  BinaryOperation1 binary_op1,
1257  BinaryOperation2 binary_op2)
1258  {
1259  return init;
1260  }
1261 };
1262 
1263 } // namespace detail
1264 
1266 template
1267 <
1268  std::size_t Size,
1269  class InputIterator1,
1270  class InputIterator2,
1271  class T,
1272  class BinaryOperation1,
1273  class BinaryOperation2
1274 >
1275 BOOST_FORCEINLINE
1276 T inner_product_k(
1277  InputIterator1 first1,
1278  InputIterator2 first2,
1279  T init,
1280  BinaryOperation1 binary_op1,
1281  BinaryOperation2 binary_op2)
1282 {
1283  return detail::inner_product_k_t<Size>::template apply(
1284  first1, first2, init, binary_op1, binary_op2);
1285 }
1286 
1288 template
1289 <
1290  typename PixelAccum,
1291  typename SrcIterator,
1292  typename KernelIterator,
1293  typename Size,
1294  typename DstIterator
1295 >
1296 inline
1297 auto correlate_pixels_n(
1298  SrcIterator src_begin,
1299  SrcIterator src_end,
1300  KernelIterator kernel_begin,
1301  Size kernel_size,
1302  DstIterator dst_begin)
1303  -> DstIterator
1304 {
1305  using src_pixel_ref_t = typename pixel_proxy
1306  <
1307  typename std::iterator_traits<SrcIterator>::value_type
1308  >::type;
1309  using dst_pixel_ref_t = typename pixel_proxy
1310  <
1311  typename std::iterator_traits<DstIterator>::value_type
1312  >::type;
1313  using kernel_value_t = typename std::iterator_traits<KernelIterator>::value_type;
1314 
1315  PixelAccum accum_zero;
1316  pixel_zeros_t<PixelAccum>()(accum_zero);
1317  while (src_begin != src_end)
1318  {
1319  pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1320  std::inner_product(
1321  src_begin,
1322  src_begin + kernel_size,
1323  kernel_begin,
1324  accum_zero,
1325  pixel_plus_t<PixelAccum, PixelAccum, PixelAccum>(),
1326  pixel_multiplies_scalar_t<src_pixel_ref_t, kernel_value_t, PixelAccum>()),
1327  *dst_begin);
1328 
1329  ++src_begin;
1330  ++dst_begin;
1331  }
1332  return dst_begin;
1333 }
1334 
1336 template
1337 <
1338  std::size_t Size,
1339  typename PixelAccum,
1340  typename SrcIterator,
1341  typename KernelIterator,
1342  typename DstIterator
1343 >
1344 inline
1345 auto correlate_pixels_k(
1346  SrcIterator src_begin,
1347  SrcIterator src_end,
1348  KernelIterator kernel_begin,
1349  DstIterator dst_begin)
1350  -> DstIterator
1351 {
1352  using src_pixel_ref_t = typename pixel_proxy
1353  <
1354  typename std::iterator_traits<SrcIterator>::value_type
1355  >::type;
1356  using dst_pixel_ref_t = typename pixel_proxy
1357  <
1358  typename std::iterator_traits<DstIterator>::value_type
1359  >::type;
1360  using kernel_type = typename std::iterator_traits<KernelIterator>::value_type;
1361 
1362  PixelAccum accum_zero;
1363  pixel_zeros_t<PixelAccum>()(accum_zero);
1364  while (src_begin != src_end)
1365  {
1366  pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1367  inner_product_k<Size>(
1368  src_begin,
1369  kernel_begin,
1370  accum_zero,
1371  pixel_plus_t<PixelAccum, PixelAccum, PixelAccum>(),
1372  pixel_multiplies_scalar_t<src_pixel_ref_t, kernel_type, PixelAccum>()),
1373  *dst_begin);
1374 
1375  ++src_begin;
1376  ++dst_begin;
1377  }
1378  return dst_begin;
1379 }
1380 
1385 template <typename PixelAccum, typename SrcView, typename Scalar, typename DstView>
1386 inline
1387 void view_multiplies_scalar(SrcView const& src_view, Scalar const& scalar, DstView const& dst_view)
1388 {
1389  static_assert(std::is_scalar<Scalar>::value, "Scalar is not scalar");
1390  BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions());
1391  using src_pixel_ref_t = typename pixel_proxy<typename SrcView::value_type>::type;
1392  using dst_pixel_ref_t = typename pixel_proxy<typename DstView::value_type>::type;
1393  using y_coord_t = typename SrcView::y_coord_t;
1394 
1395  y_coord_t const height = src_view.height();
1396  for (y_coord_t y = 0; y < height; ++y)
1397  {
1398  typename SrcView::x_iterator it_src = src_view.row_begin(y);
1399  typename DstView::x_iterator it_dst = dst_view.row_begin(y);
1400  typename SrcView::x_iterator it_src_end = src_view.row_end(y);
1401  while (it_src != it_src_end)
1402  {
1403  pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1404  pixel_multiplies_scalar_t<src_pixel_ref_t, Scalar, PixelAccum>()(*it_src, scalar),
1405  *it_dst);
1406 
1407  ++it_src;
1408  ++it_dst;
1409  }
1410  }
1411 }
1412 
1413 
1416 enum class boundary_option
1417 {
1418  output_ignore,
1419  output_zero,
1420  extend_padded,
1421  extend_zero,
1422  extend_constant
1423 };
1424 
1425 namespace detail
1426 {
1427 
1428 template <typename SrcView, typename RltView>
1429 void extend_row_impl(
1430  SrcView const& src_view,
1431  RltView result_view,
1432  std::size_t extend_count,
1433  boundary_option option)
1434 {
1435  std::ptrdiff_t extend_count_ = static_cast<std::ptrdiff_t>(extend_count);
1436 
1437  if (option == boundary_option::extend_constant)
1438  {
1439  for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1440  {
1441  if(i >= extend_count_ && i < extend_count_ + src_view.height())
1442  {
1443  assign_pixels(
1444  src_view.row_begin(i - extend_count_),
1445  src_view.row_end(i - extend_count_),
1446  result_view.row_begin(i)
1447  );
1448  }
1449  else if(i < extend_count_)
1450  {
1451  assign_pixels(src_view.row_begin(0), src_view.row_end(0), result_view.row_begin(i));
1452  }
1453  else
1454  {
1455  assign_pixels(
1456  src_view.row_begin(src_view.height() - 1),
1457  src_view.row_end(src_view.height() - 1),
1458  result_view.row_begin(i)
1459  );
1460  }
1461 
1462  }
1463  }
1464  else if (option == boundary_option::extend_zero)
1465  {
1466  typename SrcView::value_type acc_zero;
1467  pixel_zeros_t<typename SrcView::value_type>()(acc_zero);
1468 
1469  for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1470  {
1471  if (i >= extend_count_ && i < extend_count_ + src_view.height())
1472  {
1473  assign_pixels(
1474  src_view.row_begin(i - extend_count_),
1475  src_view.row_end(i - extend_count_),
1476  result_view.row_begin(i)
1477  );
1478  }
1479  else
1480  {
1481  std::fill_n(result_view.row_begin(i), result_view.width(), acc_zero);
1482  }
1483  }
1484  }
1485  else if (option == boundary_option::extend_padded)
1486  {
1487  auto original_view = subimage_view(
1488  src_view,
1489  0,
1490  -extend_count,
1491  src_view.width(),
1492  src_view.height() + (2 * extend_count)
1493  );
1494  for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1495  {
1496  assign_pixels(
1497  original_view.row_begin(i),
1498  original_view.row_end(i),
1499  result_view.row_begin(i)
1500  );
1501  }
1502  }
1503  else
1504  {
1505  BOOST_ASSERT_MSG(false, "Invalid boundary option");
1506  }
1507 }
1508 
1509 } //namespace detail
1510 
1511 
1518 template <typename SrcView>
1519 auto extend_row(
1520  SrcView const& src_view,
1521  std::size_t extend_count,
1522  boundary_option option
1523 ) -> typename gil::image<typename SrcView::value_type>
1524 {
1525  typename gil::image<typename SrcView::value_type>
1526  result_img(src_view.width(), src_view.height() + (2 * extend_count));
1527 
1528  auto result_view = view(result_img);
1529  detail::extend_row_impl(src_view, result_view, extend_count, option);
1530  return result_img;
1531 }
1532 
1533 
1540 template <typename SrcView>
1541 auto extend_col(
1542  SrcView const& src_view,
1543  std::size_t extend_count,
1544  boundary_option option
1545 ) -> typename gil::image<typename SrcView::value_type>
1546 {
1547  auto src_view_rotate = rotated90cw_view(src_view);
1548 
1549  typename gil::image<typename SrcView::value_type>
1550  result_img(src_view.width() + (2 * extend_count), src_view.height());
1551 
1552  auto result_view = rotated90cw_view(view(result_img));
1553  detail::extend_row_impl(src_view_rotate, result_view, extend_count, option);
1554  return result_img;
1555 }
1556 
1563 template <typename SrcView>
1564 auto extend_boundary(
1565  SrcView const& src_view,
1566  std::size_t extend_count,
1567  boundary_option option
1568 ) -> typename gil::image<typename SrcView::value_type>
1569 {
1570  if (option == boundary_option::extend_padded)
1571  {
1572  typename gil::image<typename SrcView::value_type>
1573  result_img(src_view.width()+(2 * extend_count), src_view.height()+(2 * extend_count));
1574  typename gil::image<typename SrcView::value_type>::view_t result_view = view(result_img);
1575 
1576  auto original_view = subimage_view(
1577  src_view,
1578  -extend_count,
1579  -extend_count,
1580  src_view.width() + (2 * extend_count),
1581  src_view.height() + (2 * extend_count)
1582  );
1583 
1584  for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1585  {
1586  assign_pixels(
1587  original_view.row_begin(i),
1588  original_view.row_end(i),
1589  result_view.row_begin(i)
1590  );
1591  }
1592 
1593  return result_img;
1594  }
1595 
1596  auto auxilary_img = extend_col(src_view, extend_count, option);
1597  return extend_row(view(auxilary_img), extend_count, option);
1598 }
1599 
1600 } } // namespace boost::gil
1601 
1602 #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:1192
boost::gil::equal_pixels
BOOST_FORCEINLINE bool equal_pixels(const View1 &v1, const View2 &v2)
std::equal for image views
Definition: algorithm.hpp:1104
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:917
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:1136
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:1169
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:894
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:1082
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