update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,7 @@
#include <boost/iterator/iterator_facade.hpp>
#include <functional>
#include <type_traits>
namespace boost { namespace gil {
@@ -62,35 +63,41 @@ public:
/// For some reason operator[] provided by iterator_adaptor returns a custom class that is convertible to reference
/// We require our own reference because it is registered in iterator_traits
reference operator[](difference_type d) const { bit_aligned_pixel_iterator it=*this; it.advance(d); return *it; }
auto operator[](difference_type d) const -> reference { bit_aligned_pixel_iterator it=*this; it.advance(d); return *it; }
reference operator->() const { return **this; }
const bit_range_t& bit_range() const { return _bit_range; }
bit_range_t& bit_range() { return _bit_range; }
auto operator->() const -> reference { return **this; }
auto bit_range() const -> bit_range_t const& { return _bit_range; }
auto bit_range() -> bit_range_t& { return _bit_range; }
private:
bit_range_t _bit_range;
static constexpr int bit_size = NonAlignedPixelReference::bit_size;
friend class boost::iterator_core_access;
reference dereference() const { return NonAlignedPixelReference(_bit_range); }
auto dereference() const -> reference { return NonAlignedPixelReference(_bit_range); }
void increment() { ++_bit_range; }
void decrement() { --_bit_range; }
void advance(difference_type d) { _bit_range.bit_advance(d*bit_size); }
difference_type distance_to(const bit_aligned_pixel_iterator& it) const { return _bit_range.bit_distance_to(it._bit_range) / bit_size; }
auto distance_to(bit_aligned_pixel_iterator const& it) const -> difference_type { return _bit_range.bit_distance_to(it._bit_range) / bit_size; }
bool equal(const bit_aligned_pixel_iterator& it) const { return _bit_range==it._bit_range; }
};
template <typename NonAlignedPixelReference>
struct const_iterator_type<bit_aligned_pixel_iterator<NonAlignedPixelReference> > {
using type = bit_aligned_pixel_iterator<typename NonAlignedPixelReference::const_reference>;
struct const_iterator_type<bit_aligned_pixel_iterator<NonAlignedPixelReference>>
{
using type =
bit_aligned_pixel_iterator<typename NonAlignedPixelReference::const_reference>;
};
template <typename NonAlignedPixelReference>
struct iterator_is_mutable<bit_aligned_pixel_iterator<NonAlignedPixelReference> > : public mpl::bool_<NonAlignedPixelReference::is_mutable> {};
struct iterator_is_mutable<bit_aligned_pixel_iterator<NonAlignedPixelReference>>
: std::integral_constant<bool, NonAlignedPixelReference::is_mutable>
{};
template <typename NonAlignedPixelReference>
struct is_iterator_adaptor<bit_aligned_pixel_iterator<NonAlignedPixelReference> > : public mpl::false_ {};
struct is_iterator_adaptor<bit_aligned_pixel_iterator<NonAlignedPixelReference>>
: std::false_type
{};
/////////////////////////////
// PixelBasedConcept
@@ -110,15 +117,19 @@ struct is_planar<bit_aligned_pixel_iterator<NonAlignedPixelReference> > : public
/////////////////////////////
template <typename NonAlignedPixelReference>
struct byte_to_memunit<bit_aligned_pixel_iterator<NonAlignedPixelReference> > : public mpl::int_<8> {};
struct byte_to_memunit<bit_aligned_pixel_iterator<NonAlignedPixelReference>>
: std::integral_constant<int, 8>
{};
template <typename NonAlignedPixelReference>
inline std::ptrdiff_t memunit_step(const bit_aligned_pixel_iterator<NonAlignedPixelReference>&) {
inline auto memunit_step(const bit_aligned_pixel_iterator<NonAlignedPixelReference>&) -> std::ptrdiff_t
{
return NonAlignedPixelReference::bit_size;
}
template <typename NonAlignedPixelReference>
inline std::ptrdiff_t memunit_distance(const bit_aligned_pixel_iterator<NonAlignedPixelReference>& p1, const bit_aligned_pixel_iterator<NonAlignedPixelReference>& p2) {
inline auto memunit_distance(bit_aligned_pixel_iterator<NonAlignedPixelReference> const& p1, bit_aligned_pixel_iterator<NonAlignedPixelReference> const& p2) -> std::ptrdiff_t
{
return (p2.bit_range().current_byte() - p1.bit_range().current_byte())*8 + p2.bit_range().bit_offset() - p1.bit_range().bit_offset();
}
@@ -128,14 +139,15 @@ inline void memunit_advance(bit_aligned_pixel_iterator<NonAlignedPixelReference>
}
template <typename NonAlignedPixelReference>
inline bit_aligned_pixel_iterator<NonAlignedPixelReference> memunit_advanced(const bit_aligned_pixel_iterator<NonAlignedPixelReference>& p, std::ptrdiff_t diff) {
inline auto memunit_advanced(bit_aligned_pixel_iterator<NonAlignedPixelReference> const& p, std::ptrdiff_t diff) -> bit_aligned_pixel_iterator<NonAlignedPixelReference> {
bit_aligned_pixel_iterator<NonAlignedPixelReference> ret=p;
memunit_advance(ret, diff);
return ret;
}
template <typename NonAlignedPixelReference> inline
NonAlignedPixelReference memunit_advanced_ref(bit_aligned_pixel_iterator<NonAlignedPixelReference> it, std::ptrdiff_t diff) {
auto memunit_advanced_ref(bit_aligned_pixel_iterator<NonAlignedPixelReference> it, std::ptrdiff_t diff) -> NonAlignedPixelReference
{
return *memunit_advanced(it,diff);
}
/////////////////////////////
@@ -174,11 +186,14 @@ namespace std {
// It is important to provide an overload of uninitialized_copy for bit_aligned_pixel_iterator. The default STL implementation calls placement new,
// which is not defined for bit_aligned_pixel_iterator.
template <typename NonAlignedPixelReference>
boost::gil::bit_aligned_pixel_iterator<NonAlignedPixelReference> uninitialized_copy(boost::gil::bit_aligned_pixel_iterator<NonAlignedPixelReference> first,
boost::gil::bit_aligned_pixel_iterator<NonAlignedPixelReference> last,
boost::gil::bit_aligned_pixel_iterator<NonAlignedPixelReference> dst) {
auto uninitialized_copy(boost::gil::bit_aligned_pixel_iterator<NonAlignedPixelReference> first,
boost::gil::bit_aligned_pixel_iterator<NonAlignedPixelReference> last,
boost::gil::bit_aligned_pixel_iterator<NonAlignedPixelReference> dst)
-> boost::gil::bit_aligned_pixel_iterator<NonAlignedPixelReference>
{
return std::copy(first,last,dst);
}
} // namespace std
} // namespace std
#endif

View File

@@ -1,5 +1,6 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
@@ -10,16 +11,10 @@
#include <boost/gil/pixel.hpp>
#include <boost/gil/channel.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/mpl/accumulate.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/vector.hpp>
#include <functional>
#include <type_traits>
@@ -35,10 +30,10 @@ namespace boost { namespace gil {
// Represents a range of bits that can span multiple consecutive bytes. The range has a size fixed at compile time, but the offset is specified at run time.
/////////////////////////////
template <int RangeSize, bool Mutable>
template <int RangeSize, bool IsMutable>
class bit_range {
public:
using byte_t = typename mpl::if_c<Mutable,unsigned char,const unsigned char>::type;
using byte_t = mp11::mp_if_c<IsMutable, unsigned char, unsigned char const>;
using difference_type = std::ptrdiff_t;
template <int RS, bool M> friend class bit_range;
private:
@@ -54,18 +49,18 @@ public:
BOOST_ASSERT(bit_offset >= 0 && bit_offset < 8);
}
bit_range(const bit_range& br) : _current_byte(br._current_byte), _bit_offset(br._bit_offset) {}
bit_range(bit_range const& br) : _current_byte(br._current_byte), _bit_offset(br._bit_offset) {}
template <bool M> bit_range(const bit_range<RangeSize,M>& br) : _current_byte(br._current_byte), _bit_offset(br._bit_offset) {}
bit_range& operator=(const bit_range& br) { _current_byte = br._current_byte; _bit_offset=br._bit_offset; return *this; }
bool operator==(const bit_range& br) const { return _current_byte==br._current_byte && _bit_offset==br._bit_offset; }
auto operator=(bit_range const& br) -> bit_range& { _current_byte = br._current_byte; _bit_offset=br._bit_offset; return *this; }
bool operator==(bit_range const& br) const { return _current_byte==br._current_byte && _bit_offset==br._bit_offset; }
bit_range& operator++() {
auto operator++() -> bit_range& {
_current_byte += (_bit_offset+RangeSize) / 8;
_bit_offset = (_bit_offset+RangeSize) % 8;
return *this;
}
bit_range& operator--() { bit_advance(-RangeSize); return *this; }
auto operator--() -> bit_range& { bit_advance(-RangeSize); return *this; }
void bit_advance(difference_type num_bits) {
int new_offset = int(_bit_offset+num_bits);
@@ -76,11 +71,13 @@ public:
--_current_byte;
}
}
difference_type bit_distance_to(const bit_range& b) const {
auto bit_distance_to(bit_range const& b) const -> difference_type
{
return (b.current_byte() - current_byte())*8 + b.bit_offset()-bit_offset();
}
byte_t* current_byte() const { return _current_byte; }
int bit_offset() const { return _bit_offset; }
auto current_byte() const -> byte_t* { return _current_byte; }
auto bit_offset() const -> int { return _bit_offset; }
};
/// \defgroup ColorBaseModelNonAlignedPixel bit_aligned_pixel_reference
@@ -96,7 +93,7 @@ public:
/// unsigned char data=0;
///
/// // A mutable reference to a 6-bit BGR pixel in "123" format (1 bit for red, 2 bits for green, 3 bits for blue)
/// using rgb123_ref_t = bit_aligned_pixel_reference<unsigned char, mpl::vector3_c<int,1,2,3>, rgb_layout_t, true> const;
/// using rgb123_ref_t = bit_aligned_pixel_reference<unsigned char, mp11::mp_list_c<int,1,2,3>, rgb_layout_t, true> const;
///
/// // create the pixel reference at bit offset 2
/// // (i.e. red = [2], green = [3,4], blue = [5,6,7] bits)
@@ -113,23 +110,23 @@ public:
/// \brief Heterogeneous pixel reference corresponding to non-byte-aligned bit range. Models ColorBaseConcept, PixelConcept, PixelBasedConcept
///
/// \tparam BitField
/// \tparam ChannelBitSizes MPL integral vector defining the number of bits for each channel. For example, for 565RGB, vector_c<int,5,6,5>
/// \tparam ChannelBitSizes Boost.MP11-compatible list of integral types defining the number of bits for each channel. For example, for 565RGB, mp_list_c<int,5,6,5>
/// \tparam Layout
/// \tparam IsMutable
template <typename BitField, typename ChannelBitSizes, typename Layout, bool IsMutable>
struct bit_aligned_pixel_reference
{
static constexpr int bit_size =
mpl::accumulate
mp11::mp_fold
<
ChannelBitSizes,
mpl::int_<0>,
mpl::plus<mpl::_1, mpl::_2>
>::type::value;
std::integral_constant<int, 0>,
mp11::mp_plus
>::value;
using bit_range_t = boost::gil::bit_range<bit_size,IsMutable>;
using bitfield_t = BitField;
using data_ptr_t =typename mpl::if_c<IsMutable,unsigned char*,const unsigned char*>::type;
using data_ptr_t = mp11::mp_if_c<IsMutable, unsigned char*, const unsigned char*>;
using layout_t = Layout;
@@ -141,8 +138,10 @@ struct bit_aligned_pixel_reference
bit_aligned_pixel_reference(){}
bit_aligned_pixel_reference(data_ptr_t data_ptr, int bit_offset) : _bit_range(data_ptr, bit_offset) {}
explicit bit_aligned_pixel_reference(const bit_range_t& bit_range) : _bit_range(bit_range) {}
template <bool IsMutable2> bit_aligned_pixel_reference(const bit_aligned_pixel_reference<BitField,ChannelBitSizes,Layout,IsMutable2>& p) : _bit_range(p._bit_range) {}
explicit bit_aligned_pixel_reference(bit_range_t const& bit_range) : _bit_range(bit_range) {}
template <bool IsMutable2>
bit_aligned_pixel_reference(bit_aligned_pixel_reference<BitField,ChannelBitSizes,Layout,IsMutable2> const& p) : _bit_range(p._bit_range) {}
// Grayscale references can be constructed from the channel reference
explicit bit_aligned_pixel_reference(typename kth_element_type<bit_aligned_pixel_reference,0>::type const channel0)
@@ -152,28 +151,64 @@ struct bit_aligned_pixel_reference
}
// Construct from another compatible pixel type
bit_aligned_pixel_reference(const bit_aligned_pixel_reference& p) : _bit_range(p._bit_range) {}
template <typename BF, typename CR> bit_aligned_pixel_reference(packed_pixel<BF,CR,Layout>& p) : _bit_range(static_cast<data_ptr_t>(&gil::at_c<0>(p)), gil::at_c<0>(p).first_bit()) {
check_compatible<packed_pixel<BF,CR,Layout> >();
bit_aligned_pixel_reference(bit_aligned_pixel_reference const& p)
: _bit_range(p._bit_range) {}
// TODO: Why p by non-const reference?
template <typename BF, typename CR>
bit_aligned_pixel_reference(packed_pixel<BF, CR, Layout>& p)
: _bit_range(static_cast<data_ptr_t>(&gil::at_c<0>(p)), gil::at_c<0>(p).first_bit())
{
check_compatible<packed_pixel<BF, CR, Layout>>();
}
const bit_aligned_pixel_reference& operator=(const bit_aligned_pixel_reference& p) const { static_copy(p,*this); return *this; }
template <typename P> const bit_aligned_pixel_reference& operator=(const P& p) const { assign(p, mpl::bool_<is_pixel<P>::value>()); return *this; }
auto operator=(bit_aligned_pixel_reference const& p) const
-> bit_aligned_pixel_reference const&
{
static_copy(p, *this);
return *this;
}
template <typename P> bool operator==(const P& p) const { return equal(p, mpl::bool_<is_pixel<P>::value>()); }
template <typename P> bool operator!=(const P& p) const { return !(*this==p); }
template <typename P>
auto operator=(P const& p) const -> bit_aligned_pixel_reference const&
{
assign(p, is_pixel<P>());
return *this;
}
const bit_aligned_pixel_reference* operator->() const { return this; }
template <typename P>
bool operator==(P const& p) const
{
return equal(p, is_pixel<P>());
}
template <typename P>
bool operator!=(P const& p) const { return !(*this==p); }
auto operator->() const -> bit_aligned_pixel_reference const* { return this; }
auto bit_range() const -> bit_range_t const& { return _bit_range; }
const bit_range_t& bit_range() const { return _bit_range; }
private:
mutable bit_range_t _bit_range;
template <typename B, typename C, typename L, bool M> friend struct bit_aligned_pixel_reference;
template <typename B, typename C, typename L, bool M>
friend struct bit_aligned_pixel_reference;
template <typename Pixel> static void check_compatible() { gil_function_requires<PixelsCompatibleConcept<Pixel,bit_aligned_pixel_reference> >(); }
template <typename Pixel> void assign(const Pixel& p, mpl::true_) const { check_compatible<Pixel>(); static_copy(p,*this); }
template <typename Pixel> bool equal(const Pixel& p, mpl::true_) const { check_compatible<Pixel>(); return static_equal(*this,p); }
template <typename Pixel>
void assign(Pixel const& p, std::true_type) const
{
check_compatible<Pixel>();
static_copy(p, *this);
}
template <typename Pixel>
bool equal(Pixel const& p, std::true_type) const
{
check_compatible<Pixel>();
return static_equal(*this, p);
}
private:
static void check_gray()
@@ -181,8 +216,19 @@ private:
static_assert(std::is_same<typename Layout::color_space_t, gray_t>::value, "");
}
template <typename Channel> void assign(const Channel& chan, mpl::false_) const { check_gray(); gil::at_c<0>(*this)=chan; }
template <typename Channel> bool equal (const Channel& chan, mpl::false_) const { check_gray(); return gil::at_c<0>(*this)==chan; }
template <typename Channel>
void assign(Channel const& channel, std::false_type) const
{
check_gray();
gil::at_c<0>(*this) = channel;
}
template <typename Channel>
bool equal (Channel const& channel, std::false_type) const
{
check_gray();
return gil::at_c<0>(*this) == channel;
}
};
/////////////////////////////
@@ -190,9 +236,18 @@ private:
/////////////////////////////
template <typename BitField, typename ChannelBitSizes, typename L, bool IsMutable, int K>
struct kth_element_type<bit_aligned_pixel_reference<BitField,ChannelBitSizes,L,IsMutable>, K>
struct kth_element_type
<
bit_aligned_pixel_reference<BitField, ChannelBitSizes, L, IsMutable>,
K
>
{
using type = packed_dynamic_channel_reference<BitField, mpl::at_c<ChannelBitSizes,K>::type::value, IsMutable> const;
using type = packed_dynamic_channel_reference
<
BitField,
mp11::mp_at_c<ChannelBitSizes, K>::value,
IsMutable
> const;
};
template <typename B, typename C, typename L, bool M, int K>
@@ -203,26 +258,35 @@ template <typename B, typename C, typename L, bool M, int K>
struct kth_element_const_reference_type<bit_aligned_pixel_reference<B,C,L,M>, K>
: public kth_element_type<bit_aligned_pixel_reference<B,C,L,M>, K> {};
namespace detail {
// returns sum of IntegralVector[0] ... IntegralVector[K-1]
template <typename IntegralVector, int K>
struct sum_k : public mpl::plus<sum_k<IntegralVector,K-1>, typename mpl::at_c<IntegralVector,K-1>::type > {};
template <typename IntegralVector> struct sum_k<IntegralVector,0> : public mpl::int_<0> {};
}
// returns sum of IntegralVector[0] ... IntegralVector[K-1]
template <typename IntegralVector, int K>
struct sum_k
: mp11::mp_plus
<
sum_k<IntegralVector, K - 1>,
typename mp11::mp_at_c<IntegralVector, K - 1>::type
>
{};
template <typename IntegralVector>
struct sum_k<IntegralVector, 0> : std::integral_constant<int, 0> {};
} // namespace detail
// at_c required by MutableColorBaseConcept
template <int K, typename BitField, typename ChannelBitSizes, typename L, bool Mutable> inline
typename kth_element_reference_type<bit_aligned_pixel_reference<BitField,ChannelBitSizes,L,Mutable>,K>::type
at_c(const bit_aligned_pixel_reference<BitField,ChannelBitSizes,L,Mutable>& p)
template <int K, typename BitField, typename ChannelBitSizes, typename L, bool IsMutable>
inline
auto at_c(const bit_aligned_pixel_reference<BitField, ChannelBitSizes, L, IsMutable>& p)
-> typename kth_element_reference_type<bit_aligned_pixel_reference<BitField, ChannelBitSizes, L, IsMutable>, K>::type
{
using pixel_t = bit_aligned_pixel_reference<BitField,ChannelBitSizes,L,Mutable>;
using channel_t = typename kth_element_reference_type<pixel_t,K>::type;
using pixel_t = bit_aligned_pixel_reference<BitField, ChannelBitSizes, L, IsMutable>;
using channel_t = typename kth_element_reference_type<pixel_t, K>::type;
using bit_range_t = typename pixel_t::bit_range_t;
bit_range_t bit_range(p.bit_range());
bit_range.bit_advance(detail::sum_k<ChannelBitSizes,K>::value);
bit_range.bit_advance(detail::sum_k<ChannelBitSizes, K>::value);
return channel_t(bit_range.current_byte(), bit_range.bit_offset());
}
@@ -233,56 +297,67 @@ at_c(const bit_aligned_pixel_reference<BitField,ChannelBitSizes,L,Mutable>& p)
/// Metafunction predicate that flags bit_aligned_pixel_reference as a model of PixelConcept. Required by PixelConcept
template <typename B, typename C, typename L, bool M>
struct is_pixel<bit_aligned_pixel_reference<B,C,L,M> > : public mpl::true_{};
struct is_pixel<bit_aligned_pixel_reference<B, C, L, M> > : std::true_type {};
/////////////////////////////
// PixelBasedConcept
/////////////////////////////
template <typename B, typename C, typename L, bool M>
struct color_space_type<bit_aligned_pixel_reference<B,C,L,M> > {
struct color_space_type<bit_aligned_pixel_reference<B, C, L, M>>
{
using type = typename L::color_space_t;
};
template <typename B, typename C, typename L, bool M>
struct channel_mapping_type<bit_aligned_pixel_reference<B,C,L,M> > {
struct channel_mapping_type<bit_aligned_pixel_reference<B, C, L, M>>
{
using type = typename L::channel_mapping_t;
};
template <typename B, typename C, typename L, bool M>
struct is_planar<bit_aligned_pixel_reference<B,C,L,M> > : mpl::false_ {};
struct is_planar<bit_aligned_pixel_reference<B, C, L, M>> : std::false_type {};
/////////////////////////////
// pixel_reference_type
/////////////////////////////
namespace detail {
// returns a vector containing K copies of the type T
template <unsigned K, typename T> struct k_copies;
template <typename T> struct k_copies<0,T> {
using type = mpl::vector0<>;
};
template <unsigned K, typename T> struct k_copies : public mpl::push_back<typename k_copies<K-1,T>::type, T> {};
}
// Constructs a homogeneous bit_aligned_pixel_reference given a channel reference
template <typename BitField, int NumBits, typename Layout>
struct pixel_reference_type<const packed_dynamic_channel_reference<BitField,NumBits,false>, Layout, false, false>
struct pixel_reference_type
<
packed_dynamic_channel_reference<BitField, NumBits, false> const,
Layout, false, false
>
{
private:
using size_t = typename mpl::size<typename Layout::color_space_t>::type;
using channel_bit_sizes_t = typename detail::k_copies<size_t::value,mpl::integral_c<unsigned,NumBits> >::type;
using channel_bit_sizes_t = mp11::mp_repeat
<
mp11::mp_list<std::integral_constant<unsigned, NumBits>>,
mp11::mp_size<typename Layout::color_space_t>
>;
public:
using type = bit_aligned_pixel_reference<BitField, channel_bit_sizes_t, Layout, false>;
using type =
bit_aligned_pixel_reference<BitField, channel_bit_sizes_t, Layout, false>;
};
// Same but for the mutable case. We cannot combine the mutable and read-only cases because this triggers ambiguity
// Same but for the mutable case. We cannot combine the mutable
// and read-only cases because this triggers ambiguity
template <typename BitField, int NumBits, typename Layout>
struct pixel_reference_type<const packed_dynamic_channel_reference<BitField,NumBits,true>, Layout, false, true>
struct pixel_reference_type
<
packed_dynamic_channel_reference<BitField, NumBits, true> const,
Layout, false, true
>
{
private:
using size_t = typename mpl::size<typename Layout::color_space_t>::type;
using channel_bit_sizes_t = typename detail::k_copies<size_t::value,mpl::integral_c<unsigned,NumBits>>::type;
using channel_bit_sizes_t = mp11::mp_repeat
<
mp11::mp_list<std::integral_constant<unsigned, NumBits>>,
mp11::mp_size<typename Layout::color_space_t>
>;
public:
using type = bit_aligned_pixel_reference<BitField, channel_bit_sizes_t, Layout, true>;
};
@@ -290,6 +365,7 @@ public:
} } // namespace boost::gil
namespace std {
// We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified.
// swap with 'left bias':
// - swap between proxy and anything
@@ -298,7 +374,7 @@ namespace std {
// Having three overloads allows us to swap between different (but compatible) models of PixelConcept
template <typename B, typename C, typename L, typename R> inline
void swap(const boost::gil::bit_aligned_pixel_reference<B,C,L,true> x, R& y) {
void swap(boost::gil::bit_aligned_pixel_reference<B,C,L,true> const x, R& y) {
boost::gil::swap_proxy<typename boost::gil::bit_aligned_pixel_reference<B,C,L,true>::value_type>(x,y);
}
@@ -310,8 +386,10 @@ void swap(typename boost::gil::bit_aligned_pixel_reference<B,C,L,true>::value_ty
template <typename B, typename C, typename L> inline
void swap(const boost::gil::bit_aligned_pixel_reference<B,C,L,true> x, const boost::gil::bit_aligned_pixel_reference<B,C,L,true> y) {
void swap(boost::gil::bit_aligned_pixel_reference<B,C,L,true> const x, const boost::gil::bit_aligned_pixel_reference<B,C,L,true> y) {
boost::gil::swap_proxy<typename boost::gil::bit_aligned_pixel_reference<B,C,L,true>::value_type>(x,y);
}
} // namespace std
} // namespace std
#endif

View File

@@ -14,10 +14,10 @@
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#include <boost/integer/integer_mask.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <cstdint>
#include <limits>
#include <type_traits>
#ifdef BOOST_GIL_DOXYGEN_ONLY
/// \def BOOST_GIL_CONFIG_HAS_UNALIGNED_ACCESS
@@ -69,42 +69,48 @@ namespace boost { namespace gil {
///////////////////////////////////////////
namespace detail {
template <typename T, bool is_class> struct channel_traits_impl;
// channel traits for custom class
template <typename T>
struct channel_traits_impl<T, true> {
using value_type = typename T::value_type;
using reference = typename T::reference;
using pointer = typename T::pointer;
using const_reference = typename T::const_reference;
using const_pointer = typename T::const_pointer;
static constexpr bool is_mutable = T::is_mutable;
static value_type min_value() { return T::min_value(); }
static value_type max_value() { return T::max_value(); }
};
template <typename T, bool IsClass>
struct channel_traits_impl;
// channel traits implementation for built-in integral or floating point channel type
template <typename T>
struct channel_traits_impl<T, false> {
using value_type = T;
using reference = T&;
using pointer = T*;
using const_reference = T const&;
using const_pointer = T const*;
static constexpr bool is_mutable = true;
static value_type min_value() { return (std::numeric_limits<T>::min)(); }
static value_type max_value() { return (std::numeric_limits<T>::max)(); }
};
// channel traits for custom class
template <typename T>
struct channel_traits_impl<T, true>
{
using value_type = typename T::value_type;
using reference = typename T::reference;
using pointer = typename T::pointer;
using const_reference = typename T::const_reference;
using const_pointer = typename T::const_pointer;
static constexpr bool is_mutable = T::is_mutable;
static value_type min_value() { return T::min_value(); }
static value_type max_value() { return T::max_value(); }
};
// channel traits implementation for constant built-in scalar or floating point type
template <typename T>
struct channel_traits_impl<const T, false> : public channel_traits_impl<T, false> {
using reference = const T &;
using pointer = const T *;
static constexpr bool is_mutable = false;
};
}
// channel traits implementation for built-in integral or floating point channel type
template <typename T>
struct channel_traits_impl<T, false>
{
using value_type = T;
using reference = T&;
using pointer = T*;
using const_reference = T const&;
using const_pointer = T const*;
static constexpr bool is_mutable = true;
static value_type min_value() { return (std::numeric_limits<T>::min)(); }
static value_type max_value() { return (std::numeric_limits<T>::max)(); }
};
// channel traits implementation for constant built-in scalar or floating point type
template <typename T>
struct channel_traits_impl<T const, false> : channel_traits_impl<T, false>
{
using reference = T const&;
using pointer = T const*;
static constexpr bool is_mutable = false;
};
} // namespace detail
/**
\ingroup ChannelModel
@@ -125,14 +131,15 @@ struct channel_traits {
\endcode
*/
template <typename T>
struct channel_traits : public detail::channel_traits_impl<T, is_class<T>::value> {};
struct channel_traits : detail::channel_traits_impl<T, std::is_class<T>::value> {};
// Channel traits for C++ reference type - remove the reference
template <typename T> struct channel_traits<T&> : public channel_traits<T> {};
template <typename T>
struct channel_traits<T&> : channel_traits<T> {};
// Channel traits for constant C++ reference type
template <typename T>
struct channel_traits<T const&> : public channel_traits<T>
struct channel_traits<T const&> : channel_traits<T>
{
using reference = typename channel_traits<T>::const_reference;
using pointer = typename channel_traits<T>::const_pointer;
@@ -140,9 +147,7 @@ struct channel_traits<T const&> : public channel_traits<T>
};
///////////////////////////////////////////
////
//// scoped_channel_value
////
///////////////////////////////////////////
/// \defgroup ScopedChannelValue scoped_channel_value
@@ -183,25 +188,46 @@ struct scoped_channel_value
static value_type min_value() { return MinVal::apply(); }
static value_type max_value() { return MaxVal::apply(); }
scoped_channel_value() {}
scoped_channel_value(const scoped_channel_value& c) : _value(c._value) {}
scoped_channel_value(BaseChannelValue val) : _value(val) {}
scoped_channel_value() = default;
scoped_channel_value(scoped_channel_value const& other) : value_(other.value_) {}
scoped_channel_value& operator=(scoped_channel_value const& other) = default;
scoped_channel_value(BaseChannelValue value) : value_(value) {}
scoped_channel_value& operator=(BaseChannelValue value)
{
value_ = value;
return *this;
}
scoped_channel_value& operator++() { ++_value; return *this; }
scoped_channel_value& operator--() { --_value; return *this; }
auto operator++() -> scoped_channel_value& { ++value_; return *this; }
auto operator--() -> scoped_channel_value& { --value_; return *this; }
scoped_channel_value operator++(int) { scoped_channel_value tmp=*this; this->operator++(); return tmp; }
scoped_channel_value operator--(int) { scoped_channel_value tmp=*this; this->operator--(); return tmp; }
auto operator++(int) -> scoped_channel_value
{
scoped_channel_value tmp=*this;
this->operator++(); return tmp;
}
auto operator--(int) -> scoped_channel_value
{
scoped_channel_value tmp=*this;
this->operator--(); return tmp;
}
template <typename Scalar2> scoped_channel_value& operator+=(Scalar2 v) { _value+=v; return *this; }
template <typename Scalar2> scoped_channel_value& operator-=(Scalar2 v) { _value-=v; return *this; }
template <typename Scalar2> scoped_channel_value& operator*=(Scalar2 v) { _value*=v; return *this; }
template <typename Scalar2> scoped_channel_value& operator/=(Scalar2 v) { _value/=v; return *this; }
template <typename Scalar2>
auto operator+=(Scalar2 v) -> scoped_channel_value& { value_+=v; return *this; }
template <typename Scalar2>
auto operator-=(Scalar2 v) -> scoped_channel_value& { value_-=v; return *this; }
scoped_channel_value& operator=(BaseChannelValue v) { _value=v; return *this; }
operator BaseChannelValue() const { return _value; }
template <typename Scalar2>
auto operator*=(Scalar2 v) -> scoped_channel_value& { value_*=v; return *this; }
template <typename Scalar2>
auto operator/=(Scalar2 v) -> scoped_channel_value& { value_/=v; return *this; }
operator BaseChannelValue() const { return value_; }
private:
BaseChannelValue _value;
BaseChannelValue value_{};
};
template <typename T>
@@ -217,9 +243,7 @@ struct float_point_one
};
///////////////////////////////////////////
////
//// Support for sub-byte channels. These are integral channels whose value is contained in a range of bits inside an integral type
////
///////////////////////////////////////////
// It is necessary for packed channels to have their own value type. They cannot simply use an integral large enough to store the data. Here is why:
@@ -227,31 +251,39 @@ struct float_point_one
// That means that after getting the value of the channel we cannot properly do channel_convert, channel_invert, etc.
// - Two channels are declared compatible if they have the same value type. That means that a packed channel is incorrectly declared compatible with an integral type
namespace detail {
// returns the smallest fast unsigned integral type that has at least NumBits bits
template <int NumBits>
struct min_fast_uint : public mpl::if_c< (NumBits<=8),
uint_least8_t,
typename mpl::if_c< (NumBits<=16),
uint_least16_t,
typename mpl::if_c< (NumBits<=32),
uint_least32_t,
uintmax_t
>::type
// returns the smallest fast unsigned integral type that has at least NumBits bits
template <int NumBits>
struct min_fast_uint :
std::conditional
<
NumBits <= 8,
std::uint_least8_t,
typename std::conditional
<
NumBits <= 16,
std::uint_least16_t,
typename std::conditional
<
NumBits <= 32,
std::uint_least32_t,
std::uintmax_t
>::type
> {};
>::type
>
{};
template <int NumBits>
struct num_value_fn : public mpl::if_c< ( NumBits < 32 )
, uint32_t
, uint64_t
> {};
template <int NumBits>
struct num_value_fn
: std::conditional<NumBits < 32, std::uint32_t, std::uint64_t>
{};
template <int NumBits>
struct max_value_fn : public mpl::if_c< ( NumBits <= 32 )
, uint32_t
, uint64_t
> {};
}
template <int NumBits>
struct max_value_fn
: std::conditional<NumBits <= 32, std::uint32_t, std::uint64_t>
{};
} // namespace detail
/// \defgroup PackedChannelValueModel packed_channel_value
/// \ingroup ChannelModel
@@ -264,14 +296,14 @@ namespace detail {
/// assert(channel_traits<bits4>::min_value()==0);
/// assert(channel_traits<bits4>::max_value()==15);
/// assert(sizeof(bits4)==1);
/// static_assert(boost::is_integral<bits4>::value, "");
/// static_assert(gil::is_channel_integral<bits4>::value, "");
/// \endcode
/// \ingroup PackedChannelValueModel
/// \brief The value of a subbyte channel. Models: ChannelValueConcept
template <int NumBits>
class packed_channel_value {
class packed_channel_value
{
public:
using integer_t = typename detail::min_fast_uint<NumBits>::type;
@@ -285,70 +317,116 @@ public:
static value_type min_value() { return 0; }
static value_type max_value() { return low_bits_mask_t< NumBits >::sig_bits; }
packed_channel_value() {}
packed_channel_value(integer_t v) { _value = static_cast< integer_t >( v & low_bits_mask_t<NumBits>::sig_bits_fast ); }
packed_channel_value() = default;
packed_channel_value(integer_t v)
{
value_ = static_cast<integer_t>(v & low_bits_mask_t<NumBits>::sig_bits_fast);
}
template <typename Scalar>
packed_channel_value(Scalar v) { _value = packed_channel_value( static_cast< integer_t >( v ) ); }
packed_channel_value(Scalar v)
{
value_ = packed_channel_value(static_cast<integer_t>(v));
}
static unsigned int num_bits() { return NumBits; }
static auto num_bits() -> unsigned int { return NumBits; }
operator integer_t() const { return value_; }
operator integer_t() const { return _value; }
private:
integer_t _value;
integer_t value_{};
};
namespace detail {
template <std::size_t K>
struct static_copy_bytes {
void operator()(const unsigned char* from, unsigned char* to) const {
struct static_copy_bytes
{
void operator()(unsigned char const* from, unsigned char* to) const
{
*to = *from;
static_copy_bytes<K-1>()(++from,++to);
static_copy_bytes<K - 1>()(++from, ++to);
}
};
template <>
struct static_copy_bytes<0> {
void operator()(const unsigned char* , unsigned char*) const {}
struct static_copy_bytes<0>
{
void operator()(unsigned char const*, unsigned char*) const {}
};
template <typename Derived, typename BitField, int NumBits, bool Mutable>
class packed_channel_reference_base {
template <typename Derived, typename BitField, int NumBits, bool IsMutable>
class packed_channel_reference_base
{
protected:
using data_ptr_t = typename mpl::if_c<Mutable,void*,const void*>::type;
using data_ptr_t = typename std::conditional<IsMutable, void*, void const*>::type;
public:
data_ptr_t _data_ptr; // void* pointer to the first byte of the bit range
using value_type = packed_channel_value<NumBits>;
using reference = const Derived;
using pointer = value_type *;
using const_pointer = const value_type *;
using reference = Derived const;
using pointer = value_type*;
using const_pointer = value_type const*;
static constexpr int num_bits = NumBits;
static constexpr bool is_mutable = Mutable;
static constexpr bool is_mutable = IsMutable;
static value_type min_value() { return channel_traits<value_type>::min_value(); }
static value_type max_value() { return channel_traits<value_type>::max_value(); }
static auto min_value() -> value_type { return channel_traits<value_type>::min_value(); }
static auto max_value() -> value_type { return channel_traits<value_type>::max_value(); }
using bitfield_t = BitField;
using integer_t = typename value_type::integer_t;
packed_channel_reference_base(data_ptr_t data_ptr) : _data_ptr(data_ptr) {}
packed_channel_reference_base(const packed_channel_reference_base& ref) : _data_ptr(ref._data_ptr) {}
const Derived& operator=(integer_t v) const { set(v); return derived(); }
packed_channel_reference_base(packed_channel_reference_base const& ref) : _data_ptr(ref._data_ptr) {}
auto operator=(integer_t v) const -> Derived const& { set(v); return derived(); }
const Derived& operator++() const { set(get()+1); return derived(); }
const Derived& operator--() const { set(get()-1); return derived(); }
auto operator++() const -> Derived const& { set(get()+1); return derived(); }
auto operator--() const -> Derived const& { set(get()-1); return derived(); }
Derived operator++(int) const { Derived tmp=derived(); this->operator++(); return tmp; }
Derived operator--(int) const { Derived tmp=derived(); this->operator--(); return tmp; }
auto operator++(int) const -> Derived
{
Derived tmp=derived();
this->operator++(); return tmp;
}
auto operator--(int) const -> Derived
{
Derived tmp=derived();
this->operator--();
return tmp;
}
template <typename Scalar2> const Derived& operator+=(Scalar2 v) const { set( static_cast<integer_t>( get() + v )); return derived(); }
template <typename Scalar2> const Derived& operator-=(Scalar2 v) const { set( static_cast<integer_t>( get() - v )); return derived(); }
template <typename Scalar2> const Derived& operator*=(Scalar2 v) const { set( static_cast<integer_t>( get() * v )); return derived(); }
template <typename Scalar2> const Derived& operator/=(Scalar2 v) const { set( static_cast<integer_t>( get() / v )); return derived(); }
template <typename Scalar2>
auto operator+=(Scalar2 v) const -> Derived const&
{
set( static_cast<integer_t>( get() + v ));
return derived();
}
template <typename Scalar2>
auto operator-=(Scalar2 v) const -> Derived const&
{
set( static_cast<integer_t>( get() - v )); return derived();
}
template <typename Scalar2>
auto operator*=(Scalar2 v) const -> Derived const&
{
set( static_cast<integer_t>( get() * v ));
return derived();
}
template <typename Scalar2>
auto operator/=(Scalar2 v) const -> Derived const&
{
set( static_cast<integer_t>( get() / v ));
return derived();
}
operator integer_t() const { return get(); }
data_ptr_t operator &() const {return _data_ptr;}
auto operator&() const -> data_ptr_t {return _data_ptr;}
protected:
using num_value_t = typename detail::num_value_fn<NumBits>::type;
@@ -361,12 +439,15 @@ protected:
const bitfield_t& get_data() const { return *static_cast<const bitfield_t*>(_data_ptr); }
void set_data(const bitfield_t& val) const { *static_cast< bitfield_t*>(_data_ptr) = val; }
#else
bitfield_t get_data() const {
auto get_data() const -> bitfield_t
{
bitfield_t ret;
static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(_data_ptr),gil_reinterpret_cast<unsigned char*>(&ret));
return ret;
}
void set_data(const bitfield_t& val) const {
void set_data(bitfield_t const& val) const
{
static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(&val),gil_reinterpret_cast<unsigned char*>(_data_ptr));
}
#endif
@@ -375,8 +456,8 @@ private:
void set(integer_t value) const { // can this be done faster??
this->derived().set_unsafe(((value % num_values) + num_values) % num_values);
}
integer_t get() const { return derived().get(); }
const Derived& derived() const { return static_cast<const Derived&>(*this); }
auto get() const -> integer_t { return derived().get(); }
auto derived() const -> Derived const& { return static_cast<const Derived&>(*this); }
};
} // namespace detail
@@ -394,28 +475,43 @@ private:
/// assert(data == 6); // == 3<<1 == 6
/// \endcode
template <typename BitField, // A type that holds the bits of the pixel from which the channel is referenced. Typically an integral type, like std::uint16_t
int FirstBit, int NumBits,// Defines the sequence of bits in the data value that contain the channel
bool Mutable> // true if the reference is mutable
/// \tparam BitField A type that holds the bits of the pixel from which the channel is referenced. Typically an integral type, like std::uint16_t
/// \tparam Defines the sequence of bits in the data value that contain the channel
/// \tparam true if the reference is mutable
template <typename BitField, int FirstBit, int NumBits, bool IsMutable>
class packed_channel_reference;
template <typename BitField, // A type that holds the bits of the pixel from which the channel is referenced. Typically an integral type, like std::uint16_t
int NumBits, // Defines the sequence of bits in the data value that contain the channel
bool Mutable> // true if the reference is mutable
/// \tparam A type that holds the bits of the pixel from which the channel is referenced. Typically an integral type, like std::uint16_t
/// \tparam Defines the sequence of bits in the data value that contain the channel
/// \tparam true if the reference is mutable
template <typename BitField, int NumBits, bool IsMutable>
class packed_dynamic_channel_reference;
/// \ingroup PackedChannelReferenceModel
/// \brief A constant subbyte channel reference whose bit offset is fixed at compile time. Models ChannelConcept
template <typename BitField, int FirstBit, int NumBits>
class packed_channel_reference<BitField,FirstBit,NumBits,false>
: public detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false>
class packed_channel_reference<BitField, FirstBit, NumBits, false>
: public detail::packed_channel_reference_base
<
packed_channel_reference<BitField, FirstBit, NumBits, false>,
BitField,
NumBits,
false
>
{
using parent_t = detail::packed_channel_reference_base<packed_channel_reference<BitField,FirstBit,NumBits,false>,BitField,NumBits,false>;
friend class packed_channel_reference<BitField,FirstBit,NumBits,true>;
using parent_t = detail::packed_channel_reference_base
<
packed_channel_reference<BitField, FirstBit, NumBits, false>,
BitField,
NumBits,
false
>;
static const BitField channel_mask = static_cast< BitField >( parent_t::max_val ) << FirstBit;
friend class packed_channel_reference<BitField, FirstBit, NumBits, true>;
void operator=(const packed_channel_reference&);
static const BitField channel_mask = static_cast<BitField>(parent_t::max_val) << FirstBit;
void operator=(packed_channel_reference const&);
public:
using const_reference = packed_channel_reference<BitField,FirstBit,NumBits,false> const;
using mutable_reference = packed_channel_reference<BitField,FirstBit,NumBits,true> const;
@@ -425,9 +521,9 @@ public:
packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
packed_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr) {}
unsigned first_bit() const { return FirstBit; }
auto first_bit() const -> unsigned int { return FirstBit; }
integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
auto get() const -> integer_t { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
};
/// \ingroup PackedChannelReferenceModel
@@ -456,21 +552,22 @@ public:
return *this;
}
const packed_channel_reference& operator=(const mutable_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
const packed_channel_reference& operator=(const const_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
auto operator=(mutable_reference const& ref) const -> packed_channel_reference const& { set_from_reference(ref.get_data()); return *this; }
auto operator=(const_reference const& ref) const -> packed_channel_reference const& { set_from_reference(ref.get_data()); return *this; }
template <bool Mutable1>
const packed_channel_reference& operator=(const packed_dynamic_channel_reference<BitField,NumBits,Mutable1>& ref) const { set_unsafe(ref.get()); return *this; }
auto operator=(packed_dynamic_channel_reference<BitField,NumBits,Mutable1> const& ref) const -> packed_channel_reference const& { set_unsafe(ref.get()); return *this; }
unsigned first_bit() const { return FirstBit; }
auto first_bit() const -> unsigned int { return FirstBit; }
integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
auto get() const -> integer_t { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
void set_unsafe(integer_t value) const { this->set_data((this->get_data() & ~channel_mask) | (( static_cast< BitField >( value )<<FirstBit))); }
private:
void set_from_reference(const BitField& other_bits) const { this->set_data((this->get_data() & ~channel_mask) | (other_bits & channel_mask)); }
};
} } // namespace boost::gil
}} // namespace boost::gil
namespace std {
// We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified.
@@ -481,25 +578,44 @@ namespace std {
/// \ingroup PackedChannelReferenceModel
/// \brief swap for packed_channel_reference
template <typename BF, int FB, int NB, bool M, typename R> inline
void swap(const boost::gil::packed_channel_reference<BF,FB,NB,M> x, R& y) {
boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
template <typename BF, int FB, int NB, bool M, typename R>
inline
void swap(boost::gil::packed_channel_reference<BF, FB, NB, M> const x, R& y)
{
boost::gil::swap_proxy
<
typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type
>(x, y);
}
/// \ingroup PackedChannelReferenceModel
/// \brief swap for packed_channel_reference
template <typename BF, int FB, int NB, bool M> inline
void swap(typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type& x, const boost::gil::packed_channel_reference<BF,FB,NB,M> y) {
boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
template <typename BF, int FB, int NB, bool M>
inline
void swap(
typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type& x,
boost::gil::packed_channel_reference<BF, FB, NB, M> const y)
{
boost::gil::swap_proxy
<
typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type
>(x,y);
}
/// \ingroup PackedChannelReferenceModel
/// \brief swap for packed_channel_reference
template <typename BF, int FB, int NB, bool M> inline
void swap(const boost::gil::packed_channel_reference<BF,FB,NB,M> x, const boost::gil::packed_channel_reference<BF,FB,NB,M> y) {
boost::gil::swap_proxy<typename boost::gil::packed_channel_reference<BF,FB,NB,M>::value_type>(x,y);
void swap(
boost::gil::packed_channel_reference<BF, FB, NB, M> const x,
boost::gil::packed_channel_reference<BF, FB, NB, M> const y)
{
boost::gil::swap_proxy
<
typename boost::gil::packed_channel_reference<BF, FB, NB, M>::value_type
>(x,y);
}
} // namespace std
namespace boost { namespace gil {
@@ -537,13 +653,14 @@ public:
using mutable_reference = packed_dynamic_channel_reference<BitField,NumBits,true> const;
using integer_t = typename parent_t::integer_t;
packed_dynamic_channel_reference(const void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
packed_dynamic_channel_reference(const const_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
packed_dynamic_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
packed_dynamic_channel_reference(void const* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
packed_dynamic_channel_reference(const_reference const& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
packed_dynamic_channel_reference(mutable_reference const& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
unsigned first_bit() const { return _first_bit; }
auto first_bit() const -> unsigned int { return _first_bit; }
integer_t get() const {
auto get() const -> integer_t
{
const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) <<_first_bit;
return static_cast< integer_t >(( this->get_data()&channel_mask ) >> _first_bit );
}
@@ -567,26 +684,30 @@ public:
using integer_t = typename parent_t::integer_t;
packed_dynamic_channel_reference(void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {}
packed_dynamic_channel_reference(const packed_dynamic_channel_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
packed_dynamic_channel_reference(packed_dynamic_channel_reference const& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {}
packed_dynamic_channel_reference const& operator=(integer_t value) const
auto operator=(integer_t value) const -> packed_dynamic_channel_reference const&
{
BOOST_ASSERT(value <= parent_t::max_val);
set_unsafe(value);
return *this;
}
const packed_dynamic_channel_reference& operator=(const mutable_reference& ref) const { set_unsafe(ref.get()); return *this; }
const packed_dynamic_channel_reference& operator=(const const_reference& ref) const { set_unsafe(ref.get()); return *this; }
auto operator=(mutable_reference const& ref) const -> packed_dynamic_channel_reference const& { set_unsafe(ref.get()); return *this; }
auto operator=(const_reference const& ref) const -> packed_dynamic_channel_reference const& { set_unsafe(ref.get()); return *this; }
template <typename BitField1, int FirstBit1, bool Mutable1>
const packed_dynamic_channel_reference& operator=(const packed_channel_reference<BitField1, FirstBit1, NumBits, Mutable1>& ref) const
{ set_unsafe(ref.get()); return *this; }
auto operator=(packed_channel_reference<BitField1, FirstBit1, NumBits, Mutable1> const& ref) const -> packed_dynamic_channel_reference const&
{
set_unsafe(ref.get());
return *this;
}
unsigned first_bit() const { return _first_bit; }
auto first_bit() const -> unsigned int { return _first_bit; }
integer_t get() const {
const BitField channel_mask = static_cast< integer_t >( parent_t::max_val ) << _first_bit;
auto get() const -> integer_t
{
BitField const channel_mask = static_cast< integer_t >( parent_t::max_val ) << _first_bit;
return static_cast< integer_t >(( this->get_data()&channel_mask ) >> _first_bit );
}
@@ -628,22 +749,6 @@ void swap(const boost::gil::packed_dynamic_channel_reference<BF,NB,M> x, const b
}
} // namespace std
namespace boost {
template <int NumBits>
struct is_integral<gil::packed_channel_value<NumBits> > : public mpl::true_ {};
template <typename BitField, int FirstBit, int NumBits, bool IsMutable>
struct is_integral<gil::packed_channel_reference<BitField,FirstBit,NumBits,IsMutable> > : public mpl::true_ {};
template <typename BitField, int NumBits, bool IsMutable>
struct is_integral<gil::packed_dynamic_channel_reference<BitField,NumBits,IsMutable> > : public mpl::true_ {};
template <typename BaseChannelValue, typename MinVal, typename MaxVal>
struct is_integral<gil::scoped_channel_value<BaseChannelValue,MinVal,MaxVal> > : public is_integral<BaseChannelValue> {};
} // namespace boost
// \brief Determines the fundamental type which may be used, e.g., to cast from larger to smaller channel types.
namespace boost { namespace gil {
template <typename T>
@@ -670,7 +775,7 @@ struct base_channel_type_impl<scoped_channel_value<ChannelValue, MinV, MaxV> >
{ using type = ChannelValue; };
template <typename T>
struct base_channel_type : base_channel_type_impl<typename remove_cv<T>::type > {};
struct base_channel_type : base_channel_type_impl<typename std::remove_cv<T>::type> {};
}} //namespace boost::gil

View File

@@ -11,56 +11,81 @@
#include <boost/gil/channel.hpp>
#include <boost/gil/promote_integral.hpp>
#include <boost/gil/typedefs.hpp>
#include <boost/mpl/less.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/greater.hpp>
#include <boost/type_traits.hpp>
#include <boost/gil/detail/is_channel_integral.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <limits>
#include <type_traits>
namespace boost { namespace gil {
namespace detail {
// some forward declarations
template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral> struct channel_converter_unsigned_impl;
template <typename SrcChannelV, typename DstChannelV, bool SrcIsGreater> struct channel_converter_unsigned_integral;
template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool SrcDivisible> struct channel_converter_unsigned_integral_impl;
template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool CannotFitInInteger> struct channel_converter_unsigned_integral_nondivisible;
template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral>
struct channel_converter_unsigned_impl;
template <typename SrcChannelV, typename DstChannelV, bool SrcIsGreater>
struct channel_converter_unsigned_integral;
template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool SrcDivisible>
struct channel_converter_unsigned_integral_impl;
template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool CannotFitInInteger>
struct channel_converter_unsigned_integral_nondivisible;
//////////////////////////////////////
//// unsigned_integral_max_value - given an unsigned integral channel type, returns its maximum value as an MPL integral constant
//////////////////////////////////////
template <typename UnsignedIntegralChannel>
struct unsigned_integral_max_value : public mpl::integral_c<UnsignedIntegralChannel,std::numeric_limits<UnsignedIntegralChannel>::max()> {};
template <>
struct unsigned_integral_max_value<uint8_t> : public mpl::integral_c<uint32_t,0xFF> {};
template <>
struct unsigned_integral_max_value<uint16_t> : public mpl::integral_c<uint32_t,0xFFFF> {};
template <>
struct unsigned_integral_max_value<uint32_t> : public mpl::integral_c<uintmax_t,0xFFFFFFFF> {};
template <int K>
struct unsigned_integral_max_value<packed_channel_value<K> >
: public mpl::integral_c<typename packed_channel_value<K>::integer_t, (uint64_t(1)<<K)-1> {};
//////////////////////////////////////
//// unsigned_integral_num_bits - given an unsigned integral channel type, returns the minimum number of bits needed to represent it
//// unsigned_integral_max_value - given an unsigned integral channel type,
//// returns its maximum value as an integral constant
//////////////////////////////////////
template <typename UnsignedIntegralChannel>
struct unsigned_integral_num_bits : public mpl::int_<sizeof(UnsignedIntegralChannel)*8> {};
struct unsigned_integral_max_value
: std::integral_constant
<
UnsignedIntegralChannel,
(std::numeric_limits<UnsignedIntegralChannel>::max)()
>
{};
template <>
struct unsigned_integral_max_value<uint8_t>
: std::integral_constant<uint32_t, 0xFF>
{};
template <>
struct unsigned_integral_max_value<uint16_t>
: std::integral_constant<uint32_t, 0xFFFF>
{};
template <>
struct unsigned_integral_max_value<uint32_t>
: std::integral_constant<uintmax_t, 0xFFFFFFFF>
{};
template <int K>
struct unsigned_integral_num_bits<packed_channel_value<K> >
: public mpl::int_<K> {};
struct unsigned_integral_max_value<packed_channel_value<K>>
: std::integral_constant
<
typename packed_channel_value<K>::integer_t,
(uint64_t(1)<<K)-1
>
{};
//////////////////////////////////////
//// unsigned_integral_num_bits - given an unsigned integral channel type,
//// returns the minimum number of bits needed to represent it
//////////////////////////////////////
template <typename UnsignedIntegralChannel>
struct unsigned_integral_num_bits
: std::integral_constant<int, static_cast<int>(sizeof(UnsignedIntegralChannel) * 8)>
{};
template <int K>
struct unsigned_integral_num_bits<packed_channel_value<K>>
: std::integral_constant<int, K>
{};
} // namespace detail
@@ -88,13 +113,11 @@ struct unsigned_integral_num_bits<packed_channel_value<K> >
/// assert(dst_channel == 255); // max value goes to max value
/// \endcode
/**
\defgroup ChannelConvertUnsignedAlgorithm channel_converter_unsigned
\ingroup ChannelConvertAlgorithm
\brief Convert one unsigned/floating point channel to another. Converts both the channel type and range
@{
*/
///
/// \defgroup ChannelConvertUnsignedAlgorithm channel_converter_unsigned
/// \ingroup ChannelConvertAlgorithm
/// \brief Convert one unsigned/floating point channel to another. Converts both the channel type and range
/// @{
//////////////////////////////////////
//// channel_converter_unsigned
@@ -102,13 +125,18 @@ struct unsigned_integral_num_bits<packed_channel_value<K> >
template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConcept
struct channel_converter_unsigned
: public detail::channel_converter_unsigned_impl<SrcChannelV,DstChannelV,is_integral<SrcChannelV>::value,is_integral<DstChannelV>::value> {};
: detail::channel_converter_unsigned_impl
<
SrcChannelV,
DstChannelV,
detail::is_channel_integral<SrcChannelV>::value,
detail::is_channel_integral<DstChannelV>::value
>
{};
/// \brief Converting a channel to itself - identity operation
template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {};
namespace detail {
//////////////////////////////////////
@@ -120,23 +148,34 @@ template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool D
struct channel_converter_unsigned_impl {
using argument_type = SrcChannelV;
using result_type = DstChannelV;
DstChannelV operator()(SrcChannelV src) const {
auto operator()(SrcChannelV src) const -> DstChannelV
{
return DstChannelV(channel_traits<DstChannelV>::min_value() +
(src - channel_traits<SrcChannelV>::min_value()) / channel_range<SrcChannelV>() * channel_range<DstChannelV>());
}
private:
template <typename C>
static double channel_range() {
static auto channel_range() -> double
{
return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value());
}
};
// When both the source and the destination are integral channels, perform a faster conversion
template <typename SrcChannelV, typename DstChannelV>
struct channel_converter_unsigned_impl<SrcChannelV,DstChannelV,true,true>
: public channel_converter_unsigned_integral<SrcChannelV,DstChannelV,
mpl::less<unsigned_integral_max_value<SrcChannelV>,unsigned_integral_max_value<DstChannelV> >::value > {};
struct channel_converter_unsigned_impl<SrcChannelV, DstChannelV, true, true>
: channel_converter_unsigned_integral
<
SrcChannelV,
DstChannelV,
mp11::mp_less
<
unsigned_integral_max_value<SrcChannelV>,
unsigned_integral_max_value<DstChannelV>
>::value
>
{};
//////////////////////////////////////
//// channel_converter_unsigned_integral
@@ -162,7 +201,8 @@ struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,false>
// and the dst max value is divisible by the src max value
template <typename SrcChannelV, typename DstChannelV>
struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,true> {
DstChannelV operator()(SrcChannelV src) const {
auto operator()(SrcChannelV src) const -> DstChannelV
{
using integer_t = typename unsigned_integral_max_value<DstChannelV>::value_type;
static const integer_t mul = unsigned_integral_max_value<DstChannelV>::value / unsigned_integral_max_value<SrcChannelV>::value;
return DstChannelV(src * mul);
@@ -174,7 +214,8 @@ struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,tru
// and the src max value is divisible by the dst max value
template <typename SrcChannelV, typename DstChannelV>
struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,true> {
DstChannelV operator()(SrcChannelV src) const {
auto operator()(SrcChannelV src) const -> DstChannelV
{
using integer_t = typename unsigned_integral_max_value<SrcChannelV>::value_type;
static const integer_t div = unsigned_integral_max_value<SrcChannelV>::value / unsigned_integral_max_value<DstChannelV>::value;
static const integer_t div2 = div/2;
@@ -185,7 +226,8 @@ struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,tr
// Prevent overflow for the largest integral type
template <typename DstChannelV>
struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true> {
DstChannelV operator()(uintmax_t src) const {
auto operator()(uintmax_t src) const -> DstChannelV
{
static const uintmax_t div = unsigned_integral_max_value<uint32_t>::value / unsigned_integral_max_value<DstChannelV>::value;
static const uintmax_t div2 = div/2;
if (src > unsigned_integral_max_value<uintmax_t>::value - div2)
@@ -198,23 +240,37 @@ struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true
// and the dst max value is not divisible by the src max value
// See if you can represent the expression (src * dst_max) / src_max in integral form
template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst>
struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,SrcLessThanDst,false>
: public channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,SrcLessThanDst,
mpl::greater<
mpl::plus<unsigned_integral_num_bits<SrcChannelV>,unsigned_integral_num_bits<DstChannelV> >,
unsigned_integral_num_bits<uintmax_t>
>::value> {};
struct channel_converter_unsigned_integral_impl<SrcChannelV, DstChannelV, SrcLessThanDst, false>
: channel_converter_unsigned_integral_nondivisible
<
SrcChannelV,
DstChannelV,
SrcLessThanDst,
mp11::mp_less
<
unsigned_integral_num_bits<uintmax_t>,
mp11::mp_plus
<
unsigned_integral_num_bits<SrcChannelV>,
unsigned_integral_num_bits<DstChannelV>
>
>::value
>
{};
// Both source and destination are unsigned integral channels,
// the src max value is less than the dst max value,
// and the dst max value is not divisible by the src max value
// The expression (src * dst_max) / src_max fits in an integer
template <typename SrcChannelV, typename DstChannelV>
struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,false> {
DstChannelV operator()(SrcChannelV src) const {
struct channel_converter_unsigned_integral_nondivisible<SrcChannelV, DstChannelV, true, false>
{
auto operator()(SrcChannelV src) const -> DstChannelV
{
using dest_t = typename base_channel_type<DstChannelV>::type;
return DstChannelV(static_cast<dest_t>( src * unsigned_integral_max_value<DstChannelV>::value) / unsigned_integral_max_value<SrcChannelV>::value);
return DstChannelV(
static_cast<dest_t>(src * unsigned_integral_max_value<DstChannelV>::value)
/ unsigned_integral_max_value<SrcChannelV>::value);
}
};
@@ -223,9 +279,13 @@ struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,
// and the dst max value is not divisible by the src max value
// The expression (src * dst_max) / src_max cannot fit in an integer (overflows). Use a double
template <typename SrcChannelV, typename DstChannelV>
struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,true> {
DstChannelV operator()(SrcChannelV src) const {
static const double mul = unsigned_integral_max_value<DstChannelV>::value / double(unsigned_integral_max_value<SrcChannelV>::value);
struct channel_converter_unsigned_integral_nondivisible<SrcChannelV, DstChannelV, true, true>
{
auto operator()(SrcChannelV src) const -> DstChannelV
{
static const double mul
= unsigned_integral_max_value<DstChannelV>::value
/ double(unsigned_integral_max_value<SrcChannelV>::value);
return DstChannelV(src * mul);
}
};
@@ -234,9 +294,10 @@ struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,
// the dst max value is less than (or equal to) the src max value,
// and the src max value is not divisible by the dst max value
template <typename SrcChannelV, typename DstChannelV, bool CannotFit>
struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> {
DstChannelV operator()(SrcChannelV src) const {
struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit>
{
auto operator()(SrcChannelV src) const -> DstChannelV
{
using src_integer_t = typename detail::unsigned_integral_max_value<SrcChannelV>::value_type;
using dst_integer_t = typename detail::unsigned_integral_max_value<DstChannelV>::value_type;
@@ -258,7 +319,7 @@ struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,
template <typename DstChannelV> struct channel_converter_unsigned<float32_t,DstChannelV> {
using argument_type = float32_t;
using result_type = DstChannelV;
DstChannelV operator()(float32_t x) const
auto operator()(float32_t x) const -> DstChannelV
{
using dst_integer_t = typename detail::unsigned_integral_max_value<DstChannelV>::value_type;
return DstChannelV( static_cast< dst_integer_t >(x*channel_traits<DstChannelV>::max_value()+0.5f ));
@@ -268,13 +329,13 @@ template <typename DstChannelV> struct channel_converter_unsigned<float32_t,DstC
template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,float32_t> {
using argument_type = float32_t;
using result_type = SrcChannelV;
float32_t operator()(SrcChannelV x) const { return float32_t(x/float(channel_traits<SrcChannelV>::max_value())); }
auto operator()(SrcChannelV x) const -> float32_t { return float32_t(x/float(channel_traits<SrcChannelV>::max_value())); }
};
template <> struct channel_converter_unsigned<float32_t,float32_t> {
using argument_type = float32_t;
using result_type = float32_t;
float32_t operator()(float32_t x) const { return x; }
auto operator()(float32_t x) const -> float32_t { return x; }
};
@@ -282,7 +343,8 @@ template <> struct channel_converter_unsigned<float32_t,float32_t> {
template <> struct channel_converter_unsigned<uint32_t,float32_t> {
using argument_type = uint32_t;
using result_type = float32_t;
float32_t operator()(uint32_t x) const {
auto operator()(uint32_t x) const -> float32_t
{
// unfortunately without an explicit check it is possible to get a round-off error. We must ensure that max_value of uint32_t matches max_value of float32_t
if (x>=channel_traits<uint32_t>::max_value()) return channel_traits<float32_t>::max_value();
return float(x) / float(channel_traits<uint32_t>::max_value());
@@ -292,7 +354,8 @@ template <> struct channel_converter_unsigned<uint32_t,float32_t> {
template <> struct channel_converter_unsigned<float32_t,uint32_t> {
using argument_type = float32_t;
using result_type = uint32_t;
uint32_t operator()(float32_t x) const {
auto operator()(float32_t x) const -> uint32_t
{
// unfortunately without an explicit check it is possible to get a round-off error. We must ensure that max_value of uint32_t matches max_value of float32_t
if (x>=channel_traits<float32_t>::max_value())
return channel_traits<uint32_t>::max_value();
@@ -352,7 +415,7 @@ template <> struct channel_convert_from_unsigned<int8_t> {
using argument_type = uint8_t;
using result_type = int8_t;
using type = int8_t;
type operator()(uint8_t val) const {
type operator()(uint8_t val) const {
return static_cast<int8_t>(static_cast<int32_t>(val) - 128);
}
};
@@ -383,7 +446,8 @@ template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConce
struct channel_converter {
using argument_type = SrcChannelV;
using result_type = DstChannelV;
DstChannelV operator()(const SrcChannelV& src) const {
auto operator()(SrcChannelV const& src) const -> DstChannelV
{
using to_unsigned = detail::channel_convert_to_unsigned<SrcChannelV>;
using from_unsigned = detail::channel_convert_from_unsigned<DstChannelV>;
using converter_unsigned = channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type>;
@@ -394,7 +458,8 @@ struct channel_converter {
/// \ingroup ChannelConvertAlgorithm
/// \brief Converting from one channel type to another.
template <typename DstChannel, typename SrcChannel> // Model ChannelConcept (could be channel references)
inline typename channel_traits<DstChannel>::value_type channel_convert(const SrcChannel& src) {
inline auto channel_convert(SrcChannel const& src) -> typename channel_traits<DstChannel>::value_type
{
return channel_converter<typename channel_traits<SrcChannel>::value_type,
typename channel_traits<DstChannel>::value_type>()(src);
}
@@ -405,17 +470,26 @@ inline typename channel_traits<DstChannel>::value_type channel_convert(const Src
/// on heterogeneous pixels.
struct default_channel_converter {
template <typename Ch1, typename Ch2>
void operator()(const Ch1& src, Ch2& dst) const {
void operator()(Ch1 const& src, Ch2& dst) const
{
dst=channel_convert<Ch2>(src);
}
};
namespace detail {
namespace detail
{
// fast integer division by 255
inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128; return (tmp + (tmp>>8))>>8; }
inline auto div255(uint32_t in) -> uint32_t
{
uint32_t tmp = in + 128;
return (tmp + (tmp >> 8)) >> 8;
}
// fast integer divison by 32768
inline uint32_t div32768(uint32_t in) { return (in+16384)>>15; }
inline auto div32768(uint32_t in) -> uint32_t
{
return (in + 16384) >> 15;
}
}
/// \defgroup ChannelMultiplyAlgorithm channel_multiply
@@ -437,7 +511,8 @@ struct channel_multiplier_unsigned {
using first_argument_type = ChannelValue;
using second_argument_type = ChannelValue;
using result_type = ChannelValue;
ChannelValue operator()(ChannelValue a, ChannelValue b) const {
auto operator()(ChannelValue a, ChannelValue b) const -> ChannelValue
{
return ChannelValue(static_cast<typename base_channel_type<ChannelValue>::type>(a / double(channel_traits<ChannelValue>::max_value()) * b));
}
};
@@ -447,7 +522,7 @@ template<> struct channel_multiplier_unsigned<uint8_t> {
using first_argument_type = uint8_t;
using second_argument_type = uint8_t;
using result_type = uint8_t;
uint8_t operator()(uint8_t a, uint8_t b) const { return uint8_t(detail::div255(uint32_t(a) * uint32_t(b))); }
auto operator()(uint8_t a, uint8_t b) const -> uint8_t { return uint8_t(detail::div255(uint32_t(a) * uint32_t(b))); }
};
/// \brief Specialization of channel_multiply for 16-bit unsigned channels
@@ -455,7 +530,7 @@ template<> struct channel_multiplier_unsigned<uint16_t> {
using first_argument_type = uint16_t;
using second_argument_type = uint16_t;
using result_type = uint16_t;
uint16_t operator()(uint16_t a, uint16_t b) const { return uint16_t((uint32_t(a) * uint32_t(b))/65535); }
auto operator()(uint16_t a, uint16_t b) const -> uint16_t { return uint16_t((uint32_t(a) * uint32_t(b))/65535); }
};
/// \brief Specialization of channel_multiply for float 0..1 channels
@@ -463,7 +538,7 @@ template<> struct channel_multiplier_unsigned<float32_t> {
using first_argument_type = float32_t;
using second_argument_type = float32_t;
using result_type = float32_t;
float32_t operator()(float32_t a, float32_t b) const { return a*b; }
auto operator()(float32_t a, float32_t b) const -> float32_t { return a*b; }
};
/// \brief A function object to multiply two channels. result = a * b / max_value
@@ -472,7 +547,8 @@ struct channel_multiplier {
using first_argument_type = ChannelValue;
using second_argument_type = ChannelValue;
using result_type = ChannelValue;
ChannelValue operator()(ChannelValue a, ChannelValue b) const {
auto operator()(ChannelValue a, ChannelValue b) const -> ChannelValue
{
using to_unsigned = detail::channel_convert_to_unsigned<ChannelValue>;
using from_unsigned = detail::channel_convert_from_unsigned<ChannelValue>;
using multiplier_unsigned = channel_multiplier_unsigned<typename to_unsigned::result_type>;
@@ -482,7 +558,8 @@ struct channel_multiplier {
/// \brief A function multiplying two channels. result = a * b / max_value
template <typename Channel> // Models ChannelConcept (could be a channel reference)
inline typename channel_traits<Channel>::value_type channel_multiply(Channel a, Channel b) {
inline auto channel_multiply(Channel a, Channel b) -> typename channel_traits<Channel>::value_type
{
return channel_multiplier<typename channel_traits<Channel>::value_type>()(a,b);
}
/// @}
@@ -502,8 +579,8 @@ inline typename channel_traits<Channel>::value_type channel_multiply(Channel a,
/// \brief Default implementation. Provide overloads for performance
/// \ingroup ChannelInvertAlgorithm channel_invert
template <typename Channel> // Models ChannelConcept (could be a channel reference)
inline typename channel_traits<Channel>::value_type channel_invert(Channel x) {
inline auto channel_invert(Channel x) -> typename channel_traits<Channel>::value_type
{
using base_t = typename base_channel_type<Channel>::type;
using promoted_t = typename promote_integral<base_t>::type;
promoted_t const promoted_x = x;
@@ -514,6 +591,6 @@ inline typename channel_traits<Channel>::value_type channel_invert(Channel x) {
return inverted_x;
}
} } // namespace boost::gil
}} // namespace boost::gil
#endif

View File

@@ -0,0 +1,253 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_CHANNEL_NUMERIC_OPERATIONS_HPP
#define BOOST_GIL_CHANNEL_NUMERIC_OPERATIONS_HPP
#include <boost/gil/channel.hpp>
namespace boost { namespace gil {
// Function objects and utilities for channel-wise numeric operations.
//
// List of currently defined functors:
// channel_plus_t (+)
// channel_minus_t (-)
// channel_multiplies_t (*)
// channel_divides_t (/),
// channel_plus_scalar_t (+s)
// channel_minus_scalar_t (-s),
// channel_multiplies_scalar_t (*s)
// channel_divides_scalar_t (/s),
// channel_halves_t (/=2)
// channel_zeros_t (=0)
// channel_assigns_t (=)
/// \ingroup ChannelNumericOperations
/// \brief Arithmetic operation of addition of two channel values.
/// \note This is a generic implementation; user should specialize it for better performance.
template <typename Channel1, typename Channel2, typename ChannelResult>
struct channel_plus_t
{
using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
"ChannelRef1 not convertible to ChannelResult");
static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
"ChannelRef2 not convertible to ChannelResult");
/// \param ch1 - first of the two addends (augend).
/// \param ch2 - second of the two addends.
auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
{
return ChannelResult(ch1) + ChannelResult(ch2);
}
};
/// \ingroup ChannelNumericOperations
/// \brief Arithmetic operation of subtraction of two channel values.
/// \note This is a generic implementation; user should specialize it for better performance.
template <typename Channel1, typename Channel2, typename ChannelResult>
struct channel_minus_t
{
using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
"ChannelRef1 not convertible to ChannelResult");
static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
"ChannelRef2 not convertible to ChannelResult");
/// \param ch1 - minuend operand of the subtraction.
/// \param ch2 - subtrahend operand of the subtraction.
auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
{
return ChannelResult(ch1) - ChannelResult(ch2);
}
};
/// \ingroup ChannelNumericOperations
/// \brief Arithmetic operation of multiplication of two channel values.
/// \note This is a generic implementation; user should specialize it for better performance.
template <typename Channel1, typename Channel2, typename ChannelResult>
struct channel_multiplies_t
{
using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
"ChannelRef1 not convertible to ChannelResult");
static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
"ChannelRef2 not convertible to ChannelResult");
/// \param ch1 - first of the two factors (multiplicand).
/// \param ch2 - second of the two factors (multiplier).
auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
{
return ChannelResult(ch1) * ChannelResult(ch2);
}
};
/// \ingroup ChannelNumericOperations
/// \brief Arithmetic operation of division of two channel values.
/// \note This is a generic implementation; user should specialize it for better performance.
template <typename Channel1, typename Channel2, typename ChannelResult>
struct channel_divides_t
{
using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
using ChannelRef2 = typename channel_traits<Channel2>::const_reference;
static_assert(std::is_convertible<ChannelRef1, ChannelResult>::value,
"ChannelRef1 not convertible to ChannelResult");
static_assert(std::is_convertible<ChannelRef2, ChannelResult>::value,
"ChannelRef2 not convertible to ChannelResult");
/// \param ch1 - dividend operand of the two division operation.
/// \param ch2 - divisor operand of the two division operation.
auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelResult
{
return ChannelResult(ch1) / ChannelResult(ch2);
}
};
/// \ingroup ChannelNumericOperations
/// \brief Arithmetic operation of adding scalar to channel value.
/// \note This is a generic implementation; user should specialize it for better performance.
template <typename Channel, typename Scalar, typename ChannelResult>
struct channel_plus_scalar_t
{
using ChannelRef = typename channel_traits<Channel>::const_reference;
static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
"ChannelRef not convertible to ChannelResult");
static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
static_assert(std::is_convertible<Scalar, ChannelResult>::value,
"Scalar not convertible to ChannelResult");
auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
{
return ChannelResult(channel) + ChannelResult(scalar);
}
};
/// \ingroup ChannelNumericOperations
/// \brief Arithmetic operation of subtracting scalar from channel value.
/// \note This is a generic implementation; user should specialize it for better performance.
template <typename Channel, typename Scalar, typename ChannelResult>
struct channel_minus_scalar_t
{
using ChannelRef = typename channel_traits<Channel>::const_reference;
static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
"ChannelRef not convertible to ChannelResult");
static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
static_assert(std::is_convertible<Scalar, ChannelResult>::value,
"Scalar not convertible to ChannelResult");
/// \param channel - minuend operand of the subtraction.
/// \param scalar - subtrahend operand of the subtraction.
auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
{
// TODO: Convertion after subtraction vs conversion of operands in channel_minus_t?
return ChannelResult(channel - scalar);
}
};
/// \ingroup ChannelNumericOperations
/// \brief Arithmetic operation of channel value by a scalar.
/// \note This is a generic implementation; user should specialize it for better performance.
template <typename Channel, typename Scalar, typename ChannelResult>
struct channel_multiplies_scalar_t
{
using ChannelRef = typename channel_traits<Channel>::const_reference;
static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
"ChannelRef not convertible to ChannelResult");
static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
static_assert(std::is_convertible<Scalar, ChannelResult>::value,
"Scalar not convertible to ChannelResult");
/// \param channel - first of the two factors (multiplicand).
/// \param scalar - second of the two factors (multiplier).
auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
{
return ChannelResult(channel) * ChannelResult(scalar);
}
};
/// \ingroup ChannelNumericOperations
/// \brief Arithmetic operation of dividing channel value by scalar.
/// \note This is a generic implementation; user should specialize it for better performance.
template <typename Channel, typename Scalar, typename ChannelResult>
struct channel_divides_scalar_t
{
using ChannelRef = typename channel_traits<Channel>::const_reference;
static_assert(std::is_convertible<ChannelRef, ChannelResult>::value,
"ChannelRef not convertible to ChannelResult");
static_assert(std::is_scalar<Scalar>::value, "Scalar not a scalar");
static_assert(std::is_convertible<Scalar, ChannelResult>::value,
"Scalar not convertible to ChannelResult");
/// \param channel - dividend operand of the two division operation.
/// \param scalar - divisor operand of the two division operation.
auto operator()(ChannelRef channel, Scalar const& scalar) const -> ChannelResult
{
return ChannelResult(channel) / ChannelResult(scalar);
}
};
/// \ingroup ChannelNumericOperations
/// \brief Arithmetic operation of dividing channel value by 2
/// \note This is a generic implementation; user should specialize it for better performance.
template <typename Channel>
struct channel_halves_t
{
using ChannelRef = typename channel_traits<Channel>::reference;
auto operator()(ChannelRef channel) const -> ChannelRef
{
// TODO: Split into steps: extract with explicit conversion to double, divide and assign?
//double const v = ch;
//ch = static_cast<Channel>(v / 2.0);
channel /= 2.0;
return channel;
}
};
/// \ingroup ChannelNumericOperations
/// \brief Operation of setting channel value to zero
/// \note This is a generic implementation; user should specialize it for better performance.
template <typename Channel>
struct channel_zeros_t
{
using ChannelRef = typename channel_traits<Channel>::reference;
auto operator()(ChannelRef channel) const -> ChannelRef
{
channel = Channel(0);
return channel;
}
};
/// \ingroup ChannelNumericOperations
/// structure for assigning one channel to another
/// \note This is a generic implementation; user should specialize it for better performance.
template <typename Channel1, typename Channel2>
struct channel_assigns_t
{
using ChannelRef1 = typename channel_traits<Channel1>::const_reference;
using ChannelRef2 = typename channel_traits<Channel2>::reference;
static_assert(std::is_convertible<ChannelRef1, Channel2>::value,
"ChannelRef1 not convertible to Channel2");
/// \param ch1 - assignor side (input) of the assignment operation
/// \param ch2 - assignee side (output) of the assignment operation
auto operator()(ChannelRef1 ch1, ChannelRef2 ch2) const -> ChannelRef2
{
ch2 = Channel2(ch1);
return ch2;
}
};
}} // namespace boost::gil
#endif

View File

@@ -9,9 +9,7 @@
#define BOOST_GIL_CMYK_HPP
#include <boost/gil/metafunctions.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <cstddef>
@@ -34,7 +32,7 @@ struct black_t {};
/// \}
/// \ingroup ColorSpaceModel
using cmyk_t = mpl::vector4<cyan_t,magenta_t,yellow_t,black_t>;
using cmyk_t = mp11::mp_list<cyan_t, magenta_t, yellow_t, black_t>;
/// \ingroup LayoutModel
using cmyk_layout_t = layout<cmyk_t>;
@@ -42,13 +40,13 @@ using cmyk_layout_t = layout<cmyk_t>;
/// \ingroup ImageViewConstructors
/// \brief from raw CMYK planar data
template <typename IC>
inline typename type_from_x_iterator<planar_pixel_iterator<IC,cmyk_t> >::view_t
planar_cmyk_view(std::size_t width, std::size_t height, IC c, IC m, IC y, IC k, std::ptrdiff_t rowsize_in_bytes)
inline auto planar_cmyk_view(std::size_t width, std::size_t height, IC c, IC m, IC y, IC k, std::ptrdiff_t rowsize_in_bytes)
-> typename type_from_x_iterator<planar_pixel_iterator<IC,cmyk_t>>::view_t
{
using view_t = typename type_from_x_iterator<planar_pixel_iterator<IC,cmyk_t> >::view_t;
return view_t(width, height, typename view_t::locator(planar_pixel_iterator<IC,cmyk_t>(c,m,y,k), rowsize_in_bytes));
}
} } // namespace gil
}} // namespace gil
#endif

View File

@@ -1,5 +1,6 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
@@ -10,13 +11,12 @@
#include <boost/gil/utilities.hpp>
#include <boost/gil/concepts.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/type_traits.hpp>
#include <type_traits>
namespace boost { namespace gil {
@@ -34,7 +34,7 @@ auto semantic_at_c(ColorBase& p)
template <int K, typename ColorBase>
typename kth_semantic_element_const_reference_type<ColorBase,K>::type semantic_at_c(const ColorBase& p);
auto semantic_at_c(const ColorBase& p) -> typename kth_semantic_element_const_reference_type<ColorBase,K>::type;
// Forward declare element_reference_type
template <typename ColorBase> struct element_reference_type;
@@ -49,14 +49,21 @@ template <typename ColorBase, int K> struct kth_element_const_reference_type<con
namespace detail {
template <typename DstLayout, typename SrcLayout, int K>
struct mapping_transform
: public mpl::at<typename SrcLayout::channel_mapping_t,
typename detail::type_to_index<typename DstLayout::channel_mapping_t,mpl::integral_c<int,K> >::type
>::type {};
struct mapping_transform : mp11::mp_at
<
typename SrcLayout::channel_mapping_t,
typename detail::type_to_index
<
typename DstLayout::channel_mapping_t,
std::integral_constant<int, K>
>
>::type
{};
/// \defgroup ColorBaseModelHomogeneous detail::homogeneous_color_base
/// \ingroup ColorBaseModel
/// \brief A homogeneous color base holding one color element. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
/// \brief A homogeneous color base holding one color element.
/// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
/// If the element type models Regular, this class models HomogeneousColorBaseValueConcept.
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
@@ -64,263 +71,480 @@ struct mapping_transform
#pragma warning(disable:4512) //assignment operator could not be generated
#endif
/// \brief A homogeneous color base holding one color element. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
/// \brief A homogeneous color base holding one color element.
/// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
/// \ingroup ColorBaseModelHomogeneous
template <typename Element, typename Layout>
struct homogeneous_color_base<Element,Layout,1> {
private:
Element _v0;
public:
struct homogeneous_color_base<Element, Layout, 1>
{
using layout_t = Layout;
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
homogeneous_color_base() {}
homogeneous_color_base(Element v) : _v0(v) {}
template
<
typename U = Element,
typename = typename std::enable_if<!std::is_reference<U>::value>::type
>
homogeneous_color_base() : v0_{} {}
explicit homogeneous_color_base(Element v) : v0_(v) {}
template <typename E2, typename L2>
homogeneous_color_base(homogeneous_color_base<E2, L2, 1> const& c)
: v0_(gil::at_c<0>(c))
{}
auto at(std::integral_constant<int, 0>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v0_; }
auto at(std::integral_constant<int, 0>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v0_; }
// grayscale pixel values are convertible to channel type
operator Element () const { return _v0; }
// FIXME: explicit?
operator Element() const { return v0_; }
template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,1>& c) : _v0(gil::at_c<0>(c)) {}
private:
Element v0_;
};
/// \brief A homogeneous color base holding two color elements. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
/// \brief A homogeneous color base holding two color elements
/// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
/// \ingroup ColorBaseModelHomogeneous
template <typename Element, typename Layout>
struct homogeneous_color_base<Element,Layout,2> {
private:
Element _v0, _v1;
public:
struct homogeneous_color_base<Element, Layout, 2>
{
using layout_t = Layout;
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) { return _v1; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
homogeneous_color_base() {}
explicit homogeneous_color_base(Element v) : _v0(v), _v1(v) {}
homogeneous_color_base(Element v0, Element v1) : _v0(v0), _v1(v1) {}
template
<
typename U = Element,
typename = typename std::enable_if<!std::is_reference<U>::value>::type
>
homogeneous_color_base() : v0_{}, v1_{} {}
template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,2>& c) :
_v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
_v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)) {}
explicit homogeneous_color_base(Element v) : v0_(v), v1_(v) {}
homogeneous_color_base(Element v0, Element v1) : v0_(v0), v1_(v1) {}
template <typename E2, typename L2>
homogeneous_color_base(homogeneous_color_base<E2, L2, 2> const& c)
: v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
, v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
{}
// Support for l-value reference proxy copy construction
template <typename E2, typename L2> homogeneous_color_base( homogeneous_color_base<E2,L2,2>& c) :
_v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
_v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)) {}
template <typename E2, typename L2>
homogeneous_color_base(homogeneous_color_base<E2, L2, 2>& c)
: v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
, v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
{}
// Support for planar_pixel_iterator construction and dereferencing
template <typename P> homogeneous_color_base(P* p,bool) :
_v0(&semantic_at_c<0>(*p)),
_v1(&semantic_at_c<1>(*p)) {}
template <typename Ref> Ref deref() const {
return Ref(*semantic_at_c<0>(*this),
*semantic_at_c<1>(*this)); }
template <typename P>
homogeneous_color_base(P* p, bool)
: v0_(&semantic_at_c<0>(*p))
, v1_(&semantic_at_c<1>(*p))
{}
// Support for planar_pixel_reference offset constructor
template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
: _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
_v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)) {}
template <typename Ptr>
homogeneous_color_base(Ptr const& ptr, std::ptrdiff_t diff)
: v0_(*memunit_advanced(semantic_at_c<0>(ptr), diff))
, v1_(*memunit_advanced(semantic_at_c<1>(ptr), diff))
{}
// Support for planar_pixel_reference operator[]
Element at_c_dynamic(std::size_t i) const {
if (i==0) return _v0;
return _v1;
template <typename Ref>
Ref deref() const
{
return Ref(*semantic_at_c<0>(*this), *semantic_at_c<1>(*this));
}
};
/// \brief A homogeneous color base holding three color elements. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
/// \ingroup ColorBaseModelHomogeneous
template <typename Element, typename Layout>
struct homogeneous_color_base<Element,Layout,3> {
private:
Element _v0, _v1, _v2;
public:
using layout_t = Layout;
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) { return _v1; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) { return _v2; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) const { return _v2; }
auto at(std::integral_constant<int, 0>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v0_; }
homogeneous_color_base() {}
explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v) {}
homogeneous_color_base(Element v0, Element v1, Element v2) : _v0(v0), _v1(v1), _v2(v2) {}
auto at(std::integral_constant<int, 0>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v0_; }
template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,3>& c) :
_v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
_v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
_v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)) {}
auto at(std::integral_constant<int, 1>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v1_; }
// Support for l-value reference proxy copy construction
template <typename E2, typename L2> homogeneous_color_base( homogeneous_color_base<E2,L2,3>& c) :
_v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
_v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
_v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)) {}
// Support for planar_pixel_iterator construction and dereferencing
template <typename P> homogeneous_color_base(P* p,bool) :
_v0(&semantic_at_c<0>(*p)),
_v1(&semantic_at_c<1>(*p)),
_v2(&semantic_at_c<2>(*p)) {}
template <typename Ref> Ref deref() const {
return Ref(*semantic_at_c<0>(*this),
*semantic_at_c<1>(*this),
*semantic_at_c<2>(*this)); }
// Support for planar_pixel_reference offset constructor
template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
: _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
_v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)),
_v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)) {}
auto at(std::integral_constant<int, 1>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v1_; }
// Support for planar_pixel_reference operator[]
Element at_c_dynamic(std::size_t i) const {
switch (i) {
case 0: return _v0;
case 1: return _v1;
auto at_c_dynamic(std::size_t i) const -> Element
{
if (i == 0)
return v0_;
else
return v1_;
}
private:
Element v0_;
Element v1_;
};
/// \brief A homogeneous color base holding three color elements.
/// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
/// \ingroup ColorBaseModelHomogeneous
template <typename Element, typename Layout>
struct homogeneous_color_base<Element, Layout, 3>
{
using layout_t = Layout;
template
<
typename U = Element,
typename = typename std::enable_if<!std::is_reference<U>::value>::type
>
homogeneous_color_base() : v0_{}, v1_{}, v2_{} {}
explicit homogeneous_color_base(Element v) : v0_(v), v1_(v), v2_(v) {}
homogeneous_color_base(Element v0, Element v1, Element v2)
: v0_(v0), v1_(v1), v2_(v2)
{}
template <typename E2, typename L2>
homogeneous_color_base(homogeneous_color_base<E2, L2, 3> const& c)
: v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
, v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
, v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c))
{}
// Support for l-value reference proxy copy construction
template <typename E2, typename L2>
homogeneous_color_base(homogeneous_color_base<E2, L2, 3>& c)
: v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
, v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
, v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c))
{}
// Support for planar_pixel_iterator construction and dereferencing
template <typename P>
homogeneous_color_base(P* p, bool)
: v0_(&semantic_at_c<0>(*p))
, v1_(&semantic_at_c<1>(*p))
, v2_(&semantic_at_c<2>(*p))
{}
// Support for planar_pixel_reference offset constructor
template <typename Ptr>
homogeneous_color_base(Ptr const& ptr, std::ptrdiff_t diff)
: v0_(*memunit_advanced(semantic_at_c<0>(ptr), diff))
, v1_(*memunit_advanced(semantic_at_c<1>(ptr), diff))
, v2_(*memunit_advanced(semantic_at_c<2>(ptr), diff))
{}
template <typename Ref>
Ref deref() const
{
return Ref(
*semantic_at_c<0>(*this),
*semantic_at_c<1>(*this),
*semantic_at_c<2>(*this));
}
auto at(std::integral_constant<int, 0>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v0_; }
auto at(std::integral_constant<int, 0>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v0_; }
auto at(std::integral_constant<int, 1>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v1_; }
auto at(std::integral_constant<int, 1>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v1_; }
auto at(std::integral_constant<int, 2>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v2_; }
auto at(std::integral_constant<int, 2>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v2_; }
// Support for planar_pixel_reference operator[]
auto at_c_dynamic(std::size_t i) const -> Element
{
switch (i)
{
case 0: return v0_;
case 1: return v1_;
}
return _v2;
return v2_;
}
private:
Element v0_;
Element v1_;
Element v2_;
};
/// \brief A homogeneous color base holding four color elements. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
/// \brief A homogeneous color base holding four color elements.
/// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
/// \ingroup ColorBaseModelHomogeneous
template <typename Element, typename Layout>
struct homogeneous_color_base<Element,Layout,4> {
private:
Element _v0, _v1, _v2, _v3;
public:
struct homogeneous_color_base<Element, Layout, 4>
{
using layout_t = Layout;
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) { return _v1; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) { return _v2; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) const { return _v2; }
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) { return _v3; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) const { return _v3; }
homogeneous_color_base() {}
explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v), _v3(v) {}
homogeneous_color_base(Element v0, Element v1, Element v2, Element v3) : _v0(v0), _v1(v1), _v2(v2), _v3(v3) {}
template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,4>& c) :
_v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
_v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
_v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)),
_v3(gil::at_c<mapping_transform<Layout,L2,3>::value>(c)) {}
template
<
typename U = Element,
typename = typename std::enable_if<!std::is_reference<U>::value>::type
>
homogeneous_color_base() : v0_{}, v1_{}, v2_{}, v3_{} {}
explicit homogeneous_color_base(Element v) : v0_(v), v1_(v), v2_(v), v3_(v) {}
homogeneous_color_base(Element v0, Element v1, Element v2, Element v3)
: v0_(v0), v1_(v1), v2_(v2), v3_(v3)
{}
template <typename E2, typename L2>
homogeneous_color_base(homogeneous_color_base<E2, L2, 4> const& c)
: v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
, v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
, v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c))
, v3_(gil::at_c<mapping_transform<Layout, L2, 3>::value>(c))
{}
// Support for l-value reference proxy copy construction
template <typename E2, typename L2> homogeneous_color_base( homogeneous_color_base<E2,L2,4>& c) :
_v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
_v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
_v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)),
_v3(gil::at_c<mapping_transform<Layout,L2,3>::value>(c)) {}
template <typename E2, typename L2>
homogeneous_color_base(homogeneous_color_base<E2, L2, 4>& c)
: v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
, v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
, v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c))
, v3_(gil::at_c<mapping_transform<Layout, L2, 3>::value>(c))
{}
// Support for planar_pixel_iterator construction and dereferencing
template <typename P> homogeneous_color_base(P* p,bool) :
_v0(&semantic_at_c<0>(*p)),
_v1(&semantic_at_c<1>(*p)),
_v2(&semantic_at_c<2>(*p)),
_v3(&semantic_at_c<3>(*p)) {}
template <typename Ref> Ref deref() const {
return Ref(*semantic_at_c<0>(*this),
*semantic_at_c<1>(*this),
*semantic_at_c<2>(*this),
*semantic_at_c<3>(*this)); }
template <typename P>
homogeneous_color_base(P * p, bool)
: v0_(&semantic_at_c<0>(*p))
, v1_(&semantic_at_c<1>(*p))
, v2_(&semantic_at_c<2>(*p))
, v3_(&semantic_at_c<3>(*p))
{}
// Support for planar_pixel_reference offset constructor
template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
: _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
_v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)),
_v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)),
_v3(*memunit_advanced(semantic_at_c<3>(ptr),diff)) {}
template <typename Ptr>
homogeneous_color_base(Ptr const& ptr, std::ptrdiff_t diff)
: v0_(*memunit_advanced(semantic_at_c<0>(ptr), diff))
, v1_(*memunit_advanced(semantic_at_c<1>(ptr), diff))
, v2_(*memunit_advanced(semantic_at_c<2>(ptr), diff))
, v3_(*memunit_advanced(semantic_at_c<3>(ptr), diff))
{}
template <typename Ref>
Ref deref() const
{
return Ref(
*semantic_at_c<0>(*this),
*semantic_at_c<1>(*this),
*semantic_at_c<2>(*this),
*semantic_at_c<3>(*this));
}
auto at(std::integral_constant<int, 0>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v0_; }
auto at(std::integral_constant<int, 0>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v0_; }
auto at(std::integral_constant<int, 1>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v1_; }
auto at(std::integral_constant<int, 1>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v1_; }
auto at(std::integral_constant<int, 2>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v2_; }
auto at(std::integral_constant<int, 2>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v2_; }
auto at(std::integral_constant<int, 3>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v3_; }
auto at(std::integral_constant<int, 3>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v3_; }
// Support for planar_pixel_reference operator[]
Element at_c_dynamic(std::size_t i) const {
switch (i) {
case 0: return _v0;
case 1: return _v1;
case 2: return _v2;
auto at_c_dynamic(std::size_t i) const -> Element
{
switch (i)
{
case 0: return v0_;
case 1: return v1_;
case 2: return v2_;
}
return _v3;
return v3_;
}
private:
Element v0_;
Element v1_;
Element v2_;
Element v3_;
};
/// \brief A homogeneous color base holding five color elements. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
/// \brief A homogeneous color base holding five color elements.
/// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
/// \ingroup ColorBaseModelHomogeneous
template <typename Element, typename Layout>
struct homogeneous_color_base<Element,Layout,5> {
private:
Element _v0, _v1, _v2, _v3, _v4;
public:
struct homogeneous_color_base<Element, Layout, 5>
{
using layout_t = Layout;
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) { return _v1; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) { return _v2; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) const { return _v2; }
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) { return _v3; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) const { return _v3; }
typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<4>) { return _v4; }
typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<4>) const { return _v4; }
homogeneous_color_base() {}
explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v), _v3(v), _v4(v) {}
homogeneous_color_base(Element v0, Element v1, Element v2, Element v3, Element v4) : _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4) {}
template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,5>& c) :
_v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
_v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
_v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)),
_v3(gil::at_c<mapping_transform<Layout,L2,3>::value>(c)),
_v4(gil::at_c<mapping_transform<Layout,L2,4>::value>(c)) {}
template
<
typename U = Element,
typename = typename std::enable_if<!std::is_reference<U>::value>::type
>
homogeneous_color_base()
: v0_{}, v1_{}, v2_{}, v3_{}, v4_{}
{}
explicit homogeneous_color_base(Element v)
: v0_(v), v1_(v), v2_(v), v3_(v), v4_(v)
{}
homogeneous_color_base(Element v0, Element v1, Element v2, Element v3, Element v4)
: v0_(v0), v1_(v1), v2_(v2), v3_(v3), v4_(v4)
{}
template <typename E2, typename L2>
homogeneous_color_base(homogeneous_color_base<E2, L2, 5> const& c)
: v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
, v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
, v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c))
, v3_(gil::at_c<mapping_transform<Layout, L2, 3>::value>(c))
, v4_(gil::at_c<mapping_transform<Layout, L2, 4>::value>(c))
{}
// Support for l-value reference proxy copy construction
template <typename E2, typename L2> homogeneous_color_base( homogeneous_color_base<E2,L2,5>& c) :
_v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
_v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
_v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)),
_v3(gil::at_c<mapping_transform<Layout,L2,3>::value>(c)),
_v4(gil::at_c<mapping_transform<Layout,L2,4>::value>(c)) {}
template <typename E2, typename L2>
homogeneous_color_base(homogeneous_color_base<E2, L2, 5>& c)
: v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c))
, v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c))
, v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c))
, v3_(gil::at_c<mapping_transform<Layout, L2, 3>::value>(c))
, v4_(gil::at_c<mapping_transform<Layout, L2, 4>::value>(c))
{}
// Support for planar_pixel_iterator construction and dereferencing
template <typename P> homogeneous_color_base(P* p,bool) :
_v0(&semantic_at_c<0>(*p)),
_v1(&semantic_at_c<1>(*p)),
_v2(&semantic_at_c<2>(*p)),
_v3(&semantic_at_c<3>(*p)),
_v4(&semantic_at_c<4>(*p)) {}
template <typename Ref> Ref deref() const {
return Ref(*semantic_at_c<0>(*this),
*semantic_at_c<1>(*this),
*semantic_at_c<2>(*this),
*semantic_at_c<3>(*this),
*semantic_at_c<4>(*this)); }
template <typename P>
homogeneous_color_base(P* p, bool)
: v0_(&semantic_at_c<0>(*p))
, v1_(&semantic_at_c<1>(*p))
, v2_(&semantic_at_c<2>(*p))
, v3_(&semantic_at_c<3>(*p))
, v4_(&semantic_at_c<4>(*p))
{}
// Support for planar_pixel_reference offset constructor
template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
: _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
_v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)),
_v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)),
_v3(*memunit_advanced(semantic_at_c<3>(ptr),diff)),
_v4(*memunit_advanced(semantic_at_c<4>(ptr),diff)) {}
template <typename Ptr>
homogeneous_color_base(Ptr const& ptr, std::ptrdiff_t diff)
: v0_(*memunit_advanced(semantic_at_c<0>(ptr), diff))
, v1_(*memunit_advanced(semantic_at_c<1>(ptr), diff))
, v2_(*memunit_advanced(semantic_at_c<2>(ptr), diff))
, v3_(*memunit_advanced(semantic_at_c<3>(ptr), diff))
, v4_(*memunit_advanced(semantic_at_c<4>(ptr), diff))
{}
auto at(std::integral_constant<int, 0>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v0_; }
auto at(std::integral_constant<int, 0>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v0_; }
auto at(std::integral_constant<int, 1>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v1_; }
auto at(std::integral_constant<int, 1>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v1_; }
auto at(std::integral_constant<int, 2>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v2_; }
auto at(std::integral_constant<int, 2>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v2_; }
auto at(std::integral_constant<int, 3>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v3_; }
auto at(std::integral_constant<int, 3>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v3_; }
auto at(std::integral_constant<int, 4>)
-> typename element_reference_type<homogeneous_color_base>::type
{ return v4_; }
auto at(std::integral_constant<int, 4>) const
-> typename element_const_reference_type<homogeneous_color_base>::type
{ return v4_; }
template <typename Ref>
Ref deref() const
{
return Ref(
*semantic_at_c<0>(*this),
*semantic_at_c<1>(*this),
*semantic_at_c<2>(*this),
*semantic_at_c<3>(*this),
*semantic_at_c<4>(*this));
}
// Support for planar_pixel_reference operator[]
Element at_c_dynamic(std::size_t i) const {
switch (i) {
case 0: return _v0;
case 1: return _v1;
case 2: return _v2;
case 3: return _v3;
auto at_c_dynamic(std::size_t i) const -> Element
{
switch (i)
{
case 0: return v0_;
case 1: return v1_;
case 2: return v2_;
case 3: return v3_;
}
return _v4;
return v4_;
}
private:
Element v0_;
Element v1_;
Element v2_;
Element v3_;
Element v4_;
};
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
@@ -338,74 +562,113 @@ public:
// However, the client must nevertheless ensure that proper compiler settings are used for their compiler and their channel types.
template <typename Element, typename Layout, int K>
typename element_reference_type<homogeneous_color_base<Element,Layout,K> >::type
dynamic_at_c(homogeneous_color_base<Element,Layout,K>& cb, std::size_t i)
auto dynamic_at_c(homogeneous_color_base<Element,Layout,K>& cb, std::size_t i)
-> typename element_reference_type<homogeneous_color_base<Element, Layout, K>>::type
{
BOOST_ASSERT(i < K);
return (gil_reinterpret_cast<Element*>(&cb))[i];
}
template <typename Element, typename Layout, int K>
typename element_const_reference_type<homogeneous_color_base<Element,Layout,K> >::type
dynamic_at_c(const homogeneous_color_base<Element,Layout,K>& cb, std::size_t i) {
auto dynamic_at_c(homogeneous_color_base<Element, Layout, K> const& cb, std::size_t i)
-> typename element_const_reference_type
<
homogeneous_color_base<Element, Layout, K>
>::type
{
BOOST_ASSERT(i < K);
return (gil_reinterpret_cast_c<const Element*>(&cb))[i];
}
template <typename Element, typename Layout, int K>
typename element_reference_type<homogeneous_color_base<Element&,Layout,K> >::type
dynamic_at_c(const homogeneous_color_base<Element&,Layout,K>& cb, std::size_t i) {
auto dynamic_at_c(homogeneous_color_base<Element&, Layout, K> const& cb, std::size_t i)
-> typename element_reference_type
<
homogeneous_color_base<Element&, Layout, K>
>::type
{
BOOST_ASSERT(i < K);
return cb.at_c_dynamic(i);
}
template <typename Element, typename Layout, int K>
typename element_const_reference_type<homogeneous_color_base<const Element&,Layout,K> >::type
dynamic_at_c(const homogeneous_color_base<const Element&,Layout,K>& cb, std::size_t i) {
auto dynamic_at_c(
homogeneous_color_base<Element const&, Layout, K>const& cb, std::size_t i)
-> typename element_const_reference_type
<
homogeneous_color_base<Element const&, Layout, K>
>::type
{
BOOST_ASSERT(i < K);
return cb.at_c_dynamic(i);
}
} // namespace detail
template <typename Element, typename Layout, int K1, int K>
struct kth_element_type<detail::homogeneous_color_base<Element,Layout,K1>, K> {
struct kth_element_type<detail::homogeneous_color_base<Element, Layout, K1>, K>
{
using type = Element;
};
template <typename Element, typename Layout, int K1, int K>
struct kth_element_reference_type<detail::homogeneous_color_base<Element,Layout,K1>, K> : public add_reference<Element> {};
struct kth_element_reference_type<detail::homogeneous_color_base<Element, Layout, K1>, K>
: std::add_lvalue_reference<Element>
{};
template <typename Element, typename Layout, int K1, int K>
struct kth_element_const_reference_type<detail::homogeneous_color_base<Element,Layout,K1>, K> : public add_reference<typename add_const<Element>::type> {};
struct kth_element_const_reference_type
<
detail::homogeneous_color_base<Element, Layout, K1>,
K
>
: std::add_lvalue_reference<typename std::add_const<Element>::type>
{};
/// \brief Provides mutable access to the K-th element, in physical order
/// \ingroup ColorBaseModelHomogeneous
template <int K, typename E, typename L, int N> inline
typename add_reference<E>::type
at_c( detail::homogeneous_color_base<E,L,N>& p) { return p.at(mpl::int_<K>()); }
template <int K, typename E, typename L, int N>
inline
auto at_c(detail::homogeneous_color_base<E, L, N>& p)
-> typename std::add_lvalue_reference<E>::type
{
return p.at(std::integral_constant<int, K>());
}
/// \brief Provides constant access to the K-th element, in physical order
/// \ingroup ColorBaseModelHomogeneous
template <int K, typename E, typename L, int N> inline
typename add_reference<typename add_const<E>::type>::type
at_c(const detail::homogeneous_color_base<E,L,N>& p) { return p.at(mpl::int_<K>()); }
namespace detail {
struct swap_fn {
template <typename T> void operator()(T& x, T& y) const {
using std::swap;
swap(x,y);
}
};
}
template <typename E, typename L, int N> inline
void swap(detail::homogeneous_color_base<E,L,N>& x, detail::homogeneous_color_base<E,L,N>& y) {
static_for_each(x,y,detail::swap_fn());
template <int K, typename E, typename L, int N>
inline
auto at_c(const detail::homogeneous_color_base<E, L, N>& p)
-> typename std::add_lvalue_reference<typename std::add_const<E>::type>::type
{
return p.at(std::integral_constant<int, K>());
}
namespace detail
{
} } // namespace boost::gil
struct swap_fn
{
template <typename T>
void operator()(T& x, T& y) const
{
using std::swap;
swap(x, y);
}
};
} // namespace detail
template <typename E, typename L, int N>
inline
void swap(
detail::homogeneous_color_base<E, L, N>& x,
detail::homogeneous_color_base<E, L, N>& y)
{
static_for_each(x, y, detail::swap_fn());
}
}} // namespace boost::gil
#endif

View File

@@ -1,5 +1,6 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
@@ -10,12 +11,9 @@
#include <boost/gil/concepts.hpp>
#include <boost/gil/utilities.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <boost/config.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/size.hpp>
#include <boost/type_traits.hpp>
#include <algorithm>
#include <type_traits>
@@ -23,15 +21,13 @@
namespace boost { namespace gil {
///////////////////////////////////////
///
/// size: Semantic channel size
///
///////////////////////////////////////
/**
\defgroup ColorBaseAlgorithmSize size
\ingroup ColorBaseAlgorithm
\brief Returns an MPL integral type specifying the number of elements in a color base
\brief Returns an integral constant type specifying the number of elements in a color base
Example:
\code
@@ -40,15 +36,13 @@ static_assert(size<cmyk8_planar_ptr_t>::value == 4, "");
\endcode
*/
/// \brief Returns an MPL integral type specifying the number of elements in a color base
/// \brief Returns an integral constant type specifying the number of elements in a color base
/// \ingroup ColorBaseAlgorithmSize
template <typename ColorBase>
struct size : public mpl::size<typename ColorBase::layout_t::color_space_t> {};
struct size : public mp11::mp_size<typename ColorBase::layout_t::color_space_t> {};
///////////////////////////////////////
///
/// semantic_at_c: Semantic channel accessors
///
///////////////////////////////////////
/**
@@ -63,7 +57,7 @@ All GIL color base algorithms taking multiple color bases use semantic indexing
Example:
\code
// 16-bit BGR pixel, 4 bits for the blue, 3 bits for the green, 2 bits for the red channel and 7 unused bits
using bgr432_pixel_t = packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,4,3,2>, bgr_layout_t>::type;
using bgr432_pixel_t = packed_pixel_type<uint16_t, mp11::mp_list_c<unsigned,4,3,2>, bgr_layout_t>::type;
// A reference to its red channel. Although the red channel is the third, its semantic index is 0 in the RGB color space
using red_channel_reference_t = kth_semantic_element_reference_type<bgr432_pixel_t, 0>::type;
@@ -83,10 +77,10 @@ template <typename ColorBase, int K>
struct kth_semantic_element_type
{
using channel_mapping_t = typename ColorBase::layout_t::channel_mapping_t;
static_assert(K < mpl::size<channel_mapping_t>::value,
static_assert(K < mp11::mp_size<channel_mapping_t>::value,
"K index should be less than size of channel_mapping_t sequence");
static constexpr int semantic_index = mpl::at_c<channel_mapping_t, K>::type::value;
static constexpr int semantic_index = mp11::mp_at_c<channel_mapping_t, K>::type::value;
using type = typename kth_element_type<ColorBase, semantic_index>::type;
};
@@ -96,23 +90,24 @@ template <typename ColorBase, int K>
struct kth_semantic_element_reference_type
{
using channel_mapping_t = typename ColorBase::layout_t::channel_mapping_t;
static_assert(K < mpl::size<channel_mapping_t>::value,
static_assert(K < mp11::mp_size<channel_mapping_t>::value,
"K index should be less than size of channel_mapping_t sequence");
static constexpr int semantic_index = mpl::at_c<channel_mapping_t, K>::type::value;
static constexpr int semantic_index = mp11::mp_at_c<channel_mapping_t, K>::type::value;
using type = typename kth_element_reference_type<ColorBase, semantic_index>::type;
static type get(ColorBase& cb) { return gil::at_c<semantic_index>(cb); }
};
/// \brief Specifies the return type of the constant semantic_at_c<K>(color_base);
/// \ingroup ColorBaseAlgorithmSemanticAtC
template <typename ColorBase, int K> struct kth_semantic_element_const_reference_type
template <typename ColorBase, int K>
struct kth_semantic_element_const_reference_type
{
using channel_mapping_t = typename ColorBase::layout_t::channel_mapping_t;
static_assert(K < mpl::size<channel_mapping_t>::value,
static_assert(K < mp11::mp_size<channel_mapping_t>::value,
"K index should be less than size of channel_mapping_t sequence");
static constexpr int semantic_index = mpl::at_c<channel_mapping_t, K>::type::value;
static constexpr int semantic_index = mp11::mp_at_c<channel_mapping_t, K>::type::value;
using type = typename kth_element_const_reference_type<ColorBase,semantic_index>::type;
static type get(const ColorBase& cb) { return gil::at_c<semantic_index>(cb); }
};
@@ -128,21 +123,21 @@ auto semantic_at_c(ColorBase& p)
typename kth_semantic_element_reference_type<ColorBase, K>::type
>::type
{
return kth_semantic_element_reference_type<ColorBase,K>::get(p);
return kth_semantic_element_reference_type<ColorBase, K>::get(p);
}
/// \brief A constant accessor to the K-th semantic element of a color base
/// \ingroup ColorBaseAlgorithmSemanticAtC
template <int K, typename ColorBase> inline
typename kth_semantic_element_const_reference_type<ColorBase,K>::type
semantic_at_c(const ColorBase& p) {
return kth_semantic_element_const_reference_type<ColorBase,K>::get(p);
template <int K, typename ColorBase>
inline
auto semantic_at_c(ColorBase const& p)
-> typename kth_semantic_element_const_reference_type<ColorBase, K>::type
{
return kth_semantic_element_const_reference_type<ColorBase, K>::get(p);
}
///////////////////////////////////////
///
/// get_color: Named channel accessors
///
///////////////////////////////////////
/**
@@ -167,7 +162,9 @@ void set_red_to_max(Pixel& pixel) {
/// \brief A predicate metafunction determining whether a given color base contains a given color
/// \ingroup ColorBaseAlgorithmColor
template <typename ColorBase, typename Color>
struct contains_color : public mpl::contains<typename ColorBase::layout_t::color_space_t,Color> {};
struct contains_color
: mp11::mp_contains<typename ColorBase::layout_t::color_space_t, Color>
{};
template <typename ColorBase, typename Color>
struct color_index_type : public detail::type_to_index<typename ColorBase::layout_t::color_space_t,Color> {};
@@ -190,14 +187,18 @@ struct color_element_const_reference_type : public kth_semantic_element_const_re
/// \brief Mutable accessor to the element associated with a given color name
/// \ingroup ColorBaseAlgorithmColor
template <typename ColorBase, typename Color>
typename color_element_reference_type<ColorBase,Color>::type get_color(ColorBase& cb, Color=Color()) {
auto get_color(ColorBase& cb, Color=Color())
-> typename color_element_reference_type<ColorBase,Color>::type
{
return color_element_reference_type<ColorBase,Color>::get(cb);
}
/// \brief Constant accessor to the element associated with a given color name
/// \ingroup ColorBaseAlgorithmColor
template <typename ColorBase, typename Color>
typename color_element_const_reference_type<ColorBase,Color>::type get_color(const ColorBase& cb, Color=Color()) {
auto get_color(const ColorBase& cb, Color=Color())
-> typename color_element_const_reference_type<ColorBase,Color>::type
{
return color_element_const_reference_type<ColorBase,Color>::get(cb);
}
@@ -241,7 +242,7 @@ template <int N>
struct element_recursion
{
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wfloat-equal"
@@ -275,7 +276,7 @@ struct element_recursion
semantic_at_c<N-1>(dst)=op();
}
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif
@@ -438,36 +439,63 @@ template<> struct element_recursion<0> {
};
// std::min and std::max don't have the mutable overloads...
template <typename Q> inline const Q& mutable_min(const Q& x, const Q& y) { return x<y ? x : y; }
template <typename Q> inline Q& mutable_min( Q& x, Q& y) { return x<y ? x : y; }
template <typename Q> inline const Q& mutable_max(const Q& x, const Q& y) { return x<y ? y : x; }
template <typename Q> inline Q& mutable_max( Q& x, Q& y) { return x<y ? y : x; }
template <typename Q>
inline auto mutable_min(Q const& x, Q const& y) -> Q const& { return x<y ? x : y; }
template <typename Q>
inline auto mutable_min(Q& x, Q& y) -> Q& { return x<y ? x : y; }
template <typename Q>
inline auto mutable_max(Q const& x, Q const& y) -> Q const& { return x<y ? y : x; }
template <typename Q>
inline auto mutable_max(Q& x, Q& y) -> Q& { return x<y ? y : x; }
// compile-time recursion for min/max element
template <int N>
struct min_max_recur {
template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) {
struct min_max_recur
{
template <typename P>
static auto max_(P const& p) -> typename element_const_reference_type<P>::type
{
return mutable_max(min_max_recur<N-1>::max_(p),semantic_at_c<N-1>(p));
}
template <typename P> static typename element_reference_type<P>::type max_( P& p) {
template <typename P>
static auto max_(P& p) -> typename element_reference_type<P>::type
{
return mutable_max(min_max_recur<N-1>::max_(p),semantic_at_c<N-1>(p));
}
template <typename P> static typename element_const_reference_type<P>::type min_(const P& p) {
template <typename P>
static auto min_(P const& p) -> typename element_const_reference_type<P>::type
{
return mutable_min(min_max_recur<N-1>::min_(p),semantic_at_c<N-1>(p));
}
template <typename P> static typename element_reference_type<P>::type min_( P& p) {
template <typename P>
static auto min_(P& p) -> typename element_reference_type<P>::type
{
return mutable_min(min_max_recur<N-1>::min_(p),semantic_at_c<N-1>(p));
}
};
// termination condition of the compile-time recursion for min/max element
template <>
struct min_max_recur<1> {
template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) { return semantic_at_c<0>(p); }
template <typename P> static typename element_reference_type<P>::type max_( P& p) { return semantic_at_c<0>(p); }
template <typename P> static typename element_const_reference_type<P>::type min_(const P& p) { return semantic_at_c<0>(p); }
template <typename P> static typename element_reference_type<P>::type min_( P& p) { return semantic_at_c<0>(p); }
struct min_max_recur<1>
{
template <typename P>
static auto max_(P const& p) -> typename element_const_reference_type<P>::type { return semantic_at_c<0>(p); }
template <typename P>
static auto max_(P& p) -> typename element_reference_type<P>::type { return semantic_at_c<0>(p); }
template <typename P>
static auto min_(P const& p) -> typename element_const_reference_type<P>::type { return semantic_at_c<0>(p); }
template <typename P>
static auto min_(P& p) -> typename element_reference_type<P>::type { return semantic_at_c<0>(p); }
};
} // namespace detail
@@ -486,19 +514,19 @@ struct min_max_recur<1> {
template <typename P>
BOOST_FORCEINLINE
typename element_const_reference_type<P>::type static_max(const P& p) { return detail::min_max_recur<size<P>::value>::max_(p); }
auto static_max(P const& p) -> typename element_const_reference_type<P>::type { return detail::min_max_recur<size<P>::value>::max_(p); }
template <typename P>
BOOST_FORCEINLINE
typename element_reference_type<P>::type static_max( P& p) { return detail::min_max_recur<size<P>::value>::max_(p); }
auto static_max(P& p) -> typename element_reference_type<P>::type { return detail::min_max_recur<size<P>::value>::max_(p); }
template <typename P>
BOOST_FORCEINLINE
typename element_const_reference_type<P>::type static_min(const P& p) { return detail::min_max_recur<size<P>::value>::min_(p); }
auto static_min(P const& p) -> typename element_const_reference_type<P>::type { return detail::min_max_recur<size<P>::value>::min_(p); }
template <typename P>
BOOST_FORCEINLINE
typename element_reference_type<P>::type static_min( P& p) { return detail::min_max_recur<size<P>::value>::min_(p); }
auto static_min(P& p) -> typename element_reference_type<P>::type { return detail::min_max_recur<size<P>::value>::min_(p); }
/// \}
/// \defgroup ColorBaseAlgorithmEqual static_equal
@@ -518,7 +546,7 @@ typename element_reference_type<P>::type static_min( P& p) { return d
template <typename P1,typename P2>
BOOST_FORCEINLINE
bool static_equal(const P1& p1, const P2& p2) { return detail::element_recursion<size<P1>::value>::static_equal(p1,p2); }
bool static_equal(P1 const& p1, const P2& p2) { return detail::element_recursion<size<P1>::value>::static_equal(p1,p2); }
/// \}
@@ -539,7 +567,10 @@ bool static_equal(const P1& p1, const P2& p2) { return detail::element_recursion
template <typename Src,typename Dst>
BOOST_FORCEINLINE
void static_copy(const Src& src, Dst& dst) { detail::element_recursion<size<Dst>::value>::static_copy(src,dst); }
void static_copy(const Src& src, Dst& dst)
{
detail::element_recursion<size<Dst>::value>::static_copy(src, dst);
}
/// \}
@@ -557,7 +588,11 @@ void static_copy(const Src& src, Dst& dst) { detail::element_recursion<size<Dst
template <typename P,typename V>
BOOST_FORCEINLINE
void static_fill(P& p, const V& v) { detail::element_recursion<size<P>::value>::static_fill(p,v); }
void static_fill(P& p, const V& v)
{
detail::element_recursion<size<P>::value>::static_fill(p,v);
}
/// \}
/// \defgroup ColorBaseAlgorithmGenerate static_generate
@@ -704,6 +739,6 @@ BOOST_FORCEINLINE
Op static_for_each(const P1& p1,const P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
///\}
} } // namespace boost::gil
}} // namespace boost::gil
#endif

View File

@@ -20,6 +20,7 @@
#include <algorithm>
#include <functional>
#include <type_traits>
namespace boost { namespace gil {
@@ -38,7 +39,12 @@ template <typename P> struct channel_type;
/// \ingroup ColorConvert
/// \brief Color Convertion function object. To be specialized for every src/dst color space
template <typename C1, typename C2>
struct default_color_converter_impl {};
struct default_color_converter_impl
{
static_assert(
std::is_same<C1, C2>::value,
"default_color_converter_impl not specialized for given color spaces");
};
/// \ingroup ColorConvert
/// \brief When the color space is the same, color convertion performs channel depth conversion
@@ -57,7 +63,8 @@ namespace detail {
// The default implementation of to_luminance uses float0..1 as the intermediate channel type
template <typename RedChannel, typename GreenChannel, typename BlueChannel, typename GrayChannelValue>
struct rgb_to_luminance_fn {
GrayChannelValue operator()(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) const {
auto operator()(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) const -> GrayChannelValue
{
return channel_convert<GrayChannelValue>(float32_t(
channel_convert<float32_t>(red )*0.30f +
channel_convert<float32_t>(green)*0.59f +
@@ -68,14 +75,16 @@ struct rgb_to_luminance_fn {
// performance specialization for unsigned char
template <typename GrayChannelValue>
struct rgb_to_luminance_fn<uint8_t,uint8_t,uint8_t, GrayChannelValue> {
GrayChannelValue operator()(uint8_t red, uint8_t green, uint8_t blue) const {
auto operator()(uint8_t red, uint8_t green, uint8_t blue) const -> GrayChannelValue
{
return channel_convert<GrayChannelValue>(uint8_t(
((uint32_t(red )*4915 + uint32_t(green)*9667 + uint32_t(blue )*1802) + 8192) >> 14));
}
};
template <typename GrayChannel, typename RedChannel, typename GreenChannel, typename BlueChannel>
typename channel_traits<GrayChannel>::value_type rgb_to_luminance(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) {
auto rgb_to_luminance(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) -> typename channel_traits<GrayChannel>::value_type
{
return rgb_to_luminance_fn<RedChannel,GreenChannel,BlueChannel,
typename channel_traits<GrayChannel>::value_type>()(red,green,blue);
}
@@ -99,6 +108,8 @@ struct default_color_converter_impl<gray_t,rgb_t> {
/// \ingroup ColorConvert
/// \brief Gray to CMYK
/// \todo FIXME: Where does this calculation come from? Shouldn't gray be inverted?
/// Currently, white becomes black and black becomes white.
template <>
struct default_color_converter_impl<gray_t,cmyk_t> {
template <typename P1, typename P2>
@@ -135,29 +146,57 @@ struct default_color_converter_impl<rgb_t,gray_t> {
/// c = (1 - r - k) / (1 - k)
/// m = (1 - g - k) / (1 - k)
/// y = (1 - b - k) / (1 - k)
/// where `1` denotes max value of channel type of destination pixel.
///
/// The conversion from RGB to CMYK is based on CMY->CMYK (Version 2)
/// from the Principles of Digital Image Processing - Fundamental Techniques
/// by Burger, Wilhelm, Burge, Mark J.
/// and it is a gross approximation not precise enough for professional work.
///
template <>
struct default_color_converter_impl<rgb_t,cmyk_t> {
template <typename P1, typename P2>
void operator()(const P1& src, P2& dst) const {
using T2 = typename channel_type<P2>::type;
get_color(dst,cyan_t()) = channel_invert(channel_convert<T2>(get_color(src,red_t()))); // c = 1 - r
get_color(dst,magenta_t()) = channel_invert(channel_convert<T2>(get_color(src,green_t()))); // m = 1 - g
get_color(dst,yellow_t()) = channel_invert(channel_convert<T2>(get_color(src,blue_t()))); // y = 1 - b
get_color(dst,black_t()) = (std::min)(get_color(dst,cyan_t()),
(std::min)(get_color(dst,magenta_t()),
get_color(dst,yellow_t()))); // k = minimum(c, m, y)
T2 x = channel_traits<T2>::max_value()-get_color(dst,black_t()); // x = 1 - k
if (x>0.0001f) {
float x1 = channel_traits<T2>::max_value()/float(x);
get_color(dst,cyan_t()) = (T2)((get_color(dst,cyan_t()) - get_color(dst,black_t()))*x1); // c = (c - k) / x
get_color(dst,magenta_t()) = (T2)((get_color(dst,magenta_t()) - get_color(dst,black_t()))*x1); // m = (m - k) / x
get_color(dst,yellow_t()) = (T2)((get_color(dst,yellow_t()) - get_color(dst,black_t()))*x1); // y = (y - k) / x
} else {
get_color(dst,cyan_t())=get_color(dst,magenta_t())=get_color(dst,yellow_t())=0;
struct default_color_converter_impl<rgb_t, cmyk_t>
{
template <typename SrcPixel, typename DstPixel>
void operator()(SrcPixel const& src, DstPixel& dst) const
{
using src_t = typename channel_type<SrcPixel>::type;
src_t const r = get_color(src, red_t());
src_t const g = get_color(src, green_t());
src_t const b = get_color(src, blue_t());
using uint_t = typename channel_type<cmyk8_pixel_t>::type;
uint_t c = channel_invert(channel_convert<uint_t>(r)); // c = 1 - r
uint_t m = channel_invert(channel_convert<uint_t>(g)); // m = 1 - g
uint_t y = channel_invert(channel_convert<uint_t>(b)); // y = 1 - b
uint_t k = (std::min)(c,(std::min)(m,y)); // k = minimum(c, m, y)
// Apply color correction, strengthening, reducing non-zero components by
// s = 1 / (1 - k) for k < 1, where 1 denotes dst_t max, otherwise s = 1 (literal).
uint_t const dst_max = channel_traits<uint_t>::max_value();
uint_t const s_div = static_cast<uint_t>(dst_max - k);
if (s_div != 0)
{
double const s = dst_max / static_cast<double>(s_div);
c = static_cast<uint_t>((c - k) * s);
m = static_cast<uint_t>((m - k) * s);
y = static_cast<uint_t>((y - k) * s);
}
else
{
// Black only for k = 1 (max of dst_t)
c = channel_traits<uint_t>::min_value();
m = channel_traits<uint_t>::min_value();
y = channel_traits<uint_t>::min_value();
}
using dst_t = typename channel_type<DstPixel>::type;
get_color(dst, cyan_t()) = channel_convert<dst_t>(c);
get_color(dst, magenta_t()) = channel_convert<dst_t>(m);
get_color(dst, yellow_t()) = channel_convert<dst_t>(y);
get_color(dst, black_t()) = channel_convert<dst_t>(k);
}
};
/// \ingroup ColorConvert
/// \brief CMYK to RGB (not the fastest code in the world)
///
@@ -211,20 +250,27 @@ struct default_color_converter_impl<cmyk_t,gray_t> {
};
namespace detail {
template <typename Pixel>
typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& p, mpl::true_) {
auto alpha_or_max_impl(Pixel const& p, std::true_type) -> typename channel_type<Pixel>::type
{
return get_color(p,alpha_t());
}
template <typename Pixel>
typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& , mpl::false_) {
auto alpha_or_max_impl(Pixel const&, std::false_type) -> typename channel_type<Pixel>::type
{
return channel_traits<typename channel_type<Pixel>::type>::max_value();
}
} // namespace detail
// Returns max_value if the pixel has no alpha channel. Otherwise returns the alpha.
template <typename Pixel>
typename channel_type<Pixel>::type alpha_or_max(const Pixel& p) {
return detail::alpha_or_max_impl(p, mpl::contains<typename color_space_type<Pixel>::type,alpha_t>());
auto alpha_or_max(Pixel const& p) -> typename channel_type<Pixel>::type
{
return detail::alpha_or_max_impl(
p,
mp11::mp_contains<typename color_space_type<Pixel>::type, alpha_t>());
}

View File

@@ -12,11 +12,12 @@
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#pragma clang diagnostic ignored "-Wuninitialized"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wuninitialized"
@@ -188,7 +189,7 @@ struct SameType
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -15,13 +15,15 @@
#include <boost/concept_check.hpp>
#include <utility> // std::swap
#include <type_traits>
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
@@ -65,7 +67,7 @@ auto channel_convert(SrcT const& val)
/// static const bool is_mutable; // use channel_traits<T>::is_mutable to access it
///
/// static T min_value(); // use channel_traits<T>::min_value to access it
/// static T max_value(); // use channel_traits<T>::min_value to access it
/// static T max_value(); // use channel_traits<T>::max_value to access it
/// };
/// \endcode
template <typename T>
@@ -150,7 +152,7 @@ struct ChannelValueConcept
/// \ingroup ChannelAlgorithm
template <typename T1, typename T2> // Models GIL Pixel
struct channels_are_compatible
: is_same
: std::is_same
<
typename channel_traits<T1>::value_type,
typename channel_traits<T2>::value_type
@@ -207,7 +209,7 @@ struct ChannelConvertibleConcept
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -10,14 +10,15 @@
#include <boost/gil/concepts/concept_check.hpp>
#include <boost/type_traits.hpp>
#include <type_traits>
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
@@ -29,7 +30,7 @@ namespace boost { namespace gil {
/// \code
/// concept ColorSpaceConcept<MPLRandomAccessSequence CS>
/// {
/// // An MPL Random Access Sequence, whose elements are color tags
/// // Boost.MP11-compatible list, whose elements are color tags.
/// };
/// \endcode
template <typename CS>
@@ -37,7 +38,7 @@ struct ColorSpaceConcept
{
void constraints()
{
// An MPL Random Access Sequence, whose elements are color tags
// Boost.MP11-compatible list, whose elements are color tags
// TODO: Is this incomplete?
}
@@ -45,9 +46,7 @@ struct ColorSpaceConcept
// Models ColorSpaceConcept
template <typename CS1, typename CS2>
struct color_spaces_are_compatible : is_same<CS1, CS2>
{
};
struct color_spaces_are_compatible : std::is_same<CS1, CS2> {};
/// \ingroup ColorSpaceAndLayoutConcept
/// \brief Two color spaces are compatible if they are the same
@@ -71,7 +70,7 @@ struct ColorSpacesCompatibleConcept
/// \code
/// concept ChannelMappingConcept<MPLRandomAccessSequence CM>
/// {
/// // An MPL Random Access Sequence, whose elements
/// // Boost.MP11-compatible list, whose elements
/// // model MPLIntegralConstant representing a permutation
/// };
/// \endcode
@@ -80,7 +79,7 @@ struct ChannelMappingConcept
{
void constraints()
{
// An MPL Random Access Sequence, whose elements model
// Boost.MP11-compatible list, whose elements model
// MPLIntegralConstant representing a permutation.
// TODO: Is this incomplete?
@@ -93,7 +92,7 @@ struct ChannelMappingConcept
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -13,14 +13,16 @@
#include <boost/gil/concepts/concept_check.hpp>
#include <boost/gil/concepts/fwd.hpp>
#include <boost/type_traits.hpp>
#include <boost/core/ignore_unused.hpp>
#include <type_traits>
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
@@ -37,11 +39,11 @@ struct homogeneous_color_base;
template <int K, typename E, typename L, int N>
auto at_c(detail::homogeneous_color_base<E, L, N>& p)
-> typename add_reference<E>::type;
-> typename std::add_lvalue_reference<E>::type;
template <int K, typename E, typename L, int N>
auto at_c(detail::homogeneous_color_base<E, L, N> const& p)
-> typename add_reference<typename add_const<E>::type>::type;
-> typename std::add_lvalue_reference<typename std::add_const<E>::type>::type;
template <typename P, typename C, typename L>
struct packed_pixel;
@@ -143,7 +145,7 @@ struct ColorBaseConcept
gil_function_requires<ColorSpaceConcept<color_space_t>>();
using channel_mapping_t = typename ColorBase::layout_t::channel_mapping_t;
// TODO: channel_mapping_t must be an MPL RandomAccessSequence
// TODO: channel_mapping_t must be an Boost.MP11-compatible random access sequence
static const int num_elements = size<ColorBase>::value;
@@ -151,7 +153,7 @@ struct ColorBaseConcept
using RN = typename kth_element_const_reference_type<ColorBase, num_elements - 1>::type;
RN r = gil::at_c<num_elements - 1>(cb);
ignore_unused_variable_warning(r);
boost::ignore_unused(r);
// functions that work for every pixel (no need to require them)
semantic_at_c<0>(cb);
@@ -233,10 +235,11 @@ struct HomogeneousColorBaseConcept
using T0 = typename kth_element_type<ColorBase, 0>::type;
using TN = typename kth_element_type<ColorBase, num_elements - 1>::type;
static_assert(is_same<T0, TN>::value, ""); // better than nothing
static_assert(std::is_same<T0, TN>::value, ""); // better than nothing
using R0 = typename kth_element_const_reference_type<ColorBase, 0>::type;
R0 r = dynamic_at_c(cb, 0);
boost::ignore_unused(r);
}
ColorBase cb;
};
@@ -259,6 +262,7 @@ struct MutableHomogeneousColorBaseConcept
gil_function_requires<HomogeneousColorBaseConcept<ColorBase>>();
using R0 = typename kth_element_reference_type<ColorBase, 0>::type;
R0 r = dynamic_at_c(cb, 0);
boost::ignore_unused(r);
dynamic_at_c(cb, 0) = dynamic_at_c(cb, 0);
}
ColorBase cb;
@@ -300,7 +304,7 @@ struct ColorBasesCompatibleConcept
{
void constraints()
{
static_assert(is_same
static_assert(std::is_same
<
typename ColorBase1::layout_t::color_space_t,
typename ColorBase2::layout_t::color_space_t
@@ -318,7 +322,7 @@ struct ColorBasesCompatibleConcept
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -12,12 +12,15 @@
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wfloat-equal"
#pragma clang diagnostic ignored "-Wuninitialized"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wuninitialized"
#endif
@@ -28,7 +31,7 @@
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif
@@ -36,17 +39,17 @@
namespace boost { namespace gil {
// TODO: What is GIL_CLASS_REQUIRE for; Why not use BOOST_CLASS_REQUIRE?
// TODO: What is BOOST_GIL_CLASS_REQUIRE for; Why not use BOOST_CLASS_REQUIRE?
// TODO: What is gil_function_requires for; Why not function_requires?
#ifdef BOOST_GIL_USE_CONCEPT_CHECK
#define GIL_CLASS_REQUIRE(type_var, ns, concept) \
#define BOOST_GIL_CLASS_REQUIRE(type_var, ns, concept) \
BOOST_CLASS_REQUIRE(type_var, ns, concept);
template <typename Concept>
void gil_function_requires() { function_requires<Concept>(); }
#else
#define GIL_CLASS_REQUIRE(type_var, ns, concept)
#define BOOST_GIL_CLASS_REQUIRE(type_var, ns, concept)
template <typename C>
void gil_function_requires() {}

View File

@@ -8,13 +8,14 @@
#ifndef BOOST_GIL_CONCEPTS_DETAIL_TYPE_TRAITS_HPP
#define BOOST_GIL_CONCEPTS_DETAIL_TYPE_TRAITS_HPP
#include <boost/type_traits.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
// TODO: C++20: deprecate and replace with std::std_remove_cvref
template <typename T>
struct remove_const_and_reference
: ::boost::remove_const<typename ::boost::remove_reference<T>::type>
: std::remove_const<typename std::remove_reference<T>::type>
{
};

View File

@@ -13,10 +13,11 @@
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
@@ -70,7 +71,7 @@ struct HasDynamicYStepTypeConcept
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -13,15 +13,17 @@
#include <boost/gil/concepts/fwd.hpp>
#include <boost/gil/concepts/image_view.hpp>
#include <boost/gil/concepts/point.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <boost/mpl/size.hpp>
#include <type_traits>
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
@@ -46,7 +48,7 @@ namespace boost { namespace gil {
/// void Image::recreate(point_t new_dims, std::size_t alignment=1);
/// void Image::recreate(point_t new_dims, value_type fill_value, std::size_t alignment);
///
/// const point_t& Image::dimensions() const;
/// point_t const& Image::dimensions() const;
/// const const_view_t& const_view(const Image&);
/// const view_t& view(Image&);
/// };
@@ -146,10 +148,10 @@ struct ImageConcept
gil_function_requires<RandomAccess2DImageConcept<Image>>();
gil_function_requires<MutableImageViewConcept<typename Image::view_t>>();
using coord_t = typename Image::coord_t;
static_assert(num_channels<Image>::value == mpl::size<typename color_space_type<Image>::type>::value, "");
static_assert(num_channels<Image>::value == mp11::mp_size<typename color_space_type<Image>::type>::value, "");
static_assert(is_same<coord_t, typename Image::x_coord_t>::value, "");
static_assert(is_same<coord_t, typename Image::y_coord_t>::value, "");
static_assert(std::is_same<coord_t, typename Image::x_coord_t>::value, "");
static_assert(std::is_same<coord_t, typename Image::y_coord_t>::value, "");
}
Image image;
};
@@ -160,7 +162,7 @@ struct ImageConcept
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -20,13 +20,15 @@
#include <cstddef>
#include <iterator>
#include <type_traits>
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
@@ -38,7 +40,7 @@ namespace boost { namespace gil {
/// \ingroup ImageViewConcept
/// \brief N-dimensional range
/// \defgroup ImageView2DConcept ImageView2DConcept
/// \defgroup ImageView2DConcept ImageView2DLocatorConcept
/// \ingroup ImageViewConcept
/// \brief 2-dimensional range
@@ -87,14 +89,14 @@ namespace boost { namespace gil {
/// iterator View::end() const;
/// reverse_iterator View::rbegin() const;
/// reverse_iterator View::rend() const;
/// iterator View::at(const point_t&);
/// iterator View::at(point_t const&);
/// point_t View::dimensions() const; // number of elements along each dimension
/// bool View::is_1d_traversable() const; // can an iterator over the first dimension visit each value? I.e. are there gaps between values?
///
/// // iterator along a given dimension starting at a given point
/// template <size_t D> View::axis<D>::iterator View::axis_iterator(const point_t&) const;
/// template <size_t D> View::axis<D>::iterator View::axis_iterator(point_t const&) const;
///
/// reference operator()(View,const point_t&) const;
/// reference operator()(View,point_t const&) const;
/// };
/// \endcode
template <typename View>
@@ -132,12 +134,12 @@ struct RandomAccessNDImageViewConcept
// point_t must be an N-dimensional point, each dimension of which must have the same type as difference_type of the corresponding iterator
gil_function_requires<PointNDConcept<point_t>>();
static_assert(point_t::num_dimensions == N, "");
static_assert(is_same
static_assert(std::is_same
<
typename std::iterator_traits<first_it_type>::difference_type,
typename point_t::template axis<0>::coord_t
>::value, "");
static_assert(is_same
static_assert(std::is_same
<
typename std::iterator_traits<last_it_type>::difference_type,
typename point_t::template axis<N-1>::coord_t
@@ -194,17 +196,17 @@ struct RandomAccessNDImageViewConcept
/// y_coord_t View::height() const;
///
/// // X-navigation
/// x_iterator View::x_at(const point_t&) const;
/// x_iterator View::x_at(point_t const&) const;
/// x_iterator View::row_begin(y_coord_t) const;
/// x_iterator View::row_end (y_coord_t) const;
///
/// // Y-navigation
/// y_iterator View::y_at(const point_t&) const;
/// y_iterator View::y_at(point_t const&) const;
/// y_iterator View::col_begin(x_coord_t) const;
/// y_iterator View::col_end (x_coord_t) const;
///
/// // navigating in 2D
/// xy_locator View::xy_at(const point_t&) const;
/// xy_locator View::xy_at(point_t const&) const;
///
/// // (x,y) versions of all methods taking point_t
/// View::View(x_coord_t,y_coord_t,const locator&);
@@ -379,7 +381,7 @@ struct ImageViewConcept
// TODO: This executes the requirements for RandomAccess2DLocatorConcept again. Fix it to improve compile time
gil_function_requires<PixelLocatorConcept<typename View::xy_locator>>();
static_assert(is_same<typename View::x_coord_t, typename View::y_coord_t>::value, "");
static_assert(std::is_same<typename View::x_coord_t, typename View::y_coord_t>::value, "");
using coord_t = typename View::coord_t; // 1D difference type (same for all dimensions)
std::size_t num_chan = view.num_channels(); ignore_unused_variable_warning(num_chan);
@@ -548,7 +550,7 @@ struct ViewsCompatibleConcept
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -16,19 +16,18 @@
#include <boost/gil/concepts/fwd.hpp>
#include <boost/gil/concepts/pixel_based.hpp>
#include <boost/gil/concepts/detail/type_traits.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <cstddef>
#include <type_traits>
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
@@ -192,7 +191,7 @@ struct HomogeneousPixelValueConcept
{
gil_function_requires<HomogeneousPixelConcept<P>>();
gil_function_requires<Regular<P>>();
static_assert(is_same<P, typename P::value_type>::value, "");
static_assert(std::is_same<P, typename P::value_type>::value, "");
}
};
@@ -200,24 +199,20 @@ namespace detail {
template <typename P1, typename P2, int K>
struct channels_are_pairwise_compatible
: public
mpl::and_
: mp11::mp_and
<
channels_are_pairwise_compatible<P1, P2, K - 1>,
channels_are_compatible
<
channels_are_pairwise_compatible<P1, P2, K - 1>,
channels_are_compatible
<
typename kth_semantic_element_reference_type<P1, K>::type,
typename kth_semantic_element_reference_type<P2, K>::type
>
typename kth_semantic_element_reference_type<P1, K>::type,
typename kth_semantic_element_reference_type<P2, K>::type
>
>
{
};
template <typename P1, typename P2>
struct channels_are_pairwise_compatible<P1, P2, -1>
: public mpl::true_
{
};
struct channels_are_pairwise_compatible<P1, P2, -1> : std::true_type {};
} // namespace detail
@@ -229,8 +224,7 @@ struct channels_are_pairwise_compatible<P1, P2, -1>
/// \tparam P2 Models PixelConcept
template <typename P1, typename P2>
struct pixels_are_compatible
: public
mpl::and_
: mp11::mp_and
<
typename color_spaces_are_compatible
<
@@ -298,7 +292,7 @@ struct PixelConvertibleConcept
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -18,10 +18,11 @@
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
@@ -96,7 +97,7 @@ struct HomogeneousPixelBasedConcept
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -15,16 +15,17 @@
#include <boost/gil/concepts/detail/type_traits.hpp>
#include <boost/concept_check.hpp>
#include <boost/type_traits.hpp>
#include <cstddef>
#include <type_traits>
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
@@ -93,8 +94,8 @@ struct PixelDereferenceAdaptorArchetype
using argument_type = P;
using result_type = P;
using const_t = PixelDereferenceAdaptorArchetype;
using value_type = typename remove_reference<P>::type;
using reference = typename add_reference<P>::type;
using value_type = typename std::remove_reference<P>::type;
using reference = typename std::add_lvalue_reference<P>::type;
using const_reference = reference;
static const bool is_mutable = false;
@@ -107,7 +108,7 @@ struct PixelDereferenceAdaptorArchetype
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -16,17 +16,18 @@
#include <boost/gil/concepts/pixel_based.hpp>
#include <boost/iterator/iterator_concepts.hpp>
#include <boost/mpl/bool.hpp>
#include <cstddef>
#include <iterator>
#include <type_traits>
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
@@ -112,7 +113,7 @@ struct PixelIteratorIsMutableConcept
{
gil_function_requires<detail::RandomAccessIteratorIsMutableConcept<Iterator>>();
using ref_t = typename remove_reference
using ref_t = typename std::remove_reference
<
typename std::iterator_traits<Iterator>::reference
>::type;
@@ -187,9 +188,9 @@ struct PixelIteratorConcept
check_base(typename is_iterator_adaptor<Iterator>::type());
}
void check_base(mpl::false_) {}
void check_base(std::false_type) {}
void check_base(mpl::true_)
void check_base(std::true_type)
{
using base_t = typename iterator_adaptor_get_base<Iterator>::type;
gil_function_requires<PixelIteratorConcept<base_t>>();
@@ -289,7 +290,7 @@ struct MutableStepIteratorConcept
///
/// In addition to GIL iterator requirements,
/// GIL iterator adaptors must provide the following metafunctions:
/// - \p is_iterator_adaptor<Iterator>: Returns \p mpl::true_
/// - \p is_iterator_adaptor<Iterator>: Returns \p std::true_type
/// - \p iterator_adaptor_get_base<Iterator>: Returns the base iterator type
/// - \p iterator_adaptor_rebind<Iterator,NewBase>: Replaces the base iterator with the new one
///
@@ -298,7 +299,7 @@ struct MutableStepIteratorConcept
/// \code
/// concept IteratorAdaptorConcept<boost_concepts::ForwardTraversalConcept Iterator>
/// {
/// where SameType<is_iterator_adaptor<Iterator>::type, mpl::true_>;
/// where SameType<is_iterator_adaptor<Iterator>::type, std::true_type>;
///
/// typename iterator_adaptor_get_base<Iterator>;
/// where Metafunction<iterator_adaptor_get_base<Iterator> >;
@@ -353,7 +354,7 @@ struct MutableIteratorAdaptorConcept
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -11,6 +11,7 @@
#include <boost/gil/concepts/basic.hpp>
#include <boost/gil/concepts/concept_check.hpp>
#include <boost/gil/concepts/fwd.hpp>
#include <boost/gil/concepts/pixel.hpp>
#include <boost/gil/concepts/pixel_dereference.hpp>
#include <boost/gil/concepts/pixel_iterator.hpp>
#include <boost/gil/concepts/point.hpp>
@@ -18,13 +19,15 @@
#include <cstddef>
#include <iterator>
#include <type_traits>
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
@@ -140,12 +143,12 @@ struct RandomAccessNDLocatorConcept
// have the same type as difference_type of the corresponding iterator
gil_function_requires<PointNDConcept<point_t>>();
static_assert(point_t::num_dimensions == N, "");
static_assert(is_same
static_assert(std::is_same
<
typename std::iterator_traits<first_it_type>::difference_type,
typename point_t::template axis<0>::coord_t
>::value, "");
static_assert(is_same
static_assert(std::is_same
<
typename std::iterator_traits<last_it_type>::difference_type,
typename point_t::template axis<N-1>::coord_t
@@ -293,7 +296,7 @@ struct PixelLocatorConcept
gil_function_requires<PixelIteratorConcept<typename Loc::x_iterator>>();
gil_function_requires<PixelIteratorConcept<typename Loc::y_iterator>>();
using coord_t = typename Loc::coord_t;
static_assert(is_same<typename Loc::x_coord_t, typename Loc::y_coord_t>::value, "");
static_assert(std::is_same<typename Loc::x_coord_t, typename Loc::y_coord_t>::value, "");
}
Loc loc;
};
@@ -401,7 +404,7 @@ struct MutablePixelLocatorConcept
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -15,10 +15,11 @@
#if defined(BOOST_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunused-local-typedefs"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
@@ -117,7 +118,7 @@ struct Point2DConcept
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
#pragma GCC diagnostic pop
#endif

View File

@@ -1,65 +0,0 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_DEPRECATED_HPP
#define BOOST_GIL_DEPRECATED_HPP
#include <cstddef>
/// This file is provided as a courtesy to ease upgrading GIL client code.
/// Please make sure your code compiles when this file is not included.
#define planar_ptr planar_pixel_iterator
#define planar_ref planar_pixel_reference
#define membased_2d_locator memory_based_2d_locator
#define pixel_step_iterator memory_based_step_iterator
#define pixel_image_iterator iterator_from_2d
#define equal_channels static_equal
#define copy_channels static_copy
#define fill_channels static_fill
#define generate_channels static_generate
#define for_each_channel static_for_each
#define transform_channels static_transform
#define max_channel static_max
#define min_channel static_min
#define semantic_channel semantic_at_c
template <typename Img>
void resize_clobber_image(Img& img, const typename Img::point_t& new_dims) {
img.recreate(new_dims);
}
template <typename Img>
void resize_clobber_image(Img& img, const typename Img::x_coord_t& width, const typename Img::y_coord_t& height) {
img.recreate(width,height);
}
template <typename T> typename T::x_coord_t get_width(const T& a) { return a.width(); }
template <typename T> typename T::y_coord_t get_height(const T& a) { return a.height(); }
template <typename T> typename T::point_t get_dimensions(const T& a) { return a.dimensions(); }
template <typename T> std::size_t get_num_channels(const T& a) { return a.num_channels(); }
#define GIL boost::gil
#define ADOBE_GIL_NAMESPACE_BEGIN namespace boost { namespace gil {
#define ADOBE_GIL_NAMESPACE_END } }
#define ByteAdvancableIteratorConcept MemoryBasedIteratorConcept
#define byte_advance memunit_advance
#define byte_advanced memunit_advanced
#define byte_step memunit_step
#define byte_distance memunit_distance
#define byte_addressable_step_iterator memory_based_step_iterator
#define byte_addressable_2d_locator memory_based_2d_locator
// These are members of memory-based locators
//#define row_bytes row_size // commented out because row_bytes is commonly used
#define pix_bytestep pixel_size
#endif

View File

@@ -0,0 +1,47 @@
//
// Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
// Copyright 2005-2007 Adobe Systems Incorporated
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_DETAIL_IS_CHANNEL_INTEGRAL_HPP
#define BOOST_GIL_DETAIL_IS_CHANNEL_INTEGRAL_HPP
#include <boost/gil/channel.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
template <typename ChannelValue>
struct is_channel_integral : std::is_integral<ChannelValue> {};
template <int NumBits>
struct is_channel_integral<boost::gil::packed_channel_value<NumBits>> : std::true_type {};
template <typename BitField, int FirstBit, int NumBits, bool IsMutable>
struct is_channel_integral
<
boost::gil::packed_channel_reference<BitField, FirstBit, NumBits, IsMutable>
> : std::true_type
{};
template <typename BitField, int NumBits, bool IsMutable>
struct is_channel_integral
<
boost::gil::packed_dynamic_channel_reference<BitField, NumBits, IsMutable>
> : std::true_type
{};
template <typename BaseChannelValue, typename MinVal, typename MaxVal>
struct is_channel_integral
<
boost::gil::scoped_channel_value<BaseChannelValue, MinVal, MaxVal>
> : std::is_integral<BaseChannelValue>
{};
}}} //namespace boost::gil::detail
#endif

View File

@@ -0,0 +1,33 @@
//
// Copyright 2019 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
//
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_GIL_IMAGE_PROCESSING_DETAIL_MATH_HPP
#define BOOST_GIL_IMAGE_PROCESSING_DETAIL_MATH_HPP
#include <array>
#include <boost/gil/image_processing/kernel.hpp>
namespace boost { namespace gil { namespace detail {
static constexpr double pi = 3.14159265358979323846;
static constexpr std::array<float, 9> dx_sobel = {{-1, 0, 1, -2, 0, 2, -1, 0, 1}};
static constexpr std::array<float, 9> dx_scharr = {{-1, 0, 1, -1, 0, 1, -1, 0, 1}};
static constexpr std::array<float, 9> dy_sobel = {{1, 2, 1, 0, 0, 0, -1, -2, -1}};
static constexpr std::array<float, 9> dy_scharr = {{1, 1, 1, 0, 0, 0, -1, -1, -1}};
template <typename T, typename Allocator>
inline auto get_identity_kernel() -> detail::kernel_2d<T, Allocator>
{
detail::kernel_2d<T, Allocator> kernel(1, 0, 0);
kernel[0] = 1;
return kernel;
}
}}} // namespace boost::gil::detail
#endif

View File

@@ -0,0 +1,25 @@
//
// Copyright 2017 Peter Dimov.
// Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_DETAIL_MP11_HPP
#define BOOST_GIL_DETAIL_MP11_HPP
#include <boost/mp11.hpp>
namespace boost { namespace gil { namespace detail {
template<typename L>
using mp_back = ::boost::mp11::mp_at_c<L, ::boost::mp11::mp_size<L>::value - 1>;
template<typename L>
using mp_pop_back = ::boost::mp11::mp_take_c<L, ::boost::mp11::mp_size<L>::value - 1>;
}}} // namespace boost::gil::detail
#endif

View File

@@ -0,0 +1,39 @@
//
// Copyright Louis Dionne 2013-2017
//
// Distributed under the Boost Software License, Version 1.0.
//(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_GIL_DETAIL_STD_COMMON_TYPE_HPP
#define BOOST_GIL_DETAIL_STD_COMMON_TYPE_HPP
#include <type_traits>
#include <utility>
namespace boost { namespace gil { namespace detail {
// Defines a SFINAE-friendly version of `std::common_type`.
//
// Based on boost/hana/detail/std_common_type.hpp
// Equivalent to `std::common_type`, except it is SFINAE-friendly and
// does not support custom specializations.
template <typename T, typename U, typename = void>
struct std_common_type {};
template <typename T, typename U>
struct std_common_type
<
T, U,
decltype((void)(true ? std::declval<T>() : std::declval<U>()))
>
{
using type = typename std::decay
<
decltype(true ? std::declval<T>() : std::declval<U>())
>::type;
};
}}} // namespace boost::gil::detail
#endif

View File

@@ -0,0 +1,39 @@
//
// Copyright 2017-2019 Peter Dimov.
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_DETAIL_TYPE_TRAITS_HPP
#define BOOST_GIL_DETAIL_TYPE_TRAITS_HPP
#include <boost/config.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 50100
template<class T>
struct is_trivially_default_constructible
: std::integral_constant
<
bool,
std::is_default_constructible<T>::value &&
std::has_trivial_default_constructor<T>::value
>
{};
#else
using std::is_trivially_default_constructible;
#endif
using std::is_trivially_destructible;
}}} //namespace boost::gil::detail
#endif

View File

@@ -10,51 +10,57 @@
#include <boost/gil/metafunctions.hpp>
#include <boost/gil/utilities.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <boost/config.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/type_traits.hpp>
#include <cstddef>
#include <type_traits>
namespace boost { namespace gil {
// TODO: Document the DeviceN Color Space and Color Model
// with reference to the Adobe documentation
// https://www.adobe.com/content/dam/acom/en/devnet/postscript/pdfs/TN5604.DeviceN_Color.pdf
/// \brief unnamed color
/// \ingroup ColorNameModel
template <int N> struct devicen_color_t {};
template <int N>
struct devicen_color_t {};
template <int N> struct devicen_t;
template <int N>
struct devicen_t;
/// \brief unnamed color space of one channel
/// \brief Unnamed color space of 1, 2, 3, 4, or 5 channels
/// \tparam N Number of color components (1, 2, 3, 4 or 5).
/// \ingroup ColorSpaceModel
template <> struct devicen_t<1> : public mpl::vector1<devicen_color_t<0> > {};
template <int N>
struct devicen_t
{
private:
template <typename T>
using color_t = devicen_color_t<T::value>;
/// \brief unnamed color space of two channels
/// \ingroup ColorSpaceModel
template <> struct devicen_t<2> : public mpl::vector2<devicen_color_t<0>, devicen_color_t<1> > {};
static_assert(
(1 <= N && N <= 5),
"invalid number of DeviceN color components");
/// \brief unnamed color space of three channels
/// \ingroup ColorSpaceModel
template <> struct devicen_t<3> : public mpl::vector3<devicen_color_t<0>, devicen_color_t<1>, devicen_color_t<2> > {};
/// \brief unnamed color space of four channels
/// \ingroup ColorSpaceModel
template <> struct devicen_t<4> : public mpl::vector4<devicen_color_t<0>, devicen_color_t<1>, devicen_color_t<2>, devicen_color_t<3> > {};
/// \brief unnamed color space of five channels
/// \ingroup ColorSpaceModel
template <> struct devicen_t<5> : public mpl::vector5<devicen_color_t<0>, devicen_color_t<1>, devicen_color_t<2>, devicen_color_t<3>, devicen_color_t<4> > {};
public:
using type = mp11::mp_transform<color_t, mp11::mp_iota_c<N>>;
};
/// \brief unnamed color layout of up to five channels
/// \ingroup LayoutModel
template <int N> struct devicen_layout_t : public layout<devicen_t<N> > {};
template <int N>
struct devicen_layout_t : layout<typename devicen_t<N>::type> {};
/// \ingroup ImageViewConstructors
/// \brief from 2-channel planar data
template <typename IC>
inline typename type_from_x_iterator<planar_pixel_iterator<IC,devicen_t<2>>>::view_t
planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, std::ptrdiff_t rowsize_in_bytes)
inline
auto planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, std::ptrdiff_t rowsize_in_bytes)
-> typename type_from_x_iterator<planar_pixel_iterator<IC,devicen_t<2>>>::view_t
{
using view_t = typename type_from_x_iterator<planar_pixel_iterator<IC,devicen_t<2>>>::view_t;
return view_t(width, height, typename view_t::locator(typename view_t::x_iterator(c0,c1), rowsize_in_bytes));
@@ -63,8 +69,9 @@ planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, std::pt
/// \ingroup ImageViewConstructors
/// \brief from 3-channel planar data
template <typename IC>
inline typename type_from_x_iterator<planar_pixel_iterator<IC,devicen_t<3>>>::view_t
planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, IC c2, std::ptrdiff_t rowsize_in_bytes)
inline
auto planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, IC c2, std::ptrdiff_t rowsize_in_bytes)
-> typename type_from_x_iterator<planar_pixel_iterator<IC,devicen_t<3>>>::view_t
{
using view_t = typename type_from_x_iterator<planar_pixel_iterator<IC,devicen_t<3>>>::view_t;
return view_t(width, height, typename view_t::locator(typename view_t::x_iterator(c0,c1,c2), rowsize_in_bytes));
@@ -73,8 +80,9 @@ planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, IC c2,
/// \ingroup ImageViewConstructors
/// \brief from 4-channel planar data
template <typename IC>
inline typename type_from_x_iterator<planar_pixel_iterator<IC,devicen_t<4>>>::view_t
planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, IC c2, IC c3, std::ptrdiff_t rowsize_in_bytes)
inline
auto planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, IC c2, IC c3, std::ptrdiff_t rowsize_in_bytes)
-> typename type_from_x_iterator<planar_pixel_iterator<IC,devicen_t<4>>>::view_t
{
using view_t = typename type_from_x_iterator<planar_pixel_iterator<IC,devicen_t<4>>>::view_t;
return view_t(width, height, typename view_t::locator(typename view_t::x_iterator(c0,c1,c2,c3), rowsize_in_bytes));
@@ -83,13 +91,14 @@ planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, IC c2,
/// \ingroup ImageViewConstructors
/// \brief from 5-channel planar data
template <typename IC>
inline typename type_from_x_iterator<planar_pixel_iterator<IC,devicen_t<5>>>::view_t
planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, IC c2, IC c3, IC c4, std::ptrdiff_t rowsize_in_bytes)
inline
auto planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, IC c2, IC c3, IC c4, std::ptrdiff_t rowsize_in_bytes)
-> typename type_from_x_iterator<planar_pixel_iterator<IC,devicen_t<5>>>::view_t
{
using view_t = typename type_from_x_iterator<planar_pixel_iterator<IC,devicen_t<5>>>::view_t;
return view_t(width, height, typename view_t::locator(typename view_t::x_iterator(c0,c1,c2,c3,c4), rowsize_in_bytes));
}
} } // namespace boost::gil
}} // namespace boost::gil
#endif

View File

@@ -1,5 +1,6 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2022 Marco Langer <langer.m86 at gmail dot com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
@@ -12,7 +13,10 @@
#include <boost/gil/algorithm.hpp>
#include <boost/variant2/variant.hpp>
#include <functional>
#include <utility>
////////////////////////////////////////////////////////////////////////////////////////
/// \file
@@ -40,34 +44,34 @@ struct equal_pixels_fn : binary_operation_obj<equal_pixels_fn, bool>
} // namespace detail
/// \ingroup ImageViewSTLAlgorithmsEqualPixels
/// \tparam Types Model MPL Random Access Container of models of ImageViewConcept
/// \tparam Types Model Boost.MP11-compatible list of models of ImageViewConcept
/// \tparam View Model MutableImageViewConcept
template <typename Types, typename View>
bool equal_pixels(any_image_view<Types> const& src, View const& dst)
template <typename ...Types, typename View>
auto equal_pixels(any_image_view<Types...> const& src, View const& dst) -> bool
{
return apply_operation(
src,
std::bind(detail::equal_pixels_fn(), std::placeholders::_1, dst));
return variant2::visit(
std::bind(detail::equal_pixels_fn(), std::placeholders::_1, dst),
src);
}
/// \ingroup ImageViewSTLAlgorithmsEqualPixels
/// \tparam View Model ImageViewConcept
/// \tparam Types Model MPL Random Access Container of models of MutableImageViewConcept
template <typename View, typename Types>
bool equal_pixels(View const& src, any_image_view<Types> const& dst)
/// \tparam Types Model Boost.MP11-compatible list of models of MutableImageViewConcept
template <typename View, typename ...Types>
auto equal_pixels(View const& src, any_image_view<Types...> const& dst) -> bool
{
return apply_operation(
dst,
std::bind(detail::equal_pixels_fn(), src, std::placeholders::_1));
return variant2::visit(
std::bind(detail::equal_pixels_fn(), src, std::placeholders::_1),
dst);
}
/// \ingroup ImageViewSTLAlgorithmsEqualPixels
/// \tparam Types1 Model MPL Random Access Container of models of ImageViewConcept
/// \tparam Types2 Model MPL Random Access Container of models of MutableImageViewConcept
template <typename Types1, typename Types2>
bool equal_pixels(any_image_view<Types1> const& src, any_image_view<Types2> const& dst)
/// \tparam Types1 Model Boost.MP11-compatible list of models of ImageViewConcept
/// \tparam Types2 Model Boost.MP11-compatible list of models of MutableImageViewConcept
template <typename ...Types1, typename ...Types2>
auto equal_pixels(any_image_view<Types1...> const& src, any_image_view<Types2...> const& dst) -> bool
{
return apply_operation(src, dst, detail::equal_pixels_fn());
return variant2::visit(detail::equal_pixels_fn(), src, dst);
}
namespace detail {
@@ -85,99 +89,99 @@ struct copy_pixels_fn : public binary_operation_obj<copy_pixels_fn>
} // namespace detail
/// \ingroup ImageViewSTLAlgorithmsCopyPixels
/// \tparam Types Model MPL Random Access Container of models of ImageViewConcept
/// \tparam Types Model Boost.MP11-compatible list of models of ImageViewConcept
/// \tparam View Model MutableImageViewConcept
template <typename Types, typename View>
void copy_pixels(any_image_view<Types> const& src, View const& dst)
template <typename ...Types, typename View>
void copy_pixels(any_image_view<Types...> const& src, View const& dst)
{
apply_operation(src, std::bind(detail::copy_pixels_fn(), std::placeholders::_1, dst));
variant2::visit(std::bind(detail::copy_pixels_fn(), std::placeholders::_1, dst), src);
}
/// \ingroup ImageViewSTLAlgorithmsCopyPixels
/// \tparam Types Model MPL Random Access Container of models of MutableImageViewConcept
/// \tparam Types Model Boost.MP11-compatible list of models of MutableImageViewConcept
/// \tparam View Model ImageViewConcept
template <typename Types, typename View>
void copy_pixels(View const& src, any_image_view<Types> const& dst)
template <typename ...Types, typename View>
void copy_pixels(View const& src, any_image_view<Types...> const& dst)
{
apply_operation(dst, std::bind(detail::copy_pixels_fn(), src, std::placeholders::_1));
variant2::visit(std::bind(detail::copy_pixels_fn(), src, std::placeholders::_1), dst);
}
/// \ingroup ImageViewSTLAlgorithmsCopyPixels
/// \tparam Types1 Model MPL Random Access Container of models of ImageViewConcept
/// \tparam Types2 Model MPL Random Access Container of models of MutableImageViewConcept
template <typename Types1, typename Types2>
void copy_pixels(any_image_view<Types1> const& src, any_image_view<Types2> const& dst)
/// \tparam Types1 Model Boost.MP11-compatible list of models of ImageViewConcept
/// \tparam Types2 Model Boost.MP11-compatible list of models of MutableImageViewConcept
template <typename ...Types1, typename ...Types2>
void copy_pixels(any_image_view<Types1...> const& src, any_image_view<Types2...> const& dst)
{
apply_operation(src, dst, detail::copy_pixels_fn());
variant2::visit(detail::copy_pixels_fn(), src, dst);
}
//forward declaration for default_color_converter (see full definition in color_convert.hpp)
struct default_color_converter;
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
/// \tparam Types Model MPL Random Access Container of models of ImageViewConcept
/// \tparam Types Model Boost.MP11-compatible list of models of ImageViewConcept
/// \tparam View Model MutableImageViewConcept
/// \tparam CC Model ColorConverterConcept
template <typename Types, typename View, typename CC>
void copy_and_convert_pixels(any_image_view<Types> const& src, View const& dst, CC cc)
template <typename ...Types, typename View, typename CC>
void copy_and_convert_pixels(any_image_view<Types...> const& src, View const& dst, CC cc)
{
using cc_fn = detail::copy_and_convert_pixels_fn<CC>;
apply_operation(src, std::bind(cc_fn{cc}, std::placeholders::_1, dst));
variant2::visit(std::bind(cc_fn{cc}, std::placeholders::_1, dst), src);
}
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
/// \tparam Types Model MPL Random Access Container of models of ImageViewConcept
/// \tparam Types Model Boost.MP11-compatible list of models of ImageViewConcept
/// \tparam View Model MutableImageViewConcept
template <typename Types, typename View>
void copy_and_convert_pixels(any_image_view<Types> const& src, View const& dst)
template <typename ...Types, typename View>
void copy_and_convert_pixels(any_image_view<Types...> const& src, View const& dst)
{
using cc_fn = detail::copy_and_convert_pixels_fn<default_color_converter>;
apply_operation(src, std::bind(cc_fn{}, std::placeholders::_1, dst));
variant2::visit(std::bind(cc_fn{}, std::placeholders::_1, dst), src);
}
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
/// \tparam View Model ImageViewConcept
/// \tparam Types Model MPL Random Access Container of models of MutableImageViewConcept
/// \tparam Types Model Boost.MP11-compatible list of models of MutableImageViewConcept
/// \tparam CC Model ColorConverterConcept
template <typename View, typename Types, typename CC>
void copy_and_convert_pixels(View const& src, any_image_view<Types> const& dst, CC cc)
template <typename View, typename ...Types, typename CC>
void copy_and_convert_pixels(View const& src, any_image_view<Types...> const& dst, CC cc)
{
using cc_fn = detail::copy_and_convert_pixels_fn<CC>;
apply_operation(dst, std::bind(cc_fn{cc}, src, std::placeholders::_1));
variant2::visit(std::bind(cc_fn{cc}, src, std::placeholders::_1), dst);
}
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
/// \tparam View Model ImageViewConcept
/// \tparam Type Model MPL Random Access Container of models of MutableImageViewConcept
template <typename View, typename Types>
void copy_and_convert_pixels(View const& src, any_image_view<Types> const& dst)
/// \tparam Type Model Boost.MP11-compatible list of models of MutableImageViewConcept
template <typename View, typename ...Types>
void copy_and_convert_pixels(View const& src, any_image_view<Types...> const& dst)
{
using cc_fn = detail::copy_and_convert_pixels_fn<default_color_converter>;
apply_operation(dst, std::bind(cc_fn{}, src, std::placeholders::_1));
variant2::visit(std::bind(cc_fn{}, src, std::placeholders::_1), dst);
}
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
/// \tparam Types1 Model MPL Random Access Container of models of ImageViewConcept
/// \tparam Types2 Model MPL Random Access Container of models of MutableImageViewConcept
/// \tparam Types1 Model Boost.MP11-compatible list of models of ImageViewConcept
/// \tparam Types2 Model Boost.MP11-compatible list of models of MutableImageViewConcept
/// \tparam CC Model ColorConverterConcept
template <typename Types1, typename Types2, typename CC>
template <typename ...Types1, typename ...Types2, typename CC>
void copy_and_convert_pixels(
any_image_view<Types1> const& src,
any_image_view<Types2> const& dst, CC cc)
any_image_view<Types1...> const& src,
any_image_view<Types2...> const& dst, CC cc)
{
apply_operation(src, dst, detail::copy_and_convert_pixels_fn<CC>(cc));
variant2::visit(detail::copy_and_convert_pixels_fn<CC>(cc), src, dst);
}
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
/// \tparam Types1 Model MPL Random Access Container of models of ImageViewConcept
/// \tparam Types2 Model MPL Random Access Container of models of MutableImageViewConcept
template <typename Types1, typename Types2>
/// \tparam Types1 Model Boost.MP11-compatible list of models of ImageViewConcept
/// \tparam Types2 Model Boost.MP11-compatible list of models of MutableImageViewConcept
template <typename ...Types1, typename ...Types2>
void copy_and_convert_pixels(
any_image_view<Types1> const& src,
any_image_view<Types2> const& dst)
any_image_view<Types1...> const& src,
any_image_view<Types2...> const& dst)
{
apply_operation(src, dst,
detail::copy_and_convert_pixels_fn<default_color_converter>());
variant2::visit(
detail::copy_and_convert_pixels_fn<default_color_converter>(), src, dst);
}
namespace detail {
@@ -186,7 +190,7 @@ template <bool IsCompatible>
struct fill_pixels_fn1
{
template <typename V, typename Value>
static void apply(V const &src, Value const &val) { fill_pixels(src, val); }
static void apply(V const& src, Value const& val) { fill_pixels(src, val); }
};
// copy_pixels invoked on incompatible images
@@ -194,7 +198,7 @@ template <>
struct fill_pixels_fn1<false>
{
template <typename V, typename Value>
static void apply(V const &, Value const &) { throw std::bad_cast();}
static void apply(V const&, Value const&) { throw std::bad_cast();}
};
template <typename Value>
@@ -223,11 +227,40 @@ struct fill_pixels_fn
/// \ingroup ImageViewSTLAlgorithmsFillPixels
/// \brief fill_pixels for any image view. The pixel to fill with must be compatible with the current view
/// \tparam Types Model MPL Random Access Container of models of MutableImageViewConcept
template <typename Types, typename Value>
void fill_pixels(any_image_view<Types> const& view, Value const& val)
/// \tparam Types Model Boost.MP11-compatible list of models of MutableImageViewConcept
template <typename ...Types, typename Value>
void fill_pixels(any_image_view<Types...> const& view, Value const& val)
{
apply_operation(view, detail::fill_pixels_fn<Value>(val));
variant2::visit(detail::fill_pixels_fn<Value>(val), view);
}
namespace detail {
template <typename F>
struct for_each_pixel_fn
{
for_each_pixel_fn(F&& fun) : fun_(std::move(fun)) {}
template <typename View>
auto operator()(View const& view) -> F
{
return for_each_pixel(view, fun_);
}
F fun_;
};
} // namespace detail
/// \defgroup ImageViewSTLAlgorithmsForEachPixel for_each_pixel
/// \ingroup ImageViewSTLAlgorithms
/// \brief std::for_each for any image views
///
/// \ingroup ImageViewSTLAlgorithmsForEachPixel
template <typename ...Types, typename F>
auto for_each_pixel(any_image_view<Types...> const& view, F fun) -> F
{
return variant2::visit(detail::for_each_pixel_fn<F>(std::move(fun)), view);
}
}} // namespace boost::gil

View File

@@ -1,5 +1,6 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2020 Samuel Debionne
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
@@ -9,11 +10,12 @@
#define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_ANY_IMAGE_HPP
#include <boost/gil/extension/dynamic_image/any_image_view.hpp>
#include <boost/gil/extension/dynamic_image/apply_operation.hpp>
#include <boost/gil/image.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <boost/config.hpp>
#include <boost/variant2/variant.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
@@ -23,35 +25,53 @@
namespace boost { namespace gil {
namespace detail {
template <typename T> struct get_view_t { using type = typename T::view_t; };
template <typename Images> struct images_get_views_t : public mpl::transform<Images, get_view_t<mpl::_1> > {};
template <typename T> struct get_const_view_t { using type = typename T::const_view_t; };
template <typename Images> struct images_get_const_views_t : public mpl::transform<Images, get_const_view_t<mpl::_1> > {};
template <typename T>
using get_view_t = typename T::view_t;
struct recreate_image_fnobj
template <typename Images>
using images_get_views_t = mp11::mp_transform<get_view_t, Images>;
template <typename T>
using get_const_view_t = typename T::const_view_t;
template <typename Images>
using images_get_const_views_t = mp11::mp_transform<get_const_view_t, Images>;
struct recreate_image_fnobj
{
using result_type = void;
point<std::ptrdiff_t> const& _dimensions;
unsigned _alignment;
recreate_image_fnobj(point<std::ptrdiff_t> const& dims, unsigned alignment)
: _dimensions(dims), _alignment(alignment)
{}
template <typename Image>
result_type operator()(Image& img) const { img.recreate(_dimensions,_alignment); }
};
template <typename AnyView> // Models AnyViewConcept
struct any_image_get_view
{
using result_type = AnyView;
template <typename Image>
result_type operator()(Image& img) const
{
using result_type = void;
point<std::ptrdiff_t> const& _dimensions;
unsigned _alignment;
return result_type(view(img));
}
};
recreate_image_fnobj(point<std::ptrdiff_t> const& dims, unsigned alignment) : _dimensions(dims), _alignment(alignment) {}
template <typename Image>
result_type operator()(Image& img) const { img.recreate(_dimensions,_alignment); }
};
template <typename AnyConstView> // Models AnyConstViewConcept
struct any_image_get_const_view
{
using result_type = AnyConstView;
template <typename Image>
result_type operator()(Image const& img) const { return result_type{const_view(img)}; }
};
template <typename AnyView> // Models AnyViewConcept
struct any_image_get_view {
using result_type = AnyView;
template <typename Image> result_type operator()( Image& img) const { return result_type(view(img)); }
};
template <typename AnyConstView> // Models AnyConstViewConcept
struct any_image_get_const_view {
using result_type = AnyConstView;
template <typename Image> result_type operator()(const Image& img) const { return result_type(const_view(img)); }
};
}
} // namespce detail
////////////////////////////////////////////////////////////////////////////////////////
/// \ingroup ImageModel
@@ -63,40 +83,63 @@ namespace detail {
/// Other requirements, such as access to the pixels, would be inefficient to provide. Thus \p any_image does not fully model ImageConcept.
/// In particular, its \p view and \p const_view methods return \p any_image_view, which does not fully model ImageViewConcept. See \p any_image_view for more.
////////////////////////////////////////////////////////////////////////////////////////
template <typename ImageTypes>
class any_image : public make_variant_over<ImageTypes>::type {
using parent_t = typename make_variant_over<ImageTypes>::type;
template <typename ...Images>
class any_image : public variant2::variant<Images...>
{
using parent_t = variant2::variant<Images...>;
public:
using const_view_t = any_image_view<typename detail::images_get_const_views_t<ImageTypes>::type>;
using view_t = any_image_view<typename detail::images_get_views_t<ImageTypes>::type>;
using view_t = mp11::mp_rename<detail::images_get_views_t<any_image>, any_image_view>;
using const_view_t = mp11::mp_rename<detail::images_get_const_views_t<any_image>, any_image_view>;
using x_coord_t = std::ptrdiff_t;
using y_coord_t = std::ptrdiff_t;
using point_t = point<std::ptrdiff_t>;
any_image() : parent_t() {}
template <typename T> explicit any_image(const T& obj) : parent_t(obj) {}
template <typename T> explicit any_image(T& obj, bool do_swap) : parent_t(obj,do_swap) {}
any_image(const any_image& v) : parent_t((const parent_t&)v) {}
template <typename Types> any_image(const any_image<Types>& v) : parent_t((const typename make_variant_over<Types>::type&)v) {}
using parent_t::parent_t;
template <typename T> any_image& operator=(const T& obj) { parent_t::operator=(obj); return *this; }
any_image& operator=(const any_image& v) { parent_t::operator=((const parent_t&)v); return *this;}
template <typename Types> any_image& operator=(const any_image<Types>& v) { parent_t::operator=((const typename make_variant_over<Types>::type&)v); return *this;}
void recreate(const point_t& dims, unsigned alignment=1)
any_image& operator=(any_image const& img)
{
apply_operation(*this,detail::recreate_image_fnobj(dims,alignment));
parent_t::operator=((parent_t const&)img);
return *this;
}
template <typename Image>
any_image& operator=(Image const& img)
{
parent_t::operator=(img);
return *this;
}
template <typename ...OtherImages>
any_image& operator=(any_image<OtherImages...> const& img)
{
parent_t::operator=((typename variant2::variant<OtherImages...> const&)img);
return *this;
}
void recreate(point_t const& dims, unsigned alignment=1)
{
variant2::visit(detail::recreate_image_fnobj(dims, alignment), *this);
}
void recreate(x_coord_t width, y_coord_t height, unsigned alignment=1)
{
recreate({width, height}, alignment);
recreate({ width, height }, alignment);
}
std::size_t num_channels() const { return apply_operation(*this, detail::any_type_get_num_channels()); }
point_t dimensions() const { return apply_operation(*this, detail::any_type_get_dimensions()); }
x_coord_t width() const { return dimensions().x; }
y_coord_t height() const { return dimensions().y; }
std::size_t num_channels() const
{
return variant2::visit(detail::any_type_get_num_channels(), *this);
}
point_t dimensions() const
{
return variant2::visit(detail::any_type_get_dimensions(), *this);
}
x_coord_t width() const { return dimensions().x; }
y_coord_t height() const { return dimensions().y; }
};
///@{
@@ -106,15 +149,23 @@ public:
/// \ingroup ImageModel
/// \brief Returns the non-constant-pixel view of any image. The returned view is any view.
template <typename Types> BOOST_FORCEINLINE // Models ImageVectorConcept
typename any_image<Types>::view_t view(any_image<Types>& anyImage) {
return apply_operation(anyImage, detail::any_image_get_view<typename any_image<Types>::view_t>());
/// \tparam Images Models ImageVectorConcept
template <typename ...Images>
BOOST_FORCEINLINE
auto view(any_image<Images...>& img) -> typename any_image<Images...>::view_t
{
using view_t = typename any_image<Images...>::view_t;
return variant2::visit(detail::any_image_get_view<view_t>(), img);
}
/// \brief Returns the constant-pixel view of any image. The returned view is any view.
template <typename Types> BOOST_FORCEINLINE // Models ImageVectorConcept
typename any_image<Types>::const_view_t const_view(const any_image<Types>& anyImage) {
return apply_operation(anyImage, detail::any_image_get_const_view<typename any_image<Types>::const_view_t>());
/// \tparam Types Models ImageVectorConcept
template <typename ...Images>
BOOST_FORCEINLINE
auto const_view(any_image<Images...> const& img) -> typename any_image<Images...>::const_view_t
{
using view_t = typename any_image<Images...>::const_view_t;
return variant2::visit(detail::any_image_get_const_view<view_t>(), img);
}
///@}

View File

@@ -1,5 +1,6 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2020 Samuel Debionne
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
@@ -12,36 +13,48 @@
#include <boost/gil/image.hpp>
#include <boost/gil/image_view.hpp>
#include <boost/gil/point.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <boost/variant.hpp>
#include <boost/variant2/variant.hpp>
namespace boost { namespace gil {
namespace detail {
template <typename View> struct get_const_t { using type = typename View::const_t; };
template <typename Views> struct views_get_const_t : public mpl::transform<Views, get_const_t<mpl::_1> > {};
}
template <typename View> struct dynamic_xy_step_transposed_type;
template <typename View>
struct dynamic_xy_step_transposed_type;
namespace detail {
// works for both image_view and image
struct any_type_get_num_channels
{
using result_type = int;
template <typename T>
result_type operator()(const T&) const { return num_channels<T>::value; }
};
template <typename View>
using get_const_t = typename View::const_t;
// works for both image_view and image
struct any_type_get_dimensions
{
using result_type = point<std::ptrdiff_t>;
template <typename T>
result_type operator()(const T& v) const { return v.dimensions(); }
};
}
template <typename Views>
using views_get_const_t = mp11::mp_transform<get_const_t, Views>;
// works for both image_view and image
struct any_type_get_num_channels
{
using result_type = int;
template <typename T>
result_type operator()(const T&) const { return num_channels<T>::value; }
};
// works for both image_view and image
struct any_type_get_dimensions
{
using result_type = point<std::ptrdiff_t>;
template <typename T>
result_type operator()(const T& v) const { return v.dimensions(); }
};
// works for image_view
struct any_type_get_size
{
using result_type = std::size_t;
template <typename T>
result_type operator()(const T& v) const { return v.size(); }
};
} // namespace detail
////////////////////////////////////////////////////////////////////////////////////////
/// CLASS any_image_view
@@ -55,28 +68,46 @@ namespace detail {
/// Other requirements, such as access to the pixels, would be inefficient to provide. Thus \p any_image_view does not fully model ImageViewConcept.
/// However, many algorithms provide overloads taking runtime specified views and thus in many cases \p any_image_view can be used in places taking a view.
///
/// To perform an algorithm on any_image_view, put the algorithm in a function object and invoke it by calling \p apply_operation(runtime_view, algorithm_fn);
/// To perform an algorithm on any_image_view, put the algorithm in a function object and invoke it by calling \p variant2::visit(algorithm_fn, runtime_view);
////////////////////////////////////////////////////////////////////////////////////////
template <typename ImageViewTypes>
class any_image_view : public make_variant_over<ImageViewTypes>::type {
using parent_t = typename make_variant_over<ImageViewTypes>::type;
template <typename ...Views>
class any_image_view : public variant2::variant<Views...>
{
using parent_t = variant2::variant<Views...>;
public:
using const_t = any_image_view<typename detail::views_get_const_t<ImageViewTypes>::type>;
using const_t = detail::views_get_const_t<any_image_view>;
using x_coord_t = std::ptrdiff_t;
using y_coord_t = std::ptrdiff_t;
using point_t = point<std::ptrdiff_t>;
using size_type = std::size_t;
any_image_view() : parent_t() {}
template <typename T> explicit any_image_view(const T& obj) : parent_t(obj) {}
any_image_view(const any_image_view& v) : parent_t((const parent_t&)v) {}
template <typename Types> any_image_view(const any_image_view<Types>& v) : parent_t((const typename make_variant_over<Types>::type&)v) {}
using parent_t::parent_t;
template <typename T> any_image_view& operator=(const T& obj) { parent_t::operator=(obj); return *this; }
any_image_view& operator=(const any_image_view& v) { parent_t::operator=((const parent_t&)v); return *this;}
template <typename Types> any_image_view& operator=(const any_image_view<Types>& v) { parent_t::operator=((const typename make_variant_over<Types>::type&)v); return *this;}
any_image_view& operator=(any_image_view const& view)
{
parent_t::operator=((parent_t const&)view);
return *this;
}
std::size_t num_channels() const { return apply_operation(*this, detail::any_type_get_num_channels()); }
point_t dimensions() const { return apply_operation(*this, detail::any_type_get_dimensions()); }
template <typename View>
any_image_view& operator=(View const& view)
{
parent_t::operator=(view);
return *this;
}
template <typename ...OtherViews>
any_image_view& operator=(any_image_view<OtherViews...> const& view)
{
parent_t::operator=((variant2::variant<OtherViews...> const&)view);
return *this;
}
std::size_t num_channels() const { return variant2::visit(detail::any_type_get_num_channels(), *this); }
point_t dimensions() const { return variant2::visit(detail::any_type_get_dimensions(), *this); }
size_type size() const { return variant2::visit(detail::any_type_get_size(), *this); }
x_coord_t width() const { return dimensions().x; }
y_coord_t height() const { return dimensions().y; }
};
@@ -85,32 +116,68 @@ public:
// HasDynamicXStepTypeConcept
/////////////////////////////
template <typename IVTypes>
struct dynamic_x_step_type<any_image_view<IVTypes>>
template <typename ...Views>
struct dynamic_x_step_type<any_image_view<Views...>>
{
using type = any_image_view<typename mpl::transform<IVTypes, dynamic_x_step_type<mpl::_1>>::type>;
private:
// FIXME: Remove class name injection with gil:: qualification
// Required as workaround for Boost.MP11 issue that treats unqualified metafunction
// in the class definition of the same name as the specialization (Peter Dimov):
// invalid template argument for template parameter 'F', expected a class template
template <typename T>
using dynamic_step_view = typename gil::dynamic_x_step_type<T>::type;
public:
using type = mp11::mp_transform<dynamic_step_view, any_image_view<Views...>>;
};
/////////////////////////////
// HasDynamicYStepTypeConcept
/////////////////////////////
template <typename IVTypes>
struct dynamic_y_step_type<any_image_view<IVTypes>>
template <typename ...Views>
struct dynamic_y_step_type<any_image_view<Views...>>
{
using type = any_image_view<typename mpl::transform<IVTypes, dynamic_y_step_type<mpl::_1>>::type>;
private:
// FIXME: Remove class name injection with gil:: qualification
// Required as workaround for Boost.MP11 issue that treats unqualified metafunction
// in the class definition of the same name as the specialization (Peter Dimov):
// invalid template argument for template parameter 'F', expected a class template
template <typename T>
using dynamic_step_view = typename gil::dynamic_y_step_type<T>::type;
public:
using type = mp11::mp_transform<dynamic_step_view, any_image_view<Views...>>;
};
template <typename IVTypes>
struct dynamic_xy_step_type<any_image_view<IVTypes>>
template <typename ...Views>
struct dynamic_xy_step_type<any_image_view<Views...>>
{
using type = any_image_view<typename mpl::transform<IVTypes, dynamic_xy_step_type<mpl::_1>>::type>;
private:
// FIXME: Remove class name injection with gil:: qualification
// Required as workaround for Boost.MP11 issue that treats unqualified metafunction
// in the class definition of the same name as the specialization (Peter Dimov):
// invalid template argument for template parameter 'F', expected a class template
template <typename T>
using dynamic_step_view = typename gil::dynamic_xy_step_type<T>::type;
public:
using type = mp11::mp_transform<dynamic_step_view, any_image_view<Views...>>;
};
template <typename IVTypes>
struct dynamic_xy_step_transposed_type<any_image_view<IVTypes>>
template <typename ...Views>
struct dynamic_xy_step_transposed_type<any_image_view<Views...>>
{
using type = any_image_view<typename mpl::transform<IVTypes, dynamic_xy_step_transposed_type<mpl::_1>>::type>;
private:
// FIXME: Remove class name injection with gil:: qualification
// Required as workaround for Boost.MP11 issue that treats unqualified metafunction
// in the class definition of the same name as the specialization (Peter Dimov):
// invalid template argument for template parameter 'F', expected a class template
template <typename T>
using dynamic_step_view = typename gil::dynamic_xy_step_type<T>::type;
public:
using type = mp11::mp_transform<dynamic_step_view, any_image_view<Views...>>;
};
}} // namespace boost::gil

View File

@@ -8,64 +8,36 @@
#ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_APPLY_OPERATION_HPP
#define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_APPLY_OPERATION_HPP
#include <boost/variant/apply_visitor.hpp>
#ifdef BOOST_GIL_DOXYGEN_ONLY
#undef BOOST_GIL_REDUCE_CODE_BLOAT
#endif
// Implements apply_operation for variants.
// Optionally performs type reduction.
#ifdef BOOST_GIL_REDUCE_CODE_BLOAT
#include <boost/gil/extension/dynamic_image/reduce.hpp>
#else
#include <boost/variant2/variant.hpp>
namespace boost { namespace gil {
/// \ingroup Variant
/// \brief Invokes a generic mutable operation (represented as a unary function object) on a variant
template <typename Types, typename UnaryOp>
/// \brief Applies the visitor op to the variants
template <typename Variant1, typename Visitor>
[[deprecated("Use variant2::visit instead.")]]
BOOST_FORCEINLINE
auto apply_operation(variant<Types>& arg, UnaryOp op)
auto apply_operation(Variant1&& arg1, Visitor&& op)
#if defined(BOOST_NO_CXX14_DECLTYPE_AUTO) || defined(BOOST_NO_CXX11_DECLTYPE_N3276)
-> typename UnaryOp::result_type
-> decltype(variant2::visit(std::forward<Visitor>(op), std::forward<Variant1>(arg1)))
#endif
{
return apply_visitor(op, arg);
return variant2::visit(std::forward<Visitor>(op), std::forward<Variant1>(arg1));
}
/// \ingroup Variant
/// \brief Invokes a generic constant operation (represented as a unary function object) on a variant
template <typename Types, typename UnaryOp>
/// \brief Applies the visitor op to the variants
template <typename Variant1, typename Variant2, typename Visitor>
[[deprecated("Use variant2::visit instead.")]]
BOOST_FORCEINLINE
auto apply_operation(variant<Types> const& arg, UnaryOp op)
auto apply_operation(Variant1&& arg1, Variant2&& arg2, Visitor&& op)
#if defined(BOOST_NO_CXX14_DECLTYPE_AUTO) || defined(BOOST_NO_CXX11_DECLTYPE_N3276)
-> typename UnaryOp::result_type
-> decltype(variant2::visit(std::forward<Visitor>(op), std::forward<Variant1>(arg1), std::forward<Variant2>(arg2)))
#endif
{
return apply_visitor(op, arg);
}
/// \ingroup Variant
/// \brief Invokes a generic constant operation (represented as a binary function object) on two variants
template <typename Types1, typename Types2, typename BinaryOp>
BOOST_FORCEINLINE
auto apply_operation(
variant<Types1> const& arg1,
variant<Types2> const& arg2,
BinaryOp op)
#if defined(BOOST_NO_CXX14_DECLTYPE_AUTO) || defined(BOOST_NO_CXX11_DECLTYPE_N3276)
-> typename BinaryOp::result_type
#endif
{
return apply_visitor(
op, arg1, arg2);
return variant2::visit(std::forward<Visitor>(op), std::forward<Variant1>(arg1), std::forward<Variant2>(arg2));
}
}} // namespace boost::gil
#endif // defined(BOOST_GIL_REDUCE_CODE_BLOAT)
#endif

View File

@@ -8,8 +8,10 @@
#ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_DYNAMIC_AT_C_HPP
#define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_DYNAMIC_AT_C_HPP
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <stdexcept>
@@ -17,16 +19,16 @@ namespace boost { namespace gil {
// Constructs for static-to-dynamic integer convesion
#define GIL_AT_C_VALUE(z, N, text) mpl::at_c<IntTypes,S+N>::type::value,
#define GIL_DYNAMIC_AT_C_LIMIT 226 // size of the maximum vector to handle
#define BOOST_GIL_AT_C_VALUE(z, N, text) mp11::mp_at_c<IntTypes, S+N>::value,
#define BOOST_GIL_DYNAMIC_AT_C_LIMIT 226 // size of the maximum vector to handle
#define GIL_AT_C_LOOKUP(z, NUM, text) \
#define BOOST_GIL_AT_C_LOOKUP(z, NUM, text) \
template<std::size_t S> \
struct at_c_fn<S,NUM> { \
template <typename IntTypes, typename ValueType> inline \
static ValueType apply(std::size_t index) { \
static ValueType table[] = { \
BOOST_PP_REPEAT(NUM, GIL_AT_C_VALUE, BOOST_PP_EMPTY) \
BOOST_PP_REPEAT(NUM, BOOST_GIL_AT_C_VALUE, BOOST_PP_EMPTY) \
}; \
return table[index]; \
} \
@@ -35,7 +37,7 @@ namespace boost { namespace gil {
namespace detail {
namespace at_c {
template <std::size_t START, std::size_t NUM> struct at_c_fn;
BOOST_PP_REPEAT(GIL_DYNAMIC_AT_C_LIMIT, GIL_AT_C_LOOKUP, BOOST_PP_EMPTY)
BOOST_PP_REPEAT(BOOST_GIL_DYNAMIC_AT_C_LIMIT, BOOST_GIL_AT_C_LOOKUP, BOOST_PP_EMPTY)
template <std::size_t QUOT> struct at_c_impl;
@@ -43,7 +45,7 @@ namespace detail {
struct at_c_impl<0> {
template <typename IntTypes, typename ValueType> inline
static ValueType apply(std::size_t index) {
return at_c_fn<0,mpl::size<IntTypes>::value>::template apply<IntTypes,ValueType>(index);
return at_c_fn<0, mp11::mp_size<IntTypes>::value>::template apply<IntTypes,ValueType>(index);
}
};
@@ -51,11 +53,11 @@ namespace detail {
struct at_c_impl<1> {
template <typename IntTypes, typename ValueType> inline
static ValueType apply(std::size_t index) {
const std::size_t SIZE=mpl::size<IntTypes>::value;
const std::size_t REM = SIZE % GIL_DYNAMIC_AT_C_LIMIT;
switch (index / GIL_DYNAMIC_AT_C_LIMIT) {
case 0: return at_c_fn<0 ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
case 1: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT ,REM >::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT);
const std::size_t SIZE = mp11::mp_size<IntTypes>::value;
const std::size_t REM = SIZE % BOOST_GIL_DYNAMIC_AT_C_LIMIT;
switch (index / BOOST_GIL_DYNAMIC_AT_C_LIMIT) {
case 0: return at_c_fn<0 ,BOOST_GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
case 1: return at_c_fn<BOOST_GIL_DYNAMIC_AT_C_LIMIT ,REM >::template apply<IntTypes,ValueType>(index - BOOST_GIL_DYNAMIC_AT_C_LIMIT);
};
throw;
}
@@ -65,12 +67,12 @@ namespace detail {
struct at_c_impl<2> {
template <typename IntTypes, typename ValueType> inline
static ValueType apply(std::size_t index) {
const std::size_t SIZE=mpl::size<IntTypes>::value;
const std::size_t REM = SIZE % GIL_DYNAMIC_AT_C_LIMIT;
switch (index / GIL_DYNAMIC_AT_C_LIMIT) {
case 0: return at_c_fn<0 ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
case 1: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT);
case 2: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT*2,REM >::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT*2);
const std::size_t SIZE = mp11::mp_size<IntTypes>::value;
const std::size_t REM = SIZE % BOOST_GIL_DYNAMIC_AT_C_LIMIT;
switch (index / BOOST_GIL_DYNAMIC_AT_C_LIMIT) {
case 0: return at_c_fn<0 ,BOOST_GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
case 1: return at_c_fn<BOOST_GIL_DYNAMIC_AT_C_LIMIT ,BOOST_GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - BOOST_GIL_DYNAMIC_AT_C_LIMIT);
case 2: return at_c_fn<BOOST_GIL_DYNAMIC_AT_C_LIMIT*2,REM >::template apply<IntTypes,ValueType>(index - BOOST_GIL_DYNAMIC_AT_C_LIMIT*2);
};
throw;
}
@@ -80,13 +82,13 @@ namespace detail {
struct at_c_impl<3> {
template <typename IntTypes, typename ValueType> inline
static ValueType apply(std::size_t index) {
const std::size_t SIZE=mpl::size<IntTypes>::value;
const std::size_t REM = SIZE % GIL_DYNAMIC_AT_C_LIMIT;
switch (index / GIL_DYNAMIC_AT_C_LIMIT) {
case 0: return at_c_fn<0 ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
case 1: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT);
case 2: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT*2,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT*2);
case 3: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT*3,REM >::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT*3);
const std::size_t SIZE = mp11::mp_size<IntTypes>::value;
const std::size_t REM = SIZE % BOOST_GIL_DYNAMIC_AT_C_LIMIT;
switch (index / BOOST_GIL_DYNAMIC_AT_C_LIMIT) {
case 0: return at_c_fn<0 ,BOOST_GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
case 1: return at_c_fn<BOOST_GIL_DYNAMIC_AT_C_LIMIT ,BOOST_GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - BOOST_GIL_DYNAMIC_AT_C_LIMIT);
case 2: return at_c_fn<BOOST_GIL_DYNAMIC_AT_C_LIMIT*2,BOOST_GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - BOOST_GIL_DYNAMIC_AT_C_LIMIT*2);
case 3: return at_c_fn<BOOST_GIL_DYNAMIC_AT_C_LIMIT*3,REM >::template apply<IntTypes,ValueType>(index - BOOST_GIL_DYNAMIC_AT_C_LIMIT*3);
};
throw;
}
@@ -96,20 +98,21 @@ namespace detail {
////////////////////////////////////////////////////////////////////////////////////
///
/// \brief Given an MPL Random Access Sequence and a dynamic index n, returns the value of the n-th element
/// It constructs a lookup table at compile time
/// \brief Given an Boost.MP11-compatible list and a dynamic index n,
/// returns the value of the n-th element.
/// It constructs a lookup table at compile time.
///
////////////////////////////////////////////////////////////////////////////////////
template <typename IntTypes, typename ValueType> inline
ValueType at_c(std::size_t index) {
const std::size_t Size=mpl::size<IntTypes>::value;
return detail::at_c::at_c_impl<Size/GIL_DYNAMIC_AT_C_LIMIT>::template apply<IntTypes,ValueType>(index);
const std::size_t Size=mp11::mp_size<IntTypes>::value;
return detail::at_c::at_c_impl<Size/BOOST_GIL_DYNAMIC_AT_C_LIMIT>::template apply<IntTypes,ValueType>(index);
}
#undef GIL_AT_C_VALUE
#undef GIL_DYNAMIC_AT_C_LIMIT
#undef GIL_AT_C_LOOKUP
#undef BOOST_GIL_AT_C_VALUE
#undef BOOST_GIL_DYNAMIC_AT_C_LIMIT
#undef BOOST_GIL_AT_C_LOOKUP
}} // namespace boost::gil

View File

@@ -12,6 +12,5 @@
#include <boost/gil/extension/dynamic_image/any_image.hpp>
#include <boost/gil/extension/dynamic_image/apply_operation.hpp>
#include <boost/gil/extension/dynamic_image/image_view_factory.hpp>
#include <boost/gil.hpp> // FIXME: Include what you use!
#endif

View File

@@ -13,6 +13,9 @@
#include <boost/gil/dynamic_step.hpp>
#include <boost/gil/image_view_factory.hpp>
#include <boost/gil/point.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <cstdint>
namespace boost { namespace gil {
@@ -20,238 +23,386 @@ namespace boost { namespace gil {
// Extends image view factory to runtime type-specified views (any_image_view)
namespace detail {
template <typename Result> struct flipped_up_down_view_fn {
using result_type = Result;
template <typename View> result_type operator()(const View& src) const { return result_type(flipped_up_down_view(src)); }
};
template <typename Result> struct flipped_left_right_view_fn {
using result_type = Result;
template <typename View> result_type operator()(const View& src) const { return result_type(flipped_left_right_view(src)); }
};
template <typename Result> struct rotated90cw_view_fn {
using result_type = Result;
template <typename View> result_type operator()(const View& src) const { return result_type(rotated90cw_view(src)); }
};
template <typename Result> struct rotated90ccw_view_fn {
using result_type = Result;
template <typename View> result_type operator()(const View& src) const { return result_type(rotated90ccw_view(src)); }
};
template <typename Result> struct tranposed_view_fn {
using result_type = Result;
template <typename View> result_type operator()(const View& src) const { return result_type(tranposed_view(src)); }
};
template <typename Result> struct rotated180_view_fn {
using result_type = Result;
template <typename View> result_type operator()(const View& src) const { return result_type(rotated180_view(src)); }
template <typename ResultView>
struct flipped_up_down_view_fn
{
using result_type = ResultView;
template <typename View>
auto operator()(View const& src) const -> result_type
{
return result_type{flipped_up_down_view(src)};
}
};
template <typename Result>
template <typename ResultView>
struct flipped_left_right_view_fn
{
using result_type = ResultView;
template <typename View>
auto operator()(View const& src) const -> result_type
{
return result_type{flipped_left_right_view(src)};
}
};
template <typename ResultView>
struct rotated90cw_view_fn
{
using result_type = ResultView;
template <typename View>
auto operator()(View const& src) const -> result_type
{
return result_type{rotated90cw_view(src)};
}
};
template <typename ResultView>
struct rotated90ccw_view_fn
{
using result_type = ResultView;
template <typename View>
auto operator()(View const& src) const -> result_type
{
return result_type{rotated90ccw_view(src)};
}
};
template <typename ResultView>
struct tranposed_view_fn
{
using result_type = ResultView;
template <typename View>
auto operator()(View const& src) const -> result_type
{
return result_type{tranposed_view(src)};
}
};
template <typename ResultView>
struct rotated180_view_fn
{
using result_type = ResultView;
template <typename View>
auto operator()(View const& src) const -> result_type
{
return result_type{rotated180_view(src)};
}
};
template <typename ResultView>
struct subimage_view_fn
{
using result_type = Result;
using result_type = ResultView;
subimage_view_fn(point_t const& topleft, point_t const& dimensions)
: _topleft(topleft), _size2(dimensions)
{}
template <typename View>
result_type operator()(const View& src) const
auto operator()(View const& src) const -> result_type
{
return result_type(subimage_view(src,_topleft,_size2));
return result_type{subimage_view(src,_topleft,_size2)};
}
point_t _topleft;
point_t _size2;
};
template <typename Result>
template <typename ResultView>
struct subsampled_view_fn
{
using result_type = Result;
using result_type = ResultView;
subsampled_view_fn(point_t const& step) : _step(step) {}
template <typename View>
result_type operator()(const View& src) const
auto operator()(View const& src) const -> result_type
{
return result_type(subsampled_view(src,_step));
return result_type{subsampled_view(src,_step)};
}
point_t _step;
};
template <typename Result> struct nth_channel_view_fn {
using result_type = Result;
template <typename ResultView>
struct nth_channel_view_fn
{
using result_type = ResultView;
nth_channel_view_fn(int n) : _n(n) {}
template <typename View>
auto operator()(View const& src) const -> result_type
{
return result_type(nth_channel_view(src,_n));
}
int _n;
template <typename View> result_type operator()(const View& src) const { return result_type(nth_channel_view(src,_n)); }
};
template <typename DstP, typename Result, typename CC = default_color_converter> struct color_converted_view_fn {
using result_type = Result;
template <typename DstP, typename ResultView, typename CC = default_color_converter>
struct color_converted_view_fn
{
using result_type = ResultView;
color_converted_view_fn(CC cc = CC()): _cc(cc) {}
template <typename View> result_type operator()(const View& src) const { return result_type(color_converted_view<DstP>(src, _cc)); }
template <typename View>
auto operator()(View const& src) const -> result_type
{
return result_type{color_converted_view<DstP>(src, _cc)};
}
private:
CC _cc;
private:
CC _cc;
};
} // namespace detail
/// \ingroup ImageViewTransformationsFlipUD
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_y_step_type<any_image_view<ViewTypes> >::type flipped_up_down_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::flipped_up_down_view_fn<typename dynamic_y_step_type<any_image_view<ViewTypes> >::type>());
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename ...Views>
inline
auto flipped_up_down_view(any_image_view<Views...> const& src)
-> typename dynamic_y_step_type<any_image_view<Views...>>::type
{
using result_view_t = typename dynamic_y_step_type<any_image_view<Views...>>::type;
return variant2::visit(detail::flipped_up_down_view_fn<result_view_t>(), src);
}
/// \ingroup ImageViewTransformationsFlipLR
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_x_step_type<any_image_view<ViewTypes> >::type flipped_left_right_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::flipped_left_right_view_fn<typename dynamic_x_step_type<any_image_view<ViewTypes> >::type>());
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename ...Views>
inline
auto flipped_left_right_view(any_image_view<Views...> const& src)
-> typename dynamic_x_step_type<any_image_view<Views...>>::type
{
using result_view_t = typename dynamic_x_step_type<any_image_view<Views...>>::type;
return variant2::visit(detail::flipped_left_right_view_fn<result_view_t>(), src);
}
/// \ingroup ImageViewTransformationsTransposed
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type transposed_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::tranposed_view_fn<typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type>());
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename ...Views>
inline
auto transposed_view(any_image_view<Views...> const& src)
-> typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type
{
using result_view_t = typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type;
return variant2::visit(detail::tranposed_view_fn<result_view_t>(), src);
}
/// \ingroup ImageViewTransformations90CW
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type rotated90cw_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::rotated90cw_view_fn<typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type>());
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename ...Views>
inline
auto rotated90cw_view(any_image_view<Views...> const& src)
-> typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type
{
using result_view_t = typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type;
return variant2::visit(detail::rotated90cw_view_fn<result_view_t>(), src);
}
/// \ingroup ImageViewTransformations90CCW
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type rotated90ccw_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::rotated90ccw_view_fn<typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type>());
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename ...Views>
inline
auto rotated90ccw_view(any_image_view<Views...> const& src)
-> typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type
{
using result_view_t = typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type;
return variant2::visit(detail::rotated90ccw_view_fn<result_view_t>(), src);
}
/// \ingroup ImageViewTransformations180
/// Models MPL Random Access Container of models of ImageViewConcept
template <typename ViewTypes>
inline auto rotated180_view(const any_image_view<ViewTypes>& src)
-> typename dynamic_xy_step_type<any_image_view<ViewTypes>>::type
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename ...Views>
inline
auto rotated180_view(any_image_view<Views...> const& src)
-> typename dynamic_xy_step_type<any_image_view<Views...>>::type
{
using step_type = typename dynamic_xy_step_type<any_image_view<ViewTypes>>::type;
return apply_operation(src, detail::rotated180_view_fn<step_type>());
using result_view_t = typename dynamic_xy_step_type<any_image_view<Views...>>::type;
return variant2::visit(detail::rotated180_view_fn<result_view_t>(), src);
}
/// \ingroup ImageViewTransformationsSubimage
/// // Models MPL Random Access Container of models of ImageViewConcept
template <typename ViewTypes>
inline auto subimage_view(any_image_view<ViewTypes> const& src,
point_t const& topleft, point_t const& dimensions)
-> any_image_view<ViewTypes>
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename ...Views>
inline
auto subimage_view(
any_image_view<Views...> const& src,
point_t const& topleft,
point_t const& dimensions)
-> any_image_view<Views...>
{
using subimage_view_fn = detail::subimage_view_fn<any_image_view<ViewTypes>>;
return apply_operation(src, subimage_view_fn(topleft, dimensions));
using subimage_view_fn = detail::subimage_view_fn<any_image_view<Views...>>;
return variant2::visit(subimage_view_fn(topleft, dimensions), src);
}
/// \ingroup ImageViewTransformationsSubimage
/// Models MPL Random Access Container of models of ImageViewConcept
template <typename ViewTypes>
inline auto subimage_view(any_image_view<ViewTypes> const& src,
int xMin, int yMin, int width, int height)
-> any_image_view<ViewTypes>
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename ...Views>
inline
auto subimage_view(
any_image_view<Views...> const& src,
std::ptrdiff_t x_min, std::ptrdiff_t y_min, std::ptrdiff_t width, std::ptrdiff_t height)
-> any_image_view<Views...>
{
using subimage_view_fn = detail::subimage_view_fn<any_image_view<ViewTypes>>;
return apply_operation(src, subimage_view_fn(point_t(xMin, yMin),point_t(width, height)));
using subimage_view_fn = detail::subimage_view_fn<any_image_view<Views...>>;
return variant2::visit(subimage_view_fn(point_t(x_min, y_min),point_t(width, height)), src);
}
/// \ingroup ImageViewTransformationsSubsampled
/// Models MPL Random Access Container of models of ImageViewConcept
template <typename ViewTypes>
inline auto subsampled_view(any_image_view<ViewTypes> const& src, point_t const& step)
-> typename dynamic_xy_step_type<any_image_view<ViewTypes>>::type
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename ...Views>
inline
auto subsampled_view(any_image_view<Views...> const& src, point_t const& step)
-> typename dynamic_xy_step_type<any_image_view<Views...>>::type
{
using step_type = typename dynamic_xy_step_type<any_image_view<ViewTypes>>::type;
using step_type = typename dynamic_xy_step_type<any_image_view<Views...>>::type;
using subsampled_view = detail::subsampled_view_fn<step_type>;
return apply_operation(src, subsampled_view(step));
return variant2::visit(subsampled_view(step), src);
}
/// \ingroup ImageViewTransformationsSubsampled
/// Models MPL Random Access Container of models of ImageViewConcept
template <typename ViewTypes>
inline auto subsampled_view(any_image_view<ViewTypes> const& src, int xStep, int yStep)
-> typename dynamic_xy_step_type<any_image_view<ViewTypes>>::type
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename ...Views>
inline
auto subsampled_view(any_image_view<Views...> const& src, std::ptrdiff_t x_step, std::ptrdiff_t y_step)
-> typename dynamic_xy_step_type<any_image_view<Views...>>::type
{
using step_type = typename dynamic_xy_step_type<any_image_view<ViewTypes>>::type;
using step_type = typename dynamic_xy_step_type<any_image_view<Views...>>::type;
using subsampled_view_fn = detail::subsampled_view_fn<step_type>;
return apply_operation(src, subsampled_view_fn(point_t(xStep, yStep)));
return variant2::visit(subsampled_view_fn(point_t(x_step, y_step)), src);
}
namespace detail {
template <typename View> struct get_nthchannel_type { using type = typename nth_channel_view_type<View>::type; };
template <typename Views> struct views_get_nthchannel_type : public mpl::transform<Views, get_nthchannel_type<mpl::_1> > {};
}
template <typename View>
struct get_nthchannel_type { using type = typename nth_channel_view_type<View>::type; };
template <typename Views>
struct views_get_nthchannel_type : mp11::mp_transform<get_nthchannel_type, Views> {};
} // namespace detail
/// \ingroup ImageViewTransformationsNthChannel
/// \brief Given a runtime source image view, returns the type of a runtime image view over a single channel of the source view
template <typename ViewTypes>
struct nth_channel_view_type<any_image_view<ViewTypes> > {
using type = any_image_view<typename detail::views_get_nthchannel_type<ViewTypes>::type>;
template <typename ...Views>
struct nth_channel_view_type<any_image_view<Views...>>
{
using type = typename detail::views_get_nthchannel_type<any_image_view<Views...>>;
};
/// \ingroup ImageViewTransformationsNthChannel
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename nth_channel_view_type<any_image_view<ViewTypes> >::type nth_channel_view(const any_image_view<ViewTypes>& src, int n) {
return apply_operation(src,detail::nth_channel_view_fn<typename nth_channel_view_type<any_image_view<ViewTypes> >::type>(n));
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename ...Views>
inline
auto nth_channel_view(any_image_view<Views...> const& src, int n)
-> typename nth_channel_view_type<any_image_view<Views...>>::type
{
using result_view_t = typename nth_channel_view_type<any_image_view<Views...>>::type;
return variant2::visit(detail::nth_channel_view_fn<result_view_t>(n), src);
}
namespace detail {
template <typename View, typename DstP, typename CC> struct get_ccv_type : public color_converted_view_type<View, DstP, CC> {};
template <typename Views, typename DstP, typename CC> struct views_get_ccv_type : public mpl::transform<Views, get_ccv_type<mpl::_1,DstP,CC> > {};
}
template <typename View, typename DstP, typename CC>
struct get_ccv_type : color_converted_view_type<View, DstP, CC> {};
template <typename Views, typename DstP, typename CC>
struct views_get_ccv_type
{
private:
// FIXME: Remove class name injection with detail:: qualification
// Required as workaround for MP11 issue that treats unqualified metafunction
// in the class definition of the same name as the specialization (Peter Dimov):
// invalid template argument for template parameter 'F', expected a class template
template <typename T>
using ccvt = detail::get_ccv_type<T, DstP, CC>;
public:
using type = mp11::mp_transform<ccvt, Views>;
};
} // namespace detail
/// \ingroup ImageViewTransformationsColorConvert
/// \brief Returns the type of a runtime-specified view, color-converted to a given pixel type with user specified color converter
template <typename ViewTypes, typename DstP, typename CC>
struct color_converted_view_type<any_image_view<ViewTypes>,DstP,CC>
template <typename ...Views, typename DstP, typename CC>
struct color_converted_view_type<any_image_view<Views...>,DstP,CC>
{
using type = any_image_view<typename detail::views_get_ccv_type<ViewTypes, DstP, CC>::type>;
//using type = any_image_view<typename detail::views_get_ccv_type<Views, DstP, CC>::type>;
using type = detail::views_get_ccv_type<any_image_view<Views...>, DstP, CC>;
};
/// \ingroup ImageViewTransformationsColorConvert
/// \brief overload of generic color_converted_view with user defined color-converter
template <typename DstP, typename ViewTypes, typename CC> inline // Models MPL Random Access Container of models of ImageViewConcept
typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type color_converted_view(const any_image_view<ViewTypes>& src, CC) {
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type >());
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename DstP, typename ...Views, typename CC>
inline
auto color_converted_view(any_image_view<Views...> const& src, CC)
-> typename color_converted_view_type<any_image_view<Views...>, DstP, CC>::type
{
using cc_view_t = typename color_converted_view_type<any_image_view<Views...>, DstP, CC>::type;
return variant2::visit(detail::color_converted_view_fn<DstP, cc_view_t>(), src);
}
/// \ingroup ImageViewTransformationsColorConvert
/// \brief Returns the type of a runtime-specified view, color-converted to a given pixel type with the default coor converter
template <typename ViewTypes, typename DstP>
struct color_converted_view_type<any_image_view<ViewTypes>,DstP>
template <typename ...Views, typename DstP>
struct color_converted_view_type<any_image_view<Views...>,DstP>
{
using type = any_image_view<typename detail::views_get_ccv_type<ViewTypes, DstP, default_color_converter>::type>;
using type = detail::views_get_ccv_type<any_image_view<Views...>, DstP, default_color_converter>;
};
/// \ingroup ImageViewTransformationsColorConvert
/// \brief overload of generic color_converted_view with the default color-converter
template <typename DstP, typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type color_converted_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type >());
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename DstP, typename ...Views>
inline
auto color_converted_view(any_image_view<Views...> const& src)
-> typename color_converted_view_type<any_image_view<Views...>, DstP>::type
{
using cc_view_t = typename color_converted_view_type<any_image_view<Views...>, DstP>::type;
return variant2::visit(detail::color_converted_view_fn<DstP, cc_view_t>(), src);
}
/// \ingroup ImageViewTransformationsColorConvert
/// \brief overload of generic color_converted_view with user defined color-converter
/// These are workarounds for GCC 3.4, which thinks color_converted_view is ambiguous with the same method for templated views (in gil/image_view_factory.hpp)
template <typename DstP, typename ViewTypes, typename CC> inline // Models MPL Random Access Container of models of ImageViewConcept
typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type any_color_converted_view(const any_image_view<ViewTypes>& src, CC) {
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type >());
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename DstP, typename ...Views, typename CC>
[[deprecated("Use color_converted_view(const any_image_view<Views...>& src, CC) instead.")]]
inline
auto any_color_converted_view(const any_image_view<Views...>& src, CC cc)
-> typename color_converted_view_type<any_image_view<Views...>, DstP, CC>::type
{
return color_converted_view(src, cc);
}
/// \ingroup ImageViewTransformationsColorConvert
/// \brief overload of generic color_converted_view with the default color-converter
/// These are workarounds for GCC 3.4, which thinks color_converted_view is ambiguous with the same method for templated views (in gil/image_view_factory.hpp)
template <typename DstP, typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type any_color_converted_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type >());
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
template <typename DstP, typename ...Views>
[[deprecated("Use color_converted_view(any_image_view<Views...> const& src) instead.")]]
inline
auto any_color_converted_view(const any_image_view<Views...>& src)
-> typename color_converted_view_type<any_image_view<Views...>, DstP>::type
{
return color_converted_view(src);
}
/// \}
} } // namespace boost::gil
}} // namespace boost::gil
#endif

View File

@@ -1,832 +0,0 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_GIL_REDUCE_HPP
#define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_GIL_REDUCE_HPP
#ifdef BOOST_GIL_DOXYGEN_ONLY
#undef BOOST_GIL_REDUCE_CODE_BLOAT
#endif
#ifdef BOOST_GIL_REDUCE_CODE_BLOAT
#include <boost/gil/extension/dynamic_image/dynamic_at_c.hpp>
#include <boost/gil/metafunctions.hpp>
#include <boost/gil/typedefs.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/insert_range.hpp>
#include <boost/mpl/long.hpp>
#include <boost/mpl/logical.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/transform.hpp>
// Max number of cases in the cross-expension of binary operation for it to be reduced as unary
#define GIL_BINARY_REDUCE_LIMIT 226
namespace boost { namespace mpl {
// Constructs for static-to-dynamic integer convesion
///////////////////////////////////////////////////////
/// Mapping vector - represents the mapping of one type vector to another
/// It is not a full-blown MPL Random Access Type sequence; just has at_c and size implemented
///
/// SrcTypes, DstTypes: MPL Random Access Type Sequences
///
/// Implements size and at_c to behave as if this is an MPL vector of integers
///////////////////////////////////////////////////////
template <typename SrcTypes, typename DstTypes>
struct mapping_vector {};
template <typename SrcTypes, typename DstTypes, long K>
struct at_c<mapping_vector<SrcTypes,DstTypes>, K>
{
static const std::size_t value=size<DstTypes>::value - order<DstTypes, typename gil::at_c<SrcTypes,K>::type>::type::value +1;
using type = size_t<value>;
};
template <typename SrcTypes, typename DstTypes>
struct size<mapping_vector<SrcTypes,DstTypes>>
{
using type = typename size<SrcTypes>::type;
static const std::size_t value=type::value;
};
///////////////////////////////////////////////////////
/// copy_to_vector - copies a sequence (mpl::set) to vector.
///
/// Temporary solution because I couldn't get mpl::copy to do this.
/// This is what I tried:
/// mpl::copy<SET, mpl::back_inserter<mpl::vector<>>>::type;
/// It works when SET is mpl::vector, but not when SET is mpl::set...
///////////////////////////////////////////////////////
namespace detail {
template <typename SFirst, std::size_t NLeft>
struct copy_to_vector_impl {
private:
using T = typename deref<SFirst>::type;
using next = typename next<SFirst>::type;
using rest = typename copy_to_vector_impl<next, NLeft-1>::type;
public:
using type = typename push_front<rest, T>::type;
};
template <typename SFirst>
struct copy_to_vector_impl<SFirst,1>
{
using type = vector<typename deref<SFirst>::type>;
};
}
template <typename Src>
struct copy_to_vector
{
using type = typename detail::copy_to_vector_impl<typename begin<Src>::type, size<Src>::value>::type;
};
template <>
struct copy_to_vector<set<>>
{
using type = vector0<>;
};
} } // boost::mpl
namespace boost { namespace gil {
///////////////////////////////////////////////////////
///
/// unary_reduce, binary_reduce - given an MPL Random Access Sequence,
/// dynamically specified index to that container, the bits of an instance of the corresponding type and
/// a generic operation, invokes the operation on the given type
///
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
///
/// \brief Unary reduce.
///
/// Given a set of types and an operation, reduces each type in the set (to reduced_t), then removes duplicates (to unique_t)
/// To apply the operation, first constructs a lookup table that maps each element from Types to its place in unique_t and uses it to map
/// the index to anther index (in map_index). Then invokes apply_operation_base on the unique types with the new index.
///
///////////////////////////////////////////////////////
template <typename Types, typename Op>
struct unary_reduce_impl {
using reduced_t = typename mpl::transform<Types, detail::reduce<Op, mpl::_1> >::type;
using unique_t = typename mpl::copy<reduced_t, mpl::inserter<mpl::set<>, mpl::insert<mpl::_1,mpl::_2>>>::type;
static const bool is_single=mpl::size<unique_t>::value==1;
};
template <typename Types, typename Op, bool IsSingle=unary_reduce_impl<Types,Op>::is_single>
struct unary_reduce : public unary_reduce_impl<Types,Op>
{
using reduced_t = typename unary_reduce_impl<Types,Op>::reduced_t;
using unique_t = typename unary_reduce_impl<Types,Op>::unique_t;
static unsigned short inline map_index(std::size_t index)
{
using indices_t = typename mpl::mapping_vector<reduced_t, unique_t>;
return gil::at_c<indices_t, unsigned short>(index);
}
template <typename Bits> BOOST_FORCEINLINE static typename Op::result_type applyc(const Bits& bits, std::size_t index, Op op) {
return apply_operation_basec<unique_t>(bits,map_index(index),op);
}
template <typename Bits> BOOST_FORCEINLINE static typename Op::result_type apply(Bits& bits, std::size_t index, Op op) {
return apply_operation_base<unique_t>(bits,map_index(index),op);
}
};
template <typename Types, typename Op>
struct unary_reduce<Types,Op,true> : public unary_reduce_impl<Types,Op> {
using unique_t = typename unary_reduce_impl<Types,Op>::unique_t;
static unsigned short inline map_index(std::size_t index) { return 0; }
template <typename Bits> BOOST_FORCEINLINE static typename Op::result_type applyc(const Bits& bits, std::size_t index, Op op) {
return op(*gil_reinterpret_cast_c<const typename mpl::front<unique_t>::type*>(&bits));
}
template <typename Bits> BOOST_FORCEINLINE static typename Op::result_type apply(Bits& bits, std::size_t index, Op op) {
return op(*gil_reinterpret_cast<typename mpl::front<unique_t>::type*>(&bits));
}
};
///////////////////////////////////////////////////////
///
/// \brief Binary reduce.
///
/// Given two sets of types, Types1 and Types2, first performs unary reduction on each. Then checks if the product of their sizes is above
/// the GIL_BINARY_REDUCE_LIMIT limit. If so, the operation is too complex to be binary-reduced and uses a specialization of binary_reduce_impl
/// to simply call the binary apply_operation_base (which performs two nested 1D apply operations)
/// If the operation is not too complex, uses the other specialization of binary_reduce_impl to create a cross-product of the input types
/// and performs unary reduction on the result (bin_reduced_t). To apply the binary operation, it simply invokes a unary apply_operation_base
/// on the reduced cross-product types
///
///////////////////////////////////////////////////////
namespace detail {
struct pair_generator {
template <typename Vec2> struct apply
{
using type = std::pair<const typename mpl::at_c<Vec2,0>::type*, const typename mpl::at_c<Vec2,1>::type*>;
};
};
// When the types are not too large, applies reduce on their cross product
template <typename Unary1, typename Unary2, typename Op, bool IsComplex>
struct binary_reduce_impl
{
//private:
using vec1_types = typename mpl::copy_to_vector<typename Unary1::unique_t>::type;
using vec2_types = typename mpl::copy_to_vector<typename Unary2::unique_t>::type;
using BIN_TYPES = mpl::cross_vector<mpl::vector2<vec1_types, vec2_types>, pair_generator>;
using bin_reduced_t = unary_reduce<BIN_TYPES,Op>;
static unsigned short inline map_index(std::size_t index1, std::size_t index2) {
unsigned short r1=Unary1::map_index(index1);
unsigned short r2=Unary2::map_index(index2);
return bin_reduced_t::map_index(r2*mpl::size<vec1_types>::value + r1);
}
public:
using unique_t = typename bin_reduced_t::unique_t
template <typename Bits1, typename Bits2>
static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
std::pair<const void*,const void*> pr(&bits1, &bits2);
return apply_operation_basec<unique_t>(pr, map_index(index1,index2),op);
}
};
// When the types are large performs a double-dispatch. Binary reduction is not done.
template <typename Unary1, typename Unary2, typename Op>
struct binary_reduce_impl<Unary1,Unary2,Op,true> {
template <typename Bits1, typename Bits2>
static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
return apply_operation_base<Unary1::unique_t,Unary2::unique_t>(bits1, index1, bits2, index2, op);
}
};
}
template <typename Types1, typename Types2, typename Op>
struct binary_reduce
{
//private:
using unary1_t = unary_reduce<Types1,Op>;
using unary2_t = unary_reduce<Types2,Op>;
static const std::size_t CROSS_SIZE = mpl::size<typename unary1_t::unique_t>::value *
mpl::size<typename unary2_t::unique_t>::value;
using impl = detail::binary_reduce_impl<unary1_t,unary2_t,Op, (CROSS_SIZE>GIL_BINARY_REDUCE_LIMIT)>;
public:
template <typename Bits1, typename Bits2>
static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
return impl::apply(bits1,index1,bits2,index2,op);
}
};
template <typename Types, typename UnaryOp>
BOOST_FORCEINLINE typename UnaryOp::result_type apply_operation(variant<Types>& arg, UnaryOp op) {
return unary_reduce<Types,UnaryOp>::template apply(arg._bits, arg._index ,op);
}
template <typename Types, typename UnaryOp>
BOOST_FORCEINLINE typename UnaryOp::result_type apply_operation(const variant<Types>& arg, UnaryOp op) {
return unary_reduce<Types,UnaryOp>::template applyc(arg._bits, arg._index ,op);
}
template <typename Types1, typename Types2, typename BinaryOp>
BOOST_FORCEINLINE typename BinaryOp::result_type apply_operation(const variant<Types1>& arg1, const variant<Types2>& arg2, BinaryOp op) {
return binary_reduce<Types1,Types2,BinaryOp>::template apply(arg1._bits, arg1._index, arg2._bits, arg2._index, op);
}
#undef GIL_BINARY_REDUCE_LIMIT
} } // namespace gil
namespace boost { namespace mpl {
///////////////////////////////////////////////////////
/// \brief Represents the virtual cross-product of the types generated from VecOfVecs.
/// \ingroup CrossVector
/// INPUT:
/// VecOfVecs - a vector of vector types. For example [ [A1,A2,A3], [B1,B2], [C1,C2,C3,C4] ]
/// Each element must be a non-empty mpl vector
/// TypeGen - a metafunction that generates a type from a vector of types, each of which can be
/// selected from the corresponding vector in VecOfVecs. For example, [A1, B2, C4]
///
/// Represents the virtual cross-product of the types generated from VecOfVecs.
/// For example, [ TypeGen[A1,B1,C1], TypeGen[A2,B1,C1], TypeGen[A3,B1,C1],
/// TypeGen[A1,B2,C1], TypeGen[A2,B2,C1], TypeGen[A3,B2,C1],
/// TypeGen[A1,B1,C2], TypeGen[A2,B1,C2], TypeGen[A3,B1,C2], ... ]
///
/// Models an immutable MPL Random Access Sequence
/// Traversal, random-access, etc, is defined, but mutable operations,
/// such as push_back and pop_front are not supported
///////////////////////////////////////////////////////
template <typename VecOfVecs, typename TypeGen>
struct cross_vector {};
/// \brief Iterator of cross_vector
/// \ingroup CrossVectorIterator
template <typename VecOfVecs, typename TypeGen, std::size_t K>
struct cross_iterator
{
using category = mpl::random_access_iterator_tag;
};
///////////////////////////////////////////////////////
/// Implementation of the iterator functions of cross vector
///////////////////////////////////////////////////////
/// \brief Dereferences a cross-vector iterator
/// \ingroup CrossVectorIterator
/// Creates a vector of the sizes of each type vector in VecOfVecs, then uses it as a basis
/// to represent the iterator's position K as a vector of indices. Extracts the corresponding type of
/// each input vector and passes the element types to the type generation function, which returns the dereferenced type
template <typename VecOfVecs, typename TypeGen, std::size_t K>
struct deref<cross_iterator<VecOfVecs,TypeGen,K>>
{
private:
using DerefTypes = typename detail::select_subvector_c<VecOfVecs, K>::type;
public:
using type = typename TypeGen::template apply<DerefTypes>::type;
};
/// \brief Increments a cross-vector iterator.
/// \ingroup CrossVectorIterator
template <typename VecOfVecs, typename TypeGen, std::size_t K>
struct next<cross_iterator<VecOfVecs,TypeGen,K>>
{
using type = cross_iterator<VecOfVecs,TypeGen,K+1>;
};
/// \brief Decrements a cross-vector iterator.
/// \ingroup CrossVectorIterator
template <typename VecOfVecs, typename TypeGen, std::size_t K>
struct prior<cross_iterator<VecOfVecs,TypeGen,K>>
{
using type = cross_iterator<VecOfVecs,TypeGen,K-1>;
};
/// \brief Advances a cross-vector iterator.
/// \ingroup CrossVectorIterator
template <typename VecOfVecs, typename TypeGen, std::size_t K, typename Distance>
struct advance<cross_iterator<VecOfVecs,TypeGen,K>, Distance>
{
using type = cross_iterator<VecOfVecs,TypeGen,K+Distance::value>;
};
/// \brief Computes the distance between two cross-vector iterator-s.
/// \ingroup CrossVectorIterator
// (shortened the names of the template arguments - otherwise doxygen cannot parse this...)
template <typename VecOfVecs, typename TypeGen, std::size_t K1, std::size_t K2>
struct distance<cross_iterator<VecOfVecs,TypeGen,K1>, cross_iterator<VecOfVecs,TypeGen,K2>>
{
using type = size_t<K2-K1>;
};
///////////////////////////////////////////////////////
/// Implementation of cross vector
///////////////////////////////////////////////////////
/// \brief Computes the size of a cross vector as the product of the sizes of all vectors in VecOfVecs
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen>
struct size<cross_vector<VecOfVecs,TypeGen>>
{
using type = typename fold<VecOfVecs, size_t<1>, times<_1, size<_2>>>::type;
static const std::size_t value=type::value;
};
/// \brief Determines whether a cross vector is empty
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen>
struct empty<cross_vector<VecOfVecs,TypeGen>> {
using type = typename empty<VecOfVecs>::type;
};
/// \brief Returns the K-th element of a cross vector
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen, typename K>
struct at<cross_vector<VecOfVecs,TypeGen>, K>
{
private:
using KthIterator = cross_iterator<VecOfVecs,TypeGen,K::value>;
public:
using type = typename deref<KthIterator>::type;
};
/// \brief Returns an iterator to the first element of a cross vector
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen>
struct begin<cross_vector<VecOfVecs,TypeGen>>
{
using type = cross_iterator<VecOfVecs,TypeGen,0>;
};
/// \brief Returns an iterator to the last element of a cross vector
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen>
struct end<cross_vector<VecOfVecs,TypeGen>>
{
private:
using this_t = cross_vector<VecOfVecs,TypeGen>;
public:
using type = cross_iterator<VecOfVecs,TypeGen,size<this_t>::value>;
};
/// \brief Returns the first element of a cross vector
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen>
struct front<cross_vector<VecOfVecs,TypeGen>> {
private:
using this_t = cross_vector<VecOfVecs,TypeGen>;
public:
using type = typename deref<typename begin<this_t>::type>::type;
};
/// \brief Returns the last element of a cross vector
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen>
struct back<cross_vector<VecOfVecs,TypeGen>>
{
private:
using this_t = cross_vector<VecOfVecs,TypeGen>;
using size = typename size<this_t>::type;
using last_index = typename minus<size, size_t<1>>::type;
public:
using type = typename at<this_t, last_index>::type;
};
/// \brief Transforms the elements of a cross vector
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen, typename OPP>
struct transform<cross_vector<VecOfVecs,TypeGen>, OPP>
{
using Op = typename lambda<OPP>::type;
struct adapter
{
template <typename Elements>
struct apply
{
using orig_t = typename TypeGen::template apply<Elements>::type;
using type = typename Op::template apply<orig_t>::type;
};
};
using type = cross_vector<VecOfVecs, adapter>;
};
} } // boost::mpl
namespace boost { namespace gil {
template <typename Types, typename T> struct type_to_index;
template <typename V> struct view_is_basic;
struct rgb_t;
struct lab_t;
struct hsb_t;
struct cmyk_t;
struct rgba_t;
struct error_t;
namespace detail {
////////////////////////////////////////////////////////
////
//// Generic reduce operation
////
////////////////////////////////////////////////////////
template <typename Op, typename T>
struct reduce
{
using type = T;
};
////////////////////////////////////////////////////////
////
//// Unary reduce_view operation. Splits into basic and non-basic views.
//// Algorithm-specific reduce should specialize for basic views
////
////////////////////////////////////////////////////////
template <typename Op, typename View, bool IsBasic>
struct reduce_view_basic
{
using type = View;
};
template <typename Op, typename Loc>
struct reduce<Op, image_view<Loc>>
: public reduce_view_basic<Op,image_view<Loc>,view_is_basic<image_view<Loc>>::value> {};
////////////////////////////////////////////////////////
////
//// Unary reduce_image operation. Splits into basic and non-basic images.
//// Algorithm-specific reduce should specialize for basic images
////
////////////////////////////////////////////////////////
template <typename Op, typename Img, bool IsBasic>
struct reduce_image_basic
{
using type = Img;
};
template <typename Op, typename V, typename Alloc>
struct reduce<Op, image<V,Alloc>> : public reduce_image_basic<Op,image<V,Alloc>,image_is_basic<image<V,Alloc>>::value > {};
////////////////////////////////////////////////////////
////
//// Binary reduce_view operation. Splits into basic and non-basic views.
//// Algorithm-specific reduce should specialize for basic views
////
////////////////////////////////////////////////////////
template <typename Op, typename V1, typename V2, bool AreBasic>
struct reduce_views_basic
{
using type = std::pair<const V1*, const V2*>;
};
template <typename Op, typename L1, typename L2>
struct reduce<Op, std::pair<const image_view<L1>*, const image_view<L2>*>>
: public reduce_views_basic<Op,image_view<L1>,image_view<L2>,
mpl::and_<view_is_basic<image_view<L1>>, view_is_basic<image_view<L2>>>::value >
{};
////////////////////////////////////////////////////////
////
//// Color space unary reduce operation. Reduce a color space to a base with the same number of channels
////
////////////////////////////////////////////////////////
template <typename CS>
struct reduce_color_space
{
using type = CS;
};
template <> struct reduce_color_space<lab_t> { using type = rgb_t; };
template <> struct reduce_color_space<hsb_t> { using type = rgb_t; };
template <> struct reduce_color_space<cmyk_t> { using type = rgba_t; };
/*
////////////////////////////////////////////////////////
////
//// Color space binary reduce operation. Given a source and destination color spaces,
//// returns a reduced source and destination color spaces that have the same mapping of channels
////
//// Precondition: The two color spaces must be compatible (i.e. must have the same set of channels)
////////////////////////////////////////////////////////
template <typename Vec, int Basis, int VecSize>
struct type_vec_to_integer_impl {
using last = typename mpl::back<Vec>::type;
using rest = typename mpl::pop_back<Vec>::type;
static const int value = type_vec_to_integer_impl<rest, Basis, VecSize-1>::value * Basis + last::value;
};
template <typename Vec, int Basis>
struct type_vec_to_integer_impl<Vec,Basis,0> {
static const int value=0;
};
template <typename Vec, int Basis=10>
struct type_vec_to_integer {
static const int value = type_vec_to_integer_impl<Vec,Basis, mpl::size<Vec>::value>::value;
};
// Given two color spaces and the mapping of the channels between them, returns the reduced pair of color spaces
// The default version performs no reduction
template <typename SrcColorSpace, typename DstColorSpace, int Mapping>
struct reduce_color_spaces_impl {
using first_t = SrcColorSpace;
using second_t = DstColorSpace;
};
// 012: RGB-RGB, bgr-bgr, lab-lab, hsb-hsb
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,12> {
using first_t = rgb_t;
using second_t = rgb_t;
};
// 210: RGB-bgr, bgr-RGB
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,210> {
using first_t = rgb_t;
using second_t = bgr_t;
};
// 0123: RGBA-RGBA, bgra-bgra, argb-argb, abgr-abgr cmyk-cmyk
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,123> {
using first_t = rgba_t;
using second_t = rgba_t;
};
// 3210: RGBA-abgr, bgra-argb, argb-bgra, abgr-RGBA
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,3210> {
using first_t = rgba_t;
using second_t = abgr_t;
};
// 1230: RGBA-argb, bgra-abgr
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,1230> {
using first_t = rgba_t;
using second_t = argb_t;
};
// 2103: RGBA-bgra, bgra-RGBA (uses subclass to ensure that base color space is not reduced to derived)
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,2103> {
using first_t = rgba_t;
using second_t = bgra_t;
};
// 3012: argb-RGBA, abgr-bgra
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,3012> {
using first_t = argb_t;
using second_t = rgba_t;
};
// 0321: argb-abgr, abgr-argb
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,321> {
using first_t = argb_t;
using second_t = abgr_t;
};
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces {
using src_order_t = typename channel_order<SrcColorSpace>::type;
using dst_order_t = typename channel_order<DstColorSpace>::type;
using mapping = typename mpl::transform<src_order_t, type_to_index<dst_order_t,mpl::_1>>::type;
static const int mapping_val = type_vec_to_integer<mapping>::value;
using _first_t = typename reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,mapping_val>::first_t;
using _second_t = typename reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,mapping_val>::second_t;
using swap_t = typename mpl::and_<color_space_is_base<DstColorSpace>, mpl::not_< color_space_is_base<_second_t>>>;
public:
using first_t = typename mpl::if_<swap_t, _second_t, _first_t>::type;
using second_t = typename mpl::if_<swap_t, _first_t, _second_t>::type;
};
*/
// TODO: Use the old code for reduce_color_spaces above to do color layout reduction
template <typename SrcLayout, typename DstLayout>
struct reduce_color_layouts
{
using first_t = SrcLayout;
using second_t = DstLayout;
};
////////////////////////////////////////////////////////
////
//// Reduce for copy_pixels
////
////////////////////////////////////////////////////////
struct copy_pixels_fn;
/*
// 1D reduce for copy_pixels reduces the channel to mutable and the color space to its base with same dimensions
template <typename View>
struct reduce_view_basic<copy_pixels_fn,View,true> {
private:
using color_space_t = typename reduce_color_space<typename View::color_space_t>::type color_space_t; // reduce the color space
using layout_t = layout<color_space_t, typename View::channel_mapping_t>;
public:
using type = typename derived_view_type<View, use_default, layout_t, use_default, use_default, mpl::true_>::type;
};
*/
// Incompatible views cannot be used in copy_pixels - will throw std::bad_cast
template <typename V1, typename V2, bool Compatible>
struct reduce_copy_pixop_compat
{
using type = error_t;
};
// For compatible basic views, reduce their color spaces based on their channel mapping.
// Make the source immutable and the destination mutable (they should already be that way)
template <typename V1, typename V2>
struct reduce_copy_pixop_compat<V1,V2,true>
{
using layout1 = layout<typename V1::color_space_t, typename V1::channel_mapping_t>;
using layout2 = layout<typename V2::color_space_t, typename V2::channel_mapping_t>;
using L1 = typename reduce_color_layouts<layout1,layout2>::first_t;
using L2 = typename reduce_color_layouts<layout1,layout2>::second_t;
using DV1 = typename derived_view_type<V1, use_default, L1, use_default, use_default, use_default, mpl::false_>::type;
using DV2 = typename derived_view_type<V2, use_default, L2, use_default, use_default, use_default, mpl::true_ >::type;
using type = std::pair<const DV1*, const DV2*>;
};
// The general 2D version branches into compatible and incompatible views
template <typename V1, typename V2>
struct reduce_views_basic<copy_pixels_fn, V1, V2, true>
: public reduce_copy_pixop_compat<V1, V2, mpl::and_<views_are_compatible<V1,V2>, view_is_mutable<V2>>::value > {
};
////////////////////////////////////////////////////////
////
//// Reduce for variant destructor (basic views have no destructor)
////
////////////////////////////////////////////////////////
struct destructor_op;
template <typename View>
struct reduce_view_basic<destructor_op,View,true>
{
using type = gray8_view_t;
};
////////////////////////////////////////////////////////
////
//// Reduce for get_dimensions (basic views and images have the same structure and the dimensions are contained at the beginning)
////
////////////////////////////////////////////////////////
struct any_type_get_dimensions;
template <typename View>
struct reduce_view_basic<any_type_get_dimensions,View,true>
{
using type = gray8_view_t;
};
template <typename Img>
struct reduce_image_basic<any_type_get_dimensions,Img,true>
{
using type = gray8_image_t;
};
////////////////////////////////////////////////////////
////
//// Reduce for get_num_channels (only color space matters)
////
////////////////////////////////////////////////////////
struct any_type_get_num_channels;
template <typename View>
struct reduce_view_basic<any_type_get_num_channels,View,true>
{
using color_space_t = typename View::color_space_t::base;
using type = typename view_type<uint8_t,typename reduce_color_space<color_space_t>::type>::type;
};
template <typename Img>
struct reduce_image_basic<any_type_get_num_channels,Img,true>
{
using color_space_t = typename Img::color_space_t::base;
using type = typename image_type<uint8_t,typename reduce_color_space<color_space_t>::type>::type;
};
////////////////////////////////////////////////////////
////
//// Reduce for resample_pixels (same as copy_pixels)
////
////////////////////////////////////////////////////////
template <typename Sampler, typename MapFn> struct resample_pixels_fn;
template <typename S, typename M, typename V, bool IsBasic>
struct reduce_view_basic<resample_pixels_fn<S,M>, V, IsBasic> : public reduce_view_basic<copy_pixels_fn, V, IsBasic> {};
template <typename S, typename M, typename V1, typename V2, bool IsBasic>
struct reduce_views_basic<resample_pixels_fn<S,M>, V1, V2, IsBasic> : public reduce_views_basic<copy_pixels_fn, V1, V2, IsBasic> {};
////////////////////////////////////////////////////////
////
//// Reduce for copy_and_convert_pixels
//// (the only reduction could be made when views are compatible and have the same mapping, planarity and stepness)
////
////////////////////////////////////////////////////////
template <typename CC> class copy_and_convert_pixels_fn;
// the only thing for 1D reduce is making them all mutable...
template <typename CC, typename View, bool IsBasic>
struct reduce_view_basic<copy_and_convert_pixels_fn<CC>, View, IsBasic>
: public derived_view_type<View, use_default, use_default, use_default, use_default, mpl::true_> {
};
// For 2D reduce, if they have the same channels and color spaces (i.e. the same pixels) then copy_and_convert is just copy.
// In this case, reduce their common color space. In general make the first immutable and the second mutable
template <typename CC, typename V1, typename V2, bool AreBasic>
struct reduce_views_basic<copy_and_convert_pixels_fn<CC>, V1, V2, AreBasic>
{
using Same = is_same<typename V1::pixel_t, typename V2::pixel_t>;
using CsR = reduce_color_space<typename V1::color_space_t::base>;
using Cs1 = typename mpl::if_<Same, typename CsR::type, typename V1::color_space_t>::type;
using Cs2 = typename mpl::if_<Same, typename CsR::type, typename V2::color_space_t>::type;
using DV1 = typename derived_view_type<V1, use_default, layout<Cs1, typename V1::channel_mapping_t>, use_default, use_default, mpl::false_>::type;
using DV2 = typename derived_view_type<V2, use_default, layout<Cs2, typename V2::channel_mapping_t>, use_default, use_default, mpl::true_ >::type;
using type = std::pair<const DV1*, const DV2*>;
};
//integral_image_generator
//resize_clobber_image_fnobj
//image_default_construct_fnobj
//fill_converted_pixels_fn
//std::bind(gil::detail::copy_pixels_fn(), std::placeholders::_1, dst)
//std::bind(gil::detail::copy_pixels_fn(), src, std::placeholders::_1)
//std::bind(detail::copy_and_convert_pixels_fn(), std::placeholders::_1, dst)
//std::bind(detail::copy_and_convert_pixels_fn(), src, std::placeholders::_1)
//gil::detail::fill_pixels_fn<Value>(val)
//detail::copy_construct_in_place_fn<base_t>
//detail::equal_to_fn<typename variant<Types>::base_t>
//detail::any_image_get_view<typename any_image<Types>::view_t>
//detail::any_image_get_const_view<typename any_image<Types>::view_t>
//detail::flipped_up_down_view_fn<any_image_view<ViewTypes>>
//detail::flipped_left_right_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
//detail::tranposed_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
//detail::rotated90cw_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
//detail::rotated90ccw_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
//detail::rotated180_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
//detail::subimage_view_fn<any_image_view<ViewTypes>>
//detail::subsampled_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
//detail::nth_channel_view_fn<typename nth_channel_view_type<any_image_view<ViewTypes>>
//detail::color_converted_view_fn<DstP,typename color_convert_view_type<any_image_view<ViewTypes>, DstP>::type >
}
}} // namespace boost::gil
#endif // defined(BOOST_GIL_REDUCE_CODE_BLOAT)
#endif

View File

@@ -0,0 +1,172 @@
//
// Copyright 2020 Debabrata Mandal <mandaldebabrata123@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_EXTENSION_HISTOGRAM_STL_HISTOGRAM_HPP
#define BOOST_GIL_EXTENSION_HISTOGRAM_STL_HISTOGRAM_HPP
#include <boost/gil/concepts/concept_check.hpp>
#include <boost/gil/gray.hpp>
#include <boost/gil/histogram.hpp>
#include <boost/gil/image_view.hpp>
#include <boost/gil/image_view_factory.hpp>
#include <array>
#include <map>
#include <utility>
#include <vector>
namespace boost { namespace gil {
//////////////////////////////////////////////////////////
/// Histogram extension for STL container
//////////////////////////////////////////////////////////
/// \defgroup Histogram - STL Containers
/// \brief Collection of functions to provide histogram support in GIL using Standard
/// Template Library Containers
/// The conversion from Boost.GIL images to compatible histograms are provided. The supported
/// container types would be std::vector, std::array, std::map.
///
/// Some general constraints on STL extension:-
/// 1. Supports only 1D histogram.
/// 2. Cannot use signed images with compatible random access containers.
/// 3. Automatic resize of std::array in case of shortage of bins, to ensure
/// correctness comes before performance.
/// 4. Container key type (if exists) has to be one of std::integral types to be
/// GIL compatible.
/// 5. Container value type has to be of std::arithmetic types.
///
///
/// \ingroup Histogram - STL Containers
/// \brief Overload for std::vector of fill_histogram
///
template <typename SrcView, typename T>
void fill_histogram(SrcView const& srcview, std::vector<T>& histogram, bool accumulate = false)
{
gil_function_requires<ImageViewConcept<SrcView>>();
static_assert(std::is_arithmetic<T>::value, "Improper container type for images.");
static_assert(
std::is_unsigned<typename channel_type<SrcView>::type>::value,
"Improper container type for signed images.");
using channel_t = typename channel_type<SrcView>::type;
using pixel_t = pixel<channel_t, gray_layout_t>;
if (!accumulate)
histogram.clear();
histogram.resize(std::numeric_limits<channel_t>::max() + 1);
for_each_pixel(color_converted_view<pixel_t>(srcview), [&](pixel_t const& p) {
++histogram[static_cast<std::size_t>(p)];
});
}
/// \ingroup Histogram - STL Containers
/// \brief Overload for std::array of fill_histogram
///
template <typename SrcView, typename T, std::size_t N>
void fill_histogram(SrcView const& srcview, std::array<T, N>& histogram, bool accumulate = false)
{
gil_function_requires<ImageViewConcept<SrcView>>();
static_assert(std::is_arithmetic<T>::value && N > 0, "Improper container type for images.");
static_assert(
std::is_unsigned<typename channel_type<SrcView>::type>::value,
"Improper container type for signed images.");
using channel_t = typename channel_type<SrcView>::type;
using pixel_t = pixel<channel_t, gray_layout_t>;
const size_t pixel_max = std::numeric_limits<channel_t>::max();
const float scale = (histogram.size() - 1.0f) / pixel_max;
if (!accumulate)
std::fill(std::begin(histogram), std::end(histogram), 0);
for_each_pixel(color_converted_view<pixel_t>(srcview), [&](pixel_t const& p) {
++histogram[static_cast<std::size_t>(p * scale)];
});
}
/// \ingroup Histogram - STL Containers
/// \brief Overload for std::map of fill_histogram
///
template <typename SrcView, typename T1, typename T2>
void fill_histogram(SrcView const& srcview, std::map<T1, T2>& histogram, bool accumulate = false)
{
gil_function_requires<ImageViewConcept<SrcView>>();
static_assert(
std::is_arithmetic<T1>::value && std::is_integral<T2>::value,
"Improper container type for images.");
using channel_t = typename channel_type<SrcView>::type;
using pixel_t = pixel<channel_t, gray_layout_t>;
if (!accumulate)
histogram.clear();
for_each_pixel(color_converted_view<pixel_t>(srcview), [&](pixel_t const& p) {
++histogram[static_cast<std::size_t>(p)];
});
}
/// \ingroup Histogram - STL Containers
/// \brief Overload for std::vector of cumulative_histogram
///
template <typename T>
std::vector<T> cumulative_histogram(std::vector<T>& hist)
{
std::vector<T> cumulative_hist(hist.size());
static_assert(std::is_arithmetic<T>::value, "Improper container type for images.");
T cumulative_counter = 0;
for (std::size_t i = 0; i < hist.size(); i++)
{
cumulative_counter += hist[i];
cumulative_hist[i] = cumulative_counter;
}
return cumulative_hist;
}
/// \ingroup Histogram - STL Containers
/// \brief Overload for std::array of cumulative_histogram
///
template <typename T, std::size_t N>
std::array<T, N> cumulative_histogram(std::array<T, N>& histogram)
{
std::array<T, N> cumulative_hist;
static_assert(std::is_arithmetic<T>::value && N > 0, "Improper container type for images.");
T cumulative_counter = 0;
for (std::size_t i = 0; i < N; i++)
{
cumulative_counter += histogram[i];
cumulative_hist[i] = cumulative_counter;
}
return cumulative_hist;
}
/// \ingroup Histogram - STL Containers
/// \brief Overload for std::map of cumulative_histogram
///
template <typename T1, typename T2>
std::map<T1, T2> cumulative_histogram(std::map<T1, T2>& histogram)
{
std::map<T1, T2> cumulative_hist;
static_assert(
std::is_arithmetic<T1>::value && std::is_integral<T2>::value,
"Improper container type for images.");
T2 cumulative_counter = 0;
for (auto const& it : histogram)
{
cumulative_counter += it.second;
cumulative_hist[it.first] = cumulative_counter;
}
return cumulative_hist;
}
}} // namespace boost::gil
#endif

View File

@@ -0,0 +1,426 @@
//
// Copyright 2020 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
// Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
//
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_GIL_EXTENSION_IMAGE_PROCESSING_DIFFUSION_HPP
#define BOOST_GIL_EXTENSION_IMAGE_PROCESSING_DIFFUSION_HPP
#include <boost/gil/detail/math.hpp>
#include <boost/gil/algorithm.hpp>
#include <boost/gil/color_base_algorithm.hpp>
#include <boost/gil/image.hpp>
#include <boost/gil/image_view.hpp>
#include <boost/gil/image_view_factory.hpp>
#include <boost/gil/pixel.hpp>
#include <boost/gil/point.hpp>
#include <boost/gil/typedefs.hpp>
#include <functional>
#include <numeric>
#include <vector>
namespace boost { namespace gil {
namespace conductivity {
struct perona_malik_conductivity
{
double kappa;
template <typename Pixel>
Pixel operator()(Pixel input)
{
using channel_type = typename channel_type<Pixel>::type;
// C++11 doesn't seem to capture members
static_transform(input, input, [this](channel_type value) {
value /= kappa;
return std::exp(-std::abs(value));
});
return input;
}
};
struct gaussian_conductivity
{
double kappa;
template <typename Pixel>
Pixel operator()(Pixel input)
{
using channel_type = typename channel_type<Pixel>::type;
// C++11 doesn't seem to capture members
static_transform(input, input, [this](channel_type value) {
value /= kappa;
return std::exp(-value * value);
});
return input;
}
};
struct wide_regions_conductivity
{
double kappa;
template <typename Pixel>
Pixel operator()(Pixel input)
{
using channel_type = typename channel_type<Pixel>::type;
// C++11 doesn't seem to capture members
static_transform(input, input, [this](channel_type value) {
value /= kappa;
return 1.0 / (1.0 + value * value);
});
return input;
}
};
struct more_wide_regions_conductivity
{
double kappa;
template <typename Pixel>
Pixel operator()(Pixel input)
{
using channel_type = typename channel_type<Pixel>::type;
// C++11 doesn't seem to capture members
static_transform(input, input, [this](channel_type value) {
value /= kappa;
return 1.0 / std::sqrt((1.0 + value * value));
});
return input;
}
};
} // namespace diffusion
/**
\brief contains discrete approximations of 2D Laplacian operator
*/
namespace laplace_function {
// The functions assume clockwise enumeration of stencil points, as such
// NW North NE 0 1 2 (-1, -1) (0, -1) (+1, -1)
// West East ===> 7 3 ===> (-1, 0) (+1, 0)
// SW South SE 6 5 4 (-1, +1) (0, +1) (+1, +1)
/**
\brief This function makes sure all Laplace functions enumerate
values in the same order and direction.
The first element is difference North West direction, second in North,
and so on in clockwise manner. Leave element as zero if it is not
to be computed.
*/
inline std::array<gil::point_t, 8> get_directed_offsets()
{
return {point_t{-1, -1}, point_t{0, -1}, point_t{+1, -1}, point_t{+1, 0},
point_t{+1, +1}, point_t{0, +1}, point_t{-1, +1}, point_t{-1, 0}};
}
template <typename PixelType>
using stencil_type = std::array<PixelType, 8>;
/**
\brief 5 point stencil approximation of Laplacian
Only main 4 directions are non-zero, the rest are zero
*/
struct stencil_5points
{
double delta_t = 0.25;
template <typename SubImageView>
stencil_type<typename SubImageView::value_type> compute_laplace(SubImageView view,
point_t origin)
{
auto current = view(origin);
stencil_type<typename SubImageView::value_type> stencil;
using channel_type = typename channel_type<typename SubImageView::value_type>::type;
std::array<gil::point_t, 8> offsets(get_directed_offsets());
typename SubImageView::value_type zero_pixel;
static_fill(zero_pixel, 0);
for (std::size_t index = 0; index < offsets.size(); ++index)
{
if (index % 2 != 0)
{
static_transform(view(origin.x + offsets[index].x, origin.y + offsets[index].y),
current, stencil[index], std::minus<channel_type>{});
}
else
{
stencil[index] = zero_pixel;
}
}
return stencil;
}
template <typename Pixel>
Pixel reduce(const stencil_type<Pixel>& stencil)
{
using channel_type = typename channel_type<Pixel>::type;
auto result = []() {
Pixel zero_pixel;
static_fill(zero_pixel, channel_type(0));
return zero_pixel;
}();
for (std::size_t index : {1u, 3u, 5u, 7u})
{
static_transform(result, stencil[index], result, std::plus<channel_type>{});
}
Pixel delta_t_pixel;
static_fill(delta_t_pixel, delta_t);
static_transform(result, delta_t_pixel, result, std::multiplies<channel_type>{});
return result;
}
};
/**
\brief 9 point stencil approximation of Laplacian
This is full 8 way approximation, though diagonal
elements are halved during reduction.
*/
struct stencil_9points_standard
{
double delta_t = 0.125;
template <typename SubImageView>
stencil_type<typename SubImageView::value_type> compute_laplace(SubImageView view,
point_t origin)
{
stencil_type<typename SubImageView::value_type> stencil;
auto out = stencil.begin();
auto current = view(origin);
using channel_type = typename channel_type<typename SubImageView::value_type>::type;
std::array<gil::point_t, 8> offsets(get_directed_offsets());
for (auto offset : offsets)
{
static_transform(view(origin.x + offset.x, origin.y + offset.y), current, *out++,
std::minus<channel_type>{});
}
return stencil;
}
template <typename Pixel>
Pixel reduce(const stencil_type<Pixel>& stencil)
{
using channel_type = typename channel_type<Pixel>::type;
auto result = []() {
Pixel zero_pixel;
static_fill(zero_pixel, channel_type(0));
return zero_pixel;
}();
for (std::size_t index : {1u, 3u, 5u, 7u})
{
static_transform(result, stencil[index], result, std::plus<channel_type>{});
}
for (std::size_t index : {0u, 2u, 4u, 6u})
{
Pixel half_pixel;
static_fill(half_pixel, channel_type(1 / 2.0));
static_transform(stencil[index], half_pixel, half_pixel,
std::multiplies<channel_type>{});
static_transform(result, half_pixel, result, std::plus<channel_type>{});
}
Pixel delta_t_pixel;
static_fill(delta_t_pixel, delta_t);
static_transform(result, delta_t_pixel, result, std::multiplies<channel_type>{});
return result;
}
};
} // namespace laplace_function
namespace brightness_function {
using laplace_function::stencil_type;
struct identity
{
template <typename Pixel>
stencil_type<Pixel> operator()(const stencil_type<Pixel>& stencil)
{
return stencil;
}
};
// TODO: Figure out how to implement color gradient brightness, as it
// seems to need dx and dy using sobel or scharr kernels
struct rgb_luminance
{
using pixel_type = rgb32f_pixel_t;
stencil_type<pixel_type> operator()(const stencil_type<pixel_type>& stencil)
{
stencil_type<pixel_type> output;
std::transform(stencil.begin(), stencil.end(), output.begin(), [](const pixel_type& pixel) {
float32_t luminance = 0.2126f * pixel[0] + 0.7152f * pixel[1] + 0.0722f * pixel[2];
pixel_type result_pixel;
static_fill(result_pixel, luminance);
return result_pixel;
});
return output;
}
};
} // namespace brightness_function
enum class matlab_connectivity
{
minimal,
maximal
};
enum class matlab_conduction_method
{
exponential,
quadratic
};
template <typename InputView, typename OutputView>
void classic_anisotropic_diffusion(const InputView& input, const OutputView& output,
unsigned int num_iter, double kappa)
{
anisotropic_diffusion(input, output, num_iter, laplace_function::stencil_5points{},
brightness_function::identity{},
conductivity::perona_malik_conductivity{kappa});
}
template <typename InputView, typename OutputView>
void matlab_anisotropic_diffusion(const InputView& input, const OutputView& output,
unsigned int num_iter, double kappa,
matlab_connectivity connectivity,
matlab_conduction_method conduction_method)
{
if (connectivity == matlab_connectivity::minimal)
{
if (conduction_method == matlab_conduction_method::exponential)
{
anisotropic_diffusion(input, output, num_iter, laplace_function::stencil_5points{},
brightness_function::identity{},
conductivity::gaussian_conductivity{kappa});
}
else if (conduction_method == matlab_conduction_method::quadratic)
{
anisotropic_diffusion(input, output, num_iter, laplace_function::stencil_5points{},
brightness_function::identity{},
conductivity::gaussian_conductivity{kappa});
}
else
{
throw std::logic_error("unhandled conduction method found");
}
}
else if (connectivity == matlab_connectivity::maximal)
{
if (conduction_method == matlab_conduction_method::exponential)
{
anisotropic_diffusion(input, output, num_iter, laplace_function::stencil_5points{},
brightness_function::identity{},
conductivity::gaussian_conductivity{kappa});
}
else if (conduction_method == matlab_conduction_method::quadratic)
{
anisotropic_diffusion(input, output, num_iter, laplace_function::stencil_5points{},
brightness_function::identity{},
conductivity::gaussian_conductivity{kappa});
}
else
{
throw std::logic_error("unhandled conduction method found");
}
}
else
{
throw std::logic_error("unhandled connectivity found");
}
}
template <typename InputView, typename OutputView>
void default_anisotropic_diffusion(const InputView& input, const OutputView& output,
unsigned int num_iter, double kappa)
{
anisotropic_diffusion(input, output, num_iter, laplace_function::stencil_9points_standard{},
brightness_function::identity{}, conductivity::gaussian_conductivity{kappa});
}
/// \brief Performs diffusion according to Perona-Malik equation
///
/// WARNING: Output channel type must be floating point,
/// otherwise there will be loss in accuracy which most
/// probably will lead to incorrect results (input will be unchanged).
/// Anisotropic diffusion is a smoothing algorithm that respects
/// edge boundaries and can work as an edge detector if suitable
/// iteration count is set and grayscale image view is used
/// as an input
template <typename InputView, typename OutputView,
typename LaplaceStrategy = laplace_function::stencil_9points_standard,
typename BrightnessFunction = brightness_function::identity,
typename DiffusivityFunction = conductivity::gaussian_conductivity>
void anisotropic_diffusion(const InputView& input, const OutputView& output, unsigned int num_iter,
LaplaceStrategy laplace, BrightnessFunction brightness,
DiffusivityFunction diffusivity)
{
using input_pixel_type = typename InputView::value_type;
using pixel_type = typename OutputView::value_type;
using channel_type = typename channel_type<pixel_type>::type;
using computation_image = image<pixel_type>;
const auto width = input.width();
const auto height = input.height();
const auto zero_pixel = []() {
pixel_type pixel;
static_fill(pixel, static_cast<channel_type>(0));
return pixel;
}();
computation_image result_image(width + 2, height + 2, zero_pixel);
auto result = view(result_image);
computation_image scratch_result_image(width + 2, height + 2, zero_pixel);
auto scratch_result = view(scratch_result_image);
transform_pixels(input, subimage_view(result, 1, 1, width, height),
[](const input_pixel_type& pixel) {
pixel_type converted;
for (std::size_t i = 0; i < num_channels<pixel_type>{}; ++i)
{
converted[i] = pixel[i];
}
return converted;
});
for (unsigned int iteration = 0; iteration < num_iter; ++iteration)
{
for (std::ptrdiff_t relative_y = 0; relative_y < height; ++relative_y)
{
for (std::ptrdiff_t relative_x = 0; relative_x < width; ++relative_x)
{
auto x = relative_x + 1;
auto y = relative_y + 1;
auto stencil = laplace.compute_laplace(result, point_t(x, y));
auto brightness_stencil = brightness(stencil);
laplace_function::stencil_type<pixel_type> diffusivity_stencil;
std::transform(brightness_stencil.begin(), brightness_stencil.end(),
diffusivity_stencil.begin(), diffusivity);
laplace_function::stencil_type<pixel_type> product_stencil;
std::transform(stencil.begin(), stencil.end(), diffusivity_stencil.begin(),
product_stencil.begin(), [](pixel_type lhs, pixel_type rhs) {
static_transform(lhs, rhs, lhs, std::multiplies<channel_type>{});
return lhs;
});
static_transform(result(x, y), laplace.reduce(product_stencil),
scratch_result(x, y), std::plus<channel_type>{});
}
}
using std::swap;
swap(result, scratch_result);
}
copy_pixels(subimage_view(result, 1, 1, width, height), output);
}
}} // namespace boost::gil
#endif

View File

@@ -0,0 +1,113 @@
// Boost.GIL (Generic Image Library) - tests
//
// Copyright 2020 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
//
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_GIL_EXTENSION_IMAGE_PROCESSING_HOUGH_PARAMETER_HPP
#define BOOST_GIL_EXTENSION_IMAGE_PROCESSING_HOUGH_PARAMETER_HPP
#include "boost/gil/point.hpp"
#include <cmath>
#include <cstddef>
namespace boost
{
namespace gil
{
/// \ingroup HoughTransform
/// \brief A type to encapsulate Hough transform parameter range
///
/// This type provides a way to express value range for a parameter
/// as well as some factory functions to simplify initialization
template <typename T>
struct hough_parameter
{
T start_point;
T step_size;
std::size_t step_count;
/// \ingroup HoughTransform
/// \brief Create Hough parameter from value neighborhood and step count
///
/// This function will take start_point as middle point, and in both
/// directions will try to walk half_step_count times until distance of
/// neighborhood is reached
static hough_parameter<T> from_step_count(T start_point, T neighborhood,
std::size_t half_step_count)
{
T step_size = neighborhood / half_step_count;
std::size_t step_count = half_step_count * 2 + 1;
// explicitly fill out members, as aggregate init will error out with narrowing
hough_parameter<T> parameter;
parameter.start_point = start_point - neighborhood;
parameter.step_size = step_size;
parameter.step_count = step_count;
return parameter;
}
/// \ingroup HoughTransform
/// \brief Create Hough parameter from value neighborhood and step size
///
/// This function will take start_point as middle point, and in both
/// directions will try to walk step_size at a time until distance of
/// neighborhood is reached
static hough_parameter<T> from_step_size(T start_point, T neighborhood, T step_size)
{
std::size_t step_count =
2 * static_cast<std::size_t>(std::floor(neighborhood / step_size)) + 1;
// do not use step_size - neighborhood, as step_size might not allow
// landing exactly on that value when starting from start_point
// also use parentheses on step_count / 2 because flooring is exactly
// what we want
// explicitly fill out members, as aggregate init will error out with narrowing
hough_parameter<T> parameter;
parameter.start_point = start_point - step_size * (step_count / 2);
parameter.step_size = step_size;
parameter.step_count = step_count;
return parameter;
}
};
/// \ingroup HoughTransform
/// \brief Calculate minimum angle which would be observable if walked on a circle
///
/// When drawing a circle or moving around a point in circular motion, it is
/// important to not do too many steps, but also to not have disconnected
/// trajectory. This function will calculate the minimum angle that is observable
/// when walking on a circle or tilting a line.
/// WARNING: do keep in mind IEEE 754 quirks, e.g. no-associativity,
/// no-commutativity and precision. Do not expect expressions that are
/// mathematically the same to produce the same values
inline double minimum_angle_step(point_t dimensions)
{
auto longer_dimension = dimensions.x > dimensions.y ? dimensions.x : dimensions.y;
return std::atan2(1, longer_dimension);
}
/// \ingroup HoughTransform
/// \brief Create a Hough transform parameter with optimal angle step
///
/// Due to computational intensity and noise sensitivity of Hough transform,
/// having any candidates missed or computed again is problematic. This function
/// will properly encapsulate optimal value range around approx_angle with amplitude of
/// neighborhood in each direction.
/// WARNING: do keep in mind IEEE 754 quirks, e.g. no-associativity,
/// no-commutativity and precision. Do not expect expressions that are
/// mathematically the same to produce the same values
inline auto make_theta_parameter(double approx_angle, double neighborhood, point_t dimensions)
-> hough_parameter<double>
{
auto angle_step = minimum_angle_step(dimensions);
// std::size_t step_count =
// 2 * static_cast<std::size_t>(std::floor(neighborhood / angle_step)) + 1;
// return {approx_angle - angle_step * (step_count / 2), angle_step, step_count};
return hough_parameter<double>::from_step_size(approx_angle, neighborhood, angle_step);
}
}} // namespace boost::gil
#endif

View File

@@ -0,0 +1,138 @@
// Boost.GIL (Generic Image Library) - tests
//
// Copyright 2020 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
//
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_GIL_EXTENSION_IMAGE_PROCESSING_HOUGH_TRANSFORM_HPP
#define BOOST_GIL_EXTENSION_IMAGE_PROCESSING_HOUGH_TRANSFORM_HPP
#include <boost/gil/extension/image_processing/hough_parameter.hpp>
#include <boost/gil/extension/rasterization/circle.hpp>
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <iterator>
#include <vector>
namespace boost { namespace gil {
/// \defgroup HoughTransform
/// \brief A family of shape detectors that are specified by equation
///
/// Hough transform is a method of mapping (voting) an object which can be described by
/// equation to single point in accumulator array (also called parameter space).
/// Each set pixel in edge map votes for every shape it can be part of.
/// Circle and ellipse transforms are very costly to brute force, while
/// non-brute-forcing algorithms tend to gamble on probabilities.
/// \ingroup HoughTransform
/// \brief Vote for best fit of a line in parameter space
///
/// The input must be an edge map with grayscale pixels. Be aware of overflow inside
/// accumulator array. The theta parameter is best computed through factory function
/// provided in hough_parameter.hpp
template <typename InputView, typename OutputView>
void hough_line_transform(InputView const& input_view, OutputView const& accumulator_array,
hough_parameter<double> const& theta,
hough_parameter<std::ptrdiff_t> const& radius)
{
std::ptrdiff_t r_lower_bound = radius.start_point;
std::ptrdiff_t r_upper_bound = r_lower_bound + radius.step_size * (radius.step_count - 1);
for (std::ptrdiff_t y = 0; y < input_view.height(); ++y)
{
for (std::ptrdiff_t x = 0; x < input_view.width(); ++x)
{
if (!input_view(x, y)[0])
{
continue;
}
for (std::size_t theta_index = 0; theta_index < theta.step_count; ++theta_index)
{
double theta_current =
theta.start_point + theta.step_size * static_cast<double>(theta_index);
std::ptrdiff_t current_r =
std::llround(static_cast<double>(x) * std::cos(theta_current) +
static_cast<double>(y) * std::sin(theta_current));
if (current_r < r_lower_bound || current_r > r_upper_bound)
{
continue;
}
std::size_t r_index = static_cast<std::size_t>(
std::llround((current_r - radius.start_point) / radius.step_size));
// one more safety guard to not get out of bounds
if (r_index < radius.step_count)
{
accumulator_array(theta_index, r_index)[0] += 1;
}
}
}
}
}
/// \ingroup HoughTransform
/// \brief Vote for best fit of a circle in parameter space according to rasterizer
///
/// The input must be an edge map with grayscale pixels. Be aware of overflow inside
/// accumulator array. Rasterizer is used to rasterize a circle for voting. The circle
/// then is translated for every origin (x, y) in x y parameter space. For available
/// circle rasterizers, please look at rasterization/circle.hpp
template <typename ImageView, typename ForwardIterator, typename Rasterizer>
void hough_circle_transform_brute(ImageView const& input,
hough_parameter<std::ptrdiff_t> const& radius_parameter,
hough_parameter<std::ptrdiff_t> const& x_parameter,
hough_parameter<std::ptrdiff_t> const& y_parameter,
ForwardIterator d_first, Rasterizer rasterizer)
{
for (std::size_t radius_index = 0; radius_index < radius_parameter.step_count; ++radius_index)
{
const auto radius = radius_parameter.start_point +
radius_parameter.step_size * static_cast<std::ptrdiff_t>(radius_index);
Rasterizer rasterizer{point_t{}, radius};
std::vector<point_t> circle_points(rasterizer.point_count());
rasterizer(circle_points.begin());
// sort by scanline to improve cache coherence for row major images
std::sort(circle_points.begin(), circle_points.end(),
[](point_t const& lhs, point_t const& rhs) { return lhs.y < rhs.y; });
const auto translate = [](std::vector<point_t>& points, point_t offset) {
std::transform(points.begin(), points.end(), points.begin(), [offset](point_t point) {
return point_t(point.x + offset.x, point.y + offset.y);
});
};
// in case somebody passes iterator to likes of std::vector<bool>
typename std::iterator_traits<ForwardIterator>::reference current_image = *d_first;
// the algorithm has to traverse over parameter space and look at input, instead
// of vice versa, as otherwise it will call translate too many times, as input
// is usually bigger than the coordinate portion of parameter space.
// This might cause extensive cache misses
for (std::size_t x_index = 0; x_index < x_parameter.step_count; ++x_index)
{
for (std::size_t y_index = 0; y_index < y_parameter.step_count; ++y_index)
{
const std::ptrdiff_t x = x_parameter.start_point + x_index * x_parameter.step_size;
const std::ptrdiff_t y = y_parameter.start_point + y_index * y_parameter.step_size;
auto translated_circle = circle_points;
translate(translated_circle, {x, y});
for (const auto& point : translated_circle)
{
if (input(point))
{
++current_image(x_index, y_index)[0];
}
}
}
}
++d_first;
}
}
}} // namespace boost::gil
#endif

View File

@@ -11,13 +11,13 @@
#include <boost/gil/extension/io/bmp/tags.hpp>
#include <boost/gil/channel.hpp>
#include <boost/mpl/bool_fwd.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
template< typename View >
bool is_allowed( const image_read_info< bmp_tag >& info
, mpl::true_ // is read_and_no_convert
, std::true_type // is read_and_no_convert
)
{
bmp_bits_per_pixel::type src_bits_per_pixel = 0;
@@ -73,7 +73,7 @@ bool is_allowed( const image_read_info< bmp_tag >& info
template< typename View >
bool is_allowed( const image_read_info< bmp_tag >& /* info */
, mpl::false_ // is read_and_convert
, std::false_type // is read_and_convert
)
{
return true;

View File

@@ -11,17 +11,16 @@
#include <boost/gil/extension/io/bmp/detail/is_allowed.hpp>
#include <boost/gil/extension/io/bmp/detail/reader_backend.hpp>
#include <boost/gil/io/detail/dynamic.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/bit_operations.hpp>
#include <boost/gil/io/conversion_policies.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/reader_base.hpp>
#include <boost/gil/io/row_buffer_helper.hpp>
#include <boost/gil/io/typedefs.hpp>
#include <boost/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <type_traits>
#include <vector>
@@ -99,7 +98,7 @@ public:
io_error( "Image header was not read." );
}
using is_read_and_convert_t = typename is_same
using is_read_and_convert_t = typename std::is_same
<
ConversionPolicy,
detail::read_and_no_convert
@@ -705,12 +704,12 @@ public:
)
{}
template< typename Images >
void apply( any_image< Images >& images )
template< typename ...Images >
void apply( any_image< Images... >& images )
{
detail::bmp_type_format_checker format_checker( this->_info._bits_per_pixel );
if( !construct_matched( images
if( !detail::construct_matched( images
, format_checker
))
{
@@ -726,8 +725,8 @@ public:
, parent_t
> op( this );
apply_operation( view( images )
, op
variant2::visit( op
,view( images )
);
}
}

View File

@@ -200,7 +200,7 @@ public:
}
/// Check if image is large enough.
void check_image_size( const point_t& img_dim )
void check_image_size( point_t const& img_dim )
{
if( _settings._dim.x > 0 )
{

View File

@@ -16,8 +16,7 @@
#include <boost/gil/packed_pixel.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/mpl/not.hpp>
#include <boost/type_traits/is_same.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
@@ -106,15 +105,17 @@ struct bmp_write_support<uint8_t
} // namespace detail
template< typename Pixel >
struct is_read_supported< Pixel
, bmp_tag
>
: mpl::bool_< detail::bmp_read_support< typename channel_type< Pixel >::type
, typename color_space_type< Pixel >::type
>::is_supported
>
template<typename Pixel>
struct is_read_supported<Pixel, bmp_tag>
: std::integral_constant
<
bool,
detail::bmp_read_support
<
typename channel_type<Pixel>::type,
typename color_space_type<Pixel>::type
>::is_supported
>
{
using parent_t = detail::bmp_read_support
<
@@ -125,14 +126,18 @@ struct is_read_supported< Pixel
static const typename bmp_bits_per_pixel::type bpp = parent_t::bpp;
};
template< typename Pixel >
struct is_write_supported< Pixel
, bmp_tag
>
: mpl::bool_< detail::bmp_write_support< typename channel_type< Pixel >::type
, typename color_space_type< Pixel >::type
>::is_supported
> {};
template<typename Pixel>
struct is_write_supported<Pixel, bmp_tag>
: std::integral_constant
<
bool,
detail::bmp_write_support
<
typename channel_type<Pixel>::type,
typename color_space_type<Pixel>::type
>::is_supported
>
{};
} // namespace gil
} // namespace boost

View File

@@ -13,7 +13,7 @@
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/detail/dynamic.hpp>
#include <vector>
@@ -194,15 +194,15 @@ public:
)
{}
template< typename Views >
void apply( const any_image_view< Views >& views )
template< typename ...Views >
void apply( const any_image_view< Views... >& views )
{
detail::dynamic_io_fnobj< detail::bmp_write_is_supported
, parent_t
> op( this );
apply_operation( views
, op
variant2::visit( op
,views
);
}
};

View File

@@ -73,7 +73,7 @@ template<>
struct image_read_info< bmp_tag >
{
/// Default contructor.
image_read_info< bmp_tag >()
image_read_info()
: _top_down(false)
, _valid( false )
{}
@@ -136,8 +136,8 @@ struct image_read_settings< bmp_tag > : public image_read_settings_base
/// Constructor
/// \param top_left Top left coordinate for reading partial image.
/// \param dim Dimensions for reading partial image.
image_read_settings( const point_t& top_left
, const point_t& dim
image_read_settings( point_t const& top_left
, point_t const& dim
)
: image_read_settings_base( top_left
, dim

View File

@@ -10,11 +10,13 @@
#include <boost/gil/extension/io/jpeg/tags.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
template< typename View >
bool is_allowed( const image_read_info< jpeg_tag >& info
, mpl::true_ // is read_and_no_convert
, std::true_type // is read_and_no_convert
)
{
if( info._color_space == JCS_YCbCr )
@@ -32,7 +34,7 @@ bool is_allowed( const image_read_info< jpeg_tag >& info
template< typename View >
bool is_allowed( const image_read_info< jpeg_tag >& /* info */
, mpl::false_ // is read_and_convert
, std::false_type // is read_and_convert
)
{
return true;

View File

@@ -12,14 +12,15 @@
#include <boost/gil/extension/io/jpeg/detail/base.hpp>
#include <boost/gil/extension/io/jpeg/detail/is_allowed.hpp>
#include <boost/gil/io/detail/dynamic.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/conversion_policies.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/reader_base.hpp>
#include <boost/gil/io/typedefs.hpp>
#include <csetjmp>
#include <type_traits>
#include <vector>
namespace boost { namespace gil {
@@ -99,7 +100,7 @@ public:
this->get()->dct_method = this->_settings._dct_method;
using is_read_and_convert_t = typename is_same
using is_read_and_convert_t = typename std::is_same
<
ConversionPolicy,
detail::read_and_no_convert
@@ -275,15 +276,15 @@ public:
)
{}
template< typename Images >
void apply( any_image< Images >& images )
template< typename ...Images >
void apply( any_image< Images... >& images )
{
detail::jpeg_type_format_checker format_checker( this->_info._color_space != JCS_YCbCr
? this->_info._color_space
: JCS_RGB
);
if( !construct_matched( images
if( !detail::construct_matched( images
, format_checker
))
{
@@ -299,8 +300,8 @@ public:
, parent_t
> op( this );
apply_operation( view( images )
, op
variant2::visit( op
, view( images )
);
}
}

View File

@@ -189,7 +189,7 @@ public:
}
/// Check if image is large enough.
void check_image_size( const point_t& img_dim )
void check_image_size( point_t const& img_dim )
{
if( _settings._dim.x > 0 )
{

View File

@@ -13,8 +13,7 @@
#include <boost/gil/channel.hpp>
#include <boost/gil/color_base.hpp>
#include <boost/mpl/bool_fwd.hpp>
#include <boost/type_traits/is_same.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
@@ -78,14 +77,17 @@ struct jpeg_write_support<uint8_t
} // namespace detail
template< typename Pixel >
struct is_read_supported< Pixel
, jpeg_tag
>
: mpl::bool_< detail::jpeg_read_support< typename channel_type< Pixel >::type
, typename color_space_type< Pixel >::type
>::is_supported
>
template<typename Pixel>
struct is_read_supported<Pixel, jpeg_tag>
: std::integral_constant
<
bool,
detail::jpeg_read_support
<
typename channel_type<Pixel>::type,
typename color_space_type<Pixel>::type
>::is_supported
>
{
using parent_t = detail::jpeg_read_support
<
@@ -96,14 +98,17 @@ struct is_read_supported< Pixel
static const typename jpeg_color_space::type _color_space = parent_t::_color_space;
};
template< typename Pixel >
struct is_write_supported< Pixel
, jpeg_tag
>
: mpl::bool_< detail::jpeg_write_support< typename channel_type< Pixel >::type
, typename color_space_type< Pixel >::type
>::is_supported
>
template<typename Pixel>
struct is_write_supported<Pixel, jpeg_tag>
: std::integral_constant
<
bool,
detail::jpeg_write_support
<
typename channel_type<Pixel>::type,
typename color_space_type<Pixel>::type
>::is_supported
>
{};
} // namespace gil

View File

@@ -14,7 +14,7 @@
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/detail/dynamic.hpp>
#include <vector>
@@ -132,6 +132,8 @@ private:
, 1
);
}
jpeg_finish_compress ( this->get() );
}
};
@@ -158,14 +160,14 @@ public:
)
{}
template< typename Views >
void apply( const any_image_view< Views >& views )
template< typename ...Views >
void apply( const any_image_view< Views... >& views )
{
detail::dynamic_io_fnobj< detail::jpeg_write_is_supported
, parent_t
> op( this );
apply_operation( views, op );
variant2::visit( op, views );
}
};

View File

@@ -113,7 +113,9 @@ public:
~writer_backend()
{
jpeg_finish_compress ( get() );
// JPEG compression object destruction does not signal errors,
// unlike jpeg_finish_compress called elsewhere,
// so there is no need for the setjmp bookmark here.
jpeg_destroy_compress( get() );
}

View File

@@ -141,7 +141,7 @@ template<>
struct image_read_settings< jpeg_tag > : public image_read_settings_base
{
/// Default constructor
image_read_settings<jpeg_tag>()
image_read_settings()
: image_read_settings_base()
, _dct_method( jpeg_dct_method::default_value )
{}
@@ -150,8 +150,8 @@ struct image_read_settings< jpeg_tag > : public image_read_settings_base
/// \param top_left Top left coordinate for reading partial image.
/// \param dim Dimensions for reading partial image.
/// \param dct_method Specifies dct method.
image_read_settings( const point_t& top_left
, const point_t& dim
image_read_settings( point_t const& top_left
, point_t const& dim
, jpeg_dct_method::type dct_method = jpeg_dct_method::default_value
)
: image_read_settings_base( top_left

View File

@@ -62,12 +62,13 @@ private:
{
if( png_ptr )
{
BOOST_ASSERT(png_ptr->_struct && png_ptr->_info);
png_destroy_read_struct( &png_ptr->_struct
, &png_ptr->_info
, nullptr
);
if( png_ptr->_struct && png_ptr->_info )
{
png_destroy_read_struct( &png_ptr->_struct
, &png_ptr->_info
, nullptr
);
}
delete png_ptr;
png_ptr = nullptr;
@@ -78,11 +79,12 @@ private:
{
if( png_ptr )
{
BOOST_ASSERT(png_ptr->_struct && png_ptr->_info);
png_destroy_write_struct( &png_ptr->_struct
, &png_ptr->_info
);
if( png_ptr->_struct && png_ptr->_info )
{
png_destroy_write_struct( &png_ptr->_struct
, &png_ptr->_info
);
}
delete png_ptr;
png_ptr = nullptr;

View File

@@ -10,14 +10,13 @@
#include <boost/gil/extension/io/png/tags.hpp>
#include <boost/mpl/bool_fwd.hpp>
#include <boost/mpl/for_each.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
template< typename View >
bool is_allowed( const image_read_info< png_tag >& info
, mpl::true_ // is read_and_no_convert
, std::true_type // is read_and_no_convert
)
{
using pixel_t = typename get_pixel_type<View>::type;
@@ -33,7 +32,7 @@ bool is_allowed( const image_read_info< png_tag >& info
template< typename View >
bool is_allowed( const image_read_info< png_tag >& /* info */
, mpl::false_ // is read_and_convert
, std::false_type // is read_and_convert
)
{
return true;

View File

@@ -13,14 +13,17 @@
#include <boost/gil/extension/io/png/detail/is_allowed.hpp>
#include <boost/gil.hpp> // FIXME: Include what you use!
#include <boost/gil/io/detail/dynamic.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/conversion_policies.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/error.hpp>
#include <boost/gil/io/reader_base.hpp>
#include <boost/gil/io/row_buffer_helper.hpp>
#include <boost/gil/io/typedefs.hpp>
#include <type_traits>
namespace boost { namespace gil {
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
@@ -81,6 +84,12 @@ public:
template< typename View >
void apply( const View& view )
{
// guard from errors in the following functions
if (setjmp( png_jmpbuf( this->get_struct() )))
{
io_error("png is invalid");
}
// The info structures are filled at this point.
// Now it's time for some transformations.
@@ -184,7 +193,7 @@ public:
default: io_error( "png_reader::read_data(): unknown combination of color type and bit depth" );
}
#else
io_error( "gray_alpha isn't enabled. Use ENABLE_GRAY_ALPHA when building application." );
io_error( "gray_alpha isn't enabled. Define BOOST_GIL_IO_ENABLE_GRAY_ALPHA when building application." );
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
@@ -228,11 +237,17 @@ private:
>
void read_rows( const View& view )
{
// guard from errors in the following functions
if (setjmp( png_jmpbuf( this->get_struct() )))
{
io_error("png is invalid");
}
using row_buffer_helper_t = detail::row_buffer_helper_view<ImagePixel>;
using it_t = typename row_buffer_helper_t::iterator_t;
using is_read_and_convert_t = typename is_same
using is_read_and_convert_t = typename std::is_same
<
ConversionPolicy,
detail::read_and_no_convert
@@ -394,14 +409,14 @@ public:
)
{}
template< typename Images >
void apply( any_image< Images >& images )
template< typename ...Images >
void apply( any_image< Images... >& images )
{
detail::png_type_format_checker format_checker( this->_info._bit_depth
, this->_info._color_type
);
if( !construct_matched( images
if( !detail::construct_matched( images
, format_checker
))
{
@@ -417,8 +432,8 @@ public:
, parent_t
> op( this );
apply_operation( view( images )
, op
variant2::visit( op
, view( images )
);
}
}

View File

@@ -601,7 +601,7 @@ public:
}
/// Check if image is large enough.
void check_image_size( const point_t& img_dim )
void check_image_size( point_t const& img_dim )
{
if( _settings._dim.x > 0 )
{

View File

@@ -15,6 +15,7 @@
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
#include <cstddef>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
@@ -318,14 +319,17 @@ struct png_write_support<uint16_t
} // namespace detail
template< typename Pixel >
struct is_read_supported< Pixel
, png_tag
>
: mpl::bool_< detail::png_read_support< typename channel_type< Pixel >::type
, typename color_space_type< Pixel >::type
>::is_supported
>
template<typename Pixel>
struct is_read_supported<Pixel, png_tag>
: std::integral_constant
<
bool,
detail::png_read_support
<
typename channel_type<Pixel>::type,
typename color_space_type<Pixel>::type
>::is_supported
>
{
using parent_t = detail::png_read_support
<
@@ -337,14 +341,17 @@ struct is_read_supported< Pixel
static const png_color_type::type _color_type = parent_t::_color_type;
};
template< typename Pixel >
struct is_write_supported< Pixel
, png_tag
>
: mpl::bool_< detail::png_write_support< typename channel_type< Pixel >::type
, typename color_space_type< Pixel >::type
>::is_supported
>
template<typename Pixel>
struct is_write_supported<Pixel, png_tag>
: std::integral_constant
<
bool,
detail::png_write_support
<
typename channel_type<Pixel>::type,
typename color_space_type<Pixel>::type
>::is_supported
>
{
using parent_t = detail::png_write_support
<

View File

@@ -11,13 +11,9 @@
#include <boost/gil/extension/io/png/detail/writer_backend.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/detail/dynamic.hpp>
#include <boost/gil/io/row_buffer_helper.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/less.hpp>
#include <boost/mpl/not.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <type_traits>
@@ -85,7 +81,7 @@ private:
template<typename View>
void write_view( const View& view
, mpl::false_ // is bit aligned
, std::false_type // is bit aligned
)
{
using pixel_t = typename get_pixel_type<View>::type;
@@ -125,7 +121,7 @@ private:
template<typename View>
void write_view( const View& view
, mpl::true_ // is bit aligned
, std::true_type // is bit aligned
)
{
using png_rw_info = detail::png_write_support
@@ -166,8 +162,35 @@ private:
);
}
template< typename Info > struct is_less_than_eight : mpl::less< mpl::int_< Info::_bit_depth >, mpl::int_< 8 > > {};
template< typename Info > struct is_equal_to_sixteen : mpl::equal_to< mpl::int_< Info::_bit_depth >, mpl::int_< 16 > > {};
template<typename Info>
struct is_less_than_eight : mp11::mp_less
<
std::integral_constant<int, Info::_bit_depth>,
std::integral_constant<int, 8>
>
{};
template<typename Info>
struct is_equal_to_sixteen : mp11::mp_and
<
mp11::mp_not
<
mp11::mp_less
<
std::integral_constant<int, Info::_bit_depth>,
std::integral_constant<int, 16>
>
>,
mp11::mp_not
<
mp11::mp_less
<
std::integral_constant<int, 16>,
std::integral_constant<int, Info::_bit_depth>
>
>
>
{};
template <typename Info>
void set_swap(typename std::enable_if<is_less_than_eight<Info>::value>::type* /*ptr*/ = 0)
@@ -185,10 +208,10 @@ private:
void set_swap(
typename std::enable_if
<
mpl::and_
mp11::mp_and
<
mpl::not_<is_less_than_eight<Info>>,
mpl::not_<is_equal_to_sixteen<Info>>
mp11::mp_not<is_less_than_eight<Info>>,
mp11::mp_not<is_equal_to_sixteen<Info>>
>::value
>::type* /*ptr*/ = nullptr)
{
@@ -218,14 +241,14 @@ public:
)
{}
template< typename Views >
void apply( const any_image_view< Views >& views )
template< typename ...Views >
void apply( const any_image_view< Views... >& views )
{
detail::dynamic_io_fnobj< detail::png_write_is_supported
, parent_t
> op( this );
apply_operation( views, op );
variant2::visit( op, views );
}
};

View File

@@ -20,7 +20,7 @@ inline point_t png_read_dimensions(String const& filename)
{
using backend_t = typename get_reader_backend<String, png_tag>::type;
backend_t backend = read_image_info(filename, png_tag());
return { backend._info._width, backend._info._height };
return { static_cast<std::ptrdiff_t>(backend._info._width), static_cast<std::ptrdiff_t>(backend._info._height) };
}
/// \ingroup PNG_IO

View File

@@ -573,7 +573,7 @@ template<>
struct image_read_info< png_tag > : public png_info_base
{
/// Default constructor.
image_read_info< png_tag >()
image_read_info()
: png_info_base()
{}
};
@@ -669,7 +669,7 @@ struct image_read_settings< png_tag > : public image_read_settings_base
, public png_read_settings_base
{
/// Default Constructor
image_read_settings< png_tag >()
image_read_settings()
: image_read_settings_base()
, png_read_settings_base()
, _screen_gamma( 1.0 )
@@ -679,8 +679,8 @@ struct image_read_settings< png_tag > : public image_read_settings_base
/// \param top_left Top left coordinate for reading partial image.
/// \param dim Dimensions for reading partial image.
/// \param gamma Screen gamma value.
image_read_settings( const point_t& top_left
, const point_t& dim
image_read_settings( point_t const& top_left
, point_t const& dim
, const bool apply_screen_gamma = false
, const png_gamma::type& screen_gamma = 1.0
)
@@ -708,15 +708,15 @@ struct image_read_settings< png_tag > : public image_read_settings_base
, public png_read_settings_base
{
/// Default Constructor.
image_read_settings< png_tag >()
image_read_settings()
: image_read_settings_base()
, png_read_settings_base()
, _apply_screen_gamma( false )
, _screen_gamma ( 2 )
{}
image_read_settings( const point_t& top_left
, const point_t& dim
image_read_settings( point_t const& top_left
, point_t const& dim
)
: image_read_settings_base( top_left
, dim

View File

@@ -10,11 +10,13 @@
#include <boost/gil/extension/io/pnm/tags.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
template< typename View >
bool is_allowed( const image_read_info< pnm_tag >& info
, mpl::true_ // is read_and_no_convert
, std::true_type // is read_and_no_convert
)
{
pnm_image_type::type asc_type = is_read_supported< typename get_pixel_type< View >::type
@@ -38,7 +40,7 @@ bool is_allowed( const image_read_info< pnm_tag >& info
template< typename View >
bool is_allowed( const image_read_info< pnm_tag >& /* info */
, mpl::false_ // is read_and_convert
, std::false_type // is read_and_convert
)
{
return true;

View File

@@ -13,11 +13,11 @@
#include <boost/gil/extension/io/pnm/detail/is_allowed.hpp>
#include <boost/gil.hpp> // FIXME: Include what you use!
#include <boost/gil/io/detail/dynamic.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/bit_operations.hpp>
#include <boost/gil/io/conversion_policies.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/reader_base.hpp>
#include <boost/gil/io/row_buffer_helper.hpp>
#include <boost/gil/io/typedefs.hpp>
@@ -85,7 +85,7 @@ public:
template<typename View>
void apply( const View& view )
{
using is_read_and_convert_t = typename is_same
using is_read_and_convert_t = typename std::is_same
<
ConversionPolicy,
detail::read_and_no_convert
@@ -237,7 +237,7 @@ private:
, View_Src >( dst
, src
, y
, typename is_same< View_Dst
, typename std::is_same< View_Dst
, gray1_image_t::view_t
>::type()
);
@@ -250,7 +250,7 @@ private:
void copy_data( const View_Dst& dst
, const View_Src& src
, typename View_Dst::y_coord_t y
, mpl::true_ // is gray1_view
, std::true_type // is gray1_view
)
{
if( this->_info._max_value == 1 )
@@ -267,11 +267,7 @@ private:
}
else
{
copy_data( dst
, src
, y
, mpl::false_()
);
copy_data(dst, src, y, std::false_type{});
}
}
@@ -281,7 +277,7 @@ private:
void copy_data( const View_Dst& view
, const View_Src& src
, typename View_Dst::y_coord_t y
, mpl::false_ // is gray1_view
, std::false_type // is gray1_view
)
{
typename View_Src::x_iterator beg = src.row_begin( 0 ) + this->_settings._top_left.x;
@@ -420,12 +416,12 @@ public:
)
{}
template< typename Images >
void apply( any_image< Images >& images )
template< typename ...Images >
void apply( any_image< Images... >& images )
{
detail::pnm_type_format_checker format_checker( this->_info._type );
if( !construct_matched( images
if( !detail::construct_matched( images
, format_checker
))
{
@@ -441,8 +437,8 @@ public:
, parent_t
> op( this );
apply_operation( view( images )
, op
variant2::visit( op
,view( images )
);
}
}

View File

@@ -82,7 +82,7 @@ public:
}
/// Check if image is large enough.
void check_image_size( const point_t& img_dim )
void check_image_size( point_t const& img_dim )
{
if( _settings._dim.x > 0 )
{

View File

@@ -14,8 +14,7 @@
#include <boost/gil/color_base.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/mpl/not.hpp>
#include <boost/type_traits/is_same.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
@@ -105,14 +104,17 @@ struct pnm_write_support<uint8_t
} // namespace detail
template< typename Pixel >
struct is_read_supported< Pixel
, pnm_tag
>
: mpl::bool_< detail::pnm_read_support< typename channel_type < Pixel >::type
, typename color_space_type< Pixel >::type
>::is_supported
>
template<typename Pixel>
struct is_read_supported<Pixel, pnm_tag>
: std::integral_constant
<
bool,
detail::pnm_read_support
<
typename channel_type<Pixel>::type,
typename color_space_type<Pixel>::type
>::is_supported
>
{
using parent_t = detail::pnm_read_support
<
@@ -124,14 +126,18 @@ struct is_read_supported< Pixel
static const pnm_image_type::type _bin_type = parent_t::_bin_type;
};
template< typename Pixel >
struct is_write_supported< Pixel
, pnm_tag
>
: mpl::bool_< detail::pnm_write_support< typename channel_type < Pixel >::type
, typename color_space_type< Pixel >::type
>::is_supported
> {};
template<typename Pixel>
struct is_write_supported<Pixel, pnm_tag>
: std::integral_constant
<
bool,
detail::pnm_write_support
<
typename channel_type<Pixel>::type,
typename color_space_type<Pixel>::type
>::is_supported
>
{};
} // namespace gil
} // namespace boost

View File

@@ -14,10 +14,12 @@
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/bit_operations.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/detail/dynamic.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <cstdlib>
#include <string>
#include <type_traits>
namespace boost { namespace gil {
@@ -108,30 +110,34 @@ public:
private:
template< int Channels >
unsigned int get_type( mpl::true_ /* is_bit_aligned */ )
unsigned int get_type( std::true_type /* is_bit_aligned */ )
{
return boost::mpl::if_c< Channels == 1
, pnm_image_type::mono_bin_t
, pnm_image_type::color_bin_t
>::type::value;
return mp11::mp_if_c
<
Channels == 1,
pnm_image_type::mono_bin_t,
pnm_image_type::color_bin_t
>::value;
}
template< int Channels >
unsigned int get_type( mpl::false_ /* is_bit_aligned */ )
unsigned int get_type( std::false_type /* is_bit_aligned */ )
{
return boost::mpl::if_c< Channels == 1
, pnm_image_type::gray_bin_t
, pnm_image_type::color_bin_t
>::type::value;
return mp11::mp_if_c
<
Channels == 1,
pnm_image_type::gray_bin_t,
pnm_image_type::color_bin_t
>::value;
}
template< typename View >
void write_data( const View& src
, std::size_t pitch
, const mpl::true_& // bit_aligned
, const std::true_type& // bit_aligned
)
{
static_assert(is_same<View, typename gray1_image_t::view_t>::value, "");
static_assert(std::is_same<View, typename gray1_image_t::view_t>::value, "");
byte_vector_t row( pitch / 8 );
@@ -154,7 +160,7 @@ private:
template< typename View >
void write_data( const View& src
, std::size_t pitch
, const mpl::false_& // bit_aligned
, const std::false_type& // bit_aligned
)
{
std::vector< pixel< typename channel_type< View >::type
@@ -220,14 +226,14 @@ public:
)
{}
template< typename Views >
void apply( const any_image_view< Views >& views )
template< typename ...Views >
void apply( const any_image_view< Views... >& views )
{
detail::dynamic_io_fnobj< detail::pnm_write_is_supported
, parent_t
> op( this );
apply_operation( views, op );
variant2::visit( op, views );
}
};

View File

@@ -12,7 +12,7 @@
#include <boost/gil/io/base.hpp>
#include <boost/mpl/integral_c.hpp>
#include <type_traits>
namespace boost { namespace gil {
@@ -24,13 +24,13 @@ struct pnm_tag : format_tag {};
/// Defines type for image type property.
struct pnm_image_type : property_base< uint32_t >
{
using mono_asc_t = boost::mpl::integral_c<type, 1>;
using gray_asc_t = boost::mpl::integral_c<type, 2>;
using color_asc_t = boost::mpl::integral_c<type, 3>;
using mono_asc_t = std::integral_constant<type, 1>;
using gray_asc_t = std::integral_constant<type, 2>;
using color_asc_t = std::integral_constant<type, 3>;
using mono_bin_t = boost::mpl::integral_c<type, 4>;
using gray_bin_t = boost::mpl::integral_c<type, 5>;
using color_bin_t = boost::mpl::integral_c<type, 6>;
using mono_bin_t = std::integral_constant<type, 4>;
using gray_bin_t = std::integral_constant<type, 5>;
using color_bin_t = std::integral_constant<type, 6>;
};
/// Defines type for image width property.
@@ -65,15 +65,15 @@ template<>
struct image_read_settings< pnm_tag > : public image_read_settings_base
{
/// Default constructor
image_read_settings< pnm_tag >()
image_read_settings()
: image_read_settings_base()
{}
/// Constructor
/// \param top_left Top left coordinate for reading partial image.
/// \param dim Dimensions for reading partial image.
image_read_settings( const point_t& top_left
, const point_t& dim
image_read_settings( point_t const& top_left
, point_t const& dim
)
: image_read_settings_base( top_left
, dim

View File

@@ -16,6 +16,7 @@
#include <memory>
#include <string>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
@@ -117,11 +118,7 @@ public:
};
template< typename FormatTag >
struct is_adaptable_input_device< FormatTag
, LibRaw
, void
>
: mpl::true_
struct is_adaptable_input_device<FormatTag, LibRaw, void> : std::true_type
{
using device_type = file_stream_device<FormatTag>;
};

View File

@@ -11,29 +11,31 @@
#include <boost/gil/extension/io/raw/tags.hpp>
#include <boost/gil/io/base.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
template< typename View >
bool is_allowed( const image_read_info< raw_tag >& info
, mpl::true_ // is read_and_no_convert
, std::true_type // is read_and_no_convert
)
{
using pixel_t = typename get_pixel_type<View>::type;
using num_channel_t = typename num_channels<pixel_t>::value_type;
using channel_t = typename channel_traits<typename element_type<typename View::value_type>::type>::value_type;
const num_channel_t dst_samples_per_pixel = num_channels< pixel_t >::value;
const unsigned int dst_bits_per_pixel = detail::unsigned_integral_num_bits< channel_t >::value;
const bool is_type_signed = boost::is_signed< channel_t >::value;
constexpr num_channel_t dst_samples_per_pixel = num_channels<pixel_t>::value;
constexpr unsigned int dst_bits_per_pixel = detail::unsigned_integral_num_bits<channel_t>::value;
constexpr bool is_type_signed = std::is_signed<channel_t>::value;
return( dst_samples_per_pixel == info._samples_per_pixel &&
dst_bits_per_pixel == static_cast<unsigned int>(info._bits_per_pixel) &&
!is_type_signed );
return (dst_samples_per_pixel == info._samples_per_pixel &&
dst_bits_per_pixel == static_cast<unsigned int>(info._bits_per_pixel) &&
!is_type_signed);
}
template< typename View >
bool is_allowed( const image_read_info< raw_tag >& /* info */
, mpl::false_ // is read_and_convert
, std::false_type // is read_and_convert
)
{
return true;

View File

@@ -13,17 +13,18 @@
#include <boost/gil/extension/io/raw/detail/is_allowed.hpp>
#include <boost/gil/extension/io/raw/detail/reader_backend.hpp>
#include <boost/gil/io/detail/dynamic.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/bit_operations.hpp>
#include <boost/gil/io/conversion_policies.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/reader_base.hpp>
#include <boost/gil/io/row_buffer_helper.hpp>
#include <boost/gil/io/typedefs.hpp>
#include <cstdio>
#include <sstream>
#include <type_traits>
#include <vector>
namespace boost { namespace gil {
@@ -100,7 +101,7 @@ public:
io_error( "Image header was not read." );
}
using is_read_and_convert_t = typename is_same
using is_read_and_convert_t = typename std::is_same
<
ConversionPolicy,
detail::read_and_no_convert
@@ -165,10 +166,7 @@ struct raw_type_format_checker
bool apply()
{
using view_t = typename Image::view_t;
return is_allowed< view_t >( _info
, mpl::true_()
);
return is_allowed<view_t>(_info, std::true_type{});
}
private:
@@ -202,12 +200,12 @@ public:
)
{}
template< typename Images >
void apply( any_image< Images >& images )
template< typename ...Images >
void apply( any_image< Images... >& images )
{
detail::raw_type_format_checker format_checker( this->_info );
if( !construct_matched( images
if( !detail::construct_matched( images
, format_checker
))
{
@@ -226,8 +224,8 @@ public:
, parent_t
> op( this );
apply_operation( view( images )
, op
variant2::visit( op
, view( images )
);
}
}

View File

@@ -98,7 +98,7 @@ public:
}
/// Check if image is large enough.
void check_image_size( const point_t& img_dim )
void check_image_size( point_t const& img_dim )
{
if( _settings._dim.x > 0 )
{

View File

@@ -14,8 +14,7 @@
#include <boost/gil/color_base.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/mpl/not.hpp>
#include <boost/type_traits/is_same.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
@@ -52,23 +51,24 @@ struct raw_write_support : write_support_false {};
} // namespace detail
template< typename Pixel >
struct is_read_supported< Pixel,
raw_tag
>
: mpl::bool_< detail::raw_read_support< typename channel_type< Pixel >::type
, typename color_space_type< Pixel >::type
>::is_supported > {};
template< typename Pixel >
struct is_write_supported< Pixel
, raw_tag
>
: mpl::bool_< detail::raw_write_support::is_supported >
template<typename Pixel>
struct is_read_supported<Pixel,raw_tag>
: std::integral_constant
<
bool,
detail::raw_read_support
<
typename channel_type<Pixel>::type,
typename color_space_type<Pixel>::type
>::is_supported
>
{};
} // namespace gil
} // namespace boost
template<typename Pixel>
struct is_write_supported<Pixel, raw_tag>
: std::integral_constant<bool, detail::raw_write_support::is_supported>
{};
}} // namespace boost::gil
#endif

View File

@@ -10,6 +10,15 @@
#include <boost/gil/io/base.hpp>
// Historically, LibRaw expects WIN32, not _WIN32 (see https://github.com/LibRaw/LibRaw/pull/206)
#ifdef _MSC_VER
#ifndef WIN32
#define WIN32
#endif
#pragma warning(push)
#pragma warning(disable:4251) // 'type' needs to have dll-interface to be used by clients of class
#endif
#include <libraw/libraw.h>
namespace boost { namespace gil {
@@ -114,7 +123,7 @@ template<>
struct image_read_info< raw_tag >
{
/// Default contructor.
image_read_info< raw_tag >()
image_read_info()
: _valid( false )
{}
@@ -173,8 +182,8 @@ struct image_read_settings< raw_tag > : public image_read_settings_base
/// Constructor
/// \param top_left Top left coordinate for reading partial image.
/// \param dim Dimensions for reading partial image.
image_read_settings( const point_t& top_left
, const point_t& dim
image_read_settings( point_t const& top_left
, point_t const& dim
)
: image_read_settings_base( top_left
, dim
@@ -190,7 +199,10 @@ struct image_write_info< raw_tag >
{
};
} // namespace gil
} // namespace boost
}} // namespace boost::gil
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif

View File

@@ -10,11 +10,13 @@
#include <boost/gil/extension/io/targa/tags.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
template< typename View >
bool is_allowed( const image_read_info< targa_tag >& info
, mpl::true_ // is read_and_no_convert
, std::true_type // is read_and_no_convert
)
{
targa_depth::type src_bits_per_pixel = 0;
@@ -42,7 +44,7 @@ bool is_allowed( const image_read_info< targa_tag >& info
template< typename View >
bool is_allowed( const image_read_info< targa_tag >& /* info */
, mpl::false_ // is read_and_convert
, std::false_type // is read_and_convert
)
{
return true;

View File

@@ -12,15 +12,16 @@
#include <boost/gil/extension/io/targa/detail/reader_backend.hpp>
#include <boost/gil/extension/io/targa/detail/is_allowed.hpp>
#include <boost/gil/io/detail/dynamic.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/bit_operations.hpp>
#include <boost/gil/io/conversion_policies.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/reader_base.hpp>
#include <boost/gil/io/row_buffer_helper.hpp>
#include <boost/gil/io/typedefs.hpp>
#include <type_traits>
#include <vector>
namespace boost { namespace gil {
@@ -82,7 +83,7 @@ public:
template< typename View >
void apply( const View& dst_view )
{
using is_read_and_convert_t = typename is_same
using is_read_and_convert_t = typename std::is_same
<
ConversionPolicy,
detail::read_and_no_convert
@@ -361,12 +362,12 @@ public:
)
{}
template< typename Images >
void apply( any_image< Images >& images )
template< typename ...Images >
void apply( any_image< Images... >& images )
{
detail::targa_type_format_checker format_checker( this->_info._bits_per_pixel );
if( !construct_matched( images
if( !detail::construct_matched( images
, format_checker
))
{
@@ -382,8 +383,8 @@ public:
, parent_t
> op( this );
apply_operation( view( images )
, op
variant2::visit( op
,view( images )
);
}
}

View File

@@ -122,7 +122,7 @@ public:
}
/// Check if image is large enough.
void check_image_size( const point_t& img_dim )
void check_image_size( point_t const& img_dim )
{
if( _settings._dim.x > 0 )
{

View File

@@ -14,8 +14,7 @@
#include <boost/gil/color_base.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/mpl/not.hpp>
#include <boost/type_traits/is_same.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
@@ -67,15 +66,17 @@ struct targa_write_support<uint8_t
} // namespace detail
template< typename Pixel >
struct is_read_supported< Pixel
, targa_tag
>
: mpl::bool_< detail::targa_read_support< typename channel_type< Pixel >::type
, typename color_space_type< Pixel >::type
>::is_supported
>
template<typename Pixel>
struct is_read_supported<Pixel, targa_tag>
: std::integral_constant
<
bool,
detail::targa_read_support
<
typename channel_type<Pixel>::type,
typename color_space_type<Pixel>::type
>::is_supported
>
{
using parent_t = detail::targa_read_support
<
@@ -86,17 +87,19 @@ struct is_read_supported< Pixel
static const typename targa_depth::type bpp = parent_t::bpp;
};
template< typename Pixel >
struct is_write_supported< Pixel
, targa_tag
>
: mpl::bool_< detail::targa_write_support< typename channel_type< Pixel >::type
, typename color_space_type< Pixel >::type
>::is_supported
> {};
} // namespace gil
} // namespace boost
template<typename Pixel>
struct is_write_supported<Pixel, targa_tag>
: std::integral_constant
<
bool,
detail::targa_write_support
<
typename channel_type<Pixel>::type,
typename color_space_type<Pixel>::type
>::is_supported
>
{};
}} // namespace boost::gil
#endif

View File

@@ -13,7 +13,7 @@
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/detail/dynamic.hpp>
#include <vector>
@@ -163,14 +163,14 @@ public:
)
{}
template< typename Views >
void apply( const any_image_view< Views >& views )
template< typename ...Views >
void apply( const any_image_view< Views... >& views )
{
detail::dynamic_io_fnobj< detail::targa_write_is_supported
, parent_t
> op( this );
apply_operation( views, op );
variant2::visit( op, views );
}
};

View File

@@ -77,7 +77,7 @@ template<>
struct image_read_info< targa_tag >
{
/// Default contructor.
image_read_info< targa_tag >()
image_read_info()
: _screen_origin_bit(false)
, _valid( false )
{}
@@ -143,8 +143,8 @@ struct image_read_settings< targa_tag > : public image_read_settings_base
/// Constructor
/// \param top_left Top left coordinate for reading partial image.
/// \param dim Dimensions for reading partial image.
image_read_settings( const point_t& top_left
, const point_t& dim
image_read_settings( point_t const& top_left
, point_t const& dim
)
: image_read_settings_base( top_left
, dim

View File

@@ -10,15 +10,15 @@
#include <boost/gil/extension/io/tiff/tags.hpp>
#include <boost/gil/extension/io/tiff/detail/log.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/mpl/size.hpp>
#include <algorithm>
#include <cstdint>
#include <memory>
#include <sstream>
#include <type_traits>
// taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
@@ -66,15 +66,13 @@ template <> struct get_property_f <2>
// Specialisation for multi-valued properties. @todo: add one of
// these for the three-parameter fields too.
template <typename Property>
bool call_me(typename Property:: type & vs, std::shared_ptr<TIFF>& file) const
bool call_me(typename Property::type& vs, std::shared_ptr<TIFF>& file) const
{
typename mpl:: at <typename Property:: arg_types, mpl::int_<0> >:: type length;
typename mpl:: at <typename Property:: arg_types, mpl::int_<1> >:: type pointer;
if (1 == TIFFGetFieldDefaulted( file.get()
, Property:: tag
, & length
, & pointer)) {
std:: copy_n (static_cast <typename Property:: type:: const_pointer> (pointer), length, std:: back_inserter (vs));
mp11::mp_at<typename Property::arg_types, std::integral_constant<int, 0>> length;
mp11::mp_at<typename Property::arg_types, std::integral_constant<int, 1>> pointer;
if (1 == TIFFGetFieldDefaulted(file.get(), Property:: tag, & length, & pointer))
{
std:: copy_n(static_cast<typename Property::type::const_pointer>(pointer), length, std:: back_inserter(vs));
return true;
} else
return false;
@@ -106,12 +104,12 @@ template <> struct set_property_f <2>
inline
bool call_me(typename Property:: type const & values, std::shared_ptr<TIFF>& file) const
{
typename mpl:: at <typename Property:: arg_types, mpl::int_<0> >:: type const length = values. size ();
typename mpl:: at <typename Property:: arg_types, mpl::int_<1> >:: type const pointer = & (values. front ());
return (1 == TIFFSetField( file.get()
, Property:: tag
, length
, pointer));
using length_t = mp11::mp_at_c<typename Property::arg_types, 0>;
auto const length = static_cast<length_t>(values.size());
using pointer_t = mp11::mp_at_c<typename Property::arg_types, 1>;
auto const pointer = static_cast<pointer_t>(&(values.front()));
return (1 == TIFFSetField( file.get(), Property:: tag, length, pointer));
}
};
@@ -132,7 +130,7 @@ public:
template <typename Property>
bool get_property( typename Property::type& value )
{
return get_property_f <mpl:: size <typename Property:: arg_types>::value > ().template call_me<Property>(value, _tiff_file);
return get_property_f<mp11::mp_size<typename Property::arg_types>::value>().template call_me<Property>(value, _tiff_file);
}
template <typename Property>
@@ -140,7 +138,7 @@ public:
bool set_property( const typename Property::type& value )
{
// http://www.remotesensing.org/libtiff/man/TIFFSetField.3tiff.html
return set_property_f <mpl:: size <typename Property:: arg_types>::value > ().template call_me<Property> (value, _tiff_file);
return set_property_f<mp11::mp_size<typename Property::arg_types>::value>().template call_me<Property>(value, _tiff_file);
}
// TIFFIsByteSwapped returns a non-zero value if the image data was in a different
@@ -195,7 +193,7 @@ public:
{
io_error_if( TIFFReadScanline( _tiff_file.get()
, reinterpret_cast< tdata_t >( &buffer.front() )
, (uint32) row
, static_cast<std::uint32_t>( row )
, plane ) == -1
, "Read error."
);
@@ -208,7 +206,7 @@ public:
{
io_error_if( TIFFReadScanline( _tiff_file.get()
, reinterpret_cast< tdata_t >( buffer )
, (uint32) row
, static_cast<std::uint32_t>( row )
, plane ) == -1
, "Read error."
);
@@ -224,9 +222,9 @@ public:
{
if( TIFFReadTile( _tiff_file.get()
, reinterpret_cast< tdata_t >( &buffer.front() )
, (uint32) x
, (uint32) y
, (uint32) z
, static_cast< std::uint32_t >( x )
, static_cast< std::uint32_t >( y )
, static_cast< std::uint32_t >( z )
, plane
) == -1 )
{
@@ -237,9 +235,9 @@ public:
}
template< typename Buffer >
void write_scaline( Buffer& buffer
, uint32 row
, tsample_t plane
void write_scaline( Buffer& buffer
, std::uint32_t row
, tsample_t plane
)
{
io_error_if( TIFFWriteScanline( _tiff_file.get()
@@ -251,9 +249,9 @@ public:
);
}
void write_scaline( byte_t* buffer
, uint32 row
, tsample_t plane
void write_scaline( byte_t* buffer
, std::uint32_t row
, tsample_t plane
)
{
io_error_if( TIFFWriteScanline( _tiff_file.get()
@@ -266,11 +264,11 @@ public:
}
template< typename Buffer >
void write_tile( Buffer& buffer
, uint32 x
, uint32 y
, uint32 z
, tsample_t plane
void write_tile( Buffer& buffer
, std::uint32_t x
, std::uint32_t y
, std::uint32_t z
, tsample_t plane
)
{
if( TIFFWriteTile( _tiff_file.get()
@@ -303,8 +301,8 @@ public:
)
{
bool result = true;
uint32 tw = static_cast< uint32 >( width );
uint32 th = static_cast< uint32 >( height );
std::uint32_t tw = static_cast< std::uint32_t >( width );
std::uint32_t th = static_cast< std::uint32_t >( height );
TIFFDefaultTileSize( _tiff_file.get()
, &tw
@@ -432,45 +430,55 @@ private:
/*
template< typename T, typename D >
struct is_adaptable_input_device< tiff_tag, T, D > : mpl::false_{};
struct is_adaptable_input_device< tiff_tag, T, D > : std::false_type {};
*/
template< typename FormatTag >
struct is_adaptable_input_device< FormatTag
, TIFF*
, void
>
: mpl::true_
template<typename FormatTag>
struct is_adaptable_input_device<FormatTag, TIFF*, void> : std::true_type
{
using device_type = file_stream_device<FormatTag>;
};
template< typename FormatTag >
struct is_adaptable_output_device< FormatTag
, TIFF*
, void
>
: mpl::true_
template<typename FormatTag>
struct is_adaptable_output_device<FormatTag, TIFF*, void> : std::true_type
{
using device_type = file_stream_device<FormatTag>;
};
template < typename Channel > struct sample_format : public mpl::int_<SAMPLEFORMAT_UINT> {};
template<> struct sample_format<uint8_t> : public mpl::int_<SAMPLEFORMAT_UINT> {};
template<> struct sample_format<uint16_t> : public mpl::int_<SAMPLEFORMAT_UINT> {};
template<> struct sample_format<uint32_t> : public mpl::int_<SAMPLEFORMAT_UINT> {};
template<> struct sample_format<float32_t> : public mpl::int_<SAMPLEFORMAT_IEEEFP> {};
template<> struct sample_format<double> : public mpl::int_<SAMPLEFORMAT_IEEEFP> {};
template<> struct sample_format<int8_t> : public mpl::int_<SAMPLEFORMAT_INT> {};
template<> struct sample_format<int16_t> : public mpl::int_<SAMPLEFORMAT_INT> {};
template<> struct sample_format<int32_t> : public mpl::int_<SAMPLEFORMAT_INT> {};
template <typename Channel>
struct sample_format : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
template<>
struct sample_format<uint8_t> : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
template<>
struct sample_format<uint16_t> : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
template<>
struct sample_format<uint32_t> : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
template<>
struct sample_format<float32_t> : std::integral_constant<int, SAMPLEFORMAT_IEEEFP> {};
template<>
struct sample_format<double> : std::integral_constant<int, SAMPLEFORMAT_IEEEFP> {};
template<>
struct sample_format<int8_t> : std::integral_constant<int, SAMPLEFORMAT_INT> {};
template<>
struct sample_format<int16_t> : std::integral_constant<int, SAMPLEFORMAT_INT> {};
template<>
struct sample_format<int32_t> : std::integral_constant<int, SAMPLEFORMAT_INT> {};
template <typename Channel> struct photometric_interpretation {};
template<> struct photometric_interpretation< gray_t > : public mpl::int_< PHOTOMETRIC_MINISBLACK > {};
template<> struct photometric_interpretation< rgb_t > : public mpl::int_< PHOTOMETRIC_RGB > {};
template<> struct photometric_interpretation< rgba_t > : public mpl::int_< PHOTOMETRIC_RGB > {};
template<> struct photometric_interpretation< cmyk_t > : public mpl::int_< PHOTOMETRIC_SEPARATED > {};
template <typename Channel>
struct photometric_interpretation {};
template<>
struct photometric_interpretation<gray_t>
: std::integral_constant<int, PHOTOMETRIC_MINISBLACK> {};
template<>
struct photometric_interpretation<rgb_t>
: std::integral_constant<int, PHOTOMETRIC_RGB> {};
template<>
struct photometric_interpretation<rgba_t>
: std::integral_constant<int, PHOTOMETRIC_RGB> {};
template<>
struct photometric_interpretation<cmyk_t>
: std::integral_constant<int, PHOTOMETRIC_SEPARATED> {};
} // namespace detail
} // namespace gil

View File

@@ -9,10 +9,10 @@
#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_IS_ALLOWED_HPP
#include <boost/gil/extension/io/tiff/tags.hpp>
#include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/mpl/for_each.hpp>
#include <type_traits>
namespace boost { namespace gil { namespace detail {
@@ -48,13 +48,13 @@ struct Format_Type
Channel,
typename std::enable_if
<
mpl::and_
mp11::mp_and
<
mpl::not_
mp11::mp_not
<
typename is_bit_aligned<typename get_pixel_type<View>::type>::type
>,
is_unsigned<Channel>
std::is_unsigned<Channel>
>::value
>::type
>
@@ -70,13 +70,13 @@ struct Format_Type
Channel,
typename std::enable_if
<
mpl::and_
mp11::mp_and
<
mpl::not_
mp11::mp_not
<
typename is_bit_aligned<typename get_pixel_type<View>::type>::type
>,
is_signed<Channel>
std::is_signed<Channel>
>::value
>::type
>
@@ -92,9 +92,9 @@ struct Format_Type
Channel,
typename std::enable_if
<
mpl::and_
mp11::mp_and
<
mpl::not_
mp11::mp_not
<
typename is_bit_aligned<typename get_pixel_type<View>::type>::type
>,
@@ -107,13 +107,13 @@ struct Format_Type
};
//template< typename Channel >
//int format_value( mpl::true_ ) // is_bit_aligned
//int format_value( std::true_type ) // is_bit_aligned
//{
// return SAMPLEFORMAT_UINT;
//}
//
//template< typename Channel >
//int format_value( mpl::false_ ) // is_bit_aligned
//int format_value( std::false_type ) // is_bit_aligned
//{
// if( is_unsigned< Channel >::value )
// {
@@ -137,8 +137,8 @@ struct Format_Type
// a pixel_t as template parameter whereas the other is using reference_t.
template< typename View >
bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
, mpl::false_ // is_bit_aligned
, mpl::true_ // is_homogeneous
, std::false_type // is_bit_aligned
, std::true_type // is_homogeneous
)
{
using pixel_t = typename View::value_type;
@@ -152,17 +152,14 @@ bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
template< typename View >
bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
, mpl::true_ // is_bit_aligned
, mpl::true_ // is_homogeneous
, std::true_type // is_bit_aligned
, std::true_type // is_homogeneous
)
{
using ref_t = typename View::reference;
using channel_t = typename channel_traits<typename element_type<ref_t>::type>::value_type;
channel_t c;
unsigned int s = detail::unsigned_integral_num_bits< channel_t >::value;
return ( s == channel_sizes[0] );
}
@@ -197,8 +194,8 @@ struct channel_sizes_type< const bit_aligned_pixel_reference< B, C, L, M > > { u
template< typename View >
bool compare_channel_sizes( channel_sizes_t& channel_sizes // in bits
, mpl::true_ // is_bit_aligned
, mpl::false_ // is_homogeneous
, std::true_type // is_bit_aligned
, std::false_type // is_homogeneous
)
{
// loop through all channels and compare
@@ -207,14 +204,14 @@ bool compare_channel_sizes( channel_sizes_t& channel_sizes // in bits
using cs_t = typename channel_sizes_type<ref_t>::type;
compare_channel_sizes_fn fn( &channel_sizes.front() );
mpl::for_each< cs_t >( fn );
mp11::mp_for_each<cs_t>(fn);
return fn._b;
}
template< typename View >
bool is_allowed( const image_read_info< tiff_tag >& info
, mpl::true_ // is read_and_no_convert
, std::true_type // is read_and_no_convert
)
{
channel_sizes_t channel_sizes( info._samples_per_pixel
@@ -243,7 +240,7 @@ bool is_allowed( const image_read_info< tiff_tag >& info
template< typename View >
bool is_allowed( const image_read_info< tiff_tag >& /* info */
, mpl::false_ // is read_and_no_convert
, std::false_type // is read_and_no_convert
)
{
return true;

View File

@@ -12,11 +12,11 @@
#include <boost/gil/extension/io/tiff/detail/is_allowed.hpp>
#include <boost/gil/extension/io/tiff/detail/reader_backend.hpp>
#include <boost/gil/io/detail/dynamic.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/bit_operations.hpp>
#include <boost/gil/io/conversion_policies.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/reader_base.hpp>
#include <boost/gil/io/row_buffer_helper.hpp>
@@ -24,6 +24,7 @@
#include <algorithm>
#include <string>
#include <type_traits>
#include <vector>
// taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
@@ -173,7 +174,7 @@ public:
// the tiff type need to compatible. Which means:
// color_spaces_are_compatible && channels_are_pairwise_compatible
using is_read_only = typename is_same
using is_read_only = typename std::is_same
<
ConversionPolicy,
detail::read_and_no_convert
@@ -208,7 +209,7 @@ private:
template< typename View >
void read( View v
, mpl::true_ // is_read_only
, std::true_type // is_read_only
)
{
read_data< detail::row_buffer_helper_view< View > >( v, 0 );
@@ -216,7 +217,7 @@ private:
template< typename View >
void read( View v
, mpl::false_ // is_read_only
, std::false_type // is_read_only
)
{
// the read_data function needs to know what gil type the source image is
@@ -302,11 +303,13 @@ private:
, this->_info._height - this->_settings._top_left.y );
// read the palette first
read_data< detail::row_buffer_helper_view< typename PaletteImage::view_t > >( view( indices ), 0 );
read_data< detail::row_buffer_helper_view
<
typename PaletteImage::view_t>
>(view(indices), 0);
read_palette_image( dst_view
, view( indices )
, typename is_same< View, rgb16_view_t >::type() );
read_palette_image(dst_view, view(indices),
typename std::is_same<View, rgb16_view_t>::type());
}
template< typename View
@@ -314,7 +317,7 @@ private:
>
void read_palette_image( const View& dst_view
, const Indices_View& indices_view
, mpl::true_ // is View rgb16_view_t
, std::true_type // is View rgb16_view_t
)
{
tiff_color_map::red_t red = nullptr;
@@ -356,7 +359,7 @@ private:
inline
void read_palette_image( const View& /* dst_view */
, const Indices_View& /* indices_view */
, mpl::false_ // is View rgb16_view_t
, std::false_type // is View rgb16_view_t
)
{
io_error( "User supplied image type must be rgb16_image_t." );
@@ -653,7 +656,7 @@ private:
template< typename Pixel >
std::size_t buffer_size( std::size_t width
, mpl::false_ // is_bit_aligned
, std::false_type // is_bit_aligned
)
{
std::size_t scanline_size_in_bytes = this->_io_dev.get_scanline_size();
@@ -669,7 +672,7 @@ private:
template< typename Pixel >
std::size_t buffer_size( std::size_t /* width */
, mpl::true_ // is_bit_aligned
, std::true_type // is_bit_aligned
)
{
return this->_io_dev.get_scanline_size();
@@ -694,7 +697,7 @@ struct tiff_type_format_checker
using view_t = typename Image::view_t;
return is_allowed< view_t >( _info
, mpl::true_()
, std::true_type()
);
}
@@ -742,8 +745,8 @@ public:
)
{}
template< typename Images >
void apply( any_image< Images >& images )
template< typename ...Images >
void apply( any_image< Images... >& images )
{
detail::tiff_type_format_checker format_checker( this->_info );
@@ -763,8 +766,8 @@ public:
, parent_t
> op( this );
apply_operation( view( images )
, op
variant2::visit( op
, view( images )
);
}
}

View File

@@ -103,7 +103,7 @@ public:
}
/// Check if image is large enough.
void check_image_size( const point_t& img_dim )
void check_image_size( point_t const& img_dim )
{
if( _settings._dim.x > 0 )
{

View File

@@ -14,8 +14,7 @@
#include <boost/gil/color_base.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/mpl/not.hpp>
#include <boost/type_traits/is_same.hpp>
#include <type_traits>
namespace boost{ namespace gil {
@@ -35,20 +34,16 @@ struct tiff_write_support : write_support_true
} // namespace detail
template< typename Pixel >
struct is_read_supported< Pixel
, tiff_tag
>
: mpl::bool_< detail::tiff_read_support::is_supported > {};
template< typename Pixel >
struct is_write_supported< Pixel
, tiff_tag
>
: mpl::bool_< detail::tiff_write_support::is_supported >
template<typename Pixel>
struct is_read_supported<Pixel, tiff_tag>
: std::integral_constant<bool, detail::tiff_read_support::is_supported>
{};
} // namespace gil
} // namespace boost
template<typename Pixel>
struct is_write_supported<Pixel, tiff_tag>
: std::integral_constant<bool, detail::tiff_write_support::is_supported>
{};
}} // namespace boost::gil
#endif

View File

@@ -15,10 +15,12 @@
#include <boost/gil/premultiply.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/detail/dynamic.hpp>
#include <algorithm>
#include <cstdint>
#include <string>
#include <type_traits>
#include <vector>
extern "C" {
@@ -39,7 +41,8 @@ template <typename PixelReference>
struct my_interleaved_pixel_iterator_type_from_pixel_reference
{
private:
using pixel_t = typename remove_reference<PixelReference>::type::value_type;
using pixel_t = typename std::remove_reference<PixelReference>::type::value_type;
public:
using type = typename iterator_type_from_pixel
<
@@ -162,7 +165,7 @@ private:
template<typename View>
void write_bit_aligned_view_to_dev( const View& view
, const std::size_t row_size_in_bytes
, const mpl::true_& // has_alpha
, const std::true_type& // has_alpha
)
{
byte_vector_t row( row_size_in_bytes );
@@ -181,7 +184,7 @@ private:
this->_io_dev.write_scaline( row
, (uint32) y
, static_cast<std::uint32_t>( y )
, 0
);
@@ -192,7 +195,7 @@ private:
template<typename View>
void write_bit_aligned_view_to_dev( const View& view
, const std::size_t row_size_in_bytes
, const mpl::false_& // has_alpha
, const std::false_type& // has_alpha
)
{
byte_vector_t row( row_size_in_bytes );
@@ -209,7 +212,7 @@ private:
this->_io_dev.write_scaline( row
, (uint32) y
, static_cast<std::uint32_t>( y )
, 0
);
@@ -222,11 +225,11 @@ private:
template< typename View >
void write_data( const View& view
, std::size_t row_size_in_bytes
, const mpl::true_& // bit_aligned
, const std::true_type& // bit_aligned
)
{
using colour_space_t = typename color_space_type<typename View::value_type>::type;
using has_alpha_t = mpl::bool_<mpl::contains<colour_space_t, alpha_t>::value>;
using has_alpha_t = mp11::mp_contains<colour_space_t, alpha_t>;
write_bit_aligned_view_to_dev(view, row_size_in_bytes, has_alpha_t());
}
@@ -235,7 +238,7 @@ private:
void write_tiled_data( const View& view
, tiff_tile_width::type tw
, tiff_tile_length::type th
, const mpl::true_& // bit_aligned
, const std::true_type& // bit_aligned
)
{
byte_vector_t row( this->_io_dev.get_tile_size() );
@@ -249,7 +252,7 @@ private:
template< typename View >
void write_data( const View& view
, std::size_t
, const mpl::false_& // bit_aligned
, const std::false_type& // bit_aligned
)
{
std::vector< pixel< typename channel_type< View >::type
@@ -271,7 +274,7 @@ private:
);
this->_io_dev.write_scaline( row_addr
, (uint32) y
, static_cast<std::uint32_t>( y )
, 0
);
@@ -283,7 +286,7 @@ private:
void write_tiled_data( const View& view
, tiff_tile_width::type tw
, tiff_tile_length::type th
, const mpl::false_& // bit_aligned
, const std::false_type& // bit_aligned
)
{
byte_vector_t row( this->_io_dev.get_tile_size() );
@@ -302,7 +305,7 @@ private:
>
void write_tiled_view_to_dev( const View& view
, IteratorType it
, const mpl::true_& // has_alpha
, const std::true_type& // has_alpha
)
{
auto pm_view = premultiply_view <typename View:: value_type>( view );
@@ -319,7 +322,7 @@ private:
>
void write_tiled_view_to_dev( const View& view
, IteratorType it
, const mpl::false_& // has_alpha
, const std::false_type& // has_alpha
)
{
std::copy( view.begin()
@@ -359,7 +362,7 @@ private:
);
using colour_space_t = typename color_space_type<typename View::value_type>::type;
using has_alpha_t = mpl::bool_<mpl::contains<colour_space_t, alpha_t>::value>;
using has_alpha_t = mp11::mp_contains<colour_space_t, alpha_t>;
write_tiled_view_to_dev(tile_subimage_view, it, has_alpha_t());
}
@@ -391,8 +394,8 @@ private:
}
this->_io_dev.write_tile( row
, static_cast< uint32 >( j )
, static_cast< uint32 >( i )
, static_cast< std::uint32_t >( j )
, static_cast< std::uint32_t >( i )
, 0
, 0
);
@@ -428,14 +431,14 @@ public:
)
{}
template< typename Views >
void apply( const any_image_view< Views >& views )
template< typename ...Views >
void apply( const any_image_view< Views... >& views )
{
detail::dynamic_io_fnobj< detail::tiff_write_is_supported
, parent_t
> op( this );
apply_operation( views, op );
variant2::visit( op, views );
}
};

View File

@@ -11,7 +11,7 @@
#include <boost/gil/extension/io/tiff/tags.hpp>
#include <boost/gil/extension/io/tiff/detail/device.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/gil/detail/mp11.hpp>
namespace boost { namespace gil {
@@ -78,10 +78,12 @@ protected:
tiff_samples_per_pixel::type samples_per_pixel = num_channels< pixel_t >::value;
this->_io_dev.template set_property<tiff_samples_per_pixel>( samples_per_pixel );
if (mpl:: contains <color_space_t, alpha_t>:: value) {
if /*constexpr*/ (mp11::mp_contains<color_space_t, alpha_t>::value)
{
std:: vector <uint16_t> extra_samples {EXTRASAMPLE_ASSOCALPHA};
this->_io_dev.template set_property<tiff_extra_samples>( extra_samples );
}
// write bits per sample
// @todo: Settings this value usually requires to write for each sample the bit
// value seperately in case they are different, like rgb556.

View File

@@ -10,9 +10,10 @@
#include <boost/gil/extension/io/tiff/detail/log.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <boost/gil/io/base.hpp>
#include <boost/mpl/vector.hpp>
#include <type_traits>
// taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
@@ -44,7 +45,7 @@ struct tiff_property_base : property_base< T >
/// this property:
/// http://www.remotesensing.org/libtiff/man/TIFFGetField.3tiff.html
/// http://www.remotesensing.org/libtiff/man/TIFFSetField.3tiff.html
using arg_types = mpl::vector<typename property_base<unsigned short>::type>;
using arg_types = mp11::mp_list<typename property_base<unsigned short>::type>;
};
/// baseline tags
@@ -153,9 +154,9 @@ struct tiff_color_map
};
/// Defines type for extra samples property.
struct tiff_extra_samples : tiff_property_base<std:: vector <uint16_t>, TIFFTAG_EXTRASAMPLES>
struct tiff_extra_samples : tiff_property_base<std::vector<uint16_t>, TIFFTAG_EXTRASAMPLES>
{
using arg_types = mpl::vector<uint16_t, uint16_t const *>;
using arg_types = mp11::mp_list<uint16_t, uint16_t const*>;
};
/// Defines type for copyright property.
@@ -182,10 +183,9 @@ struct tiff_tile_width : tiff_property_base< long, TIFFTAG_TILEWIDTH > {};
struct tiff_tile_length : tiff_property_base< long, TIFFTAG_TILELENGTH > {};
/// Defines the page to read in a multipage tiff file.
#include <boost/mpl/integral_c.hpp>
struct tiff_directory : property_base< tdir_t >
{
using default_value = boost::mpl::integral_c<type, 0>;
using default_value = std::integral_constant<type, 0>;
};
/// Non-baseline tags
@@ -193,7 +193,7 @@ struct tiff_directory : property_base< tdir_t >
/// Defines type for icc profile property.
struct tiff_icc_profile : tiff_property_base<std::vector<uint8_t>, TIFFTAG_ICCPROFILE>
{
using arg_types = mpl::vector<uint32_t, void const *>;
using arg_types = mp11::mp_list<uint32_t, void const*>;
};
/// Read information for tiff images.
@@ -270,7 +270,7 @@ template<>
struct image_read_settings< tiff_tag > : public image_read_settings_base
{
/// Default constructor
image_read_settings< tiff_tag >()
image_read_settings()
: image_read_settings_base()
, _directory( tiff_directory::default_value::value )
{}
@@ -279,8 +279,8 @@ struct image_read_settings< tiff_tag > : public image_read_settings_base
/// \param top_left Top left coordinate for reading partial image.
/// \param dim Dimensions for reading partial image.
/// \param directory Defines the page to read in a multipage tiff file.
image_read_settings( const point_t& top_left
, const point_t& dim
image_read_settings( point_t const& top_left
, point_t const& dim
, const tiff_directory::type& directory = tiff_directory::default_value::value
)
: image_read_settings_base( top_left

View File

@@ -89,6 +89,85 @@ point<F> transform(matrix3x2<F> const& mat, point<F2> const& src)
return src * mat;
}
/// Returns the inverse of the given affine transformation matrix
///
/// \warning Floating point arithmetic, use Boost.Rational if precision maters
template <typename T>
boost::gil::matrix3x2<T> inverse(boost::gil::matrix3x2<T> m)
{
T const determinant = m.a * m.d - m.b * m.c;
boost::gil::matrix3x2<T> res;
res.a = m.d / determinant;
res.b = -m.b / determinant;
res.c = -m.c / determinant;
res.d = m.a / determinant;
res.e = (m.c * m.f - m.d * m.e) / determinant;
res.f = (m.b * m.e - m.a * m.f) / determinant;
return res;
}
/// \fn gil::matrix3x2 center_rotate
/// \tparam T Data type for source image dimensions
/// \tparam F Data type for angle through which image is to be rotated
/// @param dims dimensions of source image
/// @param rads angle through which image is to be rotated
/// @return A transformation matrix for rotating the source image about its center
/// \brief rotates an image from its center point
/// using consecutive affine transformations.
template<typename T, typename F>
boost::gil::matrix3x2<F> center_rotate(boost::gil::point<T> dims,F rads)
{
const F PI = F(3.141592653589793238);
const F c_theta = std::abs(std::cos(rads));
const F s_theta = std::abs(std::sin(rads));
// Bound checks for angle rads
while(rads + PI < 0)
{
rads = rads + PI;
}
while(rads > PI)
{
rads = rads - PI;
}
// Basic Rotation Matrix
boost::gil::matrix3x2<F> rotate = boost::gil::matrix3x2<F>::get_rotate(rads);
// Find distance for translating the image into view
boost::gil::matrix3x2<F> translation(0,0,0,0,0,0);
if(rads > 0)
{
translation.b = s_theta;
}
else
{
translation.c = s_theta;
}
if(std::abs(rads) > PI/2)
{
translation.a = c_theta;
translation.d = c_theta;
}
// To bring the complete image into view
boost::gil::matrix3x2<F> translate =
boost::gil::matrix3x2<F>::get_translate(-1 * dims * translation);
// To fit inside the source dimensions
boost::gil::matrix3x2<F> scale =
boost::gil::matrix3x2<F>::get_scale(
s_theta * dims.y / dims.x + c_theta ,
s_theta * dims.x / dims.y + c_theta
);
return scale * translate * rotate;
}
}} // namespace boost::gil
#endif
#endif

View File

@@ -1,5 +1,6 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2019-2021 Pranam Lashkari <plashkari628@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
@@ -8,142 +9,8 @@
#ifndef BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
#define BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
#include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
#include <boost/config/header_deprecated.hpp>
#include <boost/gil/metafunctions.hpp>
#include <boost/gil/pixel_iterator.hpp>
#include <boost/assert.hpp>
#include <algorithm>
#include <iterator>
#include <numeric>
namespace boost { namespace gil {
/// \brief Returns the reference proxy associated with a type that has a \p "reference" member type alias.
///
/// The reference proxy is the reference type, but with stripped-out C++ reference. It models PixelConcept
template <typename T>
struct pixel_proxy : public remove_reference<typename T::reference> {};
/// \brief std::for_each for a pair of iterators
template <typename Iterator1,typename Iterator2,typename BinaryFunction>
BinaryFunction for_each(Iterator1 first1,Iterator1 last1,Iterator2 first2,BinaryFunction f) {
while(first1!=last1)
f(*first1++,*first2++);
return f;
}
template <typename SrcIterator,typename DstIterator>
inline DstIterator assign_pixels(SrcIterator src,SrcIterator src_end,DstIterator dst) {
for_each(src,src_end,dst,pixel_assigns_t<typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type,
typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type>());
return dst+(src_end-src);
}
namespace detail {
template <std::size_t Size>
struct inner_product_k_t {
template <class _InputIterator1, class _InputIterator2, class _Tp,
class _BinaryOperation1, class _BinaryOperation2>
static _Tp apply(_InputIterator1 __first1,
_InputIterator2 __first2, _Tp __init,
_BinaryOperation1 __binary_op1,
_BinaryOperation2 __binary_op2) {
__init = __binary_op1(__init, __binary_op2(*__first1, *__first2));
return inner_product_k_t<Size-1>::template apply(__first1+1,__first2+1,__init,
__binary_op1, __binary_op2);
}
};
template <>
struct inner_product_k_t<0> {
template <class _InputIterator1, class _InputIterator2, class _Tp,
class _BinaryOperation1, class _BinaryOperation2>
static _Tp apply(_InputIterator1 __first1,
_InputIterator2 __first2, _Tp __init,
_BinaryOperation1 __binary_op1,
_BinaryOperation2 __binary_op2) {
return __init;
}
};
} // namespace detail
/// static version of std::inner_product
template <std::size_t Size,
class _InputIterator1, class _InputIterator2, class _Tp,
class _BinaryOperation1, class _BinaryOperation2>
BOOST_FORCEINLINE
_Tp inner_product_k(_InputIterator1 __first1,
_InputIterator2 __first2,
_Tp __init,
_BinaryOperation1 __binary_op1,
_BinaryOperation2 __binary_op2) {
return detail::inner_product_k_t<Size>::template apply(__first1,__first2,__init,
__binary_op1, __binary_op2);
}
/// \brief 1D un-guarded correlation with a variable-size kernel
template <typename PixelAccum,typename SrcIterator,typename KernelIterator,typename Integer,typename DstIterator>
inline DstIterator correlate_pixels_n(SrcIterator src_begin,SrcIterator src_end,
KernelIterator ker_begin,Integer ker_size,
DstIterator dst_begin) {
using PIXEL_SRC_REF = typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type;
using PIXEL_DST_REF = typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type;
using kernel_type = typename std::iterator_traits<KernelIterator>::value_type;
PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
while(src_begin!=src_end) {
pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
std::inner_product(src_begin,src_begin+ker_size,ker_begin,acc_zero,
pixel_plus_t<PixelAccum,PixelAccum,PixelAccum>(),
pixel_multiplies_scalar_t<PIXEL_SRC_REF,kernel_type,PixelAccum>()),
*dst_begin);
++src_begin; ++dst_begin;
}
return dst_begin;
}
/// \brief 1D un-guarded correlation with a fixed-size kernel
template <std::size_t Size,typename PixelAccum,typename SrcIterator,typename KernelIterator,typename DstIterator>
inline DstIterator correlate_pixels_k(SrcIterator src_begin,SrcIterator src_end,
KernelIterator ker_begin,
DstIterator dst_begin) {
using PIXEL_SRC_REF = typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type;
using PIXEL_DST_REF = typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type;
using kernel_type = typename std::iterator_traits<KernelIterator>::value_type;
PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
while(src_begin!=src_end) {
pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
inner_product_k<Size>(src_begin,ker_begin,acc_zero,
pixel_plus_t<PixelAccum,PixelAccum,PixelAccum>(),
pixel_multiplies_scalar_t<PIXEL_SRC_REF,kernel_type,PixelAccum>()),
*dst_begin);
++src_begin; ++dst_begin;
}
return dst_begin;
}
/// \brief destination is set to be product of the source and a scalar
template <typename PixelAccum,typename SrcView,typename Scalar,typename DstView>
inline void view_multiplies_scalar(const SrcView& src,const Scalar& scalar,const DstView& dst) {
BOOST_ASSERT(src.dimensions() == dst.dimensions());
using PIXEL_SRC_REF = typename pixel_proxy<typename SrcView::value_type>::type;
using PIXEL_DST_REF = typename pixel_proxy<typename DstView::value_type>::type;
int height=src.height();
for(int rr=0;rr<height;++rr) {
typename SrcView::x_iterator it_src=src.row_begin(rr);
typename DstView::x_iterator it_dst=dst.row_begin(rr);
typename SrcView::x_iterator it_src_end=src.row_end(rr);
while(it_src!=it_src_end) {
pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
pixel_multiplies_scalar_t<PIXEL_SRC_REF,Scalar,PixelAccum>()(*it_src,scalar),
*it_dst);
++it_src; ++it_dst;
}
}
}
}} // namespace boost::gil
BOOST_HEADER_DEPRECATED("<boost/gil/algorithm.hpp>")
#endif

View File

@@ -1,5 +1,6 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
@@ -8,140 +9,8 @@
#ifndef BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
#define BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
#include <boost/gil/channel.hpp>
#include <boost/config/header_deprecated.hpp>
namespace boost { namespace gil {
// Structures for channel-wise numeric operations
// Currently defined structures:
// channel_plus_t (+), channel_minus_t (-),
// channel_multiplies_t (*), channel_divides_t (/),
// channel_plus_scalar_t (+s), channel_minus_scalar_t (-s),
// channel_multiplies_scalar_t (*s), channel_divides_scalar_t (/s),
// channel_halves_t (/=2), channel_zeros_t (=0), channel_assigns_t (=)
/// \ingroup ChannelNumericOperations
/// structure for adding one channel to another
/// this is a generic implementation; user should specialize it for better performance
template <typename Channel1,typename Channel2,typename ChannelR>
struct channel_plus_t {
ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
typename channel_traits<Channel2>::const_reference ch2) const {
return ChannelR(ch1)+ChannelR(ch2);
}
};
/// \ingroup ChannelNumericOperations
/// structure for subtracting one channel from another
/// this is a generic implementation; user should specialize it for better performance
template <typename Channel1,typename Channel2,typename ChannelR>
struct channel_minus_t {
ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
typename channel_traits<Channel2>::const_reference ch2) const {
return ChannelR(ch1)-ChannelR(ch2);
}
};
/// \ingroup ChannelNumericOperations
/// structure for multiplying one channel to another
/// this is a generic implementation; user should specialize it for better performance
template <typename Channel1,typename Channel2,typename ChannelR>
struct channel_multiplies_t {
ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
typename channel_traits<Channel2>::const_reference ch2) const {
return ChannelR(ch1)*ChannelR(ch2);
}
};
/// \ingroup ChannelNumericOperations
/// structure for dividing channels
/// this is a generic implementation; user should specialize it for better performance
template <typename Channel1,typename Channel2,typename ChannelR>
struct channel_divides_t {
ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
typename channel_traits<Channel2>::const_reference ch2) const {
return ChannelR(ch1)/ChannelR(ch2);
}
};
/// \ingroup ChannelNumericOperations
/// structure for adding a scalar to a channel
/// this is a generic implementation; user should specialize it for better performance
template <typename Channel,typename Scalar,typename ChannelR>
struct channel_plus_scalar_t {
ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
const Scalar& s) const {
return ChannelR(ch)+ChannelR(s);
}
};
/// \ingroup ChannelNumericOperations
/// structure for subtracting a scalar from a channel
/// this is a generic implementation; user should specialize it for better performance
template <typename Channel,typename Scalar,typename ChannelR>
struct channel_minus_scalar_t {
ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
const Scalar& s) const {
return ChannelR(ch-s);
}
};
/// \ingroup ChannelNumericOperations
/// structure for multiplying a scalar to one channel
/// this is a generic implementation; user should specialize it for better performance
template <typename Channel,typename Scalar,typename ChannelR>
struct channel_multiplies_scalar_t {
ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
const Scalar& s) const {
return ChannelR(ch)*ChannelR(s);
}
};
/// \ingroup ChannelNumericOperations
/// structure for dividing a channel by a scalar
/// this is a generic implementation; user should specialize it for better performance
template <typename Channel,typename Scalar,typename ChannelR>
struct channel_divides_scalar_t {
ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
const Scalar& s) const {
return ChannelR(ch)/ChannelR(s);
}
};
/// \ingroup ChannelNumericOperations
/// structure for halving a channel
/// this is a generic implementation; user should specialize it for better performance
template <typename Channel>
struct channel_halves_t {
typename channel_traits<Channel>::reference
operator()(typename channel_traits<Channel>::reference ch) const {
return ch/=2.0;
}
};
/// \ingroup ChannelNumericOperations
/// structure for setting a channel to zero
/// this is a generic implementation; user should specialize it for better performance
template <typename Channel>
struct channel_zeros_t {
typename channel_traits<Channel>::reference
operator()(typename channel_traits<Channel>::reference ch) const {
return ch=Channel(0);
}
};
/// \ingroup ChannelNumericOperations
/// structure for assigning one channel to another
/// this is a generic implementation; user should specialize it for better performance
template <typename Channel1,typename Channel2>
struct channel_assigns_t {
typename channel_traits<Channel2>::reference
operator()(typename channel_traits<Channel1>::const_reference ch1,
typename channel_traits<Channel2>::reference ch2) const {
return ch2=Channel2(ch1);
}
};
}} // namespace boost::gil
BOOST_HEADER_DEPRECATED("<boost/gil/channel_numeric_operations.hpp>")
#endif

View File

@@ -1,5 +1,7 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2019 Miral Shah <miralshah2211@gmail.com>
// Copyright 2019-2021 Pranam Lashkari <plashkari628@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
@@ -8,210 +10,8 @@
#ifndef BOOST_GIL_EXTENSION_NUMERIC_CONVOLVE_HPP
#define BOOST_GIL_EXTENSION_NUMERIC_CONVOLVE_HPP
#include <boost/gil/extension/numeric/algorithm.hpp>
#include <boost/gil/extension/numeric/kernel.hpp>
#include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
#include <boost/config/header_deprecated.hpp>
#include <boost/gil/algorithm.hpp>
#include <boost/gil/image_view_factory.hpp>
#include <boost/gil/metafunctions.hpp>
#include <boost/assert.hpp>
#include <algorithm>
#include <cstddef>
#include <functional>
#include <type_traits>
#include <vector>
namespace boost { namespace gil {
// 2D seperable convolutions and correlations
/// \ingroup ImageAlgorithms
/// Boundary options for 1D correlations/convolutions
enum convolve_boundary_option {
convolve_option_output_ignore, /// do nothing to the output
convolve_option_output_zero, /// set the output to zero
convolve_option_extend_padded, /// assume the source boundaries to be padded already
convolve_option_extend_zero, /// assume the source boundaries to be zero
convolve_option_extend_constant /// assume the source boundaries to be the boundary value
};
namespace detail {
/// compute the correlation of 1D kernel with the rows of an image
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView,typename Correlator>
void correlate_rows_imp(const SrcView& src, const Kernel& ker, const DstView& dst,
convolve_boundary_option option,
Correlator correlator) {
BOOST_ASSERT(src.dimensions() == dst.dimensions());
BOOST_ASSERT(ker.size() != 0);
using PIXEL_SRC_REF = typename pixel_proxy<typename SrcView::value_type>::type;
using PIXEL_DST_REF = typename pixel_proxy<typename DstView::value_type>::type;
if(ker.size()==1) {//reduces to a multiplication
view_multiplies_scalar<PixelAccum>(src,*ker.begin(),dst);
return;
}
int width=src.width(),height=src.height();
PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
if (width==0) return;
if (option==convolve_option_output_ignore || option==convolve_option_output_zero) {
typename DstView::value_type dst_zero; pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(acc_zero,dst_zero);
if (width<(int)ker.size()) {
if (option==convolve_option_output_zero)
fill_pixels(dst,dst_zero);
} else {
std::vector<PixelAccum> buffer(width);
for(int rr=0;rr<height;++rr) {
assign_pixels(src.row_begin(rr),src.row_end(rr),&buffer.front());
typename DstView::x_iterator it_dst=dst.row_begin(rr);
if (option==convolve_option_output_zero)
std::fill_n(it_dst,ker.left_size(),dst_zero);
it_dst+=ker.left_size();
correlator(&buffer.front(),&buffer.front()+width+1-ker.size(),
ker.begin(),it_dst);
it_dst+=width+1-ker.size();
if (option==convolve_option_output_zero)
std::fill_n(it_dst,ker.right_size(),dst_zero);
}
}
} else {
std::vector<PixelAccum> buffer(width+ker.size()-1);
for(int rr=0;rr<height;++rr) {
PixelAccum* it_buffer=&buffer.front();
if (option==convolve_option_extend_padded) {
assign_pixels(src.row_begin(rr)-ker.left_size(),
src.row_end(rr)+ker.right_size(),
it_buffer);
} else if (option==convolve_option_extend_zero) {
std::fill_n(it_buffer,ker.left_size(),acc_zero);
it_buffer+=ker.left_size();
assign_pixels(src.row_begin(rr),src.row_end(rr),it_buffer);
it_buffer+=width;
std::fill_n(it_buffer,ker.right_size(),acc_zero);
} else if (option==convolve_option_extend_constant) {
PixelAccum filler;
pixel_assigns_t<PIXEL_SRC_REF,PixelAccum>()(*src.row_begin(rr),filler);
std::fill_n(it_buffer,ker.left_size(),filler);
it_buffer+=ker.left_size();
assign_pixels(src.row_begin(rr),src.row_end(rr),it_buffer);
it_buffer+=width;
pixel_assigns_t<PIXEL_SRC_REF,PixelAccum>()(src.row_end(rr)[-1],filler);
std::fill_n(it_buffer,ker.right_size(),filler);
}
correlator(&buffer.front(),&buffer.front()+width,
ker.begin(),
dst.row_begin(rr));
}
}
}
template <typename PixelAccum>
class correlator_n {
private:
std::size_t _size;
public:
correlator_n(std::size_t size_in) : _size(size_in) {}
template <typename SrcIterator,typename KernelIterator,typename DstIterator>
void operator()(SrcIterator src_begin,SrcIterator src_end,
KernelIterator ker_begin,
DstIterator dst_begin) {
correlate_pixels_n<PixelAccum>(src_begin,src_end,ker_begin,_size,dst_begin);
}
};
template <std::size_t Size,typename PixelAccum>
struct correlator_k {
public:
template <typename SrcIterator,typename KernelIterator,typename DstIterator>
void operator()(SrcIterator src_begin,SrcIterator src_end,
KernelIterator ker_begin,
DstIterator dst_begin){
correlate_pixels_k<Size,PixelAccum>(src_begin,src_end,ker_begin,dst_begin);
}
};
} // namespace detail
/// \ingroup ImageAlgorithms
///correlate a 1D variable-size kernel along the rows of an image
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
BOOST_FORCEINLINE
void correlate_rows(const SrcView& src, const Kernel& ker, const DstView& dst,
convolve_boundary_option option=convolve_option_extend_zero) {
detail::correlate_rows_imp<PixelAccum>(src,ker,dst,option,detail::correlator_n<PixelAccum>(ker.size()));
}
/// \ingroup ImageAlgorithms
///correlate a 1D variable-size kernel along the columns of an image
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
BOOST_FORCEINLINE
void correlate_cols(const SrcView& src, const Kernel& ker, const DstView& dst,
convolve_boundary_option option=convolve_option_extend_zero) {
correlate_rows<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
}
/// \ingroup ImageAlgorithms
///convolve a 1D variable-size kernel along the rows of an image
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
BOOST_FORCEINLINE
void convolve_rows(const SrcView& src, const Kernel& ker, const DstView& dst,
convolve_boundary_option option=convolve_option_extend_zero) {
correlate_rows<PixelAccum>(src,reverse_kernel(ker),dst,option);
}
/// \ingroup ImageAlgorithms
///convolve a 1D variable-size kernel along the columns of an image
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
BOOST_FORCEINLINE
void convolve_cols(const SrcView& src, const Kernel& ker, const DstView& dst,
convolve_boundary_option option=convolve_option_extend_zero) {
convolve_rows<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
}
/// \ingroup ImageAlgorithms
///correlate a 1D fixed-size kernel along the rows of an image
template <typename PixelAccum, typename SrcView, typename Kernel, typename DstView>
BOOST_FORCEINLINE
void correlate_rows_fixed(const SrcView& src, const Kernel& kernel, const DstView& dst,
convolve_boundary_option option=convolve_option_extend_zero)
{
using correlator = detail::correlator_k
<
std::extent<Kernel>::value,
PixelAccum
>;
detail::correlate_rows_imp<PixelAccum>(
src, kernel, dst, option, correlator{});
}
/// \ingroup ImageAlgorithms
///correlate a 1D fixed-size kernel along the columns of an image
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
BOOST_FORCEINLINE
void correlate_cols_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
convolve_boundary_option option=convolve_option_extend_zero) {
correlate_rows_fixed<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
}
/// \ingroup ImageAlgorithms
///convolve a 1D fixed-size kernel along the rows of an image
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
BOOST_FORCEINLINE
void convolve_rows_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
convolve_boundary_option option=convolve_option_extend_zero) {
correlate_rows_fixed<PixelAccum>(src,reverse_kernel(ker),dst,option);
}
/// \ingroup ImageAlgorithms
///convolve a 1D fixed-size kernel along the columns of an image
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
BOOST_FORCEINLINE
void convolve_cols_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
convolve_boundary_option option=convolve_option_extend_zero) {
convolve_rows_fixed<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
}
}} // namespace boost::gil
BOOST_HEADER_DEPRECATED("<boost/gil/image_processing/convolve.hpp>")
#endif

View File

@@ -1,118 +1,18 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2019 Miral Shah <miralshah2211@gmail.com>
// Copyright 2022 Pranam Lashkari <plashkari628@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
#define BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
#include <boost/gil/utilities.hpp>
#include <boost/config/header_deprecated.hpp>
#include <boost/assert.hpp>
#include <algorithm>
#include <array>
#include <cstddef>
#include <memory>
#include <vector>
namespace boost { namespace gil {
// Definitions of 1D fixed-size and variable-size kernels and related operations
namespace detail {
/// \brief kernel adaptor for one-dimensional cores
/// Core needs to provide size(),begin(),end(),operator[],
/// value_type,iterator,const_iterator,reference,const_reference
template <typename Core>
class kernel_1d_adaptor : public Core {
private:
std::size_t _center;
public:
kernel_1d_adaptor() : _center(0) {}
explicit kernel_1d_adaptor(std::size_t center_in)
: _center(center_in)
{
BOOST_ASSERT(_center < this->size());
}
kernel_1d_adaptor(std::size_t size_in, std::size_t center_in)
: Core(size_in)
, _center(center_in)
{
BOOST_ASSERT(_center < this->size());
}
kernel_1d_adaptor(kernel_1d_adaptor const& k_in) : Core(k_in), _center(k_in._center) {}
kernel_1d_adaptor& operator=(const kernel_1d_adaptor& k_in) {
Core::operator=(k_in);
_center=k_in._center;
return *this;
}
std::size_t left_size() const
{
BOOST_ASSERT(_center < this->size());
return _center;
}
std::size_t right_size() const
{
BOOST_ASSERT(_center < this->size());
return this->size() - _center - 1;
}
std::size_t& center() {return _center;}
const std::size_t& center() const {return _center;}
};
} // namespace detail
/// \brief variable-size kernel
template <typename T, typename Alloc = std::allocator<T> >
class kernel_1d : public detail::kernel_1d_adaptor<std::vector<T,Alloc>>
{
using parent_t = detail::kernel_1d_adaptor<std::vector<T,Alloc>>;
public:
kernel_1d() {}
kernel_1d(std::size_t size_in,std::size_t center_in) : parent_t(size_in,center_in) {}
template <typename FwdIterator>
kernel_1d(FwdIterator elements, std::size_t size_in, std::size_t center_in) : parent_t(size_in,center_in) {
detail::copy_n(elements,size_in,this->begin());
}
kernel_1d(const kernel_1d& k_in) : parent_t(k_in) {}
};
/// \brief static-size kernel
template <typename T,std::size_t Size>
class kernel_1d_fixed : public detail::kernel_1d_adaptor<std::array<T,Size>>
{
using parent_t = detail::kernel_1d_adaptor<std::array<T,Size>>;
public:
kernel_1d_fixed() {}
explicit kernel_1d_fixed(std::size_t center_in) : parent_t(center_in) {}
template <typename FwdIterator>
explicit kernel_1d_fixed(FwdIterator elements, std::size_t center_in) : parent_t(center_in) {
detail::copy_n(elements,Size,this->begin());
}
kernel_1d_fixed(const kernel_1d_fixed& k_in) : parent_t(k_in) {}
};
/// \brief reverse a kernel
template <typename Kernel>
inline Kernel reverse_kernel(const Kernel& kernel) {
Kernel result(kernel);
result.center()=kernel.right_size();
std::reverse(result.begin(), result.end());
return result;
}
}} // namespace boost::gil
BOOST_HEADER_DEPRECATED("<boost/gil/image_processing/kernel.hpp>")
#endif

View File

@@ -1,5 +1,6 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
@@ -8,165 +9,8 @@
#ifndef BOOST_GIL_EXTENSION_NUMERIC_PIXEL_NUMERIC_OPERATIONS_HPP
#define BOOST_GIL_EXTENSION_NUMERIC_PIXEL_NUMERIC_OPERATIONS_HPP
#include <boost/gil/extension/numeric/channel_numeric_operations.hpp>
#include <boost/config/header_deprecated.hpp>
#include <boost/gil/color_base_algorithm.hpp>
#include <boost/gil/pixel.hpp>
namespace boost { namespace gil {
// Structures for pixel-wise numeric operations
// Currently defined structures:
// pixel_plus_t (+), pixel_minus_t (-)
// pixel_multiplies_scalar_t (*), pixel_divides_scalar_t (/)
// pixel_halves_t (/=2), pixel_zeros_t (=0)
// pixel_assigns_t (=)
/// \ingroup PixelNumericOperations
/// \brief construct for adding two pixels
template <typename PixelRef1, // models pixel concept
typename PixelRef2, // models pixel concept
typename PixelR> // models pixel value concept
struct pixel_plus_t {
PixelR operator() (const PixelRef1& p1,
const PixelRef2& p2) const {
PixelR result;
static_transform(p1,p2,result,
channel_plus_t<typename channel_type<PixelRef1>::type,
typename channel_type<PixelRef2>::type,
typename channel_type<PixelR>::type>());
return result;
}
};
/// \ingroup PixelNumericOperations
/// \brief construct for subtracting two pixels
template <typename PixelRef1, // models pixel concept
typename PixelRef2, // models pixel concept
typename PixelR> // models pixel value concept
struct pixel_minus_t {
PixelR operator() (const PixelRef1& p1,
const PixelRef2& p2) const {
PixelR result;
static_transform(p1,p2,result,
channel_minus_t<typename channel_type<PixelRef1>::type,
typename channel_type<PixelRef2>::type,
typename channel_type<PixelR>::type>());
return result;
}
};
/// \ingroup PixelNumericOperations
/// \brief construct for multiplying scalar to a pixel
template <typename PixelRef, // models pixel concept
typename Scalar, // models a scalar type
typename PixelR> // models pixel value concept
struct pixel_multiplies_scalar_t {
PixelR operator () (const PixelRef& p,
const Scalar& s) const {
PixelR result;
static_transform(p,result,
std::bind(channel_multiplies_scalar_t<typename channel_type<PixelRef>::type,
Scalar,
typename channel_type<PixelR>::type>(),
std::placeholders::_1, s));
return result;
}
};
/// \ingroup PixelNumericOperations
/// \brief construct for dividing two pixels
template <typename PixelRef1, // models pixel concept
typename PixelRef2, // models pixel concept
typename PixelR> // models pixel value concept
struct pixel_multiply_t {
PixelR operator() (const PixelRef1& p1,
const PixelRef2& p2) const {
PixelR result;
static_transform(p1,p2,result,
channel_multiplies_t<typename channel_type<PixelRef1>::type,
typename channel_type<PixelRef2>::type,
typename channel_type<PixelR>::type>());
return result;
}
};
/// \ingroup PixelNumericOperations
/// \brief construct for dividing a pixel by a scalar
template <typename PixelRef, // models pixel concept
typename Scalar, // models a scalar type
typename PixelR> // models pixel value concept
struct pixel_divides_scalar_t {
PixelR operator () (const PixelRef& p,
const Scalar& s) const {
PixelR result;
static_transform(p,result,
std::bind(channel_divides_scalar_t<typename channel_type<PixelRef>::type,
Scalar,
typename channel_type<PixelR>::type>(),
std::placeholders::_1, s));
return result;
}
};
/// \ingroup PixelNumericOperations
/// \brief construct for dividing two pixels
template <typename PixelRef1, // models pixel concept
typename PixelRef2, // models pixel concept
typename PixelR> // models pixel value concept
struct pixel_divide_t {
PixelR operator() (const PixelRef1& p1,
const PixelRef2& p2) const {
PixelR result;
static_transform(p1,p2,result,
channel_divides_t<typename channel_type<PixelRef1>::type,
typename channel_type<PixelRef2>::type,
typename channel_type<PixelR>::type>());
return result;
}
};
/// \ingroup PixelNumericOperations
/// \brief construct for dividing a pixel by 2
template <typename PixelRef> // models pixel concept
struct pixel_halves_t {
PixelRef& operator () (PixelRef& p) const {
static_for_each(p,channel_halves_t<typename channel_type<PixelRef>::type>());
return p;
}
};
/// \ingroup PixelNumericOperations
/// \brief construct for setting a pixel to zero (for whatever zero means)
template <typename PixelRef> // models pixel concept
struct pixel_zeros_t {
PixelRef& operator () (PixelRef& p) const {
static_for_each(p,channel_zeros_t<typename channel_type<PixelRef>::type>());
return p;
}
};
// Hailin: This is how you can do it:
template <typename Pixel>
void zero_channels(Pixel& p) {
static_for_each(p,channel_zeros_t<typename channel_type<Pixel>::type>());
}
/// \ingroup PixelNumericOperations
///definition and a generic implementation for casting and assigning a pixel to another
///user should specialize it for better performance
template <typename PixelRef, // models pixel concept
typename PixelRefR> // models pixel concept
struct pixel_assigns_t {
PixelRefR operator () (const PixelRef& src,
PixelRefR& dst) const {
static_for_each(src,dst,channel_assigns_t<typename channel_type<PixelRef>::type,
typename channel_type<PixelRefR>::type>());
return dst;
}
};
}} // namespace boost::gil
BOOST_HEADER_DEPRECATED("<boost/gil/pixel_numeric_operations.hpp>")
#endif

View File

@@ -70,34 +70,34 @@ namespace detail {
/// \brief resample_pixels when the source is run-time specified
/// If invoked on incompatible views, throws std::bad_cast()
/// \ingroup ImageAlgorithms
template <typename Sampler, typename Types1, typename V2, typename MapFn>
void resample_pixels(const any_image_view<Types1>& src, const V2& dst, const MapFn& dst_to_src, Sampler sampler=Sampler())
template <typename Sampler, typename ...Types1, typename V2, typename MapFn>
void resample_pixels(const any_image_view<Types1...>& src, const V2& dst, const MapFn& dst_to_src, Sampler sampler=Sampler())
{
apply_operation(src, std::bind(
variant2::visit(std::bind(
detail::resample_pixels_fn<Sampler, MapFn>(dst_to_src, sampler),
std::placeholders::_1,
dst));
dst), src);
}
/// \brief resample_pixels when the destination is run-time specified
/// If invoked on incompatible views, throws std::bad_cast()
/// \ingroup ImageAlgorithms
template <typename Sampler, typename V1, typename Types2, typename MapFn>
void resample_pixels(const V1& src, const any_image_view<Types2>& dst, const MapFn& dst_to_src, Sampler sampler=Sampler())
template <typename Sampler, typename V1, typename ...Types2, typename MapFn>
void resample_pixels(const V1& src, const any_image_view<Types2...>& dst, const MapFn& dst_to_src, Sampler sampler=Sampler())
{
using namespace std::placeholders;
apply_operation(dst, std::bind(
variant2::visit(std::bind(
detail::resample_pixels_fn<Sampler, MapFn>(dst_to_src, sampler),
src,
std::placeholders::_1));
std::placeholders::_1), dst);
}
/// \brief resample_pixels when both the source and the destination are run-time specified
/// If invoked on incompatible views, throws std::bad_cast()
/// \ingroup ImageAlgorithms
template <typename Sampler, typename SrcTypes, typename DstTypes, typename MapFn>
void resample_pixels(const any_image_view<SrcTypes>& src, const any_image_view<DstTypes>& dst, const MapFn& dst_to_src, Sampler sampler=Sampler()) {
apply_operation(src,dst,detail::resample_pixels_fn<Sampler,MapFn>(dst_to_src,sampler));
template <typename Sampler, typename ...SrcTypes, typename ...DstTypes, typename MapFn>
void resample_pixels(const any_image_view<SrcTypes...>& src, const any_image_view<DstTypes...>& dst, const MapFn& dst_to_src, Sampler sampler=Sampler()) {
variant2::visit(detail::resample_pixels_fn<Sampler,MapFn>(dst_to_src,sampler), src, dst);
}
///////////////////////////////////////////////////////////////////////////

View File

@@ -1,5 +1,6 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
@@ -8,8 +9,8 @@
#ifndef BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
#define BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
#include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
#include <boost/gil/pixel_numeric_operations.hpp>
namespace boost { namespace gil {
@@ -180,7 +181,6 @@ bool sample(bilinear_sampler, SrcView const& src, point<F> const& p, DstP& resul
cast_pixel(mp,src_result);
color_convert(src_result, result);
return true;
}

View File

@@ -0,0 +1,28 @@
#ifndef BOOST_GIL_EXTENSION_RASTERIZATION_APPLY_RASTERIZER
#define BOOST_GIL_EXTENSION_RASTERIZATION_APPLY_RASTERIZER
namespace boost { namespace gil {
namespace detail {
template <typename View, typename Rasterizer, typename Pixel, typename Tag>
struct apply_rasterizer_op
{
void operator()(
View const& view, Rasterizer const& rasterizer, Pixel const& pixel);
};
} // namespace detail
template <typename View, typename Rasterizer, typename Pixel>
void apply_rasterizer(
View const& view, Rasterizer const& rasterizer, Pixel const& pixel)
{
using tag_t = typename Rasterizer::type;
detail::apply_rasterizer_op<View, Rasterizer, Pixel, tag_t>{}(
view, rasterizer, pixel);
}
}} // namespace boost::gil
#endif

Some files were not shown because too many files have changed in this diff Show More