Chris@16
|
1 /*
|
Chris@16
|
2 Copyright 2005-2007 Adobe Systems Incorporated
|
Chris@16
|
3
|
Chris@16
|
4 Use, modification and distribution are subject to the Boost Software License,
|
Chris@16
|
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 http://www.boost.org/LICENSE_1_0.txt).
|
Chris@16
|
7
|
Chris@16
|
8 See http://opensource.adobe.com/gil for most recent version including documentation.
|
Chris@16
|
9 */
|
Chris@16
|
10
|
Chris@16
|
11 /*************************************************************************************************/
|
Chris@16
|
12
|
Chris@16
|
13 #ifndef GIL_IMAGE_VIEW_FACTORY_HPP
|
Chris@16
|
14 #define GIL_IMAGE_VIEW_FACTORY_HPP
|
Chris@16
|
15
|
Chris@16
|
16 /*!
|
Chris@16
|
17 /// \file
|
Chris@16
|
18 /// \brief Methods for constructing image views from raw data or other image views
|
Chris@16
|
19 /// \author Lubomir Bourdev and Hailin Jin \n
|
Chris@16
|
20 /// Adobe Systems Incorporated
|
Chris@16
|
21 /// \date 2005-2007 \n Last updated on March 9, 2007
|
Chris@16
|
22 /// Methods for creating shallow image views from raw pixel data or from other image views -
|
Chris@16
|
23 /// flipping horizontally or vertically, axis-aligned rotation, a subimage, subsampled
|
Chris@16
|
24 /// or n-th channel image view. Derived image views are shallow copies and are fast to construct.
|
Chris@16
|
25 */
|
Chris@16
|
26
|
Chris@16
|
27 #include <cassert>
|
Chris@16
|
28 #include <cstddef>
|
Chris@16
|
29 #include "gil_config.hpp"
|
Chris@16
|
30 #include "metafunctions.hpp"
|
Chris@16
|
31 #include "gray.hpp"
|
Chris@16
|
32 #include "color_convert.hpp"
|
Chris@16
|
33
|
Chris@16
|
34 /// \defgroup ImageViewConstructors Image View From Raw Data
|
Chris@16
|
35 /// \ingroup ImageViewAlgorithm
|
Chris@16
|
36 /// \brief Methods for constructing image views from raw data and for getting raw data from views
|
Chris@16
|
37
|
Chris@16
|
38 /// \defgroup ImageViewTransformations Image View Transformations
|
Chris@16
|
39 /// \ingroup ImageViewAlgorithm
|
Chris@16
|
40 /// \brief Methods for constructing one image view from another
|
Chris@16
|
41
|
Chris@16
|
42 namespace boost { namespace gil {
|
Chris@16
|
43 struct default_color_converter;
|
Chris@16
|
44
|
Chris@16
|
45 template <typename T> struct dynamic_x_step_type;
|
Chris@16
|
46 template <typename T> struct dynamic_y_step_type;
|
Chris@16
|
47 template <typename T> struct transposed_type;
|
Chris@16
|
48
|
Chris@16
|
49 /// \brief Returns the type of a view that has a dynamic step along both X and Y
|
Chris@16
|
50 /// \ingroup ImageViewTransformations
|
Chris@16
|
51 template <typename View>
|
Chris@16
|
52 struct dynamic_xy_step_type : public dynamic_y_step_type<typename dynamic_x_step_type<View>::type> {};
|
Chris@16
|
53
|
Chris@16
|
54 /// \brief Returns the type of a transposed view that has a dynamic step along both X and Y
|
Chris@16
|
55 /// \ingroup ImageViewTransformations
|
Chris@16
|
56 template <typename View>
|
Chris@16
|
57 struct dynamic_xy_step_transposed_type : public dynamic_xy_step_type<typename transposed_type<View>::type> {};
|
Chris@16
|
58
|
Chris@16
|
59
|
Chris@16
|
60 /// \ingroup ImageViewConstructors
|
Chris@16
|
61 /// \brief Constructing image views from raw interleaved pixel data
|
Chris@16
|
62 template <typename Iterator>
|
Chris@16
|
63 typename type_from_x_iterator<Iterator>::view_t
|
Chris@16
|
64 interleaved_view(std::size_t width, std::size_t height,
|
Chris@16
|
65 Iterator pixels, std::ptrdiff_t rowsize_in_bytes) {
|
Chris@16
|
66 typedef typename type_from_x_iterator<Iterator>::view_t RView;
|
Chris@16
|
67 return RView(width, height, typename RView::locator(pixels, rowsize_in_bytes));
|
Chris@16
|
68 }
|
Chris@16
|
69
|
Chris@16
|
70 /// \ingroup ImageViewConstructors
|
Chris@16
|
71 /// \brief Constructing image views from raw interleaved pixel data
|
Chris@16
|
72 template <typename Iterator>
|
Chris@16
|
73 typename type_from_x_iterator<Iterator>::view_t
|
Chris@16
|
74 interleaved_view(point2<std::size_t> dim,
|
Chris@16
|
75 Iterator pixels, std::ptrdiff_t rowsize_in_bytes) {
|
Chris@16
|
76 typedef typename type_from_x_iterator<Iterator>::view_t RView;
|
Chris@16
|
77 return RView(dim, typename RView::locator(pixels, rowsize_in_bytes));
|
Chris@16
|
78 }
|
Chris@16
|
79
|
Chris@16
|
80 /////////////////////////////
|
Chris@16
|
81 // interleaved_view_get_raw_data, planar_view_get_raw_data - return pointers to the raw data (the channels) of a basic homogeneous view.
|
Chris@16
|
82 /////////////////////////////
|
Chris@16
|
83
|
Chris@16
|
84 namespace detail {
|
Chris@16
|
85 template <typename View, bool IsMutable> struct channel_pointer_type_impl;
|
Chris@16
|
86
|
Chris@16
|
87 template <typename View> struct channel_pointer_type_impl<View, true> {
|
Chris@16
|
88 typedef typename channel_type<View>::type* type;
|
Chris@16
|
89 };
|
Chris@16
|
90 template <typename View> struct channel_pointer_type_impl<View, false> {
|
Chris@16
|
91 typedef const typename channel_type<View>::type* type;
|
Chris@16
|
92 };
|
Chris@16
|
93
|
Chris@16
|
94 template <typename View> struct channel_pointer_type
|
Chris@16
|
95 : public channel_pointer_type_impl<View, view_is_mutable<View>::value> {};
|
Chris@16
|
96 } // namespace detail
|
Chris@16
|
97
|
Chris@16
|
98 /// \ingroup ImageViewConstructors
|
Chris@16
|
99 /// \brief Returns C pointer to the the channels of an interleaved homogeneous view.
|
Chris@16
|
100 template <typename HomogeneousView>
|
Chris@16
|
101 typename detail::channel_pointer_type<HomogeneousView>::type interleaved_view_get_raw_data(const HomogeneousView& view) {
|
Chris@16
|
102 BOOST_STATIC_ASSERT((!is_planar<HomogeneousView>::value && view_is_basic<HomogeneousView>::value));
|
Chris@16
|
103 BOOST_STATIC_ASSERT((boost::is_pointer<typename HomogeneousView::x_iterator>::value));
|
Chris@16
|
104
|
Chris@16
|
105 return &gil::at_c<0>(view(0,0));
|
Chris@16
|
106 }
|
Chris@16
|
107
|
Chris@16
|
108 /// \ingroup ImageViewConstructors
|
Chris@16
|
109 /// \brief Returns C pointer to the the channels of a given color plane of a planar homogeneous view.
|
Chris@16
|
110 template <typename HomogeneousView>
|
Chris@16
|
111 typename detail::channel_pointer_type<HomogeneousView>::type planar_view_get_raw_data(const HomogeneousView& view, int plane_index) {
|
Chris@16
|
112 BOOST_STATIC_ASSERT((is_planar<HomogeneousView>::value && view_is_basic<HomogeneousView>::value));
|
Chris@16
|
113 return dynamic_at_c(view.row_begin(0),plane_index);
|
Chris@16
|
114 }
|
Chris@16
|
115
|
Chris@16
|
116
|
Chris@16
|
117 /// \defgroup ImageViewTransformationsColorConvert color_converted_view
|
Chris@16
|
118 /// \ingroup ImageViewTransformations
|
Chris@16
|
119 /// \brief Color converted view of another view
|
Chris@16
|
120
|
Chris@16
|
121 /// \ingroup ImageViewTransformationsColorConvert PixelDereferenceAdaptorModel
|
Chris@16
|
122 /// \brief Function object that given a source pixel, returns it converted to a given color space and channel depth. Models: PixelDereferenceAdaptorConcept
|
Chris@16
|
123 ///
|
Chris@16
|
124 /// Useful in constructing a color converted view over a given image view
|
Chris@16
|
125 template <typename SrcConstRefP, typename DstP, typename CC=default_color_converter > // const_reference to the source pixel and destination pixel value
|
Chris@16
|
126 class color_convert_deref_fn : public deref_base<color_convert_deref_fn<SrcConstRefP,DstP,CC>, DstP, DstP, const DstP&, SrcConstRefP, DstP, false> {
|
Chris@16
|
127 private:
|
Chris@16
|
128 CC _cc; // color-converter
|
Chris@16
|
129 public:
|
Chris@16
|
130 color_convert_deref_fn() {}
|
Chris@16
|
131 color_convert_deref_fn(CC cc_in) : _cc(cc_in) {}
|
Chris@16
|
132
|
Chris@16
|
133 DstP operator()(SrcConstRefP srcP) const {
|
Chris@16
|
134 DstP dstP;
|
Chris@16
|
135 _cc(srcP,dstP);
|
Chris@16
|
136 return dstP;
|
Chris@16
|
137 }
|
Chris@16
|
138 };
|
Chris@16
|
139
|
Chris@16
|
140 namespace detail {
|
Chris@16
|
141 // Add color converter upon dereferencing
|
Chris@16
|
142 template <typename SrcView, typename CC, typename DstP, typename SrcP>
|
Chris@16
|
143 struct _color_converted_view_type {
|
Chris@16
|
144 private:
|
Chris@16
|
145 typedef color_convert_deref_fn<typename SrcView::const_t::reference,DstP,CC> deref_t;
|
Chris@16
|
146 typedef typename SrcView::template add_deref<deref_t> add_ref_t;
|
Chris@16
|
147 public:
|
Chris@16
|
148 typedef typename add_ref_t::type type;
|
Chris@16
|
149 static type make(const SrcView& sv,CC cc) {return add_ref_t::make(sv,deref_t(cc));}
|
Chris@16
|
150 };
|
Chris@16
|
151
|
Chris@16
|
152 // If the Src view has the same pixel type as the target, there is no need for color conversion
|
Chris@16
|
153 template <typename SrcView, typename CC, typename DstP>
|
Chris@16
|
154 struct _color_converted_view_type<SrcView,CC,DstP,DstP> {
|
Chris@16
|
155 typedef SrcView type;
|
Chris@16
|
156 static type make(const SrcView& sv,CC) {return sv;}
|
Chris@16
|
157 };
|
Chris@16
|
158 } // namespace detail
|
Chris@16
|
159
|
Chris@16
|
160
|
Chris@16
|
161 /// \brief Returns the type of a view that does color conversion upon dereferencing its pixels
|
Chris@16
|
162 /// \ingroup ImageViewTransformationsColorConvert
|
Chris@16
|
163 template <typename SrcView, typename DstP, typename CC=default_color_converter>
|
Chris@16
|
164 struct color_converted_view_type : public detail::_color_converted_view_type<SrcView,
|
Chris@16
|
165 CC,
|
Chris@16
|
166 DstP,
|
Chris@16
|
167 typename SrcView::value_type> {
|
Chris@16
|
168 GIL_CLASS_REQUIRE(DstP, boost::gil, MutablePixelConcept)//why does it have to be mutable???
|
Chris@16
|
169 };
|
Chris@16
|
170
|
Chris@16
|
171
|
Chris@16
|
172 /// \ingroup ImageViewTransformationsColorConvert
|
Chris@16
|
173 /// \brief view of a different color space with a user defined color-converter
|
Chris@16
|
174 template <typename DstP, typename View, typename CC>
|
Chris@16
|
175 inline typename color_converted_view_type<View,DstP,CC>::type color_converted_view(const View& src,CC cc) {
|
Chris@16
|
176 return color_converted_view_type<View,DstP,CC>::make(src,cc);
|
Chris@16
|
177 }
|
Chris@16
|
178
|
Chris@16
|
179 /// \ingroup ImageViewTransformationsColorConvert
|
Chris@16
|
180 /// \brief overload of generic color_converted_view with the default color-converter
|
Chris@16
|
181 template <typename DstP, typename View>
|
Chris@16
|
182 inline typename color_converted_view_type<View,DstP>::type
|
Chris@16
|
183 color_converted_view(const View& src) {
|
Chris@16
|
184 return color_converted_view<DstP>(src,default_color_converter());
|
Chris@16
|
185 }
|
Chris@16
|
186
|
Chris@16
|
187 /// \defgroup ImageViewTransformationsFlipUD flipped_up_down_view
|
Chris@16
|
188 /// \ingroup ImageViewTransformations
|
Chris@16
|
189 /// \brief view of a view flipped up-to-down
|
Chris@16
|
190
|
Chris@16
|
191 /// \ingroup ImageViewTransformationsFlipUD
|
Chris@16
|
192 template <typename View>
|
Chris@16
|
193 inline typename dynamic_y_step_type<View>::type flipped_up_down_view(const View& src) {
|
Chris@16
|
194 typedef typename dynamic_y_step_type<View>::type RView;
|
Chris@16
|
195 return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(0,src.height()-1),-1));
|
Chris@16
|
196 }
|
Chris@16
|
197
|
Chris@16
|
198 /// \defgroup ImageViewTransformationsFlipLR flipped_left_right_view
|
Chris@16
|
199 /// \ingroup ImageViewTransformations
|
Chris@16
|
200 /// \brief view of a view flipped left-to-right
|
Chris@16
|
201
|
Chris@16
|
202 /// \ingroup ImageViewTransformationsFlipLR
|
Chris@16
|
203 template <typename View>
|
Chris@16
|
204 inline typename dynamic_x_step_type<View>::type flipped_left_right_view(const View& src) {
|
Chris@16
|
205 typedef typename dynamic_x_step_type<View>::type RView;
|
Chris@16
|
206 return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(src.width()-1,0),-1,1));
|
Chris@16
|
207 }
|
Chris@16
|
208
|
Chris@16
|
209 /// \defgroup ImageViewTransformationsTransposed transposed_view
|
Chris@16
|
210 /// \ingroup ImageViewTransformations
|
Chris@16
|
211 /// \brief view of a view transposed
|
Chris@16
|
212
|
Chris@16
|
213 /// \ingroup ImageViewTransformationsTransposed
|
Chris@16
|
214 template <typename View>
|
Chris@16
|
215 inline typename dynamic_xy_step_transposed_type<View>::type transposed_view(const View& src) {
|
Chris@16
|
216 typedef typename dynamic_xy_step_transposed_type<View>::type RView;
|
Chris@16
|
217 return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(0,0),1,1,true));
|
Chris@16
|
218 }
|
Chris@16
|
219
|
Chris@16
|
220 /// \defgroup ImageViewTransformations90CW rotated90cw_view
|
Chris@16
|
221 /// \ingroup ImageViewTransformations
|
Chris@16
|
222 /// \brief view of a view rotated 90 degrees clockwise
|
Chris@16
|
223
|
Chris@16
|
224 /// \ingroup ImageViewTransformations90CW
|
Chris@16
|
225 template <typename View>
|
Chris@16
|
226 inline typename dynamic_xy_step_transposed_type<View>::type rotated90cw_view(const View& src) {
|
Chris@16
|
227 typedef typename dynamic_xy_step_transposed_type<View>::type RView;
|
Chris@16
|
228 return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(0,src.height()-1),-1,1,true));
|
Chris@16
|
229 }
|
Chris@16
|
230
|
Chris@16
|
231 /// \defgroup ImageViewTransformations90CCW rotated90ccw_view
|
Chris@16
|
232 /// \ingroup ImageViewTransformations
|
Chris@16
|
233 /// \brief view of a view rotated 90 degrees counter-clockwise
|
Chris@16
|
234
|
Chris@16
|
235 /// \ingroup ImageViewTransformations90CCW
|
Chris@16
|
236 template <typename View>
|
Chris@16
|
237 inline typename dynamic_xy_step_transposed_type<View>::type rotated90ccw_view(const View& src) {
|
Chris@16
|
238 typedef typename dynamic_xy_step_transposed_type<View>::type RView;
|
Chris@16
|
239 return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(src.width()-1,0),1,-1,true));
|
Chris@16
|
240 }
|
Chris@16
|
241
|
Chris@16
|
242 /// \defgroup ImageViewTransformations180 rotated180_view
|
Chris@16
|
243 /// \ingroup ImageViewTransformations
|
Chris@16
|
244 /// \brief view of a view rotated 180 degrees
|
Chris@16
|
245
|
Chris@16
|
246 /// \ingroup ImageViewTransformations180
|
Chris@16
|
247 template <typename View>
|
Chris@16
|
248 inline typename dynamic_xy_step_type<View>::type rotated180_view(const View& src) {
|
Chris@16
|
249 typedef typename dynamic_xy_step_type<View>::type RView;
|
Chris@16
|
250 return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(src.width()-1,src.height()-1),-1,-1));
|
Chris@16
|
251 }
|
Chris@16
|
252
|
Chris@16
|
253 /// \defgroup ImageViewTransformationsSubimage subimage_view
|
Chris@16
|
254 /// \ingroup ImageViewTransformations
|
Chris@16
|
255 /// \brief view of an axis-aligned rectangular area within an image_view
|
Chris@16
|
256
|
Chris@16
|
257 /// \ingroup ImageViewTransformationsSubimage
|
Chris@16
|
258 template <typename View>
|
Chris@16
|
259 inline View subimage_view(const View& src, const typename View::point_t& topleft, const typename View::point_t& dimensions) {
|
Chris@16
|
260 return View(dimensions,src.xy_at(topleft));
|
Chris@16
|
261 }
|
Chris@16
|
262
|
Chris@16
|
263 /// \ingroup ImageViewTransformationsSubimage
|
Chris@16
|
264 template <typename View>
|
Chris@16
|
265 inline View subimage_view(const View& src, int xMin, int yMin, int width, int height) {
|
Chris@16
|
266 return View(width,height,src.xy_at(xMin,yMin));
|
Chris@16
|
267 }
|
Chris@16
|
268
|
Chris@16
|
269 /// \defgroup ImageViewTransformationsSubsampled subsampled_view
|
Chris@16
|
270 /// \ingroup ImageViewTransformations
|
Chris@16
|
271 /// \brief view of a subsampled version of an image_view, stepping over a number of channels in X and number of rows in Y
|
Chris@16
|
272
|
Chris@16
|
273 /// \ingroup ImageViewTransformationsSubsampled
|
Chris@16
|
274 template <typename View>
|
Chris@16
|
275 inline typename dynamic_xy_step_type<View>::type subsampled_view(const View& src, typename View::coord_t xStep, typename View::coord_t yStep) {
|
Chris@16
|
276 assert(xStep>0 && yStep>0);
|
Chris@16
|
277 typedef typename dynamic_xy_step_type<View>::type RView;
|
Chris@16
|
278 return RView((src.width()+(xStep-1))/xStep,(src.height()+(yStep-1))/yStep,
|
Chris@16
|
279 typename RView::xy_locator(src.xy_at(0,0),xStep,yStep));
|
Chris@16
|
280 }
|
Chris@16
|
281
|
Chris@16
|
282 /// \ingroup ImageViewTransformationsSubsampled
|
Chris@16
|
283 template <typename View>
|
Chris@16
|
284 inline typename dynamic_xy_step_type<View>::type subsampled_view(const View& src, const typename View::point_t& step) {
|
Chris@16
|
285 return subsampled_view(src,step.x,step.y);
|
Chris@16
|
286 }
|
Chris@16
|
287
|
Chris@16
|
288 /// \defgroup ImageViewTransformationsNthChannel nth_channel_view
|
Chris@16
|
289 /// \ingroup ImageViewTransformations
|
Chris@16
|
290 /// \brief single-channel (grayscale) view of the N-th channel of a given image_view
|
Chris@16
|
291
|
Chris@16
|
292 namespace detail {
|
Chris@16
|
293 template <typename View, bool AreChannelsTogether> struct __nth_channel_view_basic;
|
Chris@16
|
294
|
Chris@16
|
295 // nth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images
|
Chris@16
|
296 // or images with a step
|
Chris@16
|
297 template <typename View>
|
Chris@16
|
298 struct __nth_channel_view_basic<View,false> {
|
Chris@16
|
299 typedef typename view_type<typename channel_type<View>::type, gray_layout_t, false, true, view_is_mutable<View>::value>::type type;
|
Chris@16
|
300
|
Chris@16
|
301 static type make(const View& src, int n) {
|
Chris@16
|
302 typedef typename type::xy_locator locator_t;
|
Chris@16
|
303 typedef typename type::x_iterator x_iterator_t;
|
Chris@16
|
304 typedef typename iterator_adaptor_get_base<x_iterator_t>::type x_iterator_base_t;
|
Chris@16
|
305 x_iterator_t sit(x_iterator_base_t(&(src(0,0)[n])),src.pixels().pixel_size());
|
Chris@16
|
306 return type(src.dimensions(),locator_t(sit, src.pixels().row_size()));
|
Chris@16
|
307 }
|
Chris@16
|
308 };
|
Chris@16
|
309
|
Chris@16
|
310 // nth_channel_view when the channels are together in memory (true for simple grayscale or planar images)
|
Chris@16
|
311 template <typename View>
|
Chris@16
|
312 struct __nth_channel_view_basic<View,true> {
|
Chris@16
|
313 typedef typename view_type<typename channel_type<View>::type, gray_layout_t, false, false, view_is_mutable<View>::value>::type type;
|
Chris@16
|
314 static type make(const View& src, int n) {
|
Chris@16
|
315 typedef typename type::x_iterator x_iterator_t;
|
Chris@16
|
316 return interleaved_view(src.width(),src.height(),(x_iterator_t)&(src(0,0)[n]), src.pixels().row_size());
|
Chris@16
|
317 }
|
Chris@16
|
318 };
|
Chris@16
|
319
|
Chris@16
|
320 template <typename View, bool IsBasic> struct __nth_channel_view;
|
Chris@16
|
321
|
Chris@16
|
322 // For basic (memory-based) views dispatch to __nth_channel_view_basic
|
Chris@16
|
323 template <typename View> struct __nth_channel_view<View,true> {
|
Chris@16
|
324 private:
|
Chris@16
|
325 typedef typename View::x_iterator src_x_iterator;
|
Chris@16
|
326
|
Chris@16
|
327 // Determines whether the channels of a given pixel iterator are adjacent in memory.
|
Chris@16
|
328 // Planar and grayscale iterators have channels adjacent in memory, whereas multi-channel interleaved and iterators with non-fundamental step do not.
|
Chris@16
|
329 BOOST_STATIC_CONSTANT(bool, adjacent=
|
Chris@16
|
330 !iterator_is_step<src_x_iterator>::value &&
|
Chris@16
|
331 (is_planar<src_x_iterator>::value ||
|
Chris@16
|
332 num_channels<View>::value==1));
|
Chris@16
|
333 public:
|
Chris@16
|
334 typedef typename __nth_channel_view_basic<View,adjacent>::type type;
|
Chris@16
|
335
|
Chris@16
|
336 static type make(const View& src, int n) {
|
Chris@16
|
337 return __nth_channel_view_basic<View,adjacent>::make(src,n);
|
Chris@16
|
338 }
|
Chris@16
|
339 };
|
Chris@16
|
340
|
Chris@16
|
341 /// \brief Function object that returns a grayscale reference of the N-th channel of a given reference. Models: PixelDereferenceAdaptorConcept.
|
Chris@16
|
342 /// \ingroup PixelDereferenceAdaptorModel
|
Chris@16
|
343 ///
|
Chris@16
|
344 /// If the input is a pixel value or constant reference, the function object is immutable. Otherwise it is mutable (and returns non-const reference to the n-th channel)
|
Chris@16
|
345 template <typename SrcP> // SrcP is a reference to PixelConcept (could be pixel value or const/non-const reference)
|
Chris@16
|
346 // Examples: pixel<T,L>, pixel<T,L>&, const pixel<T,L>&, planar_pixel_reference<T&,L>, planar_pixel_reference<const T&,L>
|
Chris@16
|
347 struct nth_channel_deref_fn {
|
Chris@16
|
348 BOOST_STATIC_CONSTANT(bool, is_mutable=pixel_is_reference<SrcP>::value && pixel_reference_is_mutable<SrcP>::value);
|
Chris@16
|
349 private:
|
Chris@16
|
350 typedef typename remove_reference<SrcP>::type src_pixel_t;
|
Chris@16
|
351 typedef typename channel_type<src_pixel_t>::type channel_t;
|
Chris@16
|
352 typedef typename src_pixel_t::const_reference const_ref_t;
|
Chris@16
|
353 typedef typename pixel_reference_type<channel_t,gray_layout_t,false,is_mutable>::type ref_t;
|
Chris@16
|
354 public:
|
Chris@16
|
355 typedef nth_channel_deref_fn<const_ref_t> const_t;
|
Chris@16
|
356 typedef typename pixel_value_type<channel_t,gray_layout_t>::type value_type;
|
Chris@16
|
357 typedef typename pixel_reference_type<channel_t,gray_layout_t,false,false>::type const_reference;
|
Chris@16
|
358 typedef SrcP argument_type;
|
Chris@16
|
359 typedef typename mpl::if_c<is_mutable, ref_t, value_type>::type reference;
|
Chris@16
|
360 typedef reference result_type;
|
Chris@16
|
361
|
Chris@16
|
362 nth_channel_deref_fn(int n=0) : _n(n) {}
|
Chris@16
|
363 template <typename P> nth_channel_deref_fn(const nth_channel_deref_fn<P>& d) : _n(d._n) {}
|
Chris@16
|
364
|
Chris@16
|
365 int _n; // the channel to use
|
Chris@16
|
366
|
Chris@16
|
367 result_type operator()(argument_type srcP) const {
|
Chris@16
|
368 return result_type(srcP[_n]);
|
Chris@16
|
369 }
|
Chris@16
|
370 };
|
Chris@16
|
371
|
Chris@16
|
372 template <typename View> struct __nth_channel_view<View,false> {
|
Chris@16
|
373 private:
|
Chris@16
|
374 typedef nth_channel_deref_fn<typename View::reference> deref_t;
|
Chris@16
|
375 typedef typename View::template add_deref<deref_t> AD;
|
Chris@16
|
376 public:
|
Chris@16
|
377 typedef typename AD::type type;
|
Chris@16
|
378 static type make(const View& src, int n) {
|
Chris@16
|
379 return AD::make(src, deref_t(n));
|
Chris@16
|
380 }
|
Chris@16
|
381 };
|
Chris@16
|
382 } // namespace detail
|
Chris@16
|
383
|
Chris@16
|
384 /// \brief Given a source image view type View, returns the type of an image view over a single channel of View
|
Chris@16
|
385 /// \ingroup ImageViewTransformationsNthChannel
|
Chris@16
|
386 ///
|
Chris@16
|
387 /// If the channels in the source view are adjacent in memory (such as planar non-step view or single-channel view) then the
|
Chris@16
|
388 /// return view is a single-channel non-step view.
|
Chris@16
|
389 /// If the channels are non-adjacent (interleaved and/or step view) then the return view is a single-channel step view.
|
Chris@16
|
390 template <typename View>
|
Chris@16
|
391 struct nth_channel_view_type {
|
Chris@16
|
392 private:
|
Chris@16
|
393 GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept)
|
Chris@16
|
394 typedef detail::__nth_channel_view<View,view_is_basic<View>::value> VB;
|
Chris@16
|
395 public:
|
Chris@16
|
396 typedef typename VB::type type;
|
Chris@16
|
397 static type make(const View& src, int n) { return VB::make(src,n); }
|
Chris@16
|
398 };
|
Chris@16
|
399
|
Chris@16
|
400
|
Chris@16
|
401 /// \ingroup ImageViewTransformationsNthChannel
|
Chris@16
|
402 template <typename View>
|
Chris@16
|
403 typename nth_channel_view_type<View>::type nth_channel_view(const View& src, int n) {
|
Chris@16
|
404 return nth_channel_view_type<View>::make(src,n);
|
Chris@16
|
405 }
|
Chris@16
|
406
|
Chris@16
|
407
|
Chris@16
|
408
|
Chris@16
|
409
|
Chris@16
|
410
|
Chris@16
|
411
|
Chris@16
|
412
|
Chris@16
|
413 /// \defgroup ImageViewTransformationsKthChannel kth_channel_view
|
Chris@16
|
414 /// \ingroup ImageViewTransformations
|
Chris@16
|
415 /// \brief single-channel (grayscale) view of the K-th channel of a given image_view. The channel index is a template parameter
|
Chris@16
|
416
|
Chris@16
|
417 namespace detail {
|
Chris@16
|
418 template <int K, typename View, bool AreChannelsTogether> struct __kth_channel_view_basic;
|
Chris@16
|
419
|
Chris@16
|
420 // kth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images
|
Chris@16
|
421 // or images with a step
|
Chris@16
|
422 template <int K, typename View>
|
Chris@16
|
423 struct __kth_channel_view_basic<K,View,false> {
|
Chris@16
|
424 private:
|
Chris@16
|
425 typedef typename kth_element_type<typename View::value_type,K>::type channel_t;
|
Chris@16
|
426 public:
|
Chris@16
|
427 typedef typename view_type<channel_t, gray_layout_t, false, true, view_is_mutable<View>::value>::type type;
|
Chris@16
|
428
|
Chris@16
|
429 static type make(const View& src) {
|
Chris@16
|
430 typedef typename type::xy_locator locator_t;
|
Chris@16
|
431 typedef typename type::x_iterator x_iterator_t;
|
Chris@16
|
432 typedef typename iterator_adaptor_get_base<x_iterator_t>::type x_iterator_base_t;
|
Chris@16
|
433 x_iterator_t sit(x_iterator_base_t(&gil::at_c<K>(src(0,0))),src.pixels().pixel_size());
|
Chris@16
|
434 return type(src.dimensions(),locator_t(sit, src.pixels().row_size()));
|
Chris@16
|
435 }
|
Chris@16
|
436 };
|
Chris@16
|
437
|
Chris@16
|
438 // kth_channel_view when the channels are together in memory (true for simple grayscale or planar images)
|
Chris@16
|
439 template <int K, typename View>
|
Chris@16
|
440 struct __kth_channel_view_basic<K,View,true> {
|
Chris@16
|
441 private:
|
Chris@16
|
442 typedef typename kth_element_type<typename View::value_type, K>::type channel_t;
|
Chris@16
|
443 public:
|
Chris@16
|
444 typedef typename view_type<channel_t, gray_layout_t, false, false, view_is_mutable<View>::value>::type type;
|
Chris@16
|
445 static type make(const View& src) {
|
Chris@16
|
446 typedef typename type::x_iterator x_iterator_t;
|
Chris@16
|
447 return interleaved_view(src.width(),src.height(),(x_iterator_t)&gil::at_c<K>(src(0,0)), src.pixels().row_size());
|
Chris@16
|
448 }
|
Chris@16
|
449 };
|
Chris@16
|
450
|
Chris@16
|
451 template <int K, typename View, bool IsBasic> struct __kth_channel_view;
|
Chris@16
|
452
|
Chris@16
|
453 // For basic (memory-based) views dispatch to __kth_channel_view_basic
|
Chris@16
|
454 template <int K, typename View> struct __kth_channel_view<K,View,true> {
|
Chris@16
|
455 private:
|
Chris@16
|
456 typedef typename View::x_iterator src_x_iterator;
|
Chris@16
|
457
|
Chris@16
|
458 // Determines whether the channels of a given pixel iterator are adjacent in memory.
|
Chris@16
|
459 // Planar and grayscale iterators have channels adjacent in memory, whereas multi-channel interleaved and iterators with non-fundamental step do not.
|
Chris@16
|
460 BOOST_STATIC_CONSTANT(bool, adjacent=
|
Chris@16
|
461 !iterator_is_step<src_x_iterator>::value &&
|
Chris@16
|
462 (is_planar<src_x_iterator>::value ||
|
Chris@16
|
463 num_channels<View>::value==1));
|
Chris@16
|
464 public:
|
Chris@16
|
465 typedef typename __kth_channel_view_basic<K,View,adjacent>::type type;
|
Chris@16
|
466
|
Chris@16
|
467 static type make(const View& src) {
|
Chris@16
|
468 return __kth_channel_view_basic<K,View,adjacent>::make(src);
|
Chris@16
|
469 }
|
Chris@16
|
470 };
|
Chris@16
|
471
|
Chris@16
|
472 /// \brief Function object that returns a grayscale reference of the K-th channel (specified as a template parameter) of a given reference. Models: PixelDereferenceAdaptorConcept.
|
Chris@16
|
473 /// \ingroup PixelDereferenceAdaptorModel
|
Chris@16
|
474 ///
|
Chris@16
|
475 /// If the input is a pixel value or constant reference, the function object is immutable. Otherwise it is mutable (and returns non-const reference to the k-th channel)
|
Chris@16
|
476 template <int K, typename SrcP> // SrcP is a reference to PixelConcept (could be pixel value or const/non-const reference)
|
Chris@16
|
477 // Examples: pixel<T,L>, pixel<T,L>&, const pixel<T,L>&, planar_pixel_reference<T&,L>, planar_pixel_reference<const T&,L>
|
Chris@16
|
478 struct kth_channel_deref_fn {
|
Chris@16
|
479 BOOST_STATIC_CONSTANT(bool, is_mutable=pixel_is_reference<SrcP>::value && pixel_reference_is_mutable<SrcP>::value);
|
Chris@16
|
480 private:
|
Chris@16
|
481 typedef typename remove_reference<SrcP>::type src_pixel_t;
|
Chris@16
|
482 typedef typename kth_element_type<src_pixel_t, K>::type channel_t;
|
Chris@16
|
483 typedef typename src_pixel_t::const_reference const_ref_t;
|
Chris@16
|
484 typedef typename pixel_reference_type<channel_t,gray_layout_t,false,is_mutable>::type ref_t;
|
Chris@16
|
485 public:
|
Chris@16
|
486 typedef kth_channel_deref_fn<K,const_ref_t> const_t;
|
Chris@16
|
487 typedef typename pixel_value_type<channel_t,gray_layout_t>::type value_type;
|
Chris@16
|
488 typedef typename pixel_reference_type<channel_t,gray_layout_t,false,false>::type const_reference;
|
Chris@16
|
489 typedef SrcP argument_type;
|
Chris@16
|
490 typedef typename mpl::if_c<is_mutable, ref_t, value_type>::type reference;
|
Chris@16
|
491 typedef reference result_type;
|
Chris@16
|
492
|
Chris@16
|
493 kth_channel_deref_fn() {}
|
Chris@16
|
494 template <typename P> kth_channel_deref_fn(const kth_channel_deref_fn<K,P>&) {}
|
Chris@16
|
495
|
Chris@16
|
496 result_type operator()(argument_type srcP) const {
|
Chris@16
|
497 return result_type(gil::at_c<K>(srcP));
|
Chris@16
|
498 }
|
Chris@16
|
499 };
|
Chris@16
|
500
|
Chris@16
|
501 template <int K, typename View> struct __kth_channel_view<K,View,false> {
|
Chris@16
|
502 private:
|
Chris@16
|
503 typedef kth_channel_deref_fn<K,typename View::reference> deref_t;
|
Chris@16
|
504 typedef typename View::template add_deref<deref_t> AD;
|
Chris@16
|
505 public:
|
Chris@16
|
506 typedef typename AD::type type;
|
Chris@16
|
507 static type make(const View& src) {
|
Chris@16
|
508 return AD::make(src, deref_t());
|
Chris@16
|
509 }
|
Chris@16
|
510 };
|
Chris@16
|
511 } // namespace detail
|
Chris@16
|
512
|
Chris@16
|
513 /// \brief Given a source image view type View, returns the type of an image view over a given channel of View.
|
Chris@16
|
514 /// \ingroup ImageViewTransformationsKthChannel
|
Chris@16
|
515 ///
|
Chris@16
|
516 /// If the channels in the source view are adjacent in memory (such as planar non-step view or single-channel view) then the
|
Chris@16
|
517 /// return view is a single-channel non-step view.
|
Chris@16
|
518 /// If the channels are non-adjacent (interleaved and/or step view) then the return view is a single-channel step view.
|
Chris@16
|
519 template <int K, typename View>
|
Chris@16
|
520 struct kth_channel_view_type {
|
Chris@16
|
521 private:
|
Chris@16
|
522 GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept)
|
Chris@16
|
523 typedef detail::__kth_channel_view<K,View,view_is_basic<View>::value> VB;
|
Chris@16
|
524 public:
|
Chris@16
|
525 typedef typename VB::type type;
|
Chris@16
|
526 static type make(const View& src) { return VB::make(src); }
|
Chris@16
|
527 };
|
Chris@16
|
528
|
Chris@16
|
529 /// \ingroup ImageViewTransformationsKthChannel
|
Chris@16
|
530 template <int K, typename View>
|
Chris@16
|
531 typename kth_channel_view_type<K,View>::type kth_channel_view(const View& src) {
|
Chris@16
|
532 return kth_channel_view_type<K,View>::make(src);
|
Chris@16
|
533 }
|
Chris@16
|
534
|
Chris@16
|
535 } } // namespace boost::gil
|
Chris@16
|
536
|
Chris@16
|
537 #endif
|