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>
41 template <
typename Iterator>
43 template <
typename StepIterator>
86 template <
typename Derived,
typename Result=
void>
89 using result_type = Result;
91 template <
typename V1,
typename V2> BOOST_FORCEINLINE
92 result_type operator()(
const std::pair<const V1*,const V2*>& p)
const {
96 template <
typename V1,
typename V2> BOOST_FORCEINLINE
97 result_type operator()(
const V1& v1,
const V2& v2)
const {
101 result_type operator()(
const error_t&)
const {
throw std::bad_cast(); }
105 template <
typename V1,
typename V2>
107 result_type apply(V1
const& v1, V2
const& v2, std::false_type)
const
109 return ((
const Derived*)
this)->apply_incompatible(v1, v2);
113 template <
typename V1,
typename V2>
115 result_type apply(V1
const& v1, V2
const& v2, std::true_type)
const
117 return ((
const Derived*)
this)->apply_compatible(v1, v2);
121 template <
typename V1,
typename V2>
123 result_type apply_incompatible(V1
const& , V2
const& )
const
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>
165 namespace boost {
namespace gil {
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); }
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);
184 namespace boost {
namespace gil {
188 template <
typename I,
typename O>
190 BOOST_FORCEINLINE
void operator()(I src,
typename std::iterator_traits<I>::difference_type n, O dst)
const {
std::copy(src,src+n, dst); }
194 template <
typename IL,
typename O>
196 using diff_t =
typename std::iterator_traits<iterator_from_2d<IL>>::difference_type;
198 gil_function_requires<PixelLocatorConcept<IL>>();
199 gil_function_requires<MutablePixelIteratorConcept<O>>();
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);
212 template <
typename I,
typename OL>
214 using diff_t =
typename std::iterator_traits<I>::difference_type;
216 gil_function_requires<PixelIteratorConcept<I>>();
217 gil_function_requires<MutablePixelLocatorConcept<OL>>();
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());
230 template <
typename IL,
typename OL>
232 using diff_t =
typename iterator_from_2d<IL>::difference_type;
234 gil_function_requires<PixelLocatorConcept<IL>>();
235 gil_function_requires<MutablePixelLocatorConcept<OL>>();
236 if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
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());
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;
257 typename SrcIterator::difference_type n = last - first;
259 if (first.is_1d_traversable()) {
260 if (dst.is_1d_traversable())
265 if (dst.is_1d_traversable())
266 copier_n<SrcIterator,dst_x_iterator>()(first,n, dst.x());
268 copier_n<SrcIterator,DstIterator>()(first,n,dst);
278 template <
typename IL,
typename OL>
280 return boost::gil::detail::copy_with_2d_iterators(first,last,dst);
284 namespace boost {
namespace gil {
287 template <
typename View1,
typename View2> BOOST_FORCEINLINE
290 BOOST_ASSERT(src.dimensions() == dst.dimensions());
291 detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
305 template <
typename CC>
306 class copy_and_convert_pixels_fn :
public binary_operation_obj<copy_and_convert_pixels_fn<CC>>
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) {}
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);
321 template <
typename V1,
typename V2> BOOST_FORCEINLINE
322 result_type apply_compatible(
const V1& src,
const V2& dst)
const {
329 template <
typename V1,
typename V2,
typename CC>
332 detail::copy_and_convert_pixels_fn<CC> ccp(cc);
336 struct default_color_converter;
339 template <
typename View1,
typename View2>
342 detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
364 template <
typename IL,
typename V>
366 boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL>>();
367 if (first.is_1d_traversable()) {
371 std::ptrdiff_t n=last-first;
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);
382 namespace boost {
namespace gil {
388 template <
typename It,
typename P>
389 void operator()(It first, It last,
const P& p_in) {
395 template <
typename It,
typename P>
397 void fill_aux(It first, It last, P
const& p, std::true_type)
399 static_for_each(first, last, p,
std_fill_t());
403 template <
typename It,
typename P>
405 void fill_aux(It first, It last, P
const& p, std::false_type)
414 template <
typename View,
typename Value>
418 if (
view.is_1d_traversable())
421 view.begin().x(),
view.end().x(), value, is_planar<View>());
425 for (std::ptrdiff_t y = 0; y <
view.height(); ++y)
427 view.row_begin(y),
view.row_end(y), value, is_planar<View>());
440 template <
typename Iterator>
442 void destruct_range_impl(Iterator first, Iterator last,
443 typename std::enable_if
447 std::is_pointer<Iterator>,
450 detail::is_trivially_destructible<
typename std::iterator_traits<Iterator>::value_type>
455 while (first != last)
462 template <
typename Iterator>
464 void destruct_range_impl(Iterator , Iterator ,
465 typename std::enable_if
469 mp11::mp_not<std::is_pointer<Iterator>>,
470 detail::is_trivially_destructible<
typename std::iterator_traits<Iterator>::value_type>
476 template <
typename Iterator>
478 void destruct_range(Iterator first, Iterator last)
480 destruct_range_impl(first, last);
483 struct std_destruct_t
485 template <
typename Iterator>
486 void operator()(Iterator first, Iterator last)
const
488 destruct_range(first,last);
493 template <
typename It>
495 void destruct_aux(It first, It last, std::true_type)
497 static_for_each(first,last,std_destruct_t());
501 template <
typename It>
503 void destruct_aux(It first, It last, std::false_type)
505 destruct_range(first,last);
512 template <
typename View>
516 if (
view.is_1d_traversable())
518 detail::destruct_aux(
519 view.begin().x(),
view.end().x(), is_planar<View>());
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>());
541 template <
typename It,
typename P>
543 void uninitialized_fill_aux(It first, It last, P
const& p, std::true_type)
545 std::size_t channel = 0;
548 using pixel_t =
typename std::iterator_traits<It>::value_type;
549 while (channel < num_channels<pixel_t>::value)
551 std::uninitialized_fill(
552 dynamic_at_c(first,channel),
553 dynamic_at_c(last,channel),
554 dynamic_at_c(p,channel));
561 for (std::size_t c = 0; c < channel; ++c)
562 destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
569 template <
typename It,
typename P>
571 void uninitialized_fill_aux(It first, It last, P
const& p, std::false_type)
573 std::uninitialized_fill(first,last,p);
582 template <
typename View,
typename Value>
584 if (
view.is_1d_traversable())
585 detail::uninitialized_fill_aux(
view.begin().x(),
view.end().x(),
586 val,is_planar<View>());
588 typename View::y_coord_t y = 0;
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>());
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>());
610 template <
typename It> BOOST_FORCEINLINE
611 void default_construct_range_impl(It first, It last, std::true_type)
616 using value_t =
typename std::iterator_traits<It>::value_type;
617 while (first != last)
619 new (first) value_t();
625 destruct_range(first1, first);
630 template <
typename It>
632 void default_construct_range_impl(It, It, std::false_type) {}
634 template <
typename It>
636 void default_construct_range(It first, It last)
638 default_construct_range_impl(first, last,
typename std::is_pointer<It>::type());
642 template <
typename It>
644 void default_construct_aux(It first, It last, std::true_type)
646 std::size_t channel = 0;
649 using pixel_t =
typename std::iterator_traits<It>::value_type;
650 while (channel < num_channels<pixel_t>::value)
652 default_construct_range(dynamic_at_c(first, channel), dynamic_at_c(last, channel));
658 for (std::size_t c = 0; c < channel; ++c)
659 destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
665 template <
typename It>
667 void default_construct_aux(It first, It last, std::false_type)
669 default_construct_range(first, last);
672 template <
typename View,
bool IsPlanar>
673 struct has_trivial_pixel_constructor
674 : detail::is_trivially_default_constructible<typename View::value_type>
677 template <
typename View>
678 struct has_trivial_pixel_constructor<View, true>
679 : detail::is_trivially_default_constructible<typename channel_type<View>::type>
682 template<
typename View,
bool IsTriviallyConstructible>
684 void default_construct_pixels_impl(
686 std::enable_if<!IsTriviallyConstructible>* =
nullptr)
688 if (
view.is_1d_traversable())
690 detail::default_construct_aux(
691 view.begin().x(),
view.end().x(), is_planar<View>());
695 typename View::y_coord_t y = 0;
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>());
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>());
719 template <
typename View>
722 detail::default_construct_pixels_impl
725 detail::has_trivial_pixel_constructor
728 is_planar<View>::value
743 enum class copy_planarity_condition
746 interleaved_to_planar,
750 using planar_to_planar_type =
751 std::integral_constant
753 copy_planarity_condition, copy_planarity_condition::planar_to_planar
755 using interleaved_to_planar_type =
756 std::integral_constant
758 copy_planarity_condition, copy_planarity_condition::interleaved_to_planar
760 using mixed_to_interleaved_type =
761 std::integral_constant
763 copy_planarity_condition, copy_planarity_condition::mixed_to_interleaved
767 template <
typename It1,
typename It2>
769 void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2 last2, planar_to_planar_type)
771 std::size_t channel=0;
773 using pixel_t =
typename std::iterator_traits<It1>::value_type;
774 while (channel < num_channels<pixel_t>::value)
776 std::uninitialized_copy(
777 dynamic_at_c(first1, channel),
778 dynamic_at_c(last1, channel),
779 dynamic_at_c(first2, channel));
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));
794 template <
typename It1,
typename It2>
796 void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2 last2, mixed_to_interleaved_type)
798 std::uninitialized_copy(first1, last1, first2);
802 template <
typename It1,
typename It2>
804 void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2 last2,
805 interleaved_to_planar_type)
807 default_construct_aux(first2, last2, std::true_type());
809 typename It2::difference_type n = last2 - first2;
810 copier_n<It1,It2>()(first1, n, first2);
818 template <
typename View1,
typename View2>
821 using copy_planarity_condition = detail::copy_planarity_condition;
822 using copy_planarity_condition_type =
823 std::integral_constant
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)
832 BOOST_ASSERT(view1.dimensions() == view2.dimensions());
834 if (view1.is_1d_traversable() && view2.is_1d_traversable())
836 detail::uninitialized_copy_aux(
837 view1.begin().x(), view1.end().x(), view2.begin().x(), view2.end().x(),
838 copy_planarity_condition_type());
842 typename View1::y_coord_t y = 0;
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());
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>());
873 template <
typename View,
typename F>
876 if (
view.is_1d_traversable())
878 return std::for_each(
view.begin().x(),
view.end().x(), fun);
882 for (std::ptrdiff_t y = 0; y <
view.height(); ++y)
883 std::for_each(
view.row_begin(y),
view.row_end(y), fun);
893 template <
typename View,
typename F>
896 typename View::xy_locator loc =
view.xy_at(0, 0);
897 for (std::ptrdiff_t y = 0; y <
view.height(); ++y)
899 for (std::ptrdiff_t x = 0; x <
view.width(); ++x, ++loc.x())
901 loc.x() -=
view.width(); ++loc.y();
916 template <
typename View,
typename F>
919 if (
view.is_1d_traversable())
921 std::generate(
view.begin().x(),
view.end().x(), fun);
925 for (std::ptrdiff_t y = 0; y <
view.height(); ++y)
926 std::generate(
view.row_begin(y),
view.row_end(y), fun);
938 template <
typename I1,
typename I2>
940 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
944 template <
typename I1,
typename I2>
948 bool operator()(I1 i1, std::ptrdiff_t n, I2 i2)
const
956 template<
typename T,
typename CS>
966 template<
typename T,
typename CS>
974 template<
typename IC,
typename CS>
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)
984 if (memcmp(dynamic_at_c(i1, i), dynamic_at_c(i2, i), byte_size) != 0)
994 template <
typename Loc,
typename It>
1000 gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
1001 gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
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))
1018 template <
typename It,
typename Loc>
1024 gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
1025 gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
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()))
1040 template <
typename Loc1,
typename Loc2>
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()) {
1047 if (*i1++!=*i2++)
return false;
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()))
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);
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());
1090 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2>>()(first.x(),n, first2);
1092 if (first2.is_1d_traversable())
1100 namespace boost {
namespace gil {
1103 template <
typename View1,
typename View2> BOOST_FORCEINLINE
1105 BOOST_ASSERT(v1.dimensions() == v2.dimensions());
1106 return std::equal(v1.begin(),v1.end(),v2.begin());
1121 template <
typename View1,
typename View2,
typename F> BOOST_FORCEINLINE
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]);
1135 template <
typename View1,
typename View2,
typename View3,
typename F> BOOST_FORCEINLINE
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]);
1153 template <
typename View1,
typename View2,
typename F> BOOST_FORCEINLINE
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())
1161 loc.x()-=src.width(); ++loc.y();
1168 template <
typename View1,
typename View2,
typename View3,
typename F> BOOST_FORCEINLINE
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();
1191 template <
typename T>
1195 template <
typename Iterator1,
typename Iterator2,
typename BinaryFunction>
1196 BinaryFunction for_each(Iterator1 first1, Iterator1 last1, Iterator2 first2, BinaryFunction f)
1198 while (first1 != last1)
1199 f(*first1++, *first2++);
1203 template <
typename SrcIterator,
typename DstIterator>
1205 auto assign_pixels(SrcIterator src, SrcIterator src_end, DstIterator dst) -> DstIterator
1207 for_each(src, src_end, dst,
1210 typename pixel_proxy<
typename std::iterator_traits<SrcIterator>::value_type>::type,
1211 typename pixel_proxy<
typename std::iterator_traits<DstIterator>::value_type>::type
1213 return dst + (src_end - src);
1218 template <std::
size_t Size>
1219 struct inner_product_k_t
1223 class InputIterator1,
1224 class InputIterator2,
1226 class BinaryOperation1,
1227 class BinaryOperation2
1230 InputIterator1 first1,
1231 InputIterator2 first2, T init,
1232 BinaryOperation1 binary_op1,
1233 BinaryOperation2 binary_op2)
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);
1242 struct inner_product_k_t<0>
1246 class InputIterator1,
1247 class InputIterator2,
1249 class BinaryOperation1,
1250 class BinaryOperation2
1253 InputIterator1 first1,
1254 InputIterator2 first2,
1256 BinaryOperation1 binary_op1,
1257 BinaryOperation2 binary_op2)
1269 class InputIterator1,
1270 class InputIterator2,
1272 class BinaryOperation1,
1273 class BinaryOperation2
1277 InputIterator1 first1,
1278 InputIterator2 first2,
1280 BinaryOperation1 binary_op1,
1281 BinaryOperation2 binary_op2)
1283 return detail::inner_product_k_t<Size>::template apply(
1284 first1, first2, init, binary_op1, binary_op2);
1290 typename PixelAccum,
1291 typename SrcIterator,
1292 typename KernelIterator,
1294 typename DstIterator
1297 auto correlate_pixels_n(
1298 SrcIterator src_begin,
1299 SrcIterator src_end,
1300 KernelIterator kernel_begin,
1302 DstIterator dst_begin)
1305 using src_pixel_ref_t =
typename pixel_proxy
1307 typename std::iterator_traits<SrcIterator>::value_type
1309 using dst_pixel_ref_t =
typename pixel_proxy
1311 typename std::iterator_traits<DstIterator>::value_type
1313 using kernel_value_t =
typename std::iterator_traits<KernelIterator>::value_type;
1315 PixelAccum accum_zero;
1316 pixel_zeros_t<PixelAccum>()(accum_zero);
1317 while (src_begin != src_end)
1319 pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1322 src_begin + kernel_size,
1325 pixel_plus_t<PixelAccum, PixelAccum, PixelAccum>(),
1326 pixel_multiplies_scalar_t<src_pixel_ref_t, kernel_value_t, PixelAccum>()),
1339 typename PixelAccum,
1340 typename SrcIterator,
1341 typename KernelIterator,
1342 typename DstIterator
1345 auto correlate_pixels_k(
1346 SrcIterator src_begin,
1347 SrcIterator src_end,
1348 KernelIterator kernel_begin,
1349 DstIterator dst_begin)
1352 using src_pixel_ref_t =
typename pixel_proxy
1354 typename std::iterator_traits<SrcIterator>::value_type
1356 using dst_pixel_ref_t =
typename pixel_proxy
1358 typename std::iterator_traits<DstIterator>::value_type
1360 using kernel_type =
typename std::iterator_traits<KernelIterator>::value_type;
1362 PixelAccum accum_zero;
1363 pixel_zeros_t<PixelAccum>()(accum_zero);
1364 while (src_begin != src_end)
1366 pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1367 inner_product_k<Size>(
1371 pixel_plus_t<PixelAccum, PixelAccum, PixelAccum>(),
1372 pixel_multiplies_scalar_t<src_pixel_ref_t, kernel_type, PixelAccum>()),
1385 template <
typename PixelAccum,
typename SrcView,
typename Scalar,
typename DstView>
1387 void view_multiplies_scalar(SrcView
const& src_view, Scalar
const& scalar, DstView
const& dst_view)
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;
1395 y_coord_t
const height = src_view.height();
1396 for (y_coord_t y = 0; y < height; ++y)
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)
1403 pixel_assigns_t<PixelAccum, dst_pixel_ref_t>()(
1404 pixel_multiplies_scalar_t<src_pixel_ref_t, Scalar, PixelAccum>()(*it_src, scalar),
1416 enum class boundary_option
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)
1435 std::ptrdiff_t extend_count_ =
static_cast<std::ptrdiff_t
>(extend_count);
1437 if (option == boundary_option::extend_constant)
1439 for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1441 if(i >= extend_count_ && i < extend_count_ + src_view.height())
1444 src_view.row_begin(i - extend_count_),
1445 src_view.row_end(i - extend_count_),
1446 result_view.row_begin(i)
1449 else if(i < extend_count_)
1451 assign_pixels(src_view.row_begin(0), src_view.row_end(0), result_view.row_begin(i));
1456 src_view.row_begin(src_view.height() - 1),
1457 src_view.row_end(src_view.height() - 1),
1458 result_view.row_begin(i)
1464 else if (option == boundary_option::extend_zero)
1466 typename SrcView::value_type acc_zero;
1467 pixel_zeros_t<typename SrcView::value_type>()(acc_zero);
1469 for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1471 if (i >= extend_count_ && i < extend_count_ + src_view.height())
1474 src_view.row_begin(i - extend_count_),
1475 src_view.row_end(i - extend_count_),
1476 result_view.row_begin(i)
1481 std::fill_n(result_view.row_begin(i), result_view.width(), acc_zero);
1485 else if (option == boundary_option::extend_padded)
1492 src_view.height() + (2 * extend_count)
1494 for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1497 original_view.row_begin(i),
1498 original_view.row_end(i),
1499 result_view.row_begin(i)
1505 BOOST_ASSERT_MSG(
false,
"Invalid boundary option");
1518 template <
typename SrcView>
1520 SrcView
const& src_view,
1521 std::size_t extend_count,
1522 boundary_option option
1523 ) ->
typename gil::image<typename SrcView::value_type>
1525 typename gil::image<typename SrcView::value_type>
1526 result_img(src_view.width(), src_view.height() + (2 * extend_count));
1528 auto result_view =
view(result_img);
1529 detail::extend_row_impl(src_view, result_view, extend_count, option);
1540 template <
typename SrcView>
1542 SrcView
const& src_view,
1543 std::size_t extend_count,
1544 boundary_option option
1545 ) ->
typename gil::image<typename SrcView::value_type>
1549 typename gil::image<typename SrcView::value_type>
1550 result_img(src_view.width() + (2 * extend_count), src_view.height());
1553 detail::extend_row_impl(src_view_rotate, result_view, extend_count, option);
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>
1570 if (option == boundary_option::extend_padded)
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);
1580 src_view.width() + (2 * extend_count),
1581 src_view.height() + (2 * extend_count)
1584 for (std::ptrdiff_t i = 0; i < result_view.height(); i++)
1587 original_view.row_begin(i),
1588 original_view.row_end(i),
1589 result_view.row_begin(i)
1596 auto auxilary_img = extend_col(src_view, extend_count, option);
1597 return extend_row(
view(auxilary_img), extend_count, option);