libs/gil/example/interleaved_ptr.hpp
/*
Copyright 2005-2007 Adobe Systems Incorporated
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).
See http://opensource.adobe.com/gil for most recent version including documentation.
*/
/*************************************************************************************************/
////////////////////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Example on how to create a pixel iterator
/// \author Lubomir Bourdev and Hailin Jin \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated on February 26, 2007
///
/// Definitions of standard GIL channel models
///
////////////////////////////////////////////////////////////////////////////////////////
#ifndef GIL_INTERLEAVED_PTR_HPP
#define GIL_INTERLEAVED_PTR_HPP
#include <boost/gil/pixel_iterator.hpp>
#include "interleaved_ref.hpp"
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 : public boost::iterator_facade<interleaved_ptr<ChannelPtr,Layout>,
pixel<typename std::iterator_traits<ChannelPtr>::value_type,Layout>,
boost::random_access_traversal_tag,
const interleaved_ref<typename std::iterator_traits<ChannelPtr>::reference,Layout> >
{
private:
typedef boost::iterator_facade<interleaved_ptr<ChannelPtr,Layout>,
pixel<typename std::iterator_traits<ChannelPtr>::value_type,Layout>,
boost::random_access_traversal_tag,
const interleaved_ref<typename std::iterator_traits<ChannelPtr>::reference,Layout> > parent_t;
typedef typename std::iterator_traits<ChannelPtr>::value_type channel_t;
public:
typedef typename parent_t::reference reference;
typedef typename parent_t::difference_type 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 = mpl::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(ptrdiff_t d) { _channels+=num_channels*d; }
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:
typedef typename std::iterator_traits<ChannelPtr>::reference channel_ref_t;
typedef typename channel_traits<channel_ref_t>::const_pointer channel_const_ptr_t;
public:
typedef interleaved_ptr<channel_const_ptr_t,Layout> type;
};
template <typename ChannelPtr, typename Layout>
struct iterator_is_mutable<interleaved_ptr<ChannelPtr,Layout> > : public boost::mpl::true_ {};
template <typename Channel, typename Layout>
struct iterator_is_mutable<interleaved_ptr<const Channel*,Layout> > : public boost::mpl::false_ {};
template <typename ChannelPtr, typename Layout>
struct is_iterator_adaptor<interleaved_ptr<ChannelPtr,Layout> > : public boost::mpl::false_ {};
/////////////////////////////
// PixelBasedConcept
/////////////////////////////
template <typename ChannelPtr, typename Layout>
struct color_space_type<interleaved_ptr<ChannelPtr,Layout> > {
typedef typename Layout::color_space_t type;
};
template <typename ChannelPtr, typename Layout>
struct channel_mapping_type<interleaved_ptr<ChannelPtr,Layout> > {
typedef typename Layout::channel_mapping_t type;
};
template <typename ChannelPtr, typename Layout>
struct is_planar<interleaved_ptr<ChannelPtr,Layout> > : public mpl::false_ {};
/////////////////////////////
// HomogeneousPixelBasedConcept
/////////////////////////////
template <typename ChannelPtr, typename Layout>
struct channel_type<interleaved_ptr<ChannelPtr,Layout> > {
typedef typename std::iterator_traits<ChannelPtr>::value_type 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> > {
typedef memory_based_step_iterator<interleaved_ptr<ChannelPtr,Layout> > type;
};
} } // namespace boost::gil
#endif