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> 17 #include <boost/assert.hpp> 18 #include <boost/config.hpp> 19 #include <boost/mpl/and.hpp> 20 #include <boost/mpl/or.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>
82 using result_type = Result;
84 template <
typename V1,
typename V2> BOOST_FORCEINLINE
85 result_type operator()(
const std::pair<const V1*,const V2*>& p)
const {
89 template <
typename V1,
typename V2> BOOST_FORCEINLINE
90 result_type operator()(
const V1& v1,
const V2& v2)
const {
94 result_type operator()(
const error_t&)
const {
throw std::bad_cast(); }
98 template <
typename V1,
typename V2>
99 BOOST_FORCEINLINE result_type apply(
const V1& v1,
const V2& v2, mpl::false_)
const {
100 return ((
const Derived*)
this)->apply_incompatible(v1,v2);
104 template <
typename V1,
typename V2>
105 BOOST_FORCEINLINE result_type apply(
const V1& v1,
const V2& v2, mpl::true_)
const {
106 return ((
const Derived*)
this)->apply_compatible(v1,v2);
110 template <
typename V1,
typename V2>
111 BOOST_FORCEINLINE result_type apply_incompatible(
const V1&,
const V2&)
const {
112 throw std::bad_cast();
130 template<
typename T,
typename Cs>
139 template<
typename T,
typename Cs>
147 namespace boost {
namespace gil {
149 template <
typename I,
typename O>
struct copy_fn {
150 BOOST_FORCEINLINE I operator()(I first, I last, O dst)
const {
return std::copy(first,last,dst); }
158 template<
typename Cs,
typename IC1,
typename IC2> BOOST_FORCEINLINE
160 boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,
typename std::iterator_traits<IC2>::value_type> >();
161 static_for_each(first,last,dst,boost::gil::detail::copy_fn<IC1,IC2>());
162 return dst+(last-first);
166 namespace boost {
namespace gil {
170 template <
typename I,
typename O>
172 BOOST_FORCEINLINE
void operator()(I src,
typename std::iterator_traits<I>::difference_type n, O dst)
const {
std::copy(src,src+n, dst); }
176 template <
typename IL,
typename O>
178 using diff_t =
typename std::iterator_traits<iterator_from_2d<IL> >::difference_type;
180 gil_function_requires<PixelLocatorConcept<IL> >();
181 gil_function_requires<MutablePixelIteratorConcept<O> >();
183 diff_t l=src.width()-src.x_pos();
184 diff_t numToCopy=(n<l ? n:l);
185 detail::copy_n(src.x(), numToCopy, dst);
194 template <
typename I,
typename OL>
196 using diff_t =
typename std::iterator_traits<I>::difference_type;
198 gil_function_requires<PixelIteratorConcept<I> >();
199 gil_function_requires<MutablePixelLocatorConcept<OL> >();
201 diff_t l=dst.width()-dst.x_pos();
202 diff_t numToCopy=(n<l ? n:l);
203 detail::copy_n(src, numToCopy, dst.x());
212 template <
typename IL,
typename OL>
214 using diff_t =
typename iterator_from_2d<IL>::difference_type;
216 gil_function_requires<PixelLocatorConcept<IL> >();
217 gil_function_requires<MutablePixelLocatorConcept<OL> >();
218 if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
224 diff_t l=dst.width()-dst.x_pos();
225 diff_t numToCopy=(n<l ? n : l);
226 detail::copy_n(src.x(), numToCopy, dst.x());
234 template <
typename SrcIterator,
typename DstIterator>
235 BOOST_FORCEINLINE DstIterator copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) {
236 using src_x_iterator =
typename SrcIterator::x_iterator;
237 using dst_x_iterator =
typename DstIterator::x_iterator;
239 typename SrcIterator::difference_type n = last - first;
241 if (first.is_1d_traversable()) {
242 if (dst.is_1d_traversable())
247 if (dst.is_1d_traversable())
260 template <
typename IL,
typename OL>
262 return boost::gil::detail::copy_with_2d_iterators(first,last,dst);
266 namespace boost {
namespace gil {
269 template <
typename View1,
typename View2> BOOST_FORCEINLINE
272 BOOST_ASSERT(src.dimensions() == dst.dimensions());
273 detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
289 template <
typename CC>
290 class copy_and_convert_pixels_fn :
public binary_operation_obj<copy_and_convert_pixels_fn<CC> > {
295 copy_and_convert_pixels_fn() {}
296 copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {}
298 template <
typename V1,
typename V2> BOOST_FORCEINLINE
299 result_type apply_incompatible(
const V1& src,
const V2& dst)
const {
300 copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst);
304 template <
typename V1,
typename V2> BOOST_FORCEINLINE
305 result_type apply_compatible(
const V1& src,
const V2& dst)
const {
312 template <
typename V1,
typename V2,
typename CC>
314 void copy_and_convert_pixels(
const V1& src,
const V2& dst,CC cc) {
315 detail::copy_and_convert_pixels_fn<CC> ccp(cc);
322 template <
typename View1,
typename View2>
324 void copy_and_convert_pixels(
const View1& src,
const View2& dst) {
325 detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
349 template <
typename IL,
typename V>
351 boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL> >();
352 if (first.is_1d_traversable()) {
356 std::ptrdiff_t n=last-first;
358 std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
359 std::fill_n(first.x(), numToDo, val);
367 namespace boost {
namespace gil {
371 template <
typename It,
typename P>
372 void operator()(It first, It last,
const P& p_in) {
377 template <
typename It,
typename P>
379 void fill_aux(It first, It last,
const P& p, mpl::true_) {
383 template <
typename It,
typename P>
385 void fill_aux(It first, It last,
const P& p,mpl::false_) {
392 template <
typename View,
typename Value> BOOST_FORCEINLINE
394 if (img_view.is_1d_traversable())
395 detail::fill_aux(img_view.begin().x(), img_view.end().x(),
396 val,is_planar<View>());
398 for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
399 detail::fill_aux(img_view.row_begin(y),img_view.row_end(y),
400 val,is_planar<View>());
414 template <
typename Iterator>
416 void destruct_range_impl(Iterator first, Iterator last,
417 typename std::enable_if
421 is_pointer<Iterator>,
422 mpl::not_<std::is_trivially_destructible<
typename std::iterator_traits<Iterator>::value_type>>
426 while (first != last)
433 template <
typename Iterator>
435 void destruct_range_impl(Iterator , Iterator ,
436 typename std::enable_if
440 mpl::not_<is_pointer<Iterator>>,
441 std::is_trivially_destructible<
typename std::iterator_traits<Iterator>::value_type>
447 template <
typename Iterator>
449 void destruct_range(Iterator first, Iterator last)
451 destruct_range_impl(first, last);
454 struct std_destruct_t
456 template <
typename Iterator>
457 void operator()(Iterator first, Iterator last)
const 459 destruct_range(first,last);
464 template <
typename It>
466 void destruct_aux(It first, It last, mpl::true_) {
467 static_for_each(first,last,std_destruct_t());
470 template <
typename It>
472 void destruct_aux(It first, It last, mpl::false_) {
473 destruct_range(first,last);
479 template <
typename View> BOOST_FORCEINLINE
481 if (img_view.is_1d_traversable())
482 detail::destruct_aux(img_view.begin().x(), img_view.end().x(),
485 for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
486 detail::destruct_aux(img_view.row_begin(y),img_view.row_end(y),
503 template <
typename It,
typename P>
505 void uninitialized_fill_aux(It first, It last,
506 const P& p, mpl::true_) {
509 using pixel_t =
typename std::iterator_traits<It>::value_type;
511 std::uninitialized_fill(dynamic_at_c(first,channel), dynamic_at_c(last,channel),
512 dynamic_at_c(p,channel));
516 for (
int c=0; c<channel; ++c)
517 destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
524 template <
typename It,
typename P>
526 void uninitialized_fill_aux(It first, It last,
527 const P& p,mpl::false_) {
528 std::uninitialized_fill(first,last,p);
536 template <
typename View,
typename Value>
538 if (img_view.is_1d_traversable())
539 detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(),
540 val,is_planar<View>());
542 typename View::y_coord_t y = 0;
544 for (y=0; y<img_view.height(); ++y)
545 detail::uninitialized_fill_aux(img_view.row_begin(y),img_view.row_end(y),
546 val,is_planar<View>());
548 for (
typename View::y_coord_t y0=0; y0<y; ++y0)
549 detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>());
566 template <
typename It> BOOST_FORCEINLINE
567 void default_construct_range_impl(It first, It last, mpl::true_) {
568 using value_t =
typename std::iterator_traits<It>::value_type;
571 while (first!=last) {
572 new (first) value_t();
576 destruct_range(first1,first);
581 template <
typename It> BOOST_FORCEINLINE
582 void default_construct_range_impl(It, It, mpl::false_) {}
584 template <
typename It> BOOST_FORCEINLINE
585 void default_construct_range(It first, It last) { default_construct_range_impl(first, last,
typename is_pointer<It>::type()); }
588 template <
typename It>
590 void default_construct_aux(It first, It last, mpl::true_) {
593 using pixel_t =
typename std::iterator_traits<It>::value_type;
595 default_construct_range(dynamic_at_c(first,channel), dynamic_at_c(last,channel));
599 for (
int c=0; c<channel; ++c)
600 destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
606 template <
typename It>
608 void default_construct_aux(It first, It last, mpl::false_) {
609 default_construct_range(first,last);
612 template <
typename View,
bool IsPlanar>
613 struct has_trivial_pixel_constructor :
public boost::has_trivial_constructor<typename View::value_type> {};
614 template <
typename View>
615 struct has_trivial_pixel_constructor<View, true> :
public boost::has_trivial_constructor<typename channel_type<View>::type> {};
620 template<
typename View,
bool IsTriviallyConstructible>
622 void default_construct_pixels_impl(
623 View
const& img_view,
624 std::enable_if<!IsTriviallyConstructible>* =
nullptr)
626 if( img_view.is_1d_traversable() )
628 detail::default_construct_aux( img_view.begin().x()
635 typename View::y_coord_t y = 0;
638 for( y = 0; y < img_view.height(); ++y )
640 detail::default_construct_aux( img_view.row_begin( y )
641 ,img_view.row_end( y )
647 for (
typename View::y_coord_t y0 = 0; y0 < y; ++y0 )
649 detail::destruct_aux( img_view.row_begin(y0)
650 , img_view.row_end(y0)
665 template <
typename View>
667 detail::default_construct_pixels_impl< View
668 , detail::has_trivial_pixel_constructor< View
669 , is_planar< View >::value
686 template <
typename It1,
typename It2>
688 void uninitialized_copy_aux(It1 first1, It1 last1,
689 It2 first2, mpl::true_) {
692 using pixel_t =
typename std::iterator_traits<It1>::value_type;
694 std::uninitialized_copy(dynamic_at_c(first1,channel), dynamic_at_c(last1,channel), dynamic_at_c(first2,channel));
699 std::advance(last2, std::distance(first1,last1));
700 for (
int c=0; c<channel; ++c)
701 destruct_range(dynamic_at_c(first2,c), dynamic_at_c(last2,c));
706 template <
typename It1,
typename It2>
708 void uninitialized_copy_aux(It1 first1, It1 last1,
709 It2 first2,mpl::false_) {
710 std::uninitialized_copy(first1,last1,first2);
718 template <
typename View1,
typename View2>
720 using is_planar = mpl::bool_<is_planar<View1>::value && is_planar<View2>::value>;
721 BOOST_ASSERT(view1.dimensions() == view2.dimensions());
722 if (view1.is_1d_traversable() && view2.is_1d_traversable())
723 detail::uninitialized_copy_aux(view1.begin().x(), view1.end().x(),
727 typename View1::y_coord_t y = 0;
729 for (y=0; y<view1.height(); ++y)
730 detail::uninitialized_copy_aux(view1.row_begin(y), view1.row_end(y),
734 for (
typename View1::y_coord_t y0=0; y0<y; ++y0)
735 detail::destruct_aux(view2.row_begin(y0),view2.row_end(y0), is_planar());
757 template <
typename V,
typename F>
758 F for_each_pixel(
const V& img, F fun) {
759 if (img.is_1d_traversable()) {
760 return std::for_each(img.begin().x(), img.end().x(), fun);
762 for (std::ptrdiff_t y=0; y<img.height(); ++y)
763 std::for_each(img.row_begin(y),img.row_end(y),fun);
773 template <
typename View,
typename F>
774 F for_each_pixel_position(
const View& img, F fun) {
775 typename View::xy_locator loc=img.xy_at(0,0);
776 for (std::ptrdiff_t y=0; y<img.height(); ++y) {
777 for (std::ptrdiff_t x=0; x<img.width(); ++x, ++loc.x())
779 loc.x()-=img.width(); ++loc.y();
796 template <
typename View,
typename F>
798 if (v.is_1d_traversable()) {
799 std::generate(v.begin().x(), v.end().x(), fun);
801 for (std::ptrdiff_t y=0; y<v.height(); ++y)
802 std::generate(v.row_begin(y),v.row_end(y),fun);
816 template <
typename I1,
typename I2> BOOST_FORCEINLINE
bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
819 template <
typename I1,
typename I2>
821 BOOST_FORCEINLINE
bool operator()(I1 i1, std::ptrdiff_t n, I2 i2)
const {
return std::equal(i1,i1+n, i2); }
826 template<
typename T,
typename Cs>
832 template<
typename T,
typename Cs>
838 template<
typename IC,
typename Cs>
841 std::ptrdiff_t numBytes=n*
sizeof(
typename std::iterator_traits<IC>::value_type);
843 for (std::ptrdiff_t i=0; i<mpl::size<Cs>::value; ++i)
844 if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0)
851 template <
typename Loc,
typename I2>
854 gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
855 gil_function_requires<boost::gil::PixelIteratorConcept<I2> >();
857 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
858 if (!equal_n(i1.x(), num, i2))
869 template <
typename I1,
typename Loc>
872 gil_function_requires<boost::gil::PixelIteratorConcept<I1> >();
873 gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
875 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
876 if (!equal_n(i1, num, i2.x()))
887 template <
typename Loc1,
typename Loc2>
890 gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
891 gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
892 if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
894 if (*i1++!=*i2++)
return false;
898 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
899 if (!equal_n(i1.x(), num, i2.x()))
910 template <
typename I1,
typename I2> BOOST_FORCEINLINE
911 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
912 return detail::equal_n_fn<I1,I2>()(i1,n,i2);
928 template <
typename Loc1,
typename Loc2> BOOST_FORCEINLINE
930 boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
931 boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
932 std::ptrdiff_t n=last-first;
933 if (first.is_1d_traversable()) {
934 if (first2.is_1d_traversable())
935 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
937 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2> >()(first.x(),n, first2);
939 if (first2.is_1d_traversable())
947 namespace boost {
namespace gil {
950 template <
typename View1,
typename View2> BOOST_FORCEINLINE
952 BOOST_ASSERT(v1.dimensions() == v2.dimensions());
953 return std::equal(v1.begin(),v1.end(),v2.begin());
968 template <
typename View1,
typename View2,
typename F> BOOST_FORCEINLINE
970 BOOST_ASSERT(src.dimensions() == dst.dimensions());
971 for (std::ptrdiff_t y=0; y<src.height(); ++y) {
972 typename View1::x_iterator srcIt=src.row_begin(y);
973 typename View2::x_iterator dstIt=dst.row_begin(y);
974 for (std::ptrdiff_t x=0; x<src.width(); ++x)
975 dstIt[x]=fun(srcIt[x]);
982 template <
typename View1,
typename View2,
typename View3,
typename F> BOOST_FORCEINLINE
984 for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
985 typename View1::x_iterator srcIt1=src1.row_begin(y);
986 typename View2::x_iterator srcIt2=src2.row_begin(y);
987 typename View3::x_iterator dstIt=dst.row_begin(y);
988 for (std::ptrdiff_t x=0; x<dst.width(); ++x)
989 dstIt[x]=fun(srcIt1[x],srcIt2[x]);
1000 template <
typename View1,
typename View2,
typename F> BOOST_FORCEINLINE
1002 BOOST_ASSERT(src.dimensions() == dst.dimensions());
1003 typename View1::xy_locator loc=src.xy_at(0,0);
1004 for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1005 typename View2::x_iterator dstIt=dst.row_begin(y);
1006 for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
1008 loc.x()-=src.width(); ++loc.y();
1015 template <
typename View1,
typename View2,
typename View3,
typename F> BOOST_FORCEINLINE
1017 BOOST_ASSERT(src1.dimensions() == dst.dimensions());
1018 BOOST_ASSERT(src2.dimensions() == dst.dimensions());
1019 typename View1::xy_locator loc1=src1.xy_at(0,0);
1020 typename View2::xy_locator loc2=src2.xy_at(0,0);
1021 for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
1022 typename View3::x_iterator dstIt=dst.row_begin(y);
1023 for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
1024 dstIt[x]=fun(loc1,loc2);
1025 loc1.x()-=src1.width(); ++loc1.y();
1026 loc2.x()-=src2.width(); ++loc2.y();
void uninitialized_fill_pixels(const View &img_view, const Value &val)
std::uninitialized_fill for image views. Does not support planar heterogeneous views. If an exception is thrown destructs any in-place copy-constructed pixels
Definition: algorithm.hpp:537
Definition: algorithm.hpp:30
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept, PixelValueConcept, HomogeneousPixelBasedConcept.
Definition: metafunctions.hpp:31
void generate_pixels(const View &v, F fun)
std::generate for image views
Definition: algorithm.hpp:797
Definition: algorithm.hpp:127
An iterator over planar pixels. Models HomogeneousColorBaseConcept, PixelIteratorConcept, HomogeneousPixelBasedConcept, MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept.
Definition: algorithm.hpp:34
Definition: algorithm.hpp:171
Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept.
Definition: iterator_from_2d.hpp:42
Memory-based pixel locator. Models: PixelLocatorConcept,HasDynamicXStepTypeConcept,HasDynamicYStepTypeConcept,HasTransposedTypeConceptThe class takes a step iterator as a parameter. The step iterator provides navigation along the vertical axis while its base iterator provides horizontal navigation.
Definition: algorithm.hpp:38
BOOST_FORCEINLINE bool equal_pixels(const View1 &v1, const View2 &v2)
std::equal for image views
Definition: algorithm.hpp:951
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:350
Returns whether two views are compatible.
Definition: concepts/image_view.hpp:520
BOOST_FORCEINLINE void copy_pixels(const View1 &src, const View2 &dst)
std::copy for image views
Definition: algorithm.hpp:270
BOOST_FORCEINLINE void fill_pixels(const View &img_view, const Value &val)
std::fill for image views
Definition: algorithm.hpp:393
void default_construct_pixels(const View &img_view)
Invokes the in-place default constructor on every pixel of the (uninitialized) view. Does not support planar heterogeneous views. If an exception is thrown destructs any in-place default-constructed pixels.
Definition: algorithm.hpp:666
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:261
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:159
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:929
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:370
void uninitialized_copy_pixels(const View1 &view1, const View2 &view2)
std::uninitialized_copy for image views. Does not support planar heterogeneous views. If an exception is thrown destructs any in-place copy-constructed objects
Definition: algorithm.hpp:719
class for color-converting one pixel to another
Definition: color_convert.hpp:282
Returns the number of channels of a pixel-based GIL construct.
Definition: locator.hpp:38
BOOST_FORCEINLINE void destruct_pixels(const View &img_view)
Invokes the in-place destructor on every pixel of the view.
Definition: algorithm.hpp:480
MEMORY-BASED STEP ITERATOR.
Definition: algorithm.hpp:36