8 #ifndef BOOST_GIL_ALGORITHM_HPP 9 #define BOOST_GIL_ALGORITHM_HPP 11 #include <boost/gil/bit_aligned_pixel_iterator.hpp> 12 #include <boost/gil/color_base_algorithm.hpp> 13 #include <boost/gil/concepts.hpp> 14 #include <boost/gil/image_view.hpp> 15 #include <boost/gil/image_view_factory.hpp> 16 #include <boost/gil/detail/mp11.hpp> 17 #include <boost/gil/detail/type_traits.hpp> 19 #include <boost/assert.hpp> 20 #include <boost/config.hpp> 27 #include <type_traits> 30 namespace boost {
namespace gil {
33 template <
typename ChannelPtr,
typename ColorSpace>
35 template <
typename Iterator>
37 template <
typename StepIterator>
80 template <
typename Derived,
typename Result=
void>
83 using result_type = Result;
85 template <
typename V1,
typename V2> BOOST_FORCEINLINE
86 result_type operator()(
const std::pair<const V1*,const V2*>& p)
const {
90 template <
typename V1,
typename V2> BOOST_FORCEINLINE
91 result_type operator()(
const V1& v1,
const V2& v2)
const {
95 result_type operator()(
const error_t&)
const {
throw std::bad_cast(); }
99 template <
typename V1,
typename V2>
101 result_type apply(V1
const& v1, V2
const& v2, std::false_type)
const 103 return ((
const Derived*)
this)->apply_incompatible(v1, v2);
107 template <
typename V1,
typename V2>
109 result_type apply(V1
const& v1, V2
const& v2, std::true_type)
const 111 return ((
const Derived*)
this)->apply_compatible(v1, v2);
115 template <
typename V1,
typename V2>
117 result_type apply_incompatible(V1
const& , V2
const& )
const 119 throw std::bad_cast();
137 template<
typename T,
typename CS>
145 auto p =
std::copy((
unsigned char*)first, (
unsigned char*)last, (
unsigned char*)dst);
151 template<
typename T,
typename CS>
159 namespace boost {
namespace gil {
161 template <
typename I,
typename O>
struct copy_fn {
162 BOOST_FORCEINLINE I operator()(I first, I last, O dst)
const {
return std::copy(first,last,dst); }
170 template<
typename CS,
typename IC1,
typename IC2> BOOST_FORCEINLINE
172 boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,
typename std::iterator_traits<IC2>::value_type>>();
173 static_for_each(first,last,dst,boost::gil::detail::copy_fn<IC1,IC2>());
174 return dst+(last-first);
178 namespace boost {
namespace gil {
182 template <
typename I,
typename O>
184 BOOST_FORCEINLINE
void operator()(I src,
typename std::iterator_traits<I>::difference_type n, O dst)
const {
std::copy(src,src+n, dst); }
188 template <
typename IL,
typename O>
190 using diff_t =
typename std::iterator_traits<iterator_from_2d<IL>>::difference_type;
192 gil_function_requires<PixelLocatorConcept<IL>>();
193 gil_function_requires<MutablePixelIteratorConcept<O>>();
195 diff_t l=src.width()-src.x_pos();
196 diff_t numToCopy=(n<l ? n:l);
197 detail::copy_n(src.x(), numToCopy, dst);
206 template <
typename I,
typename OL>
208 using diff_t =
typename std::iterator_traits<I>::difference_type;
210 gil_function_requires<PixelIteratorConcept<I>>();
211 gil_function_requires<MutablePixelLocatorConcept<OL>>();
213 diff_t l=dst.width()-dst.x_pos();
214 diff_t numToCopy=(n<l ? n:l);
215 detail::copy_n(src, numToCopy, dst.x());
224 template <
typename IL,
typename OL>
226 using diff_t =
typename iterator_from_2d<IL>::difference_type;
228 gil_function_requires<PixelLocatorConcept<IL>>();
229 gil_function_requires<MutablePixelLocatorConcept<OL>>();
230 if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
236 diff_t l=dst.width()-dst.x_pos();
237 diff_t numToCopy=(n<l ? n : l);
238 detail::copy_n(src.x(), numToCopy, dst.x());
246 template <
typename SrcIterator,
typename DstIterator>
247 BOOST_FORCEINLINE DstIterator copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) {
248 using src_x_iterator =
typename SrcIterator::x_iterator;
249 using dst_x_iterator =
typename DstIterator::x_iterator;
251 typename SrcIterator::difference_type n = last - first;
253 if (first.is_1d_traversable()) {
254 if (dst.is_1d_traversable())
259 if (dst.is_1d_traversable())
260 copier_n<SrcIterator,dst_x_iterator>()(first,n, dst.x());
262 copier_n<SrcIterator,DstIterator>()(first,n,dst);
272 template <
typename IL,
typename OL>
274 return boost::gil::detail::copy_with_2d_iterators(first,last,dst);
278 namespace boost {
namespace gil {
281 template <
typename View1,
typename View2> BOOST_FORCEINLINE
284 BOOST_ASSERT(src.dimensions() == dst.dimensions());
285 detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
299 template <
typename CC>
300 class copy_and_convert_pixels_fn :
public binary_operation_obj<copy_and_convert_pixels_fn<CC>>
305 using result_type =
typename binary_operation_obj<copy_and_convert_pixels_fn<default_color_converter>>::result_type;
306 copy_and_convert_pixels_fn() {}
307 copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {}
309 template <
typename V1,
typename V2> BOOST_FORCEINLINE
310 result_type apply_incompatible(
const V1& src,
const V2& dst)
const {
311 copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst);
315 template <
typename V1,
typename V2> BOOST_FORCEINLINE
316 result_type apply_compatible(
const V1& src,
const V2& dst)
const {
323 template <
typename V1,
typename V2,
typename CC>
325 void copy_and_convert_pixels(
const V1& src,
const V2& dst,CC cc) {
326 detail::copy_and_convert_pixels_fn<CC> ccp(cc);
330 struct default_color_converter;
333 template <
typename View1,
typename View2>
335 void copy_and_convert_pixels(
const View1& src,
const View2& dst) {
336 detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
358 template <
typename IL,
typename V>
360 boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL>>();
361 if (first.is_1d_traversable()) {
365 std::ptrdiff_t n=last-first;
367 std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
368 std::fill_n(first.x(), numToDo, val);
376 namespace boost {
namespace gil {
382 template <
typename It,
typename P>
383 void operator()(It first, It last,
const P& p_in) {
389 template <
typename It,
typename P>
391 void fill_aux(It first, It last, P
const& p, std::true_type)
393 static_for_each(first, last, p,
std_fill_t());
397 template <
typename It,
typename P>
399 void fill_aux(It first, It last, P
const& p, std::false_type)
408 template <
typename View,
typename Value>
412 if (
view.is_1d_traversable())
415 view.begin().x(),
view.end().x(), value, is_planar<View>());
419 for (std::ptrdiff_t y = 0; y <
view.height(); ++y)
421 view.row_begin(y),
view.row_end(y), value, is_planar<View>());
434 template <
typename Iterator>
436 void destruct_range_impl(Iterator first, Iterator last,
437 typename std::enable_if
441 std::is_pointer<Iterator>,
444 detail::is_trivially_destructible<
typename std::iterator_traits<Iterator>::value_type>
449 while (first != last)
456 template <
typename Iterator>
458 void destruct_range_impl(Iterator , Iterator ,
459 typename std::enable_if
463 mp11::mp_not<std::is_pointer<Iterator>>,
464 detail::is_trivially_destructible<
typename std::iterator_traits<Iterator>::value_type>
470 template <
typename Iterator>
472 void destruct_range(Iterator first, Iterator last)
474 destruct_range_impl(first, last);
477 struct std_destruct_t
479 template <
typename Iterator>
480 void operator()(Iterator first, Iterator last)
const 482 destruct_range(first,last);
487 template <
typename It>
489 void destruct_aux(It first, It last, std::true_type)
491 static_for_each(first,last,std_destruct_t());
495 template <
typename It>
497 void destruct_aux(It first, It last, std::false_type)
499 destruct_range(first,last);
506 template <
typename View>
510 if (
view.is_1d_traversable())
512 detail::destruct_aux(
513 view.begin().x(),
view.end().x(), is_planar<View>());
517 for (std::ptrdiff_t y = 0; y <
view.height(); ++y)
518 detail::destruct_aux(
519 view.row_begin(y),
view.row_end(y), is_planar<View>());
535 template <
typename It,
typename P>
537 void uninitialized_fill_aux(It first, It last, P
const& p, std::true_type)
539 std::size_t channel = 0;
542 using pixel_t =
typename std::iterator_traits<It>::value_type;
543 while (channel < num_channels<pixel_t>::value)
545 std::uninitialized_fill(
546 dynamic_at_c(first,channel),
547 dynamic_at_c(last,channel),
548 dynamic_at_c(p,channel));
555 for (std::size_t c = 0; c < channel; ++c)
556 destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
563 template <
typename It,
typename P>
565 void uninitialized_fill_aux(It first, It last, P
const& p, std::false_type)
567 std::uninitialized_fill(first,last,p);
576 template <
typename View,
typename Value>
578 if (
view.is_1d_traversable())
579 detail::uninitialized_fill_aux(
view.begin().x(),
view.end().x(),
580 val,is_planar<View>());
582 typename View::y_coord_t y = 0;
584 for (y=0; y<
view.height(); ++y)
585 detail::uninitialized_fill_aux(
view.row_begin(y),
view.row_end(y),
586 val,is_planar<View>());
588 for (
typename View::y_coord_t y0=0; y0<y; ++y0)
589 detail::destruct_aux(
view.row_begin(y0),
view.row_end(y0), is_planar<View>());
604 template <
typename It> BOOST_FORCEINLINE
605 void default_construct_range_impl(It first, It last, std::true_type)
610 using value_t =
typename std::iterator_traits<It>::value_type;
611 while (first != last)
613 new (first) value_t();
619 destruct_range(first1, first);
624 template <
typename It>
626 void default_construct_range_impl(It, It, std::false_type) {}
628 template <
typename It>
630 void default_construct_range(It first, It last)
632 default_construct_range_impl(first, last,
typename std::is_pointer<It>::type());
636 template <
typename It>
638 void default_construct_aux(It first, It last, std::true_type)
640 std::size_t channel = 0;
643 using pixel_t =
typename std::iterator_traits<It>::value_type;
644 while (channel < num_channels<pixel_t>::value)
646 default_construct_range(dynamic_at_c(first, channel), dynamic_at_c(last, channel));
652 for (std::size_t c = 0; c < channel; ++c)
653 destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
659 template <
typename It>
661 void default_construct_aux(It first, It last, std::false_type)
663 default_construct_range(first, last);
666 template <
typename View,
bool IsPlanar>
667 struct has_trivial_pixel_constructor
668 : detail::is_trivially_default_constructible<typename View::value_type>
671 template <
typename View>
672 struct has_trivial_pixel_constructor<View, true>
673 : detail::is_trivially_default_constructible<typename channel_type<View>::type>
676 template<
typename View,
bool IsTriviallyConstructible>
678 void default_construct_pixels_impl(
680 std::enable_if<!IsTriviallyConstructible>* =
nullptr)
682 if (
view.is_1d_traversable())
684 detail::default_construct_aux(
685 view.begin().x(),
view.end().x(), is_planar<View>());
689 typename View::y_coord_t y = 0;
692 for( y = 0; y <
view.height(); ++y )
693 detail::default_construct_aux(
694 view.row_begin(y),
view.row_end(y), is_planar<View>());
698 for (
typename View::y_coord_t y0 = 0; y0 < y; ++y0 )
699 detail::destruct_aux(
700 view.row_begin(y0),
view.row_end(y0), is_planar<View>());
713 template <
typename View>
716 detail::default_construct_pixels_impl
719 detail::has_trivial_pixel_constructor
722 is_planar<View>::value
738 template <
typename It1,
typename It2>
740 void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, std::true_type)
742 std::size_t channel=0;
744 using pixel_t =
typename std::iterator_traits<It1>::value_type;
745 while (channel < num_channels<pixel_t>::value)
747 std::uninitialized_copy(
748 dynamic_at_c(first1, channel),
749 dynamic_at_c(last1, channel),
750 dynamic_at_c(first2, channel));
757 std::advance(last2, std::distance(first1, last1));
758 for (std::size_t c = 0; c < channel; ++c)
759 destruct_range(dynamic_at_c(first2, c), dynamic_at_c(last2, c));
765 template <
typename It1,
typename It2>
767 void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, std::false_type)
769 std::uninitialized_copy(first1, last1, first2);
777 template <
typename View1,
typename View2>
780 using is_planar = std::integral_constant<bool, is_planar<View1>::value && is_planar<View2>::value>;
781 BOOST_ASSERT(view1.dimensions() == view2.dimensions());
783 if (view1.is_1d_traversable() && view2.is_1d_traversable())
785 detail::uninitialized_copy_aux(
786 view1.begin().x(), view1.end().x(), view2.begin().x(), is_planar());
790 typename View1::y_coord_t y = 0;
793 for (y = 0; y < view1.height(); ++y)
794 detail::uninitialized_copy_aux(
795 view1.row_begin(y), view1.row_end(y), view2.row_begin(y), is_planar());
799 for (
typename View1::y_coord_t y0 = 0; y0 < y; ++y0)
800 detail::destruct_aux(view2.row_begin(y0), view2.row_end(y0), is_planar());
820 template <
typename View,
typename F>
821 F for_each_pixel(View
const&
view, F fun)
823 if (
view.is_1d_traversable())
825 return std::for_each(
view.begin().x(),
view.end().x(), fun);
829 for (std::ptrdiff_t y = 0; y <
view.height(); ++y)
830 std::for_each(
view.row_begin(y),
view.row_end(y), fun);
840 template <
typename View,
typename F>
841 F for_each_pixel_position(View
const&
view, F fun)
843 typename View::xy_locator loc =
view.xy_at(0, 0);
844 for (std::ptrdiff_t y = 0; y <
view.height(); ++y)
846 for (std::ptrdiff_t x = 0; x <
view.width(); ++x, ++loc.x())
848 loc.x() -=
view.width(); ++loc.y();
863 template <
typename View,
typename F>
866 if (
view.is_1d_traversable())
868 std::generate(
view.begin().x(),
view.end().x(), fun);
872 for (std::ptrdiff_t y = 0; y <
view.height(); ++y)
873 std::generate(
view.row_begin(y),
view.row_end(y), fun);
885 template <
typename I1,
typename I2>
887 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
891 template <
typename I1,
typename I2>
895 bool operator()(I1 i1, std::ptrdiff_t n, I2 i2)
const 903 template<
typename T,
typename CS>
913 template<
typename T,
typename CS>
921 template<
typename IC,
typename CS>
928 constexpr std::ptrdiff_t byte_size = n *
sizeof(
typename std::iterator_traits<IC>::value_type);
929 for (std::ptrdiff_t i = 0; i < mp11::mp_size<CS>::value; ++i)
931 if (memcmp(dynamic_at_c(i1, i), dynamic_at_c(i2, i), byte_size) != 0)
941 template <
typename Loc,
typename It>
947 gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
948 gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
951 std::ptrdiff_t
const num = std::min<std::ptrdiff_t>(n, i1.width() - i1.x_pos());
952 if (!equal_n(i1.x(), num, i2))
965 template <
typename It,
typename Loc>
971 gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
972 gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
975 std::ptrdiff_t
const num = std::min<std::ptrdiff_t>(n, i2.width() - i2.x_pos());
976 if (!equal_n(i1, num, i2.x()))
987 template <
typename Loc1,
typename Loc2>
990 gil_function_requires<boost::gil::PixelLocatorConcept<Loc1>>();
991 gil_function_requires<boost::gil::PixelLocatorConcept<Loc2>>();
992 if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
994 if (*i1++!=*i2++)
return false;
998 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
999 if (!equal_n(i1.x(), num, i2.x()))
1010 template <
typename I1,
typename I2> BOOST_FORCEINLINE
1011 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
1012 return detail::equal_n_fn<I1,I2>()(i1,n,i2);
1028 template <
typename Loc1,
typename Loc2> BOOST_FORCEINLINE
1030 boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1>>();
1031 boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2>>();
1032 std::ptrdiff_t n=last-first;
1033 if (first.is_1d_traversable()) {
1034 if (first2.is_1d_traversable())
1035 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
1037 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2>>()(first.x(),n, first2);
1039 if (first2.is_1d_traversable())
1047 namespace boost {
namespace gil {
1050 template <
typename View1,
typename View2> BOOST_FORCEINLINE
1052 BOOST_ASSERT(v1.dimensions() == v2.dimensions());
1053 return std::equal(v1.begin(),v1.end(),v2.begin());
1068 template <
typename View1,
typename View2,
typename F> BOOST_FORCEINLINE
1070 BOOST_ASSERT(src.dimensions() == dst.dimensions());
1071 for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1072 typename View1::x_iterator srcIt=src.row_begin(y);
1073 typename View2::x_iterator dstIt=dst.row_begin(y);
1074 for (std::ptrdiff_t x=0; x<src.width(); ++x)
1075 dstIt[x]=fun(srcIt[x]);
1082 template <
typename View1,
typename View2,
typename View3,
typename F> BOOST_FORCEINLINE
1084 for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
1085 typename View1::x_iterator srcIt1=src1.row_begin(y);
1086 typename View2::x_iterator srcIt2=src2.row_begin(y);
1087 typename View3::x_iterator dstIt=dst.row_begin(y);
1088 for (std::ptrdiff_t x=0; x<dst.width(); ++x)
1089 dstIt[x]=fun(srcIt1[x],srcIt2[x]);
1100 template <
typename View1,
typename View2,
typename F> BOOST_FORCEINLINE
1102 BOOST_ASSERT(src.dimensions() == dst.dimensions());
1103 typename View1::xy_locator loc=src.xy_at(0,0);
1104 for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1105 typename View2::x_iterator dstIt=dst.row_begin(y);
1106 for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
1108 loc.x()-=src.width(); ++loc.y();
1115 template <
typename View1,
typename View2,
typename View3,
typename F> BOOST_FORCEINLINE
1117 BOOST_ASSERT(src1.dimensions() == dst.dimensions());
1118 BOOST_ASSERT(src2.dimensions() == dst.dimensions());
1119 typename View1::xy_locator loc1=src1.xy_at(0,0);
1120 typename View2::xy_locator loc2=src2.xy_at(0,0);
1121 for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
1122 typename View3::x_iterator dstIt=dst.row_begin(y);
1123 for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
1124 dstIt[x]=fun(loc1,loc2);
1125 loc1.x()-=src1.width(); ++loc1.y();
1126 loc2.x()-=src2.width(); ++loc2.y();
void default_construct_pixels(View const &view)
Invokes the in-place default constructor on every pixel of the (uninitialized) view....
Definition: algorithm.hpp:714
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept,...
Definition: metafunctions.hpp:23
BOOST_FORCEINLINE void fill_pixels(View const &view, Value const &value)
std::fill for image views
Definition: algorithm.hpp:410
An iterator over planar pixels. Models HomogeneousColorBaseConcept, PixelIteratorConcept,...
Definition: algorithm.hpp:34
Definition: algorithm.hpp:183
Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept,...
Definition: iterator_from_2d.hpp:42
BOOST_FORCEINLINE boost::gil::planar_pixel_iterator< IC2, CS > copy(boost::gil::planar_pixel_iterator< IC1, CS > first, boost::gil::planar_pixel_iterator< IC1, CS > last, boost::gil::planar_pixel_iterator< IC2, CS > dst)
Copy when both src and dst are planar pointers is copy for each channel.
Definition: algorithm.hpp:171
void generate_pixels(View const &view, F fun)
std::generate for image views
Definition: algorithm.hpp:864
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:778
Memory-based pixel locator. Models: PixelLocatorConcept,HasDynamicXStepTypeConcept,...
Definition: algorithm.hpp:38
BOOST_FORCEINLINE bool equal_pixels(const View1 &v1, const View2 &v2)
std::equal for image views
Definition: algorithm.hpp:1051
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:359
Returns whether two views are compatible.
Definition: concepts/image_view.hpp:522
BOOST_FORCEINLINE void copy_pixels(const View1 &src, const View2 &dst)
std::copy for image views
Definition: algorithm.hpp:282
BOOST_FORCEINLINE boost::gil::iterator_from_2d< OL > copy1(boost::gil::iterator_from_2d< IL > first, boost::gil::iterator_from_2d< IL > last, boost::gil::iterator_from_2d< OL > dst)
std::copy(I1,I1,I2) with I1 and I2 being a iterator_from_2d
Definition: algorithm.hpp:273
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:577
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:1029
A generic binary operation on viewsUse this class as a convenience superclass when defining an operat...
Definition: algorithm.hpp:81
struct to do std::fill
Definition: algorithm.hpp:381
const image< Pixel, IsPlanar, Alloc >::view_t & view(image< Pixel, IsPlanar, Alloc > &img)
Returns the non-constant-pixel view of an image.
Definition: image.hpp:535
BOOST_FORCEINLINE void destruct_pixels(View const &view)
Invokes the in-place destructor on every pixel of the view.
Definition: algorithm.hpp:508
MEMORY-BASED STEP ITERATOR.
Definition: algorithm.hpp:36