gil/example/interleaved_ref.hpp
Mateusz Łoskot 348fd6942e
Include <boost/gil.hpp> in examples (#355)
A typical user is supposed to include the main header and
to not know the library enough to include headers selectively.
2019-07-29 20:49:32 +02:00

159 lines
6.2 KiB
C++

//
// 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_EXAMPLE_INTERLEAVED_REF_HPP
#define BOOST_GIL_EXAMPLE_INTERLEAVED_REF_HPP
#include <boost/gil.hpp>
#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
#include <type_traits>
// Example on how to create a new model of a pixel reference
namespace boost { namespace gil {
// A model of an interleaved pixel reference. Holds a pointer to the first channel
// MODELS:
// MutableHomogeneousPixelConcept
// MutableHomogeneousColorBaseConcept
// MutableColorBaseConcept
// HomogeneousColorBaseConcept
// ColorBaseConcept
// HomogeneousPixelBasedConcept
// PixelBasedConcept
//
// For planar reference proxies to work properly, all of their methods must be const-qualified
// and their iterator's reference type must be const-qualified.
// Mutability of the reference proxy is part of its type (in this case, depends on the mutability of ChannelReference)
/// \tparam ChannelReference - Models ChannelConcept.
/// A channel reference, unsigned char& or const unsigned char&
/// \tparam Layout - A layout (includes the color space and channel ordering)
template <typename ChannelReference, typename Layout>
struct interleaved_ref
{
private:
using channel_t = typename channel_traits<ChannelReference>::value_type;
using channel_pointer_t = typename channel_traits<ChannelReference>::pointer;
using channel_reference_t = typename channel_traits<ChannelReference>::reference;
using channel_const_reference_t = typename channel_traits<ChannelReference>::const_reference;
public:
using layout_t = Layout; // Required by ColorBaseConcept
// Copy construction from a compatible type. The copy constructor of references is shallow. The channels themselves are not copied.
interleaved_ref(const interleaved_ref& p) : _channels(p._channels) {}
template <typename P> interleaved_ref(const P& p) : _channels(p._channels) { check_compatible<P>(); }
template <typename P> bool operator==(const P& p) const { check_compatible<P>(); return static_equal(*this,p); }
template <typename P> bool operator!=(const P& p) const { return !(*this==p); }
// Required by MutableColorBaseConcept
// Assignment from a compatible type
const interleaved_ref& operator=(const interleaved_ref& p) const { static_copy(p,*this); return *this; }
template <typename P> const interleaved_ref& operator=(const P& p) const { check_compatible<P>(); static_copy(p,*this); return *this; }
// Required by PixelConcept
using value_type = pixel<channel_t, layout_t>;
using reference = interleaved_ref;
using const_reference = interleaved_ref<channel_const_reference_t, layout_t>;
static const bool is_mutable = channel_traits<ChannelReference>::is_mutable;
// Required by HomogeneousPixelConcept
ChannelReference operator[](std::size_t i) const { return _channels[i]; }
// Custom constructor (not part of any concept)
explicit interleaved_ref(channel_pointer_t channels) : _channels(channels) {}
// This is needed for the reference proxy to work properly
const interleaved_ref* operator->() const { return this; }
private:
channel_pointer_t _channels;
template <typename Pixel> static void check_compatible() { gil_function_requires<PixelsCompatibleConcept<Pixel,interleaved_ref>>(); }
};
// Required by ColorBaseConcept
template <typename ChannelReference, typename Layout, int K>
struct kth_element_type<interleaved_ref<ChannelReference, Layout>, K>
{
using type = ChannelReference;
};
template <typename ChannelReference, typename Layout, int K>
struct kth_element_reference_type<interleaved_ref<ChannelReference, Layout>, K>
{
using type = ChannelReference;
};
template <typename ChannelReference, typename Layout, int K>
struct kth_element_const_reference_type<interleaved_ref<ChannelReference, Layout>, K>
{
using type = ChannelReference;
// XXX: using type = typename channel_traits<ChannelReference>::const_reference;
};
// Required by ColorBaseConcept
template <int K, typename ChannelReference, typename Layout>
typename element_reference_type<interleaved_ref<ChannelReference,Layout>>::type
at_c(const interleaved_ref<ChannelReference,Layout>& p) { return p[K]; };
// Required by HomogeneousColorBaseConcept
template <typename ChannelReference, typename Layout>
typename element_reference_type<interleaved_ref<ChannelReference,Layout>>::type
dynamic_at_c(const interleaved_ref<ChannelReference,Layout>& p, std::size_t n) { return p[n]; };
namespace detail {
struct swap_fn_t {
template <typename T> void operator()(T& x, T& y) const {
using std::swap;
swap(x,y);
}
};
}
// Required by MutableColorBaseConcept. The default std::swap does not do the right thing for proxy references - it swaps the references, not the values
template <typename ChannelReference, typename Layout>
void swap(const interleaved_ref<ChannelReference,Layout>& x, const interleaved_ref<ChannelReference,Layout>& y) {
static_for_each(x,y,detail::swap_fn_t());
};
// Required by PixelConcept
template <typename ChannelReference, typename Layout>
struct is_pixel<interleaved_ref<ChannelReference,Layout>> : public std::true_type {};
// Required by PixelBasedConcept
template <typename ChannelReference, typename Layout>
struct color_space_type<interleaved_ref<ChannelReference, Layout>>
{
using type = typename Layout::color_space_t;
};
// Required by PixelBasedConcept
template <typename ChannelReference, typename Layout>
struct channel_mapping_type<interleaved_ref<ChannelReference, Layout>>
{
using type = typename Layout::channel_mapping_t;
};
// Required by PixelBasedConcept
template <typename ChannelReference, typename Layout>
struct is_planar<interleaved_ref<ChannelReference,Layout>> : std::false_type {};
// Required by HomogeneousPixelBasedConcept
template <typename ChannelReference, typename Layout>
struct channel_type<interleaved_ref<ChannelReference, Layout>>
{
using type = typename channel_traits<ChannelReference>::value_type;
};
} } // namespace boost::gil
#endif