update boost
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
253
linx64/include/boost/gil/channel_numeric_operations.hpp
Normal file
253
linx64/include/boost/gil/channel_numeric_operations.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
47
linx64/include/boost/gil/detail/is_channel_integral.hpp
Normal file
47
linx64/include/boost/gil/detail/is_channel_integral.hpp
Normal 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
|
||||
33
linx64/include/boost/gil/detail/math.hpp
Normal file
33
linx64/include/boost/gil/detail/math.hpp
Normal 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
|
||||
25
linx64/include/boost/gil/detail/mp11.hpp
Normal file
25
linx64/include/boost/gil/detail/mp11.hpp
Normal 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
|
||||
39
linx64/include/boost/gil/detail/std_common_type.hpp
Normal file
39
linx64/include/boost/gil/detail/std_common_type.hpp
Normal 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
|
||||
39
linx64/include/boost/gil/detail/type_traits.hpp
Normal file
39
linx64/include/boost/gil/detail/type_traits.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
///@}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
172
linx64/include/boost/gil/extension/histogram/std.hpp
Normal file
172
linx64/include/boost/gil/extension/histogram/std.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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() );
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
<
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user