1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
//
// 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_PTR_HPP
#define BOOST_GIL_EXAMPLE_INTERLEAVED_PTR_HPP
#include <boost/gil.hpp>
#include <boost/mp11.hpp>
#include <type_traits>
#include "interleaved_ref.hpp"
// Example on how to create a pixel iterator
namespace boost { namespace gil {
// A model of an interleaved pixel iterator. Contains an iterator to the first channel of the current pixel
//
// Models:
// MutablePixelIteratorConcept
// PixelIteratorConcept
// boost_concepts::RandomAccessTraversalConcept
// PixelBasedConcept
// HomogeneousPixelBasedConcept
// PixelBasedConcept
// ByteAdvanceableConcept
// HasDynamicXStepTypeConcept
template <typename ChannelPtr, // Models Channel Iterator (examples: unsigned char* or const unsigned char*)
typename Layout> // A layout (includes the color space and channel ordering)
struct interleaved_ptr : boost::iterator_facade
<
interleaved_ptr<ChannelPtr, Layout>,
pixel<typename std::iterator_traits<ChannelPtr>::value_type, Layout>,
boost::random_access_traversal_tag,
interleaved_ref<typename std::iterator_traits<ChannelPtr>::reference, Layout> const
>
{
private:
using parent_t = boost::iterator_facade
<
interleaved_ptr<ChannelPtr, Layout>,
pixel<typename std::iterator_traits<ChannelPtr>::value_type, Layout>,
boost::random_access_traversal_tag,
interleaved_ref
<
typename std::iterator_traits<ChannelPtr>::reference,
Layout
> const
>;
using channel_t = typename std::iterator_traits<ChannelPtr>::value_type;
public:
using reference = typename parent_t::reference;
using difference_type = typename parent_t::difference_type;
interleaved_ptr() {}
interleaved_ptr(const interleaved_ptr& ptr) : _channels(ptr._channels) {}
template <typename CP> interleaved_ptr(const interleaved_ptr<CP,Layout>& ptr) : _channels(ptr._channels) {}
interleaved_ptr(const ChannelPtr& channels) : _channels(channels) {}
// Construct from a pointer to the reference type. Not required by concepts but important
interleaved_ptr(reference* pix) : _channels(&((*pix)[0])) {}
interleaved_ptr& operator=(reference* pix) { _channels=&((*pix)[0]); return *this; }
/// For some reason operator[] provided by boost::iterator_facade 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 { return memunit_advanced_ref(*this,d*sizeof(channel_t));}
// Put this for every iterator whose reference is a proxy type
reference operator->() const { return **this; }
// Channels accessor (not required by any concept)
const ChannelPtr& channels() const { return _channels; }
ChannelPtr& channels() { return _channels; }
// Not required by concepts but useful
static const std::size_t num_channels = mp11::mp_size<typename Layout::color_space_t>::value;
private:
ChannelPtr _channels;
friend class boost::iterator_core_access;
template <typename CP, typename L> friend struct interleaved_ptr;
void increment() { _channels+=num_channels; }
void decrement() { _channels-=num_channels; }
void advance(std::ptrdiff_t d) { _channels+=num_channels*d; }
std::ptrdiff_t distance_to(const interleaved_ptr& it) const { return (it._channels-_channels)/num_channels; }
bool equal(const interleaved_ptr& it) const { return _channels==it._channels; }
reference dereference() const { return reference(_channels); }
};
/////////////////////////////
// PixelIteratorConcept
/////////////////////////////
// To get from the channel pointer a channel pointer to const, we have to go through the channel traits, which take a model of channel
// So we can get a model of channel from the channel pointer via iterator_traits. Notice that we take the iterator_traits::reference and not
// iterator_traits::value_type. This is because sometimes multiple reference and pointer types share the same value type. An example of this is
// GIL's planar reference and iterator ("planar_pixel_reference" and "planar_pixel_iterator") which share the class "pixel" as the value_type. The
// class "pixel" is also the value type for interleaved pixel references. Here we are dealing with channels, not pixels, but the principles still apply.
template <typename ChannelPtr, typename Layout>
struct const_iterator_type<interleaved_ptr<ChannelPtr,Layout>> {
private:
using channel_ref_t = typename std::iterator_traits<ChannelPtr>::reference;
using channel_const_ptr_t = typename channel_traits<channel_ref_t>::const_pointer;
public:
using type = interleaved_ptr<channel_const_ptr_t, Layout>;
};
template <typename ChannelPtr, typename Layout>
struct iterator_is_mutable<interleaved_ptr<ChannelPtr,Layout>> : std::true_type {};
template <typename Channel, typename Layout>
struct iterator_is_mutable<interleaved_ptr<const Channel*,Layout>> : std::false_type {};
template <typename ChannelPtr, typename Layout>
struct is_iterator_adaptor<interleaved_ptr<ChannelPtr,Layout>> : std::false_type {};
/////////////////////////////
// PixelBasedConcept
/////////////////////////////
template <typename ChannelPtr, typename Layout>
struct color_space_type<interleaved_ptr<ChannelPtr,Layout>>
{
using type = typename Layout::color_space_t;
};
template <typename ChannelPtr, typename Layout>
struct channel_mapping_type<interleaved_ptr<ChannelPtr,Layout>>
{
using type = typename Layout::channel_mapping_t;
};
template <typename ChannelPtr, typename Layout>
struct is_planar<interleaved_ptr<ChannelPtr,Layout>> : std::false_type {};
/////////////////////////////
// HomogeneousPixelBasedConcept
/////////////////////////////
template <typename ChannelPtr, typename Layout>
struct channel_type<interleaved_ptr<ChannelPtr, Layout>>
{
using type = typename std::iterator_traits<ChannelPtr>::value_type;
};
/////////////////////////////
// ByteAdvanceableConcept
/////////////////////////////
template <typename ChannelPtr, typename Layout>
inline std::ptrdiff_t memunit_step(const interleaved_ptr<ChannelPtr,Layout>&) {
return sizeof(typename std::iterator_traits<ChannelPtr>::value_type)* // size of each channel in bytes
interleaved_ptr<ChannelPtr,Layout>::num_channels; // times the number of channels
}
template <typename ChannelPtr, typename Layout>
inline std::ptrdiff_t memunit_distance(const interleaved_ptr<ChannelPtr,Layout>& p1, const interleaved_ptr<ChannelPtr,Layout>& p2) {
return memunit_distance(p1.channels(),p2.channels());
}
template <typename ChannelPtr, typename Layout>
inline void memunit_advance(interleaved_ptr<ChannelPtr,Layout>& p, std::ptrdiff_t diff) {
memunit_advance(p.channels(), diff);
}
template <typename ChannelPtr, typename Layout>
inline interleaved_ptr<ChannelPtr,Layout> memunit_advanced(const interleaved_ptr<ChannelPtr,Layout>& p, std::ptrdiff_t diff) {
interleaved_ptr<ChannelPtr,Layout> ret=p;
memunit_advance(ret, diff);
return ret;
}
template <typename ChannelPtr, typename Layout>
inline typename interleaved_ptr<ChannelPtr,Layout>::reference memunit_advanced_ref(const interleaved_ptr<ChannelPtr,Layout>& p, std::ptrdiff_t diff) {
interleaved_ptr<ChannelPtr,Layout> ret=p;
memunit_advance(ret, diff);
return *ret;
}
/////////////////////////////
// HasDynamicXStepTypeConcept
/////////////////////////////
template <typename ChannelPtr, typename Layout>
struct dynamic_x_step_type<interleaved_ptr<ChannelPtr, Layout>>
{
using type = memory_based_step_iterator<interleaved_ptr<ChannelPtr, Layout>>;
};
} } // namespace boost::gil
#endif
|