2
0
mirror of https://github.com/boostorg/gil.git synced 2026-02-01 20:42:10 +00:00
Files
gil/example/interleaved_ptr.hpp
Mateusz Łoskot 32fec9f05b Refactor library includes to #include <boost/gil/...>
Group include directives, sort within group:
* In headers of GIL core and extensions:
  1. boost/gil/extension/*
  2. boost/gil/*
  3. boost/*
  4. C++ standard library headers
* In programs:
  1. boost/gil/*
  2. boost/*
  3. C++ standard library headers
  4. "xxx.hpp" for local headers
Add basic guidelines to CONTRIBUTING.md.
Add/Remove #include <boost/config.hpp> or std headers un/necessary.
Rename gil_concept.hpp to concepts.hpp.
Remove gil_all.hpp - we already have all-in-one boost/gil.hpp.
Tidy up and unify copyright and license header.
Tidy up formatting and excessive whitespaces in some comments.
Remove Doxygen block with file description, author, date, etc.
Remove dead or commented pragmas and directives.
Trim trailing whitespaces.
2018-09-28 16:26:34 +02:00

182 lines
8.0 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_PTR_HPP
#define BOOST_GIL_EXAMPLE_INTERLEAVED_PTR_HPP
#include <boost/gil/pixel_iterator.hpp>
#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 : 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(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:
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