1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132 |
- #ifndef BOOST_GIL_ALGORITHM_HPP
- #define BOOST_GIL_ALGORITHM_HPP
- #include <boost/gil/bit_aligned_pixel_iterator.hpp>
- #include <boost/gil/color_base_algorithm.hpp>
- #include <boost/gil/concepts.hpp>
- #include <boost/gil/image_view.hpp>
- #include <boost/gil/image_view_factory.hpp>
- #include <boost/gil/detail/mp11.hpp>
- #include <boost/gil/detail/type_traits.hpp>
- #include <boost/assert.hpp>
- #include <boost/config.hpp>
- #include <algorithm>
- #include <cstddef>
- #include <cstring>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <typeinfo>
- namespace boost { namespace gil {
- template <typename ChannelPtr, typename ColorSpace>
- struct planar_pixel_iterator;
- template <typename Iterator>
- class memory_based_step_iterator;
- template <typename StepIterator>
- class memory_based_2d_locator;
- struct error_t {};
- template <typename Derived, typename Result=void>
- struct binary_operation_obj
- {
- using result_type = Result;
- template <typename V1, typename V2> BOOST_FORCEINLINE
- result_type operator()(const std::pair<const V1*,const V2*>& p) const {
- return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type());
- }
- template <typename V1, typename V2> BOOST_FORCEINLINE
- result_type operator()(const V1& v1, const V2& v2) const {
- return apply(v1, v2, typename views_are_compatible<V1,V2>::type());
- }
- result_type operator()(const error_t&) const { throw std::bad_cast(); }
- private:
-
- template <typename V1, typename V2>
- BOOST_FORCEINLINE
- result_type apply(V1 const& v1, V2 const& v2, std::false_type) const
- {
- return ((const Derived*)this)->apply_incompatible(v1, v2);
- }
-
- template <typename V1, typename V2>
- BOOST_FORCEINLINE
- result_type apply(V1 const& v1, V2 const& v2, std::true_type) const
- {
- return ((const Derived*)this)->apply_compatible(v1, v2);
- }
-
- template <typename V1, typename V2>
- BOOST_FORCEINLINE
- result_type apply_incompatible(V1 const& , V2 const& ) const
- {
- throw std::bad_cast();
- }
- };
- }}
- namespace std {
- template<typename T, typename CS>
- BOOST_FORCEINLINE
- auto copy(
- boost::gil::pixel<T, CS>* first,
- boost::gil::pixel<T, CS>* last,
- boost::gil::pixel<T, CS>* dst)
- -> boost::gil::pixel<T, CS>*
- {
- auto p = std::copy((unsigned char*)first, (unsigned char*)last, (unsigned char*)dst);
- return reinterpret_cast<boost::gil::pixel<T, CS>*>(p);
- }
- template<typename T, typename CS>
- BOOST_FORCEINLINE boost::gil::pixel<T,CS>*
- copy(const boost::gil::pixel<T,CS>* first, const boost::gil::pixel<T,CS>* last,
- boost::gil::pixel<T,CS>* dst) {
- return (boost::gil::pixel<T,CS>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
- }
- }
- namespace boost { namespace gil {
- namespace detail {
- template <typename I, typename O> struct copy_fn {
- BOOST_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); }
- };
- }
- } }
- namespace std {
- template<typename CS, typename IC1, typename IC2> 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) {
- boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type>>();
- static_for_each(first,last,dst,boost::gil::detail::copy_fn<IC1,IC2>());
- return dst+(last-first);
- }
- }
- namespace boost { namespace gil {
- namespace detail {
- template <typename I, typename O>
- struct copier_n {
- BOOST_FORCEINLINE void operator()(I src, typename std::iterator_traits<I>::difference_type n, O dst) const { std::copy(src,src+n, dst); }
- };
- template <typename IL, typename O>
- struct copier_n<iterator_from_2d<IL>,O> {
- using diff_t = typename std::iterator_traits<iterator_from_2d<IL>>::difference_type;
- BOOST_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, O dst) const {
- gil_function_requires<PixelLocatorConcept<IL>>();
- gil_function_requires<MutablePixelIteratorConcept<O>>();
- while (n>0) {
- diff_t l=src.width()-src.x_pos();
- diff_t numToCopy=(n<l ? n:l);
- detail::copy_n(src.x(), numToCopy, dst);
- dst+=numToCopy;
- src+=numToCopy;
- n-=numToCopy;
- }
- }
- };
- template <typename I, typename OL>
- struct copier_n<I,iterator_from_2d<OL>> {
- using diff_t = typename std::iterator_traits<I>::difference_type;
- BOOST_FORCEINLINE void operator()(I src, diff_t n, iterator_from_2d<OL> dst) const {
- gil_function_requires<PixelIteratorConcept<I>>();
- gil_function_requires<MutablePixelLocatorConcept<OL>>();
- while (n>0) {
- diff_t l=dst.width()-dst.x_pos();
- diff_t numToCopy=(n<l ? n:l);
- detail::copy_n(src, numToCopy, dst.x());
- dst+=numToCopy;
- src+=numToCopy;
- n-=numToCopy;
- }
- }
- };
- template <typename IL, typename OL>
- struct copier_n<iterator_from_2d<IL>,iterator_from_2d<OL>> {
- using diff_t = typename iterator_from_2d<IL>::difference_type;
- BOOST_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, iterator_from_2d<OL> dst) const {
- gil_function_requires<PixelLocatorConcept<IL>>();
- gil_function_requires<MutablePixelLocatorConcept<OL>>();
- if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
- while(n-->0) {
- *dst++=*src++;
- }
- }
- while (n>0) {
- diff_t l=dst.width()-dst.x_pos();
- diff_t numToCopy=(n<l ? n : l);
- detail::copy_n(src.x(), numToCopy, dst.x());
- dst+=numToCopy;
- src+=numToCopy;
- n-=numToCopy;
- }
- }
- };
- template <typename SrcIterator, typename DstIterator>
- BOOST_FORCEINLINE DstIterator copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) {
- using src_x_iterator = typename SrcIterator::x_iterator;
- using dst_x_iterator = typename DstIterator::x_iterator;
- typename SrcIterator::difference_type n = last - first;
- if (first.is_1d_traversable()) {
- if (dst.is_1d_traversable())
- copier_n<src_x_iterator,dst_x_iterator>()(first.x(),n, dst.x());
- else
- copier_n<src_x_iterator,DstIterator >()(first.x(),n, dst);
- } else {
- if (dst.is_1d_traversable())
- copier_n<SrcIterator,dst_x_iterator>()(first,n, dst.x());
- else
- copier_n<SrcIterator,DstIterator>()(first,n,dst);
- }
- return dst+n;
- }
- }
- } }
- namespace std {
- template <typename IL, typename OL>
- 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) {
- return boost::gil::detail::copy_with_2d_iterators(first,last,dst);
- }
- }
- namespace boost { namespace gil {
- template <typename View1, typename View2> BOOST_FORCEINLINE
- void copy_pixels(const View1& src, const View2& dst)
- {
- BOOST_ASSERT(src.dimensions() == dst.dimensions());
- detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
- }
- namespace detail {
- template <typename CC>
- class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC>>
- {
- private:
- CC _cc;
- public:
- using result_type = typename binary_operation_obj<copy_and_convert_pixels_fn<default_color_converter>>::result_type;
- copy_and_convert_pixels_fn() {}
- copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {}
-
- template <typename V1, typename V2> BOOST_FORCEINLINE
- result_type apply_incompatible(const V1& src, const V2& dst) const {
- copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst);
- }
-
- template <typename V1, typename V2> BOOST_FORCEINLINE
- result_type apply_compatible(const V1& src, const V2& dst) const {
- copy_pixels(src,dst);
- }
- };
- }
- template <typename V1, typename V2,typename CC>
- BOOST_FORCEINLINE
- void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) {
- detail::copy_and_convert_pixels_fn<CC> ccp(cc);
- ccp(src,dst);
- }
- struct default_color_converter;
- template <typename View1, typename View2>
- BOOST_FORCEINLINE
- void copy_and_convert_pixels(const View1& src, const View2& dst) {
- detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
- ccp(src,dst);
- }
- } }
- namespace std {
- template <typename IL, typename V>
- void fill(boost::gil::iterator_from_2d<IL> first, boost::gil::iterator_from_2d<IL> last, const V& val) {
- boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL>>();
- if (first.is_1d_traversable()) {
- std::fill(first.x(), last.x(), val);
- } else {
-
- std::ptrdiff_t n=last-first;
- while (n>0) {
- std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
- std::fill_n(first.x(), numToDo, val);
- first+=numToDo;
- n-=numToDo;
- }
- }
- }
- }
- namespace boost { namespace gil {
- namespace detail {
- struct std_fill_t {
- template <typename It, typename P>
- void operator()(It first, It last, const P& p_in) {
- std::fill(first,last,p_in);
- }
- };
- template <typename It, typename P>
- BOOST_FORCEINLINE
- void fill_aux(It first, It last, P const& p, std::true_type)
- {
- static_for_each(first, last, p, std_fill_t());
- }
- template <typename It, typename P>
- BOOST_FORCEINLINE
- void fill_aux(It first, It last, P const& p, std::false_type)
- {
- std::fill(first, last, p);
- }
- }
- template <typename View, typename Value>
- BOOST_FORCEINLINE
- void fill_pixels(View const& view, Value const& value)
- {
- if (view.is_1d_traversable())
- {
- detail::fill_aux(
- view.begin().x(), view.end().x(), value, is_planar<View>());
- }
- else
- {
- for (std::ptrdiff_t y = 0; y < view.height(); ++y)
- detail::fill_aux(
- view.row_begin(y), view.row_end(y), value, is_planar<View>());
- }
- }
- namespace detail {
- template <typename Iterator>
- BOOST_FORCEINLINE
- void destruct_range_impl(Iterator first, Iterator last,
- typename std::enable_if
- <
- mp11::mp_and
- <
- std::is_pointer<Iterator>,
- mp11::mp_not
- <
- detail::is_trivially_destructible<typename std::iterator_traits<Iterator>::value_type>
- >
- >::value
- >::type* = 0)
- {
- while (first != last)
- {
- first->~value_t();
- ++first;
- }
- }
- template <typename Iterator>
- BOOST_FORCEINLINE
- void destruct_range_impl(Iterator , Iterator ,
- typename std::enable_if
- <
- mp11::mp_or
- <
- mp11::mp_not<std::is_pointer<Iterator>>,
- detail::is_trivially_destructible<typename std::iterator_traits<Iterator>::value_type>
- >::value
- >::type* = nullptr)
- {
- }
- template <typename Iterator>
- BOOST_FORCEINLINE
- void destruct_range(Iterator first, Iterator last)
- {
- destruct_range_impl(first, last);
- }
- struct std_destruct_t
- {
- template <typename Iterator>
- void operator()(Iterator first, Iterator last) const
- {
- destruct_range(first,last);
- }
- };
- template <typename It>
- BOOST_FORCEINLINE
- void destruct_aux(It first, It last, std::true_type)
- {
- static_for_each(first,last,std_destruct_t());
- }
- template <typename It>
- BOOST_FORCEINLINE
- void destruct_aux(It first, It last, std::false_type)
- {
- destruct_range(first,last);
- }
- }
- template <typename View>
- BOOST_FORCEINLINE
- void destruct_pixels(View const& view)
- {
- if (view.is_1d_traversable())
- {
- detail::destruct_aux(
- view.begin().x(), view.end().x(), is_planar<View>());
- }
- else
- {
- for (std::ptrdiff_t y = 0; y < view.height(); ++y)
- detail::destruct_aux(
- view.row_begin(y), view.row_end(y), is_planar<View>());
- }
- }
- namespace detail {
- template <typename It, typename P>
- BOOST_FORCEINLINE
- void uninitialized_fill_aux(It first, It last, P const& p, std::true_type)
- {
- std::size_t channel = 0;
- try
- {
- using pixel_t = typename std::iterator_traits<It>::value_type;
- while (channel < num_channels<pixel_t>::value)
- {
- std::uninitialized_fill(
- dynamic_at_c(first,channel),
- dynamic_at_c(last,channel),
- dynamic_at_c(p,channel));
- ++channel;
- }
- }
- catch (...)
- {
- for (std::size_t c = 0; c < channel; ++c)
- destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
- throw;
- }
- }
- template <typename It, typename P>
- BOOST_FORCEINLINE
- void uninitialized_fill_aux(It first, It last, P const& p, std::false_type)
- {
- std::uninitialized_fill(first,last,p);
- }
- }
- template <typename View, typename Value>
- void uninitialized_fill_pixels(const View& view, const Value& val) {
- if (view.is_1d_traversable())
- detail::uninitialized_fill_aux(view.begin().x(), view.end().x(),
- val,is_planar<View>());
- else {
- typename View::y_coord_t y = 0;
- try {
- for (y=0; y<view.height(); ++y)
- detail::uninitialized_fill_aux(view.row_begin(y),view.row_end(y),
- val,is_planar<View>());
- } catch(...) {
- for (typename View::y_coord_t y0=0; y0<y; ++y0)
- detail::destruct_aux(view.row_begin(y0),view.row_end(y0), is_planar<View>());
- throw;
- }
- }
- }
- namespace detail {
- template <typename It> BOOST_FORCEINLINE
- void default_construct_range_impl(It first, It last, std::true_type)
- {
- It first1 = first;
- try
- {
- using value_t = typename std::iterator_traits<It>::value_type;
- while (first != last)
- {
- new (first) value_t();
- ++first;
- }
- }
- catch (...)
- {
- destruct_range(first1, first);
- throw;
- }
- }
- template <typename It>
- BOOST_FORCEINLINE
- void default_construct_range_impl(It, It, std::false_type) {}
- template <typename It>
- BOOST_FORCEINLINE
- void default_construct_range(It first, It last)
- {
- default_construct_range_impl(first, last, typename std::is_pointer<It>::type());
- }
- template <typename It>
- BOOST_FORCEINLINE
- void default_construct_aux(It first, It last, std::true_type)
- {
- std::size_t channel = 0;
- try
- {
- using pixel_t = typename std::iterator_traits<It>::value_type;
- while (channel < num_channels<pixel_t>::value)
- {
- default_construct_range(dynamic_at_c(first, channel), dynamic_at_c(last, channel));
- ++channel;
- }
- }
- catch (...)
- {
- for (std::size_t c = 0; c < channel; ++c)
- destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
- throw;
- }
- }
- template <typename It>
- BOOST_FORCEINLINE
- void default_construct_aux(It first, It last, std::false_type)
- {
- default_construct_range(first, last);
- }
- template <typename View, bool IsPlanar>
- struct has_trivial_pixel_constructor
- : detail::is_trivially_default_constructible<typename View::value_type>
- {};
- template <typename View>
- struct has_trivial_pixel_constructor<View, true>
- : detail::is_trivially_default_constructible<typename channel_type<View>::type>
- {};
- template<typename View, bool IsTriviallyConstructible>
- BOOST_FORCEINLINE
- void default_construct_pixels_impl(
- View const& view,
- std::enable_if<!IsTriviallyConstructible>* = nullptr)
- {
- if (view.is_1d_traversable())
- {
- detail::default_construct_aux(
- view.begin().x(), view.end().x(), is_planar<View>());
- }
- else
- {
- typename View::y_coord_t y = 0;
- try
- {
- for( y = 0; y < view.height(); ++y )
- detail::default_construct_aux(
- view.row_begin(y), view.row_end(y), is_planar<View>());
- }
- catch(...)
- {
- for (typename View::y_coord_t y0 = 0; y0 < y; ++y0 )
- detail::destruct_aux(
- view.row_begin(y0), view.row_end(y0), is_planar<View>());
- throw;
- }
- }
- }
- }
- template <typename View>
- void default_construct_pixels(View const& view)
- {
- detail::default_construct_pixels_impl
- <
- View,
- detail::has_trivial_pixel_constructor
- <
- View,
- is_planar<View>::value
- >::value
- >(view);
- }
- namespace detail {
- template <typename It1, typename It2>
- BOOST_FORCEINLINE
- void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, std::true_type)
- {
- std::size_t channel=0;
- try {
- using pixel_t = typename std::iterator_traits<It1>::value_type;
- while (channel < num_channels<pixel_t>::value)
- {
- std::uninitialized_copy(
- dynamic_at_c(first1, channel),
- dynamic_at_c(last1, channel),
- dynamic_at_c(first2, channel));
- ++channel;
- }
- }
- catch (...)
- {
- It2 last2 = first2;
- std::advance(last2, std::distance(first1, last1));
- for (std::size_t c = 0; c < channel; ++c)
- destruct_range(dynamic_at_c(first2, c), dynamic_at_c(last2, c));
- throw;
- }
- }
- template <typename It1, typename It2>
- BOOST_FORCEINLINE
- void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, std::false_type)
- {
- std::uninitialized_copy(first1, last1, first2);
- }
- }
- template <typename View1, typename View2>
- void uninitialized_copy_pixels(View1 const& view1, View2 const& view2)
- {
- using is_planar = std::integral_constant<bool, is_planar<View1>::value && is_planar<View2>::value>;
- BOOST_ASSERT(view1.dimensions() == view2.dimensions());
- if (view1.is_1d_traversable() && view2.is_1d_traversable())
- {
- detail::uninitialized_copy_aux(
- view1.begin().x(), view1.end().x(), view2.begin().x(), is_planar());
- }
- else
- {
- typename View1::y_coord_t y = 0;
- try
- {
- for (y = 0; y < view1.height(); ++y)
- detail::uninitialized_copy_aux(
- view1.row_begin(y), view1.row_end(y), view2.row_begin(y), is_planar());
- }
- catch(...)
- {
- for (typename View1::y_coord_t y0 = 0; y0 < y; ++y0)
- detail::destruct_aux(view2.row_begin(y0), view2.row_end(y0), is_planar());
- throw;
- }
- }
- }
- template <typename View, typename F>
- F for_each_pixel(View const& view, F fun)
- {
- if (view.is_1d_traversable())
- {
- return std::for_each(view.begin().x(), view.end().x(), fun);
- }
- else
- {
- for (std::ptrdiff_t y = 0; y < view.height(); ++y)
- std::for_each(view.row_begin(y), view.row_end(y), fun);
- return fun;
- }
- }
- template <typename View, typename F>
- F for_each_pixel_position(View const& view, F fun)
- {
- typename View::xy_locator loc = view.xy_at(0, 0);
- for (std::ptrdiff_t y = 0; y < view.height(); ++y)
- {
- for (std::ptrdiff_t x = 0; x < view.width(); ++x, ++loc.x())
- fun(loc);
- loc.x() -= view.width(); ++loc.y();
- }
- return fun;
- }
- template <typename View, typename F>
- void generate_pixels(View const& view, F fun)
- {
- if (view.is_1d_traversable())
- {
- std::generate(view.begin().x(), view.end().x(), fun);
- }
- else
- {
- for (std::ptrdiff_t y = 0; y < view.height(); ++y)
- std::generate(view.row_begin(y), view.row_end(y), fun);
- }
- }
- template <typename I1, typename I2>
- BOOST_FORCEINLINE
- bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
- namespace detail {
- template <typename I1, typename I2>
- struct equal_n_fn
- {
- BOOST_FORCEINLINE
- bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const
- {
- return std::equal(i1, i1 + n, i2);
- }
- };
- template<typename T, typename CS>
- struct equal_n_fn<pixel<T, CS> const*, pixel<T, CS> const*>
- {
- BOOST_FORCEINLINE
- bool operator()(pixel<T, CS> const* i1, std::ptrdiff_t n, pixel<T, CS> const* i2) const
- {
- return memcmp(i1, i2, n * sizeof(pixel<T, CS>)) == 0;
- }
- };
- template<typename T, typename CS>
- struct equal_n_fn<pixel<T, CS>*, pixel<T, CS>*>
- : equal_n_fn<pixel<T, CS> const*, pixel<T, CS> const*>
- {};
- template<typename IC, typename CS>
- struct equal_n_fn<planar_pixel_iterator<IC, CS>, planar_pixel_iterator<IC, CS>>
- {
- BOOST_FORCEINLINE
- bool operator()(planar_pixel_iterator<IC, CS> const i1, std::ptrdiff_t n, planar_pixel_iterator<IC, CS> const i2) const
- {
-
- constexpr std::ptrdiff_t byte_size = n * sizeof(typename std::iterator_traits<IC>::value_type);
- for (std::ptrdiff_t i = 0; i < mp11::mp_size<CS>::value; ++i)
- {
- if (memcmp(dynamic_at_c(i1, i), dynamic_at_c(i2, i), byte_size) != 0)
- return false;
- }
- return true;
- }
- };
- template <typename Loc, typename It>
- struct equal_n_fn<boost::gil::iterator_from_2d<Loc>, It>
- {
- BOOST_FORCEINLINE
- bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, It i2) const
- {
- gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
- gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
- while (n > 0)
- {
- std::ptrdiff_t const num = std::min<std::ptrdiff_t>(n, i1.width() - i1.x_pos());
- if (!equal_n(i1.x(), num, i2))
- return false;
- i1 += num;
- i2 += num;
- n -= num;
- }
- return true;
- }
- };
- template <typename It, typename Loc>
- struct equal_n_fn<It, boost::gil::iterator_from_2d<Loc>>
- {
- BOOST_FORCEINLINE
- bool operator()(It i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const
- {
- gil_function_requires<boost::gil::PixelIteratorConcept<It>>();
- gil_function_requires<boost::gil::PixelLocatorConcept<Loc>>();
- while (n > 0)
- {
- std::ptrdiff_t const num = std::min<std::ptrdiff_t>(n, i2.width() - i2.x_pos());
- if (!equal_n(i1, num, i2.x()))
- return false;
- i1 += num;
- i2 += num;
- n -= num;
- }
- return true;
- }
- };
- template <typename Loc1, typename Loc2>
- struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2>> {
- BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const {
- gil_function_requires<boost::gil::PixelLocatorConcept<Loc1>>();
- gil_function_requires<boost::gil::PixelLocatorConcept<Loc2>>();
- if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
- while(n-->0) {
- if (*i1++!=*i2++) return false;
- }
- }
- while (n>0) {
- std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
- if (!equal_n(i1.x(), num, i2.x()))
- return false;
- i1+=num;
- i2+=num;
- n-=num;
- }
- return true;
- }
- };
- }
- template <typename I1, typename I2> BOOST_FORCEINLINE
- bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
- return detail::equal_n_fn<I1,I2>()(i1,n,i2);
- }
- } }
- namespace std {
- template <typename Loc1, typename Loc2> 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) {
- boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1>>();
- boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2>>();
- std::ptrdiff_t n=last-first;
- if (first.is_1d_traversable()) {
- if (first2.is_1d_traversable())
- return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
- else
- return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2>>()(first.x(),n, first2);
- } else {
- if (first2.is_1d_traversable())
- return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
- else
- return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2>>()(first,n,first2);
- }
- }
- }
- namespace boost { namespace gil {
- template <typename View1, typename View2> BOOST_FORCEINLINE
- bool equal_pixels(const View1& v1, const View2& v2) {
- BOOST_ASSERT(v1.dimensions() == v2.dimensions());
- return std::equal(v1.begin(),v1.end(),v2.begin());
- }
- template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
- F transform_pixels(const View1& src,const View2& dst, F fun) {
- BOOST_ASSERT(src.dimensions() == dst.dimensions());
- for (std::ptrdiff_t y=0; y<src.height(); ++y) {
- typename View1::x_iterator srcIt=src.row_begin(y);
- typename View2::x_iterator dstIt=dst.row_begin(y);
- for (std::ptrdiff_t x=0; x<src.width(); ++x)
- dstIt[x]=fun(srcIt[x]);
- }
- return fun;
- }
- template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
- F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) {
- for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
- typename View1::x_iterator srcIt1=src1.row_begin(y);
- typename View2::x_iterator srcIt2=src2.row_begin(y);
- typename View3::x_iterator dstIt=dst.row_begin(y);
- for (std::ptrdiff_t x=0; x<dst.width(); ++x)
- dstIt[x]=fun(srcIt1[x],srcIt2[x]);
- }
- return fun;
- }
- template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
- F transform_pixel_positions(const View1& src,const View2& dst, F fun) {
- BOOST_ASSERT(src.dimensions() == dst.dimensions());
- typename View1::xy_locator loc=src.xy_at(0,0);
- for (std::ptrdiff_t y=0; y<src.height(); ++y) {
- typename View2::x_iterator dstIt=dst.row_begin(y);
- for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
- dstIt[x]=fun(loc);
- loc.x()-=src.width(); ++loc.y();
- }
- return fun;
- }
- template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
- F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) {
- BOOST_ASSERT(src1.dimensions() == dst.dimensions());
- BOOST_ASSERT(src2.dimensions() == dst.dimensions());
- typename View1::xy_locator loc1=src1.xy_at(0,0);
- typename View2::xy_locator loc2=src2.xy_at(0,0);
- for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
- typename View3::x_iterator dstIt=dst.row_begin(y);
- for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
- dstIt[x]=fun(loc1,loc2);
- loc1.x()-=src1.width(); ++loc1.y();
- loc2.x()-=src2.width(); ++loc2.y();
- }
- return fun;
- }
- } }
- #endif
|