9 #ifndef BOOST_GIL_ALGORITHM_HPP
10 #define BOOST_GIL_ALGORITHM_HPP
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>
24 #include <boost/assert.hpp>
25 #include <boost/config.hpp>
32 #include <type_traits>
36 namespace boost {
namespace gil {
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;
86 template <
typename Derived,
typename Result=
void>
89 using result_type = Result;
91 template <
typename V1,
typename V2> BOOST_FORCEINLINE
92 auto operator()(
const std::pair<const V1*,const V2*>& p)
const -> result_type {
96 template <
typename V1,
typename V2> BOOST_FORCEINLINE
97 auto operator()(
const V1& v1,
const V2& v2)
const -> result_type {
101 auto operator()(
const error_t&)
const -> result_type {
throw std::bad_cast(); }
105 template <
typename V1,
typename V2>
107 auto apply(V1
const& v1, V2
const& v2, std::false_type)
const -> result_type
109 return ((
const Derived*)
this)->apply_incompatible(v1, v2);
113 template <
typename V1,
typename V2>
115 auto apply(V1
const& v1, V2
const& v2, std::true_type)
const -> result_type
117 return ((
const Derived*)
this)->apply_compatible(v1, v2);
121 template <
typename V1,
typename V2>
123 auto apply_incompatible(V1
const& , V2
const& )
const -> result_type
125 throw std::bad_cast();
143 template<
typename T,
typename CS>
151 auto p =
std::copy((
unsigned char*)first, (
unsigned char*)last, (
unsigned char*)dst);
157 template<
typename T,
typename CS>
166 namespace boost {
namespace gil {
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); }
177 template<
typename CS,
typename IC1,
typename IC2> BOOST_FORCEINLINE
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);
186 namespace boost {
namespace gil {
190 template <
typename I,
typename O>
192 BOOST_FORCEINLINE
void operator()(I src,
typename std::iterator_traits<I>::difference_type n, O dst)
const {
std::copy(src,src+n, dst); }
196 template <
typename IL,
typename O>
198 using diff_t =
typename std::iterator_traits<iterator_from_2d<IL>>::difference_type;
200 gil_function_requires<PixelLocatorConcept<IL>>();
201 gil_function_requires<MutablePixelIteratorConcept<O>>();
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);
214 template <
typename I,
typename OL>
216 using diff_t =
typename std::iterator_traits<I>::difference_type;
218 gil_function_requires<PixelIteratorConcept<I>>();
219 gil_function_requires<MutablePixelLocatorConcept<OL>>();
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());
232 template <
typename IL,
typename OL>
234 using diff_t =
typename iterator_from_2d<IL>::difference_type;
236 gil_function_requires<PixelLocatorConcept<IL>>();
237 gil_function_requires<MutablePixelLocatorConcept<OL>>();
238 if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
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());
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;
259 typename SrcIterator::difference_type n = last - first;
261 if (first.is_1d_traversable()) {
262 if (dst.is_1d_traversable())
267 if (dst.is_1d_traversable())
268 copier_n<SrcIterator,dst_x_iterator>()(first,n, dst.x());
270 copier_n<SrcIterator,DstIterator>()(first,n,dst);
280 template <
typename IL,
typename OL>
283 return boost::gil::detail::copy_with_2d_iterators(first,last,dst);
288 namespace boost {
namespace gil {
291 template <
typename View1,
typename View2> BOOST_FORCEINLINE
294 BOOST_ASSERT(src.dimensions() == dst.dimensions());
295 detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
309 template <
typename CC>
310 class copy_and_convert_pixels_fn :
public binary_operation_obj<copy_and_convert_pixels_fn<CC>>
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) {}
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);
325 template <
typename V1,
typename V2> BOOST_FORCEINLINE
326 auto apply_compatible(
const V1& src,
const V2& dst)
const -> result_type {
333 template <
typename V1,
typename V2,
typename CC>
335 void copy_and_convert_pixels(
const V1& src,
const V2& dst,CC cc) {
336 detail::copy_and_convert_pixels_fn<CC> ccp(cc);
340 struct default_color_converter;
343 template <
typename View1,
typename View2>
345 void copy_and_convert_pixels(
const View1& src,
const View2& dst) {
346 detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
368 template <
typename IL,
typename V>
370 boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL>>();
371 if (first.is_1d_traversable()) {
375 std::ptrdiff_t n=last-first;
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);
386 namespace boost {
namespace gil {
392 template <
typename It,
typename P>
393 void operator()(It first, It last,
const P& p_in) {
399 template <
typename It,
typename P>
401 void fill_aux(It first, It last, P
const& p, std::true_type)
403 static_for_each(first, last, p,
std_fill_t());
407 template <
typename It,
typename P>
409 void fill_aux(It first, It last, P
const& p, std::false_type)
418 template <
typename View,
typename Value>
422 if (
view.is_1d_traversable())
425 view.begin().x(),
view.end().x(), value, is_planar<View>());
429 for (std::ptrdiff_t y = 0; y <
view.height(); ++y)
431 view.row_begin(y),
view.row_end(y), value, is_planar<View>());
444 template <
typename Iterator>
446 void destruct_range_impl(Iterator first, Iterator last,
447 typename std::enable_if
451 std::is_pointer<Iterator>,
454 detail::is_trivially_destructible<
typename std::iterator_traits<Iterator>::value_type>
459 while (first != last)
466 template <
typename Iterator>
468 void destruct_range_impl(Iterator , Iterator ,
469 typename std::enable_if
473 mp11::mp_not<std::is_pointer<Iterator>>,
474 detail::is_trivially_destructible<
typename std::iterator_traits<Iterator>::value_type>
480 template <
typename Iterator>
482 void destruct_range(Iterator first, Iterator last)
484 destruct_range_impl(first, last);
487 struct std_destruct_t
489 template <
typename Iterator>
490 void operator()(Iterator first, Iterator last)
const
492 destruct_range(first,last);
497 template <
typename It>
499 void destruct_aux(It first, It last, std::true_type)
501 static_for_each(first,last,std_destruct_t());
505 template <
typename It>
507 void destruct_aux(It first, It last, std::false_type)
509 destruct_range(first,last);
516 template <
typename View>
520 if (
view.is_1d_traversable())
522 detail::destruct_aux(
523 view.begin().x(),
view.end().x(), is_planar<View>());
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>());
545 template <
typename It,
typename P>
547 void uninitialized_fill_aux(It first, It last, P
const& p, std::true_type)
549 std::size_t channel = 0;
552 using pixel_t =
typename std::iterator_traits<It>::value_type;
553 while (channel < num_channels<pixel_t>::value)
555 std::uninitialized_fill(
556 dynamic_at_c(first,channel),
557 dynamic_at_c(last,channel),
558 dynamic_at_c(p,channel));
565 for (std::size_t c = 0; c < channel; ++c)
566 destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
573 template <
typename It,
typename P>
575 void uninitialized_fill_aux(It first, It last, P
const& p, std::false_type)
577 std::uninitialized_fill(first,last,p);
586 template <
typename View,
typename Value>
588 if (
view.is_1d_traversable())
589 detail::uninitialized_fill_aux(
view.begin().x(),
view.end().x(),
590 val,is_planar<View>());
592 typename View::y_coord_t y = 0;
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>());
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>());
614 template <
typename It> BOOST_FORCEINLINE
615 void default_construct_range_impl(It first, It last, std::true_type)
620 using value_t =
typename std::iterator_traits<It>::value_type;
621 while (first != last)
623 new (first) value_t();
629 destruct_range(first1, first);
634 template <
typename It>
636 void default_construct_range_impl(It, It, std::false_type) {}
638 template <
typename It>
640 void default_construct_range(It first, It last)
642 default_construct_range_impl(first, last,
typename std::is_pointer<It>::type());
646 template <
typename It>
648 void default_construct_aux(It first, It last, std::true_type)
650 std::size_t channel = 0;
653 using pixel_t =
typename std::iterator_traits<It>::value_type;
654 while (channel < num_channels<pixel_t>::value)
656 default_construct_range(dynamic_at_c(first, channel), dynamic_at_c(last, channel));
662 for (std::size_t c = 0; c < channel; ++c)
663 destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
669 template <
typename It>
671 void default_construct_aux(It first, It last, std::false_type)
673 default_construct_range(first, last);
676 template <
typename View,
bool IsPlanar>
677 struct has_trivial_pixel_constructor
678 : detail::is_trivially_default_constructible<typename View::value_type>
681 template <
typename View>
682 struct has_trivial_pixel_constructor<View, true>
683 : detail::is_trivially_default_constructible<typename channel_type<View>::type>
686 template<
typename View,
bool IsTriviallyConstructible>
688 void default_construct_pixels_impl(
690 std::enable_if<!IsTriviallyConstructible>* =
nullptr)
692 if (
view.is_1d_traversable())
694 detail::default_construct_aux(
695 view.begin().x(),
view.end().x(), is_planar<View>());
699 typename View::y_coord_t y = 0;
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>());
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>());
723 template <
typename View>
726 detail::default_construct_pixels_impl
729 detail::has_trivial_pixel_constructor
732 is_planar<View>::value
747 enum class copy_planarity_condition
750 interleaved_to_planar,
754 using planar_to_planar_type =
755 std::integral_constant
757 copy_planarity_condition, copy_planarity_condition::planar_to_planar
759 using interleaved_to_planar_type =
760 std::integral_constant
762 copy_planarity_condition, copy_planarity_condition::interleaved_to_planar
764 using mixed_to_interleaved_type =
765 std::integral_constant
767 copy_planarity_condition, copy_planarity_condition::mixed_to_interleaved
771 template <
typename It1,
typename It2>
773 void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2 last2, planar_to_planar_type)
775 std::size_t channel=0;
777 using pixel_t =
typename std::iterator_traits<It1>::value_type;
778 while (channel < num_channels<pixel_t>::value)
780 std::uninitialized_copy(
781 dynamic_at_c(first1, channel),
782 dynamic_at_c(last1, channel),
783 dynamic_at_c(first2, channel));
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));
798 template <
typename It1,
typename It2>
800 void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2, mixed_to_interleaved_type)
802 std::uninitialized_copy(first1, last1, first2);
806 template <
typename It1,
typename It2>
808 void uninitialized_copy_aux(It1 first1, It1, It2 first2, It2 last2,
809 interleaved_to_planar_type)
811 default_construct_aux(first2, last2, std::true_type());
813 typename It2::difference_type n = last2 - first2;
814 copier_n<It1,It2>()(first1, n, first2);
822 template <
typename View1,
typename View2>
825 using copy_planarity_condition = detail::copy_planarity_condition;
826 using copy_planarity_condition_type =
827 std::integral_constant
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)
836 BOOST_ASSERT(view1.dimensions() == view2.dimensions());
838 if (view1.is_1d_traversable() && view2.is_1d_traversable())
840 detail::uninitialized_copy_aux(
841 view1.begin().x(), view1.end().x(), view2.begin().x(), view2.end().x(),
842 copy_planarity_condition_type());
846 typename View1::y_coord_t y = 0;
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());
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>());
877 template <
typename View,
typename F>
878 F for_each_pixel(View
const&
view, F fun)
880 if (
view.is_1d_traversable())
882 return std::for_each(
view.begin().x(),
view.end().x(), fun);
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)
898 template <
typename View,
typename F>
899 F for_each_pixel_position(View
const&
view, F fun)
901 typename View::xy_locator loc =
view.xy_at(0, 0);
902 for (std::ptrdiff_t y = 0; y <
view.height(); ++y)
904 for (std::ptrdiff_t x = 0; x <
view.width(); ++x, ++loc.x())
906 loc.x() -=
view.width(); ++loc.y();
921 template <
typename View,
typename F>
924 if (
view.is_1d_traversable())
926 std::generate(
view.begin().x(),
view.end().x(), fun);
930 for (std::ptrdiff_t y = 0; y <
view.height(); ++y)
931 std::generate(
view.row_begin(y),
view.row_end(y), fun);
943 template <
typename I1,
typename I2>
945 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
949 template <
typename I1,
typename I2>
953 bool operator()(I1 i1, std::ptrdiff_t n, I2 i2)
const
961 template<
typename T,
typename CS>
971 template<
typename T,
typename CS>
979 template<
typename IC,
typename CS>
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)
989 if (memcmp(dynamic_at_c(i1, i), dynamic_at_c(i2, i), byte_size) != 0)
999 template <
typename Loc,
typename It>
1005 gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
1006 gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
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))
1023 template <
typename It,
typename Loc>
1029 gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
1030 gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
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()))
1045 template <
typename Loc1,
typename Loc2>
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()) {
1052 if (*i1++!=*i2++)
return false;
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()))
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);
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());
1095 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2>>()(first.x(),n, first2);
1097 if (first2.is_1d_traversable())
1105 namespace boost {
namespace gil {
1108 template <
typename View1,
typename View2> BOOST_FORCEINLINE
1110 BOOST_ASSERT(v1.dimensions() == v2.dimensions());
1111 return std::equal(v1.begin(),v1.end(),v2.begin());
1126 template <
typename View1,
typename View2,
typename F> BOOST_FORCEINLINE
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]);
1140 template <
typename View1,
typename View2,
typename View3,
typename F> BOOST_FORCEINLINE
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]);
1158 template <
typename View1,
typename View2,
typename F> BOOST_FORCEINLINE
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())
1166 loc.x()-=src.width(); ++loc.y();
1173 template <
typename View1,
typename View2,
typename View3,
typename F> BOOST_FORCEINLINE
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();
1196 template <
typename T>
1200 template <
typename Iterator1,
typename Iterator2,
typename BinaryFunction>
1201 BinaryFunction for_each(Iterator1 first1, Iterator1 last1, Iterator2 first2, BinaryFunction f)
1203 while (first1 != last1)
1204 f(*first1++, *first2++);
1208 template <
typename SrcIterator,
typename DstIterator>
1210 auto assign_pixels(SrcIterator src, SrcIterator src_end, DstIterator dst) -> DstIterator
1212 for_each(src, src_end, dst,
1215 typename pixel_proxy<
typename std::iterator_traits<SrcIterator>::value_type>::type,
1216 typename pixel_proxy<
typename std::iterator_traits<DstIterator>::value_type>::type
1218 return dst + (src_end - src);
1223 template <std::
size_t Size>
1224 struct inner_product_k_t
1228 class InputIterator1,
1229 class InputIterator2,
1231 class BinaryOperation1,
1232 class BinaryOperation2
1235 InputIterator1 first1,
1236 InputIterator2 first2, T init,
1237 BinaryOperation1 binary_op1,
1238 BinaryOperation2 binary_op2)
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);
1247 struct inner_product_k_t<0>
1251 class InputIterator1,
1252 class InputIterator2,
1254 class BinaryOperation1,
1255 class BinaryOperation2
1258 InputIterator1 first1,
1259 InputIterator2 first2,
1261 BinaryOperation1 binary_op1,
1262 BinaryOperation2 binary_op2)
1274 class InputIterator1,
1275 class InputIterator2,
1277 class BinaryOperation1,
1278 class BinaryOperation2
1282 InputIterator1 first1,
1283 InputIterator2 first2,
1285 BinaryOperation1 binary_op1,
1286 BinaryOperation2 binary_op2)
1288 return detail::inner_product_k_t<Size>::template apply(
1289 first1, first2, init, binary_op1, binary_op2);
1295 typename PixelAccum,
1296 typename SrcIterator,
1297 typename KernelIterator,
1299 typename DstIterator
1302 auto correlate_pixels_n(
1303 SrcIterator src_begin,
1304 SrcIterator src_end,
1305 KernelIterator kernel_begin,
1307 DstIterator dst_begin)
1310 using src_pixel_ref_t =
typename pixel_proxy
1312 typename std::iterator_traits<SrcIterator>::value_type
1314 using dst_pixel_ref_t =
typename pixel_proxy
1316 typename std::iterator_traits<DstIterator>::value_type
1318 using kernel_value_t =
typename std::iterator_traits<KernelIterator>::value_type;
1320 PixelAccum accum_zero;
1321 pixel_zeros_t<PixelAccum>()(accum_zero);
1322 while (src_begin != src_end)
1324 pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1327 src_begin + kernel_size,
1330 pixel_plus_t<PixelAccum, PixelAccum, PixelAccum>(),
1331 pixel_multiplies_scalar_t<src_pixel_ref_t, kernel_value_t, PixelAccum>()),
1344 typename PixelAccum,
1345 typename SrcIterator,
1346 typename KernelIterator,
1347 typename DstIterator
1350 auto correlate_pixels_k(
1351 SrcIterator src_begin,
1352 SrcIterator src_end,
1353 KernelIterator kernel_begin,
1354 DstIterator dst_begin)
1357 using src_pixel_ref_t =
typename pixel_proxy
1359 typename std::iterator_traits<SrcIterator>::value_type
1361 using dst_pixel_ref_t =
typename pixel_proxy
1363 typename std::iterator_traits<DstIterator>::value_type
1365 using kernel_type =
typename std::iterator_traits<KernelIterator>::value_type;
1367 PixelAccum accum_zero;
1368 pixel_zeros_t<PixelAccum>()(accum_zero);
1369 while (src_begin != src_end)
1371 pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1372 inner_product_k<Size>(
1376 pixel_plus_t<PixelAccum, PixelAccum, PixelAccum>(),
1377 pixel_multiplies_scalar_t<src_pixel_ref_t, kernel_type, PixelAccum>()),
1390 template <
typename PixelAccum,
typename SrcView,
typename Scalar,
typename DstView>
1392 void view_multiplies_scalar(SrcView
const& src_view, Scalar
const& scalar, DstView
const& dst_view)
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;
1400 y_coord_t
const height = src_view.height();
1401 for (y_coord_t y = 0; y < height; ++y)
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)
1408 pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1409 pixel_multiplies_scalar_t<src_pixel_ref_t, Scalar, PixelAccum>()(*it_src, scalar),
1421 enum class boundary_option
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)
1440 std::ptrdiff_t extend_count_ =
static_cast<std::ptrdiff_t
>(extend_count);
1442 if (option == boundary_option::extend_constant)
1444 for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1446 if(i >= extend_count_ && i < extend_count_ + src_view.height())
1449 src_view.row_begin(i - extend_count_),
1450 src_view.row_end(i - extend_count_),
1451 result_view.row_begin(i)
1454 else if(i < extend_count_)
1456 assign_pixels(src_view.row_begin(0), src_view.row_end(0), result_view.row_begin(i));
1461 src_view.row_begin(src_view.height() - 1),
1462 src_view.row_end(src_view.height() - 1),
1463 result_view.row_begin(i)
1469 else if (option == boundary_option::extend_zero)
1471 typename SrcView::value_type acc_zero;
1472 pixel_zeros_t<typename SrcView::value_type>()(acc_zero);
1474 for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1476 if (i >= extend_count_ && i < extend_count_ + src_view.height())
1479 src_view.row_begin(i - extend_count_),
1480 src_view.row_end(i - extend_count_),
1481 result_view.row_begin(i)
1486 std::fill_n(result_view.row_begin(i), result_view.width(), acc_zero);
1490 else if (option == boundary_option::extend_padded)
1492 auto original_view = subimage_view(
1497 src_view.height() + (2 * extend_count)
1499 for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1502 original_view.row_begin(i),
1503 original_view.row_end(i),
1504 result_view.row_begin(i)
1510 BOOST_ASSERT_MSG(
false,
"Invalid boundary option");
1523 template <
typename SrcView>
1525 SrcView
const& src_view,
1526 std::size_t extend_count,
1527 boundary_option option
1528 ) ->
typename gil::image<typename SrcView::value_type>
1530 typename gil::image<typename SrcView::value_type>
1531 result_img(src_view.width(), src_view.height() + (2 * extend_count));
1533 auto result_view =
view(result_img);
1534 detail::extend_row_impl(src_view, result_view, extend_count, option);
1545 template <
typename SrcView>
1547 SrcView
const& src_view,
1548 std::size_t extend_count,
1549 boundary_option option
1550 ) ->
typename gil::image<typename SrcView::value_type>
1552 auto src_view_rotate = rotated90cw_view(src_view);
1554 typename gil::image<typename SrcView::value_type>
1555 result_img(src_view.width() + (2 * extend_count), src_view.height());
1557 auto result_view = rotated90cw_view(
view(result_img));
1558 detail::extend_row_impl(src_view_rotate, result_view, extend_count, option);
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>
1575 if (option == boundary_option::extend_padded)
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);
1581 auto original_view = subimage_view(
1585 src_view.width() + (2 * extend_count),
1586 src_view.height() + (2 * extend_count)
1589 for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1592 original_view.row_begin(i),
1593 original_view.row_end(i),
1594 result_view.row_begin(i)
1601 auto auxilary_img = extend_col(src_view, extend_count, option);
1602 return extend_row(
view(auxilary_img), extend_count, option);
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
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