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>
40 struct planar_pixel_iterator;
41 template <typename Iterator>
42 class memory_based_step_iterator;
43 template <typename StepIterator>
44 class memory_based_2d_locator;
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  auto operator()(const std::pair<const V1*,const V2*>& p) const -> result_type {
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  auto operator()(const V1& v1, const V2& v2) const -> result_type {
98  return apply(v1, v2, typename views_are_compatible<V1,V2>::type());
99  }
100 
101  auto operator()(const error_t&) const -> result_type { 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  auto apply(V1 const& v1, V2 const& v2, std::false_type) const -> result_type
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  auto apply(V1 const& v1, V2 const& v2, std::true_type) const -> result_type
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  auto apply_incompatible(V1 const& /*v1*/, V2 const& /*v2*/) const -> result_type
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
159 auto copy(const boost::gil::pixel<T,CS>* first, const boost::gil::pixel<T,CS>* last,
161 {
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 {
180  boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type>>();
181  static_for_each(first,last,dst,boost::gil::detail::copy_fn<IC1,IC2>());
182  return dst+(last-first);
183 }
184 } // namespace std
185 
186 namespace boost { namespace gil {
187 namespace detail {
190 template <typename I, typename O>
191 struct copier_n {
192  BOOST_FORCEINLINE void operator()(I src, typename std::iterator_traits<I>::difference_type n, O dst) const { std::copy(src,src+n, dst); }
193 };
194 
196 template <typename IL, typename O> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
197 struct copier_n<iterator_from_2d<IL>,O> {
198  using diff_t = typename std::iterator_traits<iterator_from_2d<IL>>::difference_type;
199  BOOST_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, O dst) const {
200  gil_function_requires<PixelLocatorConcept<IL>>();
201  gil_function_requires<MutablePixelIteratorConcept<O>>();
202  while (n>0) {
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  using diff_t = typename std::iterator_traits<I>::difference_type;
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  using diff_t = typename iterator_from_2d<IL>::difference_type;
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 auto copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) -> DstIterator {
256  using src_x_iterator = typename SrcIterator::x_iterator;
257  using dst_x_iterator = typename DstIterator::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 {
283  return boost::gil::detail::copy_with_2d_iterators(first,last,dst);
284 }
285 
286 } // namespace std
287 
288 namespace boost { namespace gil {
291 template <typename View1, typename View2> BOOST_FORCEINLINE
292 void copy_pixels(const View1& src, const View2& dst)
293 {
294  BOOST_ASSERT(src.dimensions() == dst.dimensions());
295  detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
296 }
297 
299 // copy_and_convert_pixels
301 
307 
308 namespace detail {
309 template <typename CC>
310 class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC>>
311 {
312 private:
313  CC _cc;
314 public:
315  using result_type = typename binary_operation_obj<copy_and_convert_pixels_fn<default_color_converter>>::result_type;
316  copy_and_convert_pixels_fn() {}
317  copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {}
318  // when the two color spaces are incompatible, a color conversion is performed
319  template <typename V1, typename V2> BOOST_FORCEINLINE
320  auto apply_incompatible(const V1& src, const V2& dst) const -> result_type {
321  copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst);
322  }
323 
324  // If the two color spaces are compatible, copy_and_convert is just copy
325  template <typename V1, typename V2> BOOST_FORCEINLINE
326  auto apply_compatible(const V1& src, const V2& dst) const -> result_type {
327  copy_pixels(src,dst);
328  }
329 };
330 } // namespace detail
331 
333 template <typename V1, typename V2,typename CC>
334 BOOST_FORCEINLINE
335 void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) {
336  detail::copy_and_convert_pixels_fn<CC> ccp(cc);
337  ccp(src,dst);
338 }
339 
340 struct default_color_converter;
341 
343 template <typename View1, typename View2>
344 BOOST_FORCEINLINE
345 void copy_and_convert_pixels(const View1& src, const View2& dst) {
346  detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
347  ccp(src,dst);
348 }
349 } } // namespace boost::gil
350 
352 // std::fill and gil::fill_pixels
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  std::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 
388 namespace detail {
389 
391 struct std_fill_t {
392  template <typename It, typename P>
393  void operator()(It first, It last, const P& p_in) {
394  std::fill(first,last,p_in);
395  }
396 };
397 
399 template <typename It, typename P>
400 BOOST_FORCEINLINE
401 void fill_aux(It first, It last, P const& p, std::true_type)
402 {
403  static_for_each(first, last, p, std_fill_t());
404 }
405 
407 template <typename It, typename P>
408 BOOST_FORCEINLINE
409 void fill_aux(It first, It last, P const& p, std::false_type)
410 {
411  std::fill(first, last, p);
412 }
413 
414 } // namespace detail
415 
418 template <typename View, typename Value>
419 BOOST_FORCEINLINE
420 void fill_pixels(View const& view, Value const& value)
421 {
422  if (view.is_1d_traversable())
423  {
424  detail::fill_aux(
425  view.begin().x(), view.end().x(), value, is_planar<View>());
426  }
427  else
428  {
429  for (std::ptrdiff_t y = 0; y < view.height(); ++y)
430  detail::fill_aux(
431  view.row_begin(y), view.row_end(y), value, is_planar<View>());
432  }
433 }
434 
436 // destruct_pixels
438 
442 
443 namespace detail {
444 template <typename Iterator>
445 BOOST_FORCEINLINE
446 void destruct_range_impl(Iterator first, Iterator last,
447  typename std::enable_if
448  <
449  mp11::mp_and
450  <
451  std::is_pointer<Iterator>,
452  mp11::mp_not
453  <
454  detail::is_trivially_destructible<typename std::iterator_traits<Iterator>::value_type>
455  >
456  >::value
457  >::type* /*ptr*/ = 0)
458 {
459  while (first != last)
460  {
461  first->~value_t();
462  ++first;
463  }
464 }
465 
466 template <typename Iterator>
467 BOOST_FORCEINLINE
468 void destruct_range_impl(Iterator /*first*/, Iterator /*last*/,
469  typename std::enable_if
470  <
471  mp11::mp_or
472  <
473  mp11::mp_not<std::is_pointer<Iterator>>,
474  detail::is_trivially_destructible<typename std::iterator_traits<Iterator>::value_type>
475  >::value
476  >::type* /* ptr */ = nullptr)
477 {
478 }
479 
480 template <typename Iterator>
481 BOOST_FORCEINLINE
482 void destruct_range(Iterator first, Iterator last)
483 {
484  destruct_range_impl(first, last);
485 }
486 
487 struct std_destruct_t
488 {
489  template <typename Iterator>
490  void operator()(Iterator first, Iterator last) const
491  {
492  destruct_range(first,last);
493  }
494 };
495 
497 template <typename It>
498 BOOST_FORCEINLINE
499 void destruct_aux(It first, It last, std::true_type)
500 {
501  static_for_each(first,last,std_destruct_t());
502 }
503 
505 template <typename It>
506 BOOST_FORCEINLINE
507 void destruct_aux(It first, It last, std::false_type)
508 {
509  destruct_range(first,last);
510 }
511 
512 } // namespace detail
513 
516 template <typename View>
517 BOOST_FORCEINLINE
518 void destruct_pixels(View const& view)
519 {
520  if (view.is_1d_traversable())
521  {
522  detail::destruct_aux(
523  view.begin().x(), view.end().x(), is_planar<View>());
524  }
525  else
526  {
527  for (std::ptrdiff_t y = 0; y < view.height(); ++y)
528  detail::destruct_aux(
529  view.row_begin(y), view.row_end(y), is_planar<View>());
530  }
531 }
532 
534 // uninitialized_fill_pixels
536 
540 
541 namespace detail {
542 
545 template <typename It, typename P>
546 BOOST_FORCEINLINE
547 void uninitialized_fill_aux(It first, It last, P const& p, std::true_type)
548 {
549  std::size_t channel = 0;
550  try
551  {
552  using pixel_t = typename std::iterator_traits<It>::value_type;
553  while (channel < num_channels<pixel_t>::value)
554  {
555  std::uninitialized_fill(
556  dynamic_at_c(first,channel),
557  dynamic_at_c(last,channel),
558  dynamic_at_c(p,channel));
559 
560  ++channel;
561  }
562  }
563  catch (...)
564  {
565  for (std::size_t c = 0; c < channel; ++c)
566  destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
567  throw;
568  }
569 }
570 
573 template <typename It, typename P>
574 BOOST_FORCEINLINE
575 void uninitialized_fill_aux(It first, It last, P const& p, std::false_type)
576 {
577  std::uninitialized_fill(first,last,p);
578 }
579 
580 } // namespace detail
581 
586 template <typename View, typename Value>
587 void uninitialized_fill_pixels(const View& view, const Value& val) {
588  if (view.is_1d_traversable())
589  detail::uninitialized_fill_aux(view.begin().x(), view.end().x(),
590  val,is_planar<View>());
591  else {
592  typename View::y_coord_t y = 0;
593  try {
594  for (y=0; y<view.height(); ++y)
595  detail::uninitialized_fill_aux(view.row_begin(y),view.row_end(y),
596  val,is_planar<View>());
597  } catch(...) {
598  for (typename View::y_coord_t y0=0; y0<y; ++y0)
599  detail::destruct_aux(view.row_begin(y0),view.row_end(y0), is_planar<View>());
600  throw;
601  }
602  }
603 }
604 
606 // default_construct_pixels
608 
612 
613 namespace detail {
614 template <typename It> BOOST_FORCEINLINE
615 void default_construct_range_impl(It first, It last, std::true_type)
616 {
617  It first1 = first;
618  try
619  {
620  using value_t = typename std::iterator_traits<It>::value_type;
621  while (first != last)
622  {
623  new (first) value_t();
624  ++first;
625  }
626  }
627  catch (...)
628  {
629  destruct_range(first1, first);
630  throw;
631  }
632 }
633 
634 template <typename It>
635 BOOST_FORCEINLINE
636 void default_construct_range_impl(It, It, std::false_type) {}
637 
638 template <typename It>
639 BOOST_FORCEINLINE
640 void default_construct_range(It first, It last)
641 {
642  default_construct_range_impl(first, last, typename std::is_pointer<It>::type());
643 }
644 
646 template <typename It>
647 BOOST_FORCEINLINE
648 void default_construct_aux(It first, It last, std::true_type)
649 {
650  std::size_t channel = 0;
651  try
652  {
653  using pixel_t = typename std::iterator_traits<It>::value_type;
654  while (channel < num_channels<pixel_t>::value)
655  {
656  default_construct_range(dynamic_at_c(first, channel), dynamic_at_c(last, channel));
657  ++channel;
658  }
659  }
660  catch (...)
661  {
662  for (std::size_t c = 0; c < channel; ++c)
663  destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
664  throw;
665  }
666 }
667 
669 template <typename It>
670 BOOST_FORCEINLINE
671 void default_construct_aux(It first, It last, std::false_type)
672 {
673  default_construct_range(first, last);
674 }
675 
676 template <typename View, bool IsPlanar>
677 struct has_trivial_pixel_constructor
678  : detail::is_trivially_default_constructible<typename View::value_type>
679 {};
680 
681 template <typename View>
682 struct has_trivial_pixel_constructor<View, true>
683  : detail::is_trivially_default_constructible<typename channel_type<View>::type>
684 {};
685 
686 template<typename View, bool IsTriviallyConstructible>
687 BOOST_FORCEINLINE
688 void default_construct_pixels_impl(
689  View const& view,
690  std::enable_if<!IsTriviallyConstructible>* /*ptr*/ = nullptr)
691 {
692  if (view.is_1d_traversable())
693  {
694  detail::default_construct_aux(
695  view.begin().x(), view.end().x(), is_planar<View>());
696  }
697  else
698  {
699  typename View::y_coord_t y = 0;
700  try
701  {
702  for( y = 0; y < view.height(); ++y )
703  detail::default_construct_aux(
704  view.row_begin(y), view.row_end(y), is_planar<View>());
705  }
706  catch(...)
707  {
708  for (typename View::y_coord_t y0 = 0; y0 < y; ++y0 )
709  detail::destruct_aux(
710  view.row_begin(y0), view.row_end(y0), is_planar<View>());
711 
712  throw;
713  }
714  }
715 }
716 
717 } // namespace detail
718 
723 template <typename View>
725 {
726  detail::default_construct_pixels_impl
727  <
728  View,
729  detail::has_trivial_pixel_constructor
730  <
731  View,
732  is_planar<View>::value
733  >::value
734  >(view);
735 }
736 
738 // uninitialized_copy_pixels
740 
744 
745 namespace detail {
746 
747 enum class copy_planarity_condition
748 {
749  planar_to_planar,
750  interleaved_to_planar,
751  mixed_to_interleaved
752 };
753 
754 using planar_to_planar_type =
755  std::integral_constant
756  <
757  copy_planarity_condition, copy_planarity_condition::planar_to_planar
758  >;
759 using interleaved_to_planar_type =
760  std::integral_constant
761  <
762  copy_planarity_condition, copy_planarity_condition::interleaved_to_planar
763  >;
764 using mixed_to_interleaved_type =
765  std::integral_constant
766  <
767  copy_planarity_condition, copy_planarity_condition::mixed_to_interleaved
768  >;
769 
771 template <typename It1, typename It2>
772 BOOST_FORCEINLINE
773 void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2 last2, planar_to_planar_type)
774 {
775  std::size_t channel=0;
776  try {
777  using pixel_t = typename std::iterator_traits<It1>::value_type;
778  while (channel < num_channels<pixel_t>::value)
779  {
780  std::uninitialized_copy(
781  dynamic_at_c(first1, channel),
782  dynamic_at_c(last1, channel),
783  dynamic_at_c(first2, channel));
784  ++channel;
785  }
786  }
787  catch (...)
788  {
789  It2 last2 = first2;
790  std::advance(last2, std::distance(first1, last1));
791  for (std::size_t c = 0; c < channel; ++c)
792  destruct_range(dynamic_at_c(first2, c), dynamic_at_c(last2, c));
793  throw;
794  }
795 }
796 
798 template <typename It1, typename It2>
799 BOOST_FORCEINLINE
800 void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2, mixed_to_interleaved_type)
801 {
802  std::uninitialized_copy(first1, last1, first2);
803 }
804 
806 template <typename It1, typename It2>
807 BOOST_FORCEINLINE
808 void uninitialized_copy_aux(It1 first1, It1, It2 first2, It2 last2,
809 interleaved_to_planar_type)
810 {
811  default_construct_aux(first2, last2, std::true_type());
812 
813  typename It2::difference_type n = last2 - first2;
814  copier_n<It1,It2>()(first1, n, first2);
815 }
816 } // namespace detail
817 
822 template <typename View1, typename View2>
823 void uninitialized_copy_pixels(View1 const& view1, View2 const& view2)
824 {
825  using copy_planarity_condition = detail::copy_planarity_condition;
826  using copy_planarity_condition_type =
827  std::integral_constant
828  <
829  copy_planarity_condition,
830  !is_planar<View2>::value
831  ? copy_planarity_condition::mixed_to_interleaved
832  : (is_planar<View1>::value
833  ? copy_planarity_condition::planar_to_planar
834  : copy_planarity_condition::interleaved_to_planar)
835  >;
836  BOOST_ASSERT(view1.dimensions() == view2.dimensions());
837 
838  if (view1.is_1d_traversable() && view2.is_1d_traversable())
839  {
840  detail::uninitialized_copy_aux(
841  view1.begin().x(), view1.end().x(), view2.begin().x(), view2.end().x(),
842  copy_planarity_condition_type());
843  }
844  else
845  {
846  typename View1::y_coord_t y = 0;
847  try
848  {
849  for (y = 0; y < view1.height(); ++y)
850  detail::uninitialized_copy_aux(
851  view1.row_begin(y), view1.row_end(y), view2.row_begin(y), view2.row_end(y),
852  copy_planarity_condition_type());
853  }
854  catch(...)
855  {
856  for (typename View1::y_coord_t y0 = 0; y0 < y; ++y0)
857  detail::destruct_aux(view2.row_begin(y0), view2.row_end(y0), is_planar<View2>());
858  throw;
859  }
860  }
861 }
862 
864 // for_each_pixel
866 
875 
877 template <typename View, typename F>
878 F for_each_pixel(View const& view, F fun)
879 {
880  if (view.is_1d_traversable())
881  {
882  return std::for_each(view.begin().x(), view.end().x(), fun);
883  }
884  else
885  {
886  for (std::ptrdiff_t y = 0; y < view.height(); ++y)
887  for (auto begin = view.row_begin(y), end = view.row_end(y); begin != end; ++begin)
888  fun(*begin);
889  return fun;
890  }
891 }
892 
896 
898 template <typename View, typename F>
899 F for_each_pixel_position(View const& view, F fun)
900 {
901  typename View::xy_locator loc = view.xy_at(0, 0);
902  for (std::ptrdiff_t y = 0; y < view.height(); ++y)
903  {
904  for (std::ptrdiff_t x = 0; x < view.width(); ++x, ++loc.x())
905  fun(loc);
906  loc.x() -= view.width(); ++loc.y();
907  }
908  return fun;
909 }
910 
912 // generate_pixels
914 
918 
921 template <typename View, typename F>
922 void generate_pixels(View const& view, F fun)
923 {
924  if (view.is_1d_traversable())
925  {
926  std::generate(view.begin().x(), view.end().x(), fun);
927  }
928  else
929  {
930  for (std::ptrdiff_t y = 0; y < view.height(); ++y)
931  std::generate(view.row_begin(y), view.row_end(y), fun);
932  }
933 }
934 
936 // std::equal and gil::equal_pixels for GIL constructs
938 
942 
943 template <typename I1, typename I2>
944 BOOST_FORCEINLINE
945 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
946 
947 namespace detail {
948 
949 template <typename I1, typename I2>
950 struct equal_n_fn
951 {
952  BOOST_FORCEINLINE
953  bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const
954  {
955  return std::equal(i1, i1 + n, i2);
956  }
957 };
958 
961 template<typename T, typename CS>
962 struct equal_n_fn<pixel<T, CS> const*, pixel<T, CS> const*>
963 {
964  BOOST_FORCEINLINE
965  bool operator()(pixel<T, CS> const* i1, std::ptrdiff_t n, pixel<T, CS> const* i2) const
966  {
967  return memcmp(i1, i2, n * sizeof(pixel<T, CS>)) == 0;
968  }
969 };
970 
971 template<typename T, typename CS>
972 struct equal_n_fn<pixel<T, CS>*, pixel<T, CS>*>
973  : equal_n_fn<pixel<T, CS> const*, pixel<T, CS> const*>
974 {};
975 
979 template<typename IC, typename CS>
980 struct equal_n_fn<planar_pixel_iterator<IC, CS>, planar_pixel_iterator<IC, CS>>
981 {
982  BOOST_FORCEINLINE
983  bool operator()(planar_pixel_iterator<IC, CS> const i1, std::ptrdiff_t n, planar_pixel_iterator<IC, CS> const i2) const
984  {
985  // FIXME: ptrdiff_t vs size_t
986  constexpr std::ptrdiff_t byte_size = n * sizeof(typename std::iterator_traits<IC>::value_type);
987  for (std::ptrdiff_t i = 0; i < mp11::mp_size<CS>::value; ++i)
988  {
989  if (memcmp(dynamic_at_c(i1, i), dynamic_at_c(i2, i), byte_size) != 0)
990  return false;
991  }
992  return true;
993  }
994 };
995 
999 template <typename Loc, typename It>
1000 struct equal_n_fn<boost::gil::iterator_from_2d<Loc>, It>
1001 {
1002  BOOST_FORCEINLINE
1003  bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, It i2) const
1004  {
1005  gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
1006  gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
1007  while (n > 0)
1008  {
1009  std::ptrdiff_t const num = std::min<std::ptrdiff_t>(n, i1.width() - i1.x_pos());
1010  if (!equal_n(i1.x(), num, i2))
1011  return false;
1012  i1 += num;
1013  i2 += num;
1014  n -= num;
1015  }
1016  return true;
1017  }
1018 };
1019 
1023 template <typename It, typename Loc>
1024 struct equal_n_fn<It, boost::gil::iterator_from_2d<Loc>>
1025 {
1026  BOOST_FORCEINLINE
1027  bool operator()(It i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const
1028  {
1029  gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
1030  gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
1031  while (n > 0)
1032  {
1033  std::ptrdiff_t const num = std::min<std::ptrdiff_t>(n, i2.width() - i2.x_pos());
1034  if (!equal_n(i1, num, i2.x()))
1035  return false;
1036  i1 += num;
1037  i2 += num;
1038  n -= num;
1039  }
1040  return true;
1041  }
1042 };
1043 
1045 template <typename Loc1, typename Loc2>
1047  BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const {
1048  gil_function_requires<boost::gil::PixelLocatorConcept<Loc1>>();
1049  gil_function_requires<boost::gil::PixelLocatorConcept<Loc2>>();
1050  if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
1051  while(n-->0) {
1052  if (*i1++!=*i2++) return false;
1053  }
1054  }
1055  while (n>0) {
1056  std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
1057  if (!equal_n(i1.x(), num, i2.x()))
1058  return false;
1059  i1+=num;
1060  i2+=num;
1061  n-=num;
1062  }
1063  return true;
1064  }
1065 };
1066 } // namespace detail
1067 
1068 template <typename I1, typename I2> BOOST_FORCEINLINE
1069 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
1070  return detail::equal_n_fn<I1,I2>()(i1,n,i2);
1071 }
1072 } } // namespace boost::gil
1073 
1074 namespace std {
1086 template <typename Loc1, typename Loc2> BOOST_FORCEINLINE
1088  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1>>();
1089  boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2>>();
1090  std::ptrdiff_t n=last-first;
1091  if (first.is_1d_traversable()) {
1092  if (first2.is_1d_traversable())
1093  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
1094  else
1095  return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2>>()(first.x(),n, first2);
1096  } else {
1097  if (first2.is_1d_traversable())
1098  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
1099  else
1100  return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2>>()(first,n,first2);
1101  }
1102 }
1103 } // namespace std
1104 
1105 namespace boost { namespace gil {
1108 template <typename View1, typename View2> BOOST_FORCEINLINE
1109 bool equal_pixels(const View1& v1, const View2& v2) {
1110  BOOST_ASSERT(v1.dimensions() == v2.dimensions());
1111  return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance
1112 }
1113 
1119 
1123 
1126 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
1127 F transform_pixels(const View1& src,const View2& dst, F fun) {
1128  BOOST_ASSERT(src.dimensions() == dst.dimensions());
1129  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1130  typename View1::x_iterator srcIt=src.row_begin(y);
1131  typename View2::x_iterator dstIt=dst.row_begin(y);
1132  for (std::ptrdiff_t x=0; x<src.width(); ++x)
1133  dstIt[x]=fun(srcIt[x]);
1134  }
1135  return fun;
1136 }
1137 
1140 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
1141 F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) {
1142  for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
1143  typename View1::x_iterator srcIt1=src1.row_begin(y);
1144  typename View2::x_iterator srcIt2=src2.row_begin(y);
1145  typename View3::x_iterator dstIt=dst.row_begin(y);
1146  for (std::ptrdiff_t x=0; x<dst.width(); ++x)
1147  dstIt[x]=fun(srcIt1[x],srcIt2[x]);
1148  }
1149  return fun;
1150 }
1151 
1155 
1158 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
1159 F transform_pixel_positions(const View1& src,const View2& dst, F fun) {
1160  BOOST_ASSERT(src.dimensions() == dst.dimensions());
1161  typename View1::xy_locator loc=src.xy_at(0,0);
1162  for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1163  typename View2::x_iterator dstIt=dst.row_begin(y);
1164  for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
1165  dstIt[x]=fun(loc);
1166  loc.x()-=src.width(); ++loc.y();
1167  }
1168  return fun;
1169 }
1170 
1173 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
1174 F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) {
1175  BOOST_ASSERT(src1.dimensions() == dst.dimensions());
1176  BOOST_ASSERT(src2.dimensions() == dst.dimensions());
1177  typename View1::xy_locator loc1=src1.xy_at(0,0);
1178  typename View2::xy_locator loc2=src2.xy_at(0,0);
1179  for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
1180  typename View3::x_iterator dstIt=dst.row_begin(y);
1181  for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
1182  dstIt[x]=fun(loc1,loc2);
1183  loc1.x()-=src1.width(); ++loc1.y();
1184  loc2.x()-=src2.width(); ++loc2.y();
1185  }
1186  return fun;
1187 }
1188 
1189 
1190 // Code below this line is moved here from <boost/gil/extension/numeric/algorithm.hpp>
1191 
1196 template <typename T>
1197 struct pixel_proxy : std::remove_reference<typename T::reference> {};
1198 
1200 template <typename Iterator1, typename Iterator2, typename BinaryFunction>
1201 BinaryFunction for_each(Iterator1 first1, Iterator1 last1, Iterator2 first2, BinaryFunction f)
1202 {
1203  while (first1 != last1)
1204  f(*first1++, *first2++);
1205  return f;
1206 }
1207 
1208 template <typename SrcIterator, typename DstIterator>
1209 inline
1210 auto assign_pixels(SrcIterator src, SrcIterator src_end, DstIterator dst) -> DstIterator
1211 {
1212  for_each(src, src_end, dst,
1213  pixel_assigns_t
1214  <
1215  typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type,
1216  typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type
1217  >());
1218  return dst + (src_end - src);
1219 }
1220 
1221 namespace detail {
1222 
1223 template <std::size_t Size>
1224 struct inner_product_k_t
1225 {
1226  template
1227  <
1228  class InputIterator1,
1229  class InputIterator2,
1230  class T,
1231  class BinaryOperation1,
1232  class BinaryOperation2
1233  >
1234  static T apply(
1235  InputIterator1 first1,
1236  InputIterator2 first2, T init,
1237  BinaryOperation1 binary_op1,
1238  BinaryOperation2 binary_op2)
1239  {
1240  init = binary_op1(init, binary_op2(*first1, *first2));
1241  return inner_product_k_t<Size - 1>::template apply(
1242  first1 + 1, first2 + 1, init, binary_op1, binary_op2);
1243  }
1244 };
1245 
1246 template <>
1247 struct inner_product_k_t<0>
1248 {
1249  template
1250  <
1251  class InputIterator1,
1252  class InputIterator2,
1253  class T,
1254  class BinaryOperation1,
1255  class BinaryOperation2
1256  >
1257  static T apply(
1258  InputIterator1 first1,
1259  InputIterator2 first2,
1260  T init,
1261  BinaryOperation1 binary_op1,
1262  BinaryOperation2 binary_op2)
1263  {
1264  return init;
1265  }
1266 };
1267 
1268 } // namespace detail
1269 
1271 template
1272 <
1273  std::size_t Size,
1274  class InputIterator1,
1275  class InputIterator2,
1276  class T,
1277  class BinaryOperation1,
1278  class BinaryOperation2
1279 >
1280 BOOST_FORCEINLINE
1281 T inner_product_k(
1282  InputIterator1 first1,
1283  InputIterator2 first2,
1284  T init,
1285  BinaryOperation1 binary_op1,
1286  BinaryOperation2 binary_op2)
1287 {
1288  return detail::inner_product_k_t<Size>::template apply(
1289  first1, first2, init, binary_op1, binary_op2);
1290 }
1291 
1293 template
1294 <
1295  typename PixelAccum,
1296  typename SrcIterator,
1297  typename KernelIterator,
1298  typename Size,
1299  typename DstIterator
1300 >
1301 inline
1302 auto correlate_pixels_n(
1303  SrcIterator src_begin,
1304  SrcIterator src_end,
1305  KernelIterator kernel_begin,
1306  Size kernel_size,
1307  DstIterator dst_begin)
1308  -> DstIterator
1309 {
1310  using src_pixel_ref_t = typename pixel_proxy
1311  <
1312  typename std::iterator_traits<SrcIterator>::value_type
1313  >::type;
1314  using dst_pixel_ref_t = typename pixel_proxy
1315  <
1316  typename std::iterator_traits<DstIterator>::value_type
1317  >::type;
1318  using kernel_value_t = typename std::iterator_traits<KernelIterator>::value_type;
1319 
1320  PixelAccum accum_zero;
1321  pixel_zeros_t<PixelAccum>()(accum_zero);
1322  while (src_begin != src_end)
1323  {
1324  pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1325  std::inner_product(
1326  src_begin,
1327  src_begin + kernel_size,
1328  kernel_begin,
1329  accum_zero,
1330  pixel_plus_t<PixelAccum, PixelAccum, PixelAccum>(),
1331  pixel_multiplies_scalar_t<src_pixel_ref_t, kernel_value_t, PixelAccum>()),
1332  *dst_begin);
1333 
1334  ++src_begin;
1335  ++dst_begin;
1336  }
1337  return dst_begin;
1338 }
1339 
1341 template
1342 <
1343  std::size_t Size,
1344  typename PixelAccum,
1345  typename SrcIterator,
1346  typename KernelIterator,
1347  typename DstIterator
1348 >
1349 inline
1350 auto correlate_pixels_k(
1351  SrcIterator src_begin,
1352  SrcIterator src_end,
1353  KernelIterator kernel_begin,
1354  DstIterator dst_begin)
1355  -> DstIterator
1356 {
1357  using src_pixel_ref_t = typename pixel_proxy
1358  <
1359  typename std::iterator_traits<SrcIterator>::value_type
1360  >::type;
1361  using dst_pixel_ref_t = typename pixel_proxy
1362  <
1363  typename std::iterator_traits<DstIterator>::value_type
1364  >::type;
1365  using kernel_type = typename std::iterator_traits<KernelIterator>::value_type;
1366 
1367  PixelAccum accum_zero;
1368  pixel_zeros_t<PixelAccum>()(accum_zero);
1369  while (src_begin != src_end)
1370  {
1371  pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1372  inner_product_k<Size>(
1373  src_begin,
1374  kernel_begin,
1375  accum_zero,
1376  pixel_plus_t<PixelAccum, PixelAccum, PixelAccum>(),
1377  pixel_multiplies_scalar_t<src_pixel_ref_t, kernel_type, PixelAccum>()),
1378  *dst_begin);
1379 
1380  ++src_begin;
1381  ++dst_begin;
1382  }
1383  return dst_begin;
1384 }
1385 
1390 template <typename PixelAccum, typename SrcView, typename Scalar, typename DstView>
1391 inline
1392 void view_multiplies_scalar(SrcView const& src_view, Scalar const& scalar, DstView const& dst_view)
1393 {
1394  static_assert(std::is_scalar<Scalar>::value, "Scalar is not scalar");
1395  BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions());
1396  using src_pixel_ref_t = typename pixel_proxy<typename SrcView::value_type>::type;
1397  using dst_pixel_ref_t = typename pixel_proxy<typename DstView::value_type>::type;
1398  using y_coord_t = typename SrcView::y_coord_t;
1399 
1400  y_coord_t const height = src_view.height();
1401  for (y_coord_t y = 0; y < height; ++y)
1402  {
1403  typename SrcView::x_iterator it_src = src_view.row_begin(y);
1404  typename DstView::x_iterator it_dst = dst_view.row_begin(y);
1405  typename SrcView::x_iterator it_src_end = src_view.row_end(y);
1406  while (it_src != it_src_end)
1407  {
1408  pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1409  pixel_multiplies_scalar_t<src_pixel_ref_t, Scalar, PixelAccum>()(*it_src, scalar),
1410  *it_dst);
1411 
1412  ++it_src;
1413  ++it_dst;
1414  }
1415  }
1416 }
1417 
1418 
1421 enum class boundary_option
1422 {
1423  output_ignore,
1424  output_zero,
1425  extend_padded,
1426  extend_zero,
1427  extend_constant
1428 };
1429 
1430 namespace detail
1431 {
1432 
1433 template <typename SrcView, typename RltView>
1434 void extend_row_impl(
1435  SrcView const& src_view,
1436  RltView result_view,
1437  std::size_t extend_count,
1438  boundary_option option)
1439 {
1440  std::ptrdiff_t extend_count_ = static_cast<std::ptrdiff_t>(extend_count);
1441 
1442  if (option == boundary_option::extend_constant)
1443  {
1444  for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1445  {
1446  if(i >= extend_count_ && i < extend_count_ + src_view.height())
1447  {
1448  assign_pixels(
1449  src_view.row_begin(i - extend_count_),
1450  src_view.row_end(i - extend_count_),
1451  result_view.row_begin(i)
1452  );
1453  }
1454  else if(i < extend_count_)
1455  {
1456  assign_pixels(src_view.row_begin(0), src_view.row_end(0), result_view.row_begin(i));
1457  }
1458  else
1459  {
1460  assign_pixels(
1461  src_view.row_begin(src_view.height() - 1),
1462  src_view.row_end(src_view.height() - 1),
1463  result_view.row_begin(i)
1464  );
1465  }
1466 
1467  }
1468  }
1469  else if (option == boundary_option::extend_zero)
1470  {
1471  typename SrcView::value_type acc_zero;
1472  pixel_zeros_t<typename SrcView::value_type>()(acc_zero);
1473 
1474  for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1475  {
1476  if (i >= extend_count_ && i < extend_count_ + src_view.height())
1477  {
1478  assign_pixels(
1479  src_view.row_begin(i - extend_count_),
1480  src_view.row_end(i - extend_count_),
1481  result_view.row_begin(i)
1482  );
1483  }
1484  else
1485  {
1486  std::fill_n(result_view.row_begin(i), result_view.width(), acc_zero);
1487  }
1488  }
1489  }
1490  else if (option == boundary_option::extend_padded)
1491  {
1492  auto original_view = subimage_view(
1493  src_view,
1494  0,
1495  -extend_count,
1496  src_view.width(),
1497  src_view.height() + (2 * extend_count)
1498  );
1499  for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1500  {
1501  assign_pixels(
1502  original_view.row_begin(i),
1503  original_view.row_end(i),
1504  result_view.row_begin(i)
1505  );
1506  }
1507  }
1508  else
1509  {
1510  BOOST_ASSERT_MSG(false, "Invalid boundary option");
1511  }
1512 }
1513 
1514 } //namespace detail
1515 
1516 
1523 template <typename SrcView>
1524 auto extend_row(
1525  SrcView const& src_view,
1526  std::size_t extend_count,
1527  boundary_option option
1528 ) -> typename gil::image<typename SrcView::value_type>
1529 {
1530  typename gil::image<typename SrcView::value_type>
1531  result_img(src_view.width(), src_view.height() + (2 * extend_count));
1532 
1533  auto result_view = view(result_img);
1534  detail::extend_row_impl(src_view, result_view, extend_count, option);
1535  return result_img;
1536 }
1537 
1538 
1545 template <typename SrcView>
1546 auto extend_col(
1547  SrcView const& src_view,
1548  std::size_t extend_count,
1549  boundary_option option
1550 ) -> typename gil::image<typename SrcView::value_type>
1551 {
1552  auto src_view_rotate = rotated90cw_view(src_view);
1553 
1554  typename gil::image<typename SrcView::value_type>
1555  result_img(src_view.width() + (2 * extend_count), src_view.height());
1556 
1557  auto result_view = rotated90cw_view(view(result_img));
1558  detail::extend_row_impl(src_view_rotate, result_view, extend_count, option);
1559  return result_img;
1560 }
1561 
1568 template <typename SrcView>
1569 auto extend_boundary(
1570  SrcView const& src_view,
1571  std::size_t extend_count,
1572  boundary_option option
1573 ) -> typename gil::image<typename SrcView::value_type>
1574 {
1575  if (option == boundary_option::extend_padded)
1576  {
1577  typename gil::image<typename SrcView::value_type>
1578  result_img(src_view.width()+(2 * extend_count), src_view.height()+(2 * extend_count));
1579  typename gil::image<typename SrcView::value_type>::view_t result_view = view(result_img);
1580 
1581  auto original_view = subimage_view(
1582  src_view,
1583  -extend_count,
1584  -extend_count,
1585  src_view.width() + (2 * extend_count),
1586  src_view.height() + (2 * extend_count)
1587  );
1588 
1589  for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1590  {
1591  assign_pixels(
1592  original_view.row_begin(i),
1593  original_view.row_end(i),
1594  result_view.row_begin(i)
1595  );
1596  }
1597 
1598  return result_img;
1599  }
1600 
1601  auto auxilary_img = extend_col(src_view, extend_count, option);
1602  return extend_row(view(auxilary_img), extend_count, option);
1603 }
1604 
1605 } } // namespace boost::gil
1606 
1607 #endif
Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept,...
Definition: iterator_from_2d.hpp:46
auto view(image< Pixel, IsPlanar, Alloc > &img) -> typename image< Pixel, IsPlanar, Alloc >::view_t const &
Returns the non-constant-pixel view of an image.
Definition: image.hpp:565
BOOST_FORCEINLINE void copy_pixels(const View1 &src, const View2 &dst)
std::copy for image views
Definition: algorithm.hpp:292
void default_construct_pixels(View const &view)
Invokes the in-place default constructor on every pixel of the (uninitialized) view....
Definition: algorithm.hpp:724
BOOST_FORCEINLINE void destruct_pixels(View const &view)
Invokes the in-place destructor on every pixel of the view.
Definition: algorithm.hpp:518
BOOST_FORCEINLINE bool equal_pixels(const View1 &v1, const View2 &v2)
std::equal for image views
Definition: algorithm.hpp:1109
BOOST_FORCEINLINE void fill_pixels(View const &view, Value const &value)
std::fill for image views
Definition: algorithm.hpp:420
void generate_pixels(View const &view, F fun)
std::generate for image views
Definition: algorithm.hpp:922
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:1174
BOOST_FORCEINLINE F transform_pixels(const View1 &src1, const View2 &src2, const View3 &dst, F fun)
transform_pixels with two sources
Definition: algorithm.hpp:1141
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:823
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:587
BOOST_FORCEINLINE auto copy1(boost::gil::iterator_from_2d< IL > first, boost::gil::iterator_from_2d< IL > last, boost::gil::iterator_from_2d< OL > dst) -> boost::gil::iterator_from_2d< OL >
std::copy(I1,I1,I2) with I1 and I2 being a iterator_from_2d
Definition: algorithm.hpp:281
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:1087
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
BOOST_FORCEINLINE auto 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) -> boost::gil::planar_pixel_iterator< IC2, CS >
Copy when both src and dst are planar pointers is copy for each channel.
Definition: algorithm.hpp:178
defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
Definition: algorithm.hpp:36
A generic binary operation on views.
Definition: algorithm.hpp:88
Definition: algorithm.hpp:191
struct to do std::fill
Definition: algorithm.hpp:391
Reference proxy associated with a type that has a "reference" member type alias.
Definition: algorithm.hpp:1197
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept,...
Definition: pixel.hpp:106
An iterator over planar pixels. Models HomogeneousColorBaseConcept, PixelIteratorConcept,...
Definition: planar_pixel_iterator.hpp:58
Returns whether two views are compatible.
Definition: concepts/image_view.hpp:524