#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 <boost/mpl/and.hpp>
-#include <boost/mpl/or.hpp>
#include <algorithm>
#include <cstddef>
/// You must provide apply_compatible(V1,V2) method in your subclass, but apply_incompatible(V1,V2)
/// is not required and the default throws std::bad_cast.
template <typename Derived, typename Result=void>
-struct binary_operation_obj {
+struct binary_operation_obj
+{
using result_type = Result;
template <typename V1, typename V2> BOOST_FORCEINLINE
// dispatch from apply overload to a function with distinct name
template <typename V1, typename V2>
- BOOST_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::false_) const {
- return ((const Derived*)this)->apply_incompatible(v1,v2);
+ BOOST_FORCEINLINE
+ result_type apply(V1 const& v1, V2 const& v2, std::false_type) const
+ {
+ return ((const Derived*)this)->apply_incompatible(v1, v2);
}
// dispatch from apply overload to a function with distinct name
template <typename V1, typename V2>
- BOOST_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::true_) const {
- return ((const Derived*)this)->apply_compatible(v1,v2);
+ BOOST_FORCEINLINE
+ result_type apply(V1 const& v1, V2 const& v2, std::true_type) const
+ {
+ return ((const Derived*)this)->apply_compatible(v1, v2);
}
// function with distinct name - it can be overloaded by subclasses
template <typename V1, typename V2>
- BOOST_FORCEINLINE result_type apply_incompatible(const V1&, const V2&) const {
+ BOOST_FORCEINLINE
+ result_type apply_incompatible(V1 const& /*v1*/, V2 const& /*v2*/) const
+ {
throw std::bad_cast();
}
};
-} } // namespace boost::gil
+
+}} // namespace boost::gil
//////////////////////////////////////////////////////////////////////////////////////
-///
-/// std::copy and gil::copy_pixels
-///
+// std::copy and gil::copy_pixels
//////////////////////////////////////////////////////////////////////////////////////
/// \defgroup ImageViewSTLAlgorithmsCopyPixels copy_pixels
/// \brief std::copy for image views
namespace std {
+
/// \ingroup STLOptimizations
/// \brief Copy when both src and dst are interleaved and of the same type can be just memmove
-template<typename T, typename Cs>
-BOOST_FORCEINLINE boost::gil::pixel<T,Cs>*
-copy(boost::gil::pixel<T,Cs>* first, 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);
+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);
}
/// \ingroup STLOptimizations
/// \brief Copy when both src and dst are interleaved and of the same type can be just memmove
-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);
+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 std
namespace std {
/// \ingroup STLOptimizations
/// \brief Copy when both src and dst are planar pointers is copy for each channel
-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> >();
+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);
}
/// Source range is delimited by image iterators
template <typename IL, typename O> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
struct copier_n<iterator_from_2d<IL>,O> {
- using diff_t = typename std::iterator_traits<iterator_from_2d<IL> >::difference_type;
+ 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> >();
+ 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);
/// Destination range is delimited by image iterators
template <typename I, typename OL> // I Models ConstPixelIteratorConcept, OL Models PixelLocatorConcept
-struct copier_n<I,iterator_from_2d<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> >();
+ 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);
/// Both source and destination ranges are delimited by image iterators
template <typename IL, typename OL>
-struct copier_n<iterator_from_2d<IL>,iterator_from_2d<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> >();
+ 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++;
}
//////////////////////////////////////////////////////////////////////////////////////
-///
-/// copy_and_convert_pixels
-///
+// copy_and_convert_pixels
//////////////////////////////////////////////////////////////////////////////////////
/// \defgroup ImageViewSTLAlgorithmsCopyAndConvertPixels copy_and_convert_pixels
namespace detail {
template <typename CC>
-class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<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;
+ 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) {}
// when the two color spaces are incompatible, a color conversion is performed
} } // namespace boost::gil
//////////////////////////////////////////////////////////////////////////////////////
-//
// std::fill and gil::fill_pixels
-//
//////////////////////////////////////////////////////////////////////////////////////
/// \defgroup ImageViewSTLAlgorithmsFillPixels fill_pixels
/// resolves to fill of each row using the underlying pixel iterator, which is still faster
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> >();
+ boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL>>();
if (first.is_1d_traversable()) {
std::fill(first.x(), last.x(), val);
} else {
} // namespace std
namespace boost { namespace gil {
+
namespace detail {
+
/// struct to do std::fill
struct std_fill_t {
template <typename It, typename P>
std::fill(first,last,p_in);
}
};
+
/// std::fill for planar iterators
template <typename It, typename P>
BOOST_FORCEINLINE
-void fill_aux(It first, It last, const P& p, mpl::true_) {
- static_for_each(first,last,p,std_fill_t());
+void fill_aux(It first, It last, P const& p, std::true_type)
+{
+ static_for_each(first, last, p, std_fill_t());
}
+
/// std::fill for interleaved iterators
template <typename It, typename P>
BOOST_FORCEINLINE
-void fill_aux(It first, It last, const P& p,mpl::false_) {
- std::fill(first,last,p);
+void fill_aux(It first, It last, P const& p, std::false_type)
+{
+ std::fill(first, last, p);
}
+
} // namespace detail
/// \ingroup ImageViewSTLAlgorithmsFillPixels
/// \brief std::fill for image views
-template <typename View, typename Value> BOOST_FORCEINLINE
-void fill_pixels(const View& img_view, const Value& val) {
- if (img_view.is_1d_traversable())
- detail::fill_aux(img_view.begin().x(), img_view.end().x(),
- val,is_planar<View>());
+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<img_view.height(); ++y)
- detail::fill_aux(img_view.row_begin(y),img_view.row_end(y),
- val,is_planar<View>());
+ {
+ 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>());
+ }
}
//////////////////////////////////////////////////////////////////////////////////////
-///
-/// destruct_pixels
-///
+// destruct_pixels
//////////////////////////////////////////////////////////////////////////////////////
/// \defgroup ImageViewSTLAlgorithmsDestructPixels destruct_pixels
void destruct_range_impl(Iterator first, Iterator last,
typename std::enable_if
<
- mpl::and_
+ mp11::mp_and
<
- is_pointer<Iterator>,
- mpl::not_<std::is_trivially_destructible<typename std::iterator_traits<Iterator>::value_type>>
+ std::is_pointer<Iterator>,
+ mp11::mp_not
+ <
+ detail::is_trivially_destructible<typename std::iterator_traits<Iterator>::value_type>
+ >
>::value
>::type* /*ptr*/ = 0)
{
void destruct_range_impl(Iterator /*first*/, Iterator /*last*/,
typename std::enable_if
<
- mpl::or_
+ mp11::mp_or
<
- mpl::not_<is_pointer<Iterator>>,
- std::is_trivially_destructible<typename std::iterator_traits<Iterator>::value_type>
+ mp11::mp_not<std::is_pointer<Iterator>>,
+ detail::is_trivially_destructible<typename std::iterator_traits<Iterator>::value_type>
>::value
>::type* /* ptr */ = nullptr)
{
/// destruct for planar iterators
template <typename It>
BOOST_FORCEINLINE
-void destruct_aux(It first, It last, mpl::true_) {
+void destruct_aux(It first, It last, std::true_type)
+{
static_for_each(first,last,std_destruct_t());
}
+
/// destruct for interleaved iterators
template <typename It>
BOOST_FORCEINLINE
-void destruct_aux(It first, It last, mpl::false_) {
+void destruct_aux(It first, It last, std::false_type)
+{
destruct_range(first,last);
}
+
} // namespace detail
/// \ingroup ImageViewSTLAlgorithmsDestructPixels
/// \brief Invokes the in-place destructor on every pixel of the view
-template <typename View> BOOST_FORCEINLINE
-void destruct_pixels(const View& img_view) {
- if (img_view.is_1d_traversable())
- detail::destruct_aux(img_view.begin().x(), img_view.end().x(),
- is_planar<View>());
+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<img_view.height(); ++y)
- detail::destruct_aux(img_view.row_begin(y),img_view.row_end(y),
- is_planar<View>());
+ {
+ for (std::ptrdiff_t y = 0; y < view.height(); ++y)
+ detail::destruct_aux(
+ view.row_begin(y), view.row_end(y), is_planar<View>());
+ }
}
//////////////////////////////////////////////////////////////////////////////////////
-///
-/// uninitialized_fill_pixels
-///
+// uninitialized_fill_pixels
//////////////////////////////////////////////////////////////////////////////////////
/// \defgroup ImageViewSTLAlgorithmsUninitializedFillPixels uninitialized_fill_pixels
/// \brief std::uninitialized_fill for image views
namespace detail {
+
/// std::uninitialized_fill for planar iterators
/// If an exception is thrown destructs any in-place copy-constructed objects
template <typename It, typename P>
BOOST_FORCEINLINE
-void uninitialized_fill_aux(It first, It last,
- const P& p, mpl::true_) {
- int channel=0;
- try {
+void uninitialized_fill_aux(It first, It last, P const& p, std::true_type)
+{
+ int 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));
+ 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 (int c=0; c<channel; ++c)
- destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
+ }
+ catch (...)
+ {
+ for (int c = 0; c < channel; ++c)
+ destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
throw;
}
}
/// If an exception is thrown destructs any in-place copy-constructed objects
template <typename It, typename P>
BOOST_FORCEINLINE
-void uninitialized_fill_aux(It first, It last,
- const P& p,mpl::false_) {
+void uninitialized_fill_aux(It first, It last, P const& p, std::false_type)
+{
std::uninitialized_fill(first,last,p);
}
+
} // namespace detail
/// \ingroup ImageViewSTLAlgorithmsUninitializedFillPixels
/// Does not support planar heterogeneous views.
/// If an exception is thrown destructs any in-place copy-constructed pixels
template <typename View, typename Value>
-void uninitialized_fill_pixels(const View& img_view, const Value& val) {
- if (img_view.is_1d_traversable())
- detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(),
+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<img_view.height(); ++y)
- detail::uninitialized_fill_aux(img_view.row_begin(y),img_view.row_end(y),
+ 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(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>());
+ detail::destruct_aux(view.row_begin(y0),view.row_end(y0), is_planar<View>());
throw;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////
-///
-/// default_construct_pixels
-///
+// default_construct_pixels
//////////////////////////////////////////////////////////////////////////////////////
/// \defgroup ImageViewSTLAlgorithmsDefaultConstructPixels default_construct_pixels
namespace detail {
template <typename It> BOOST_FORCEINLINE
-void default_construct_range_impl(It first, It last, mpl::true_) {
- using value_t = typename std::iterator_traits<It>::value_type;
- It first1=first;
- try {
- while (first!=last) {
+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);
+ }
+ catch (...)
+ {
+ destruct_range(first1, first);
throw;
}
}
-template <typename It> BOOST_FORCEINLINE
-void default_construct_range_impl(It, It, mpl::false_) {}
+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 is_pointer<It>::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());
+}
/// uninitialized_default_construct for planar iterators
template <typename It>
BOOST_FORCEINLINE
-void default_construct_aux(It first, It last, mpl::true_) {
- int channel=0;
- try {
+void default_construct_aux(It first, It last, std::true_type)
+{
+ int 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));
+ while (channel < num_channels<pixel_t>::value)
+ {
+ default_construct_range(dynamic_at_c(first, channel), dynamic_at_c(last, channel));
++channel;
}
- } catch (...) {
- for (int c=0; c<channel; ++c)
- destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
+ }
+ catch (...)
+ {
+ for (int c = 0; c < channel; ++c)
+ destruct_range(dynamic_at_c(first, c), dynamic_at_c(last, c));
throw;
}
}
/// uninitialized_default_construct for interleaved iterators
template <typename It>
BOOST_FORCEINLINE
-void default_construct_aux(It first, It last, mpl::false_) {
- default_construct_range(first,last);
+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 : public boost::has_trivial_constructor<typename View::value_type> {};
-template <typename View>
-struct has_trivial_pixel_constructor<View, true> : public boost::has_trivial_constructor<typename channel_type<View>::type> {};
-} // namespace detail
+struct has_trivial_pixel_constructor
+ : detail::is_trivially_default_constructible<typename View::value_type>
+{};
-namespace detail {
+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& img_view,
- std::enable_if<!IsTriviallyConstructible>* /* ptr */ = nullptr)
+ View const& view,
+ std::enable_if<!IsTriviallyConstructible>* /*ptr*/ = nullptr)
{
- if( img_view.is_1d_traversable() )
+ if (view.is_1d_traversable())
{
- detail::default_construct_aux( img_view.begin().x()
- , img_view.end().x()
- , is_planar<View>()
- );
+ 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 < img_view.height(); ++y )
- {
- detail::default_construct_aux( img_view.row_begin( y )
- ,img_view.row_end( y )
- , is_planar<View>()
- );
- }
- } catch(...)
+ 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( img_view.row_begin(y0)
- , img_view.row_end(y0)
- , is_planar<View>()
- );
- }
+ detail::destruct_aux(
+ view.row_begin(y0), view.row_end(y0), is_planar<View>());
throw;
}
}
}
+
} // namespace detail
/// \ingroup ImageViewSTLAlgorithmsDefaultConstructPixels
/// Does not support planar heterogeneous views.
/// If an exception is thrown destructs any in-place default-constructed pixels
template <typename View>
-void default_construct_pixels(const View& img_view) {
- detail::default_construct_pixels_impl< View
- , detail::has_trivial_pixel_constructor< View
- , is_planar< View >::value
- >::value
- >( img_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);
}
//////////////////////////////////////////////////////////////////////////////////////
-///
-/// uninitialized_copy_pixels
-///
+// uninitialized_copy_pixels
//////////////////////////////////////////////////////////////////////////////////////
/// \defgroup ImageViewSTLAlgorithmsUninitializedCopyPixels uninitialized_copy_pixels
/// \brief std::uninitialized_copy for image views
namespace detail {
+
/// std::uninitialized_copy for pairs of planar iterators
template <typename It1, typename It2>
BOOST_FORCEINLINE
-void uninitialized_copy_aux(It1 first1, It1 last1,
- It2 first2, mpl::true_) {
+void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, std::true_type)
+{
int 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));
+ 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 (int c=0; c<channel; ++c)
- destruct_range(dynamic_at_c(first2,c), dynamic_at_c(last2,c));
+ }
+ catch (...)
+ {
+ It2 last2 = first2;
+ std::advance(last2, std::distance(first1, last1));
+ for (int c = 0; c < channel; ++c)
+ destruct_range(dynamic_at_c(first2, c), dynamic_at_c(last2, c));
throw;
}
}
+
/// std::uninitialized_copy for interleaved or mixed iterators
template <typename It1, typename It2>
BOOST_FORCEINLINE
-void uninitialized_copy_aux(It1 first1, It1 last1,
- It2 first2,mpl::false_) {
- std::uninitialized_copy(first1,last1,first2);
+void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, std::false_type)
+{
+ std::uninitialized_copy(first1, last1, first2);
}
} // namespace detail
/// Does not support planar heterogeneous views.
/// If an exception is thrown destructs any in-place copy-constructed objects
template <typename View1, typename View2>
-void uninitialized_copy_pixels(const View1& view1, const View2& view2) {
- using is_planar = mpl::bool_<is_planar<View1>::value && is_planar<View2>::value>;
+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 {
+ {
+ 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());
+ 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;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////
-///
-/// for_each_pixel
-///
+// for_each_pixel
//////////////////////////////////////////////////////////////////////////////////////
/// \defgroup ImageViewSTLAlgorithmsForEachPixel for_each_pixel
/// pixel iterator, which is still faster
/// \ingroup ImageViewSTLAlgorithmsForEachPixel
-template <typename V, typename F>
-F for_each_pixel(const V& img, F fun) {
- if (img.is_1d_traversable()) {
- return std::for_each(img.begin().x(), img.end().x(), fun);
- } else {
- for (std::ptrdiff_t y=0; y<img.height(); ++y)
- std::for_each(img.row_begin(y),img.row_end(y),fun);
+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;
}
}
/// \ingroup ImageViewSTLAlgorithmsForEachPixelPosition
template <typename View, typename F>
-F for_each_pixel_position(const View& img, F fun) {
- typename View::xy_locator loc=img.xy_at(0,0);
- for (std::ptrdiff_t y=0; y<img.height(); ++y) {
- for (std::ptrdiff_t x=0; x<img.width(); ++x, ++loc.x())
+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()-=img.width(); ++loc.y();
+ loc.x() -= view.width(); ++loc.y();
}
return fun;
}
//////////////////////////////////////////////////////////////////////////////////////
-///
-/// generate_pixels
-///
+// generate_pixels
//////////////////////////////////////////////////////////////////////////////////////
/// \defgroup ImageViewSTLAlgorithmsGeneratePixels generate_pixels
/// \ingroup ImageViewSTLAlgorithmsGeneratePixels
/// \brief std::generate for image views
template <typename View, typename F>
-void generate_pixels(const View& v, F fun) {
- if (v.is_1d_traversable()) {
- std::generate(v.begin().x(), v.end().x(), fun);
- } else {
- for (std::ptrdiff_t y=0; y<v.height(); ++y)
- std::generate(v.row_begin(y),v.row_end(y),fun);
+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);
}
}
//////////////////////////////////////////////////////////////////////////////////////
-///
-/// std::equal and gil::equal_pixels for GIL constructs
-///
+// std::equal and gil::equal_pixels for GIL constructs
//////////////////////////////////////////////////////////////////////////////////////
/// \defgroup ImageViewSTLAlgorithmsEqualPixels equal_pixels
/// \ingroup ImageViewSTLAlgorithms
/// \brief std::equal for image views
-template <typename I1, typename I2> BOOST_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
+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); }
+struct equal_n_fn
+{
+ BOOST_FORCEINLINE
+ bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const
+ {
+ return std::equal(i1, i1 + n, i2);
+ }
};
/// Equal when both ranges are interleaved and of the same type.
/// GIL pixels are bitwise comparable, so memcmp is used. User-defined pixels that are not bitwise comparable need to provide an overload
-template<typename T, typename Cs>
-struct equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {
- BOOST_FORCEINLINE bool operator()(const pixel<T,Cs>* i1, std::ptrdiff_t n, const pixel<T,Cs>* i2) const {
- return memcmp(i1, i2, n*sizeof(pixel<T,Cs>))==0;
+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<const pixel<T,Cs>*, const pixel<T,Cs>*> {};
+
+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*>
+{};
/// EqualPixels
/// Equal when both ranges are planar pointers of the same type. memcmp is invoked for each channel plane
/// User-defined channels that are not bitwise comparable need to provide an overload
-template<typename IC, typename Cs>
-struct equal_n_fn<planar_pixel_iterator<IC,Cs>, planar_pixel_iterator<IC,Cs> > {
- BOOST_FORCEINLINE bool operator()(const planar_pixel_iterator<IC,Cs> i1, std::ptrdiff_t n, const planar_pixel_iterator<IC,Cs> i2) const {
- std::ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type);
-
- for (std::ptrdiff_t i=0; i<mpl::size<Cs>::value; ++i)
- if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0)
+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
+ {
+ // FIXME: ptrdiff_t vs size_t
+ 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;
}
};
/// Source range is delimited by image iterators
-template <typename Loc, typename I2> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
-struct equal_n_fn<boost::gil::iterator_from_2d<Loc>,I2> {
- BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, I2 i2) const {
- gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
- gil_function_requires<boost::gil::PixelIteratorConcept<I2> >();
- while (n>0) {
- std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
+/// \tparam Loc Models ConstPixelLocatorConcept
+/// \tparam It Models PixelIteratorConcept
+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;
+ i1 += num;
+ i2 += num;
+ n -= num;
}
return true;
}
};
/// Destination range is delimited by image iterators
-template <typename I1, typename Loc> // I Models PixelIteratorConcept, OL Models PixelLocatorConcept
-struct equal_n_fn<I1,boost::gil::iterator_from_2d<Loc> > {
- BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const {
- gil_function_requires<boost::gil::PixelIteratorConcept<I1> >();
- gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
- while (n>0) {
- std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
+/// \tparam It Models PixelIteratorConcept
+/// \tparam Loc Models PixelLocatorConcept
+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;
+ i1 += num;
+ i2 += num;
+ n -= num;
}
return true;
}
/// Both source and destination ranges are delimited by image iterators
template <typename Loc1, typename Loc2>
-struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<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> >();
+ 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;
/// to memcmp. Otherwise it resolves to copying each row using the underlying pixel iterator
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> >();
+ 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);
+ 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);
+ return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2>>()(first,n,first2);
}
}
} // namespace std