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