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_EXTENSION_DYNAMIC_IMAGE_IMAGE_VIEW_FACTORY_HPP
9 #define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_IMAGE_VIEW_FACTORY_HPP
10
11 #include <boost/gil/extension/dynamic_image/any_image_view.hpp>
12
13 #include <boost/gil/dynamic_step.hpp>
14 #include <boost/gil/image_view_factory.hpp>
15 #include <boost/gil/point.hpp>
16 #include <boost/gil/detail/mp11.hpp>
17
18 #include <cstdint>
19
20 namespace boost { namespace gil {
21
22 // Methods for constructing any image views from other any image views
23 // Extends image view factory to runtime type-specified views (any_image_view)
24
25 namespace detail {
26
27 template <typename ResultView>
28 struct flipped_up_down_view_fn
29 {
30 using result_type = ResultView;
31
32 template <typename View>
operator ()boost::gil::detail::flipped_up_down_view_fn33 auto operator()(View const& src) const -> result_type
34 {
35 return result_type{flipped_up_down_view(src)};
36 }
37 };
38
39 template <typename ResultView>
40 struct flipped_left_right_view_fn
41 {
42 using result_type = ResultView;
43
44 template <typename View>
operator ()boost::gil::detail::flipped_left_right_view_fn45 auto operator()(View const& src) const -> result_type
46 {
47 return result_type{flipped_left_right_view(src)};
48 }
49 };
50
51 template <typename ResultView>
52 struct rotated90cw_view_fn
53 {
54 using result_type = ResultView;
55
56 template <typename View>
operator ()boost::gil::detail::rotated90cw_view_fn57 auto operator()(View const& src) const -> result_type
58 {
59 return result_type{rotated90cw_view(src)};
60 }
61 };
62
63 template <typename ResultView>
64 struct rotated90ccw_view_fn
65 {
66 using result_type = ResultView;
67
68 template <typename View>
operator ()boost::gil::detail::rotated90ccw_view_fn69 auto operator()(View const& src) const -> result_type
70 {
71 return result_type{rotated90ccw_view(src)};
72 }
73 };
74
75 template <typename ResultView>
76 struct tranposed_view_fn
77 {
78 using result_type = ResultView;
79
80 template <typename View>
operator ()boost::gil::detail::tranposed_view_fn81 auto operator()(View const& src) const -> result_type
82 {
83 return result_type{tranposed_view(src)};
84 }
85 };
86
87 template <typename ResultView>
88 struct rotated180_view_fn
89 {
90 using result_type = ResultView;
91
92 template <typename View>
operator ()boost::gil::detail::rotated180_view_fn93 auto operator()(View const& src) const -> result_type
94 {
95 return result_type{rotated180_view(src)};
96 }
97 };
98
99 template <typename ResultView>
100 struct subimage_view_fn
101 {
102 using result_type = ResultView;
103
subimage_view_fnboost::gil::detail::subimage_view_fn104 subimage_view_fn(point_t const& topleft, point_t const& dimensions)
105 : _topleft(topleft), _size2(dimensions)
106 {}
107
108 template <typename View>
operator ()boost::gil::detail::subimage_view_fn109 auto operator()(View const& src) const -> result_type
110 {
111 return result_type{subimage_view(src,_topleft,_size2)};
112 }
113
114 point_t _topleft;
115 point_t _size2;
116 };
117
118 template <typename ResultView>
119 struct subsampled_view_fn
120 {
121 using result_type = ResultView;
122
subsampled_view_fnboost::gil::detail::subsampled_view_fn123 subsampled_view_fn(point_t const& step) : _step(step) {}
124
125 template <typename View>
operator ()boost::gil::detail::subsampled_view_fn126 auto operator()(View const& src) const -> result_type
127 {
128 return result_type{subsampled_view(src,_step)};
129 }
130
131 point_t _step;
132 };
133
134 template <typename ResultView>
135 struct nth_channel_view_fn
136 {
137 using result_type = ResultView;
138
nth_channel_view_fnboost::gil::detail::nth_channel_view_fn139 nth_channel_view_fn(int n) : _n(n) {}
140
141 template <typename View>
operator ()boost::gil::detail::nth_channel_view_fn142 auto operator()(View const& src) const -> result_type
143 {
144 return result_type(nth_channel_view(src,_n));
145 }
146
147 int _n;
148 };
149
150 template <typename DstP, typename ResultView, typename CC = default_color_converter>
151 struct color_converted_view_fn
152 {
153 using result_type = ResultView;
154
color_converted_view_fnboost::gil::detail::color_converted_view_fn155 color_converted_view_fn(CC cc = CC()): _cc(cc) {}
156
157 template <typename View>
operator ()boost::gil::detail::color_converted_view_fn158 auto operator()(View const& src) const -> result_type
159 {
160 return result_type{color_converted_view<DstP>(src, _cc)};
161 }
162
163 private:
164 CC _cc;
165 };
166
167 } // namespace detail
168
169 /// \ingroup ImageViewTransformationsFlipUD
170 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
171 template <typename ...Views>
172 inline
flipped_up_down_view(any_image_view<Views...> const & src)173 auto flipped_up_down_view(any_image_view<Views...> const& src)
174 -> typename dynamic_y_step_type<any_image_view<Views...>>::type
175 {
176 using result_view_t = typename dynamic_y_step_type<any_image_view<Views...>>::type;
177 return apply_operation(src, detail::flipped_up_down_view_fn<result_view_t>());
178 }
179
180 /// \ingroup ImageViewTransformationsFlipLR
181 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
182 template <typename ...Views>
183 inline
flipped_left_right_view(any_image_view<Views...> const & src)184 auto flipped_left_right_view(any_image_view<Views...> const& src)
185 -> typename dynamic_x_step_type<any_image_view<Views...>>::type
186 {
187 using result_view_t = typename dynamic_x_step_type<any_image_view<Views...>>::type;
188 return apply_operation(src, detail::flipped_left_right_view_fn<result_view_t>());
189 }
190
191 /// \ingroup ImageViewTransformationsTransposed
192 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
193 template <typename ...Views>
194 inline
transposed_view(const any_image_view<Views...> & src)195 auto transposed_view(const any_image_view<Views...>& src)
196 -> typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type
197 {
198 using result_view_t = typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type;
199 return apply_operation(src, detail::tranposed_view_fn<result_view_t>());
200 }
201
202 /// \ingroup ImageViewTransformations90CW
203 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
204 template <typename ...Views>
205 inline
rotated90cw_view(const any_image_view<Views...> & src)206 auto rotated90cw_view(const any_image_view<Views...>& src)
207 -> typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type
208 {
209 using result_view_t = typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type;
210 return apply_operation(src,detail::rotated90cw_view_fn<result_view_t>());
211 }
212
213 /// \ingroup ImageViewTransformations90CCW
214 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
215 template <typename ...Views>
216 inline
rotated90ccw_view(const any_image_view<Views...> & src)217 auto rotated90ccw_view(const any_image_view<Views...>& src)
218 -> typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type
219 {
220 return apply_operation(src,detail::rotated90ccw_view_fn<typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type>());
221 }
222
223 /// \ingroup ImageViewTransformations180
224 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
225 template <typename ...Views>
226 inline
rotated180_view(any_image_view<Views...> const & src)227 auto rotated180_view(any_image_view<Views...> const& src)
228 -> typename dynamic_xy_step_type<any_image_view<Views...>>::type
229 {
230 using step_type = typename dynamic_xy_step_type<any_image_view<Views...>>::type;
231 return apply_operation(src, detail::rotated180_view_fn<step_type>());
232 }
233
234 /// \ingroup ImageViewTransformationsSubimage
235 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
236 template <typename ...Views>
237 inline
subimage_view(any_image_view<Views...> const & src,point_t const & topleft,point_t const & dimensions)238 auto subimage_view(
239 any_image_view<Views...> const& src,
240 point_t const& topleft,
241 point_t const& dimensions)
242 -> any_image_view<Views...>
243 {
244 using subimage_view_fn = detail::subimage_view_fn<any_image_view<Views...>>;
245 return apply_operation(src, subimage_view_fn(topleft, dimensions));
246 }
247
248 /// \ingroup ImageViewTransformationsSubimage
249 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
250 template <typename ...Views>
251 inline
subimage_view(any_image_view<Views...> const & src,std::ptrdiff_t x_min,std::ptrdiff_t y_min,std::ptrdiff_t width,std::ptrdiff_t height)252 auto subimage_view(
253 any_image_view<Views...> const& src,
254 std::ptrdiff_t x_min, std::ptrdiff_t y_min, std::ptrdiff_t width, std::ptrdiff_t height)
255 -> any_image_view<Views...>
256 {
257 using subimage_view_fn = detail::subimage_view_fn<any_image_view<Views...>>;
258 return apply_operation(src, subimage_view_fn(point_t(x_min, y_min),point_t(width, height)));
259 }
260
261 /// \ingroup ImageViewTransformationsSubsampled
262 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
263 template <typename ...Views>
264 inline
subsampled_view(any_image_view<Views...> const & src,point_t const & step)265 auto subsampled_view(any_image_view<Views...> const& src, point_t const& step)
266 -> typename dynamic_xy_step_type<any_image_view<Views...>>::type
267 {
268 using step_type = typename dynamic_xy_step_type<any_image_view<Views...>>::type;
269 using subsampled_view = detail::subsampled_view_fn<step_type>;
270 return apply_operation(src, subsampled_view(step));
271 }
272
273 /// \ingroup ImageViewTransformationsSubsampled
274 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
275 template <typename ...Views>
276 inline
subsampled_view(any_image_view<Views...> const & src,std::ptrdiff_t x_step,std::ptrdiff_t y_step)277 auto subsampled_view(any_image_view<Views...> const& src, std::ptrdiff_t x_step, std::ptrdiff_t y_step)
278 -> typename dynamic_xy_step_type<any_image_view<Views...>>::type
279 {
280 using step_type = typename dynamic_xy_step_type<any_image_view<Views...>>::type;
281 using subsampled_view_fn = detail::subsampled_view_fn<step_type>;
282 return apply_operation(src, subsampled_view_fn(point_t(x_step, y_step)));
283 }
284
285 namespace detail {
286
287 template <typename View>
288 struct get_nthchannel_type { using type = typename nth_channel_view_type<View>::type; };
289
290 template <typename Views>
291 struct views_get_nthchannel_type : mp11::mp_transform<get_nthchannel_type, Views> {};
292
293 } // namespace detail
294
295 /// \ingroup ImageViewTransformationsNthChannel
296 /// \brief Given a runtime source image view, returns the type of a runtime image view over a single channel of the source view
297 template <typename ...Views>
298 struct nth_channel_view_type<any_image_view<Views...>>
299 {
300 using type = typename detail::views_get_nthchannel_type<any_image_view<Views...>>;
301 };
302
303 /// \ingroup ImageViewTransformationsNthChannel
304 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
305 template <typename ...Views>
306 inline
nth_channel_view(const any_image_view<Views...> & src,int n)307 auto nth_channel_view(const any_image_view<Views...>& src, int n)
308 -> typename nth_channel_view_type<any_image_view<Views...>>::type
309 {
310 using result_view_t = typename nth_channel_view_type<any_image_view<Views...>>::type;
311 return apply_operation(src,detail::nth_channel_view_fn<result_view_t>(n));
312 }
313
314 namespace detail {
315
316 template <typename View, typename DstP, typename CC>
317 struct get_ccv_type : color_converted_view_type<View, DstP, CC> {};
318
319 template <typename Views, typename DstP, typename CC>
320 struct views_get_ccv_type
321 {
322 private:
323 // FIXME: Remove class name injection with detail:: qualification
324 // Required as workaround for MP11 issue that treats unqualified metafunction
325 // in the class definition of the same name as the specialization (Peter Dimov):
326 // invalid template argument for template parameter 'F', expected a class template
327 template <typename T>
328 using ccvt = detail::get_ccv_type<T, DstP, CC>;
329
330 public:
331 using type = mp11::mp_transform<ccvt, Views>;
332 };
333
334 } // namespace detail
335
336 /// \ingroup ImageViewTransformationsColorConvert
337 /// \brief Returns the type of a runtime-specified view, color-converted to a given pixel type with user specified color converter
338 template <typename ...Views, typename DstP, typename CC>
339 struct color_converted_view_type<any_image_view<Views...>,DstP,CC>
340 {
341 //using type = any_image_view<typename detail::views_get_ccv_type<Views, DstP, CC>::type>;
342 using type = detail::views_get_ccv_type<any_image_view<Views...>, DstP, CC>;
343 };
344
345 /// \ingroup ImageViewTransformationsColorConvert
346 /// \brief overload of generic color_converted_view with user defined color-converter
347 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
348 template <typename DstP, typename ...Views, typename CC>
349 inline
color_converted_view(const any_image_view<Views...> & src,CC)350 auto color_converted_view(const any_image_view<Views...>& src, CC)
351 -> typename color_converted_view_type<any_image_view<Views...>, DstP, CC>::type
352 {
353 using cc_view_t = typename color_converted_view_type<any_image_view<Views...>, DstP, CC>::type;
354 return apply_operation(src, detail::color_converted_view_fn<DstP, cc_view_t>());
355 }
356
357 /// \ingroup ImageViewTransformationsColorConvert
358 /// \brief Returns the type of a runtime-specified view, color-converted to a given pixel type with the default coor converter
359 template <typename ...Views, typename DstP>
360 struct color_converted_view_type<any_image_view<Views...>,DstP>
361 {
362 using type = detail::views_get_ccv_type<any_image_view<Views...>, DstP, default_color_converter>;
363 };
364
365 /// \ingroup ImageViewTransformationsColorConvert
366 /// \brief overload of generic color_converted_view with the default color-converter
367 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
368 template <typename DstP, typename ...Views>
369 inline
color_converted_view(any_image_view<Views...> const & src)370 auto color_converted_view(any_image_view<Views...> const& src)
371 -> typename color_converted_view_type<any_image_view<Views...>, DstP>::type
372 {
373 using cc_view_t = typename color_converted_view_type<any_image_view<Views...>, DstP>::type;
374 return apply_operation(src, detail::color_converted_view_fn<DstP, cc_view_t>());
375 }
376
377 /// \ingroup ImageViewTransformationsColorConvert
378 /// \brief overload of generic color_converted_view with user defined color-converter
379 /// These are workarounds for GCC 3.4, which thinks color_converted_view is ambiguous with the same method for templated views (in gil/image_view_factory.hpp)
380 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
381 template <typename DstP, typename ...Views, typename CC>
382 inline
any_color_converted_view(const any_image_view<Views...> & src,CC)383 auto any_color_converted_view(const any_image_view<Views...>& src, CC)
384 -> typename color_converted_view_type<any_image_view<Views...>, DstP, CC>::type
385 {
386 using cc_view_t = typename color_converted_view_type<any_image_view<Views...>, DstP, CC>::type;
387 return apply_operation(src, detail::color_converted_view_fn<DstP, cc_view_t>());
388 }
389
390 /// \ingroup ImageViewTransformationsColorConvert
391 /// \brief overload of generic color_converted_view with the default color-converter
392 /// These are workarounds for GCC 3.4, which thinks color_converted_view is ambiguous with the same method for templated views (in gil/image_view_factory.hpp)
393 /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
394 template <typename DstP, typename ...Views>
395 inline
any_color_converted_view(const any_image_view<Views...> & src)396 auto any_color_converted_view(const any_image_view<Views...>& src)
397 -> typename color_converted_view_type<any_image_view<Views...>, DstP>::type
398 {
399 using cc_view_t = typename color_converted_view_type<any_image_view<Views...>, DstP>::type;
400 return apply_operation(src, detail::color_converted_view_fn<DstP, cc_view_t>());
401 }
402
403 /// \}
404
405 }} // namespace boost::gil
406
407 #endif
408