Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / gil / extension / toolbox / image_types / subchroma_image.hpp
1 //
2 // Copyright 2013 Christian Henning and Juan V. Puertos
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_TOOLBOX_IMAGE_TYPES_SUBCHROMA_IMAGE_HPP
9 #define BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_SUBCHROMA_IMAGE_HPP
10
11 #include <boost/gil/dynamic_step.hpp>
12 #include <boost/gil/image.hpp>
13 #include <boost/gil/image_view.hpp>
14 #include <boost/gil/point.hpp>
15 #include <boost/gil/virtual_locator.hpp>
16 #include <boost/gil/detail/mp11.hpp>
17
18 #include <cstddef>
19 #include <memory>
20 #include <type_traits>
21
22 namespace boost { namespace gil {
23
24 namespace detail {
25
26 template< int J, int A, int B>
27 struct scaling_factors
28 {
29     static_assert(std::integral_constant<int, J>::value == 4, "");
30
31     static_assert(
32         std::integral_constant<int, A>::value == 4 ||
33         std::integral_constant<int, A>::value == 2 ||
34         std::integral_constant<int, A>::value == 1,
35         "");
36
37     static_assert(
38         std::integral_constant<int, B>::value == 4 ||
39         std::integral_constant<int, B>::value == 2 ||
40         std::integral_constant<int, B>::value == 1 ||
41         std::integral_constant<int, B>::value == 0,
42         "");
43
44     static constexpr int ss_X =
45         std::integral_constant<int, J>::value / std::integral_constant<int, A>::value;
46
47     static constexpr int ss_Y =
48         mp11::mp_if_c
49         <
50             std::integral_constant<int, B>::value == 0,
51             std::integral_constant<int, 2>,
52             mp11::mp_if_c
53             <
54                 std::integral_constant<int, A>::value == std::integral_constant<int, B>::value,
55                 std::integral_constant<int, 1>,
56                 std::integral_constant<int, 4>
57             >
58         >::value;
59 };
60
61 } // namespace detail
62
63 ////////////////////////////////////////////////////////////////////////////////////////
64 /// \class subchroma_image_deref_fn
65 /// \ingroup PixelLocatorModel PixelBasedModel
66 /// \brief Used for virtual_2D_locator
67 ///
68 ////////////////////////////////////////////////////////////////////////////////////////
69 template< typename Locator
70         , typename Factors
71         >
72 struct subchroma_image_deref_fn
73 {
74     using plane_locator_t = gray8_view_t::locator;
75
76     using const_t = subchroma_image_deref_fn<Locator, Factors>;
77     using value_type = typename Locator::value_type;
78     using reference = value_type;
79     using const_reference = value_type;
80     using argument_type = point_t;
81     using result_type = reference;
82
83     static const bool is_mutable = false;
84
85     /// default constructor
86     subchroma_image_deref_fn() {}
87
88     /// constructor
89     subchroma_image_deref_fn( const plane_locator_t& y_locator
90                             , const plane_locator_t& v_locator
91                             , const plane_locator_t& u_locator
92                              )
93     : _y_locator( y_locator )
94     , _v_locator( v_locator )
95     , _u_locator( u_locator )
96     {}
97
98     /// operator()
99     result_type operator()( const point_t& p ) const
100     {
101         using scaling_factors_t = detail::scaling_factors
102             <
103                 mp11::mp_at_c<Factors, 0>::value,
104                 mp11::mp_at_c<Factors, 1>::value,
105                 mp11::mp_at_c<Factors, 2>::value
106             >;
107
108         plane_locator_t y = _y_locator.xy_at( p );
109         plane_locator_t v = _v_locator.xy_at( p.x / scaling_factors_t::ss_X, p.y / scaling_factors_t::ss_X );
110         plane_locator_t u = _u_locator.xy_at( p.x / scaling_factors_t::ss_X, p.y / scaling_factors_t::ss_X );
111
112         return value_type( at_c< 0 >( *y )
113                          , at_c< 0 >( *v )
114                          , at_c< 0 >( *u )
115                          );
116     }
117
118     ///
119     const plane_locator_t& y_locator() const { return _y_locator; }
120     const plane_locator_t& v_locator() const { return _v_locator; }
121     const plane_locator_t& u_locator() const { return _u_locator; }
122
123 private:
124
125     plane_locator_t _y_locator;
126     plane_locator_t _v_locator;
127     plane_locator_t _u_locator;
128 };
129
130
131 ////////////////////////////////////////////////////////////////////////////////////////
132 /// \class subchroma_image_locator_type
133 /// \ingroup PixelLocatorModel PixelBasedModel
134 /// \brief
135 ///
136 ////////////////////////////////////////////////////////////////////////////////////////
137 template< typename Locator
138         , typename Factors
139         >
140 struct subchroma_image_locator
141 {
142     using type = virtual_2d_locator
143         <
144             subchroma_image_deref_fn<Locator, Factors>, // Deref
145             false // IsTransposed
146         >;
147 };
148
149 /////////////////////////////
150 //  PixelBasedConcept
151 /////////////////////////////
152
153 template < typename Locator, typename Factors >
154 struct channel_type< subchroma_image_locator< Locator, Factors > >
155     : public channel_type< typename subchroma_image_locator< Locator, Factors >::type > {};
156
157 template < typename Locator, typename Factors >
158 struct color_space_type< subchroma_image_locator< Locator, Factors > >
159     : public color_space_type< typename subchroma_image_locator< Locator, Factors >::type > {};
160
161 template < typename Locator, typename Factors >
162 struct channel_mapping_type< subchroma_image_locator< Locator, Factors > >
163     : public channel_mapping_type< typename subchroma_image_locator< Locator, Factors >::type > {};
164
165 template < typename Locator, typename Factors >
166 struct is_planar< subchroma_image_locator< Locator, Factors > >
167     : public is_planar< typename subchroma_image_locator< Locator, Factors >::type > {};
168
169 /////////////////////////////
170 //  HasDynamicXStepTypeConcept
171 /////////////////////////////
172
173 template < typename Locator, typename Factors >
174 struct dynamic_x_step_type< subchroma_image_locator< Locator, Factors > >
175 {
176     using type = typename subchroma_image_locator<Locator, Factors>::type;
177 };
178
179 /////////////////////////////
180 //  HasDynamicYStepTypeConcept
181 /////////////////////////////
182
183 template < typename Locator, typename Factors >
184 struct dynamic_y_step_type< subchroma_image_locator< Locator, Factors > >
185 {
186     using type = typename subchroma_image_locator<Locator, Factors>::type;
187 };
188
189 /////////////////////////////
190 //  HasTransposedTypeConcept
191 /////////////////////////////
192
193 template < typename Locator, typename Factors >
194 struct transposed_type< subchroma_image_locator< Locator, Factors > >
195 {
196     using type = typename subchroma_image_locator<Locator, Factors>::type;
197 };
198
199 //////////////////////////////////
200
201 ////////////////////////////////////////////////////////////////////////////////////////
202 /// \class subchroma_image_view
203 /// \ingroup ImageViewModel PixelBasedModel
204 /// \brief A lightweight object that interprets a subchroma image.
205 ///
206 ////////////////////////////////////////////////////////////////////////////////////////
207 template
208 <
209     typename Locator,
210     typename Factors = mp11::mp_list_c<int, 4, 4, 4>
211 >
212 class subchroma_image_view : public image_view<Locator>
213 {
214 public:
215
216     using locator = Locator;
217     using deref_fn_t = typename locator::deref_fn_t;
218     using plane_locator_t = typename deref_fn_t::plane_locator_t;
219
220
221     using const_t = subchroma_image_view<Locator, Factors>;
222
223     using plane_view_t = image_view<plane_locator_t>;
224
225     /// default constructor
226     subchroma_image_view()
227     : image_view< Locator >()
228     {}
229
230     /// constructor
231     subchroma_image_view( const point_t& y_dimensions
232                         , const point_t& v_dimensions
233                         , const point_t& u_dimensions
234                         , const Locator& locator
235                         )
236     : image_view< Locator >( y_dimensions, locator )
237     , _y_dimensions( y_dimensions )
238     , _v_dimensions( v_dimensions )
239     , _u_dimensions( u_dimensions )
240     {}
241
242     /// copy constructor
243     template< typename Subchroma_View >
244     subchroma_image_view( const Subchroma_View& v )
245     : image_view< locator >( v )
246     {}
247
248     const point_t& v_ssfactors() const { return point_t( get_deref_fn().vx_ssfactor(), get_deref_fn().vx_ssfactor() ); }
249     const point_t& u_ssfactors() const { return point_t( get_deref_fn().ux_ssfactor(), get_deref_fn().ux_ssfactor() ); }
250
251     const point_t& y_dimension() const { return _y_dimensions; }
252     const point_t& v_dimension() const { return _v_dimensions; }
253     const point_t& u_dimension() const { return _u_dimensions; }
254
255     const plane_locator_t& y_plane() const { return get_deref_fn().y_locator(); }
256     const plane_locator_t& v_plane() const { return get_deref_fn().v_locator(); }
257     const plane_locator_t& u_plane() const { return get_deref_fn().u_locator(); }
258
259     const plane_view_t y_plane_view() const { return plane_view_t( _y_dimensions, y_plane() ); }
260     const plane_view_t v_plane_view() const { return plane_view_t( _v_dimensions, v_plane() ); }
261     const plane_view_t u_plane_view() const { return plane_view_t( _u_dimensions, u_plane() ); }
262
263
264 private:
265
266     const deref_fn_t& get_deref_fn() const { return this->pixels().deref_fn(); }
267
268 private:
269
270     point_t _y_dimensions;
271     point_t _v_dimensions;
272     point_t _u_dimensions;
273 };
274
275
276 /////////////////////////////
277 //  PixelBasedConcept
278 /////////////////////////////
279
280 template < typename Locator, typename Factors >
281 struct channel_type< subchroma_image_view< Locator, Factors > >
282     : public channel_type< Locator > {};
283
284 template < typename Locator, typename Factors >
285 struct color_space_type< subchroma_image_view< Locator, Factors > >
286     : public color_space_type< Locator > {};
287
288 template < typename Locator, typename Factors >
289 struct channel_mapping_type< subchroma_image_view< Locator, Factors > >
290      : public channel_mapping_type< Locator > {};
291
292 template < typename Locator, typename Factors >
293 struct is_planar< subchroma_image_view< Locator, Factors > >
294     : public is_planar< Locator > {};
295
296 /////////////////////////////
297 //  HasDynamicXStepTypeConcept
298 /////////////////////////////
299
300 template < typename Locator, typename Factors >
301 struct dynamic_x_step_type< subchroma_image_view< Locator, Factors > >
302 {
303     using type = image_view<typename dynamic_x_step_type<Locator>::type>;
304 };
305
306 /////////////////////////////
307 //  HasDynamicYStepTypeConcept
308 /////////////////////////////
309
310 template < typename Locator, typename Factors >
311 struct dynamic_y_step_type< subchroma_image_view< Locator, Factors > >
312 {
313     using type = image_view<typename dynamic_y_step_type<Locator>::type>;
314 };
315
316 /////////////////////////////
317 //  HasTransposedTypeConcept
318 /////////////////////////////
319
320 template < typename Locator, typename Factors >
321 struct transposed_type< subchroma_image_view< Locator, Factors > >
322 {
323     using type = image_view<typename transposed_type<Locator>::type>;
324 };
325
326 ////////////////////////////////////////////////////////////////////////////////////////
327 /// \ingroup ImageModel PixelBasedModel
328 /// \brief container interface over image view. Models ImageConcept, PixelBasedConcept
329 ///
330 /// A subchroma image holds a bunch of planes which don't need to have the same resolution.
331 ///
332 ////////////////////////////////////////////////////////////////////////////////////////
333 template
334 <
335     typename Pixel,
336     typename Factors = mp11::mp_list_c<int, 4, 4, 4>,
337     typename Allocator = std::allocator<unsigned char>
338 >
339 class subchroma_image : public detail::scaling_factors
340     <
341         mp11::mp_at_c<Factors, 0>::value,
342         mp11::mp_at_c<Factors, 1>::value,
343         mp11::mp_at_c<Factors, 2>::value
344     >
345 {
346
347 private:
348     using parent_t = detail::scaling_factors
349         <
350             mp11::mp_at_c<Factors, 0>::value,
351             mp11::mp_at_c<Factors, 1>::value,
352             mp11::mp_at_c<Factors, 2>::value
353         >;
354
355 public:
356
357     using channel_t = typename channel_type<Pixel>::type;
358     using pixel_t = pixel<channel_t, gray_layout_t>;
359
360     using plane_image_t = image<pixel_t, false, Allocator>;
361
362     using plane_view_t = typename plane_image_t::view_t;
363     using plane_const_view_t = typename plane_image_t::const_view_t;
364     using plane_locator_t = typename plane_view_t::locator;
365
366     using pixel_view_t = typename view_type_from_pixel<Pixel>::type;
367     using pixel_locator_t = typename pixel_view_t::locator;
368
369     using locator_t = typename subchroma_image_locator
370         <
371             pixel_locator_t,
372             Factors
373         >::type;
374
375     using x_coord_t = typename plane_image_t::coord_t;
376     using y_coord_t = typename plane_image_t::coord_t;
377
378     using view_t = subchroma_image_view<locator_t, Factors>;
379     using const_view_t = typename view_t::const_t;
380
381
382     /// constructor
383     subchroma_image( const x_coord_t y_width
384                    , const y_coord_t y_height
385                    )
386     : _y_plane(        y_width,        y_height, 0, Allocator() )
387     , _v_plane( y_width / parent_t::ss_X, y_height / parent_t::ss_Y, 0, Allocator() )
388     , _u_plane( y_width / parent_t::ss_X, y_height / parent_t::ss_Y, 0, Allocator() )
389     {
390         init();
391     }
392
393 public:
394
395     view_t _view;
396
397 private:
398
399     void init()
400     {
401         using defer_fn_t = subchroma_image_deref_fn<pixel_locator_t, Factors>;
402
403         defer_fn_t deref_fn( view( _y_plane ).xy_at( 0, 0 )
404                            , view( _v_plane ).xy_at( 0, 0 )
405                            , view( _u_plane ).xy_at( 0, 0 )
406                            );
407
408         // init a virtual_2d_locator
409         locator_t locator( point_t( 0, 0 ) // p
410                          , point_t( 1, 1 ) // step
411                          , deref_fn
412                          );
413
414         _view = view_t( _y_plane.dimensions()
415                       , _v_plane.dimensions()
416                       , _u_plane.dimensions()
417                       , locator
418                       );
419     }
420
421
422 private:
423
424     plane_image_t _y_plane;
425     plane_image_t _v_plane;
426     plane_image_t _u_plane;
427 };
428
429
430 /////////////////////////////
431 //  PixelBasedConcept
432 /////////////////////////////
433
434 template < typename Pixel, typename Factors, typename Alloc >
435 struct channel_type< subchroma_image< Pixel, Factors, Alloc > >
436     : channel_type< Pixel > {};
437
438 template < typename Pixel, typename Factors, typename Alloc >
439 struct color_space_type< subchroma_image< Pixel, Factors, Alloc > >
440     : color_space_type< Pixel > {};
441
442 template < typename Pixel, typename Factors, typename Alloc >
443 struct channel_mapping_type<  subchroma_image< Pixel, Factors, Alloc > >
444     : channel_mapping_type< Pixel > {};
445
446 template < typename Pixel, typename Factors, typename Alloc >
447 struct is_planar< subchroma_image< Pixel, Factors, Alloc > >
448     : std::integral_constant<bool, false>
449 {};
450
451
452 /////////////////////////////////////////////////////////////////////////////////////////
453 /// \name view, const_view
454 /// \brief Get an image view from an subchroma_image
455 /// \ingroup ImageModel
456 /// \brief Returns the non-constant-pixel view of an image
457 /////////////////////////////////////////////////////////////////////////////////////////
458 template< typename Pixel
459         , typename Factors
460         >
461 inline
462 const typename subchroma_image< Pixel, Factors >::view_t& view( subchroma_image< Pixel, Factors >& img )
463 {
464     return img._view;
465 }
466
467 template< typename Pixel
468         , typename Factors
469         >
470 inline
471 const typename subchroma_image< Pixel, Factors >::const_view_t const_view( subchroma_image< Pixel, Factors >& img )
472 {
473     return static_cast< const typename subchroma_image< Pixel, Factors >::const_view_t>( img._view );
474 }
475
476 /////////////////////////////////////////////////////////////////////////////////////////
477 /// \ingroup ImageViewSTLAlgorithmsFillPixels
478 /// \brief std::fill for subchroma_image views
479 /////////////////////////////////////////////////////////////////////////////////////////
480 template< typename Locator
481         , typename Factors
482         , typename Pixel
483         >
484 void fill_pixels( const subchroma_image_view< Locator, Factors >& view
485                 , const Pixel&                                    value
486                 )
487 {
488     using channel_t = typename subchroma_image
489         <
490             Pixel,
491             Factors
492         >::plane_view_t::value_type;
493
494     fill_pixels( view.y_plane_view(), channel_t( at_c< 0 >( value )));
495     fill_pixels( view.v_plane_view(), channel_t( at_c< 1 >( value )));
496     fill_pixels( view.u_plane_view(), channel_t( at_c< 2 >( value )));
497 }
498
499 /////////////////////////////////////////////////////////////////////////////////////////
500 /// \ingroup ImageViewConstructors
501 /// \brief Creates a subchroma view from a raw memory
502 /////////////////////////////////////////////////////////////////////////////////////////
503 template< typename Pixel
504         , typename Factors
505         >
506 typename subchroma_image< Pixel
507                         , Factors
508                         >::view_t subchroma_view( std::size_t    y_width
509                                                 , std::size_t    y_height
510                                                 , unsigned char* y_base
511                                                 )
512 {
513     using scaling_factors_t = detail::scaling_factors
514         <
515             mp11::mp_at_c<Factors, 0>::type::value,
516             mp11::mp_at_c<Factors, 1>::type::value,
517             mp11::mp_at_c<Factors, 2>::type::value
518         >;
519
520     std::size_t y_channel_size = 1;
521     std::size_t u_channel_size = 1;
522
523     unsigned char* u_base = y_base + ( y_width  * y_height * y_channel_size );
524     unsigned char* v_base = u_base + ( y_width  / scaling_factors_t::ss_X )
525                                    * u_channel_size;
526
527     using plane_view_t = typename subchroma_image<Pixel, Factors>::plane_view_t;
528
529     plane_view_t y_plane = interleaved_view( y_width
530                                            , y_height
531                                            , (typename plane_view_t::value_type*) y_base // pixels
532                                            , y_width                            // rowsize_in_bytes
533                                            );
534
535     plane_view_t v_plane = interleaved_view( y_width  / scaling_factors_t::ss_X
536                                            , y_height / scaling_factors_t::ss_Y
537                                            , (typename plane_view_t::value_type*) v_base // pixels
538                                            , y_width                            // rowsize_in_bytes
539                                            );
540
541     plane_view_t u_plane = interleaved_view( y_width  / scaling_factors_t::ss_X
542                                            , y_height / scaling_factors_t::ss_Y
543                                            , (typename plane_view_t::value_type*) u_base // pixels
544                                            , y_width                            // rowsize_in_bytes
545                                            );
546
547     using defer_fn_t = subchroma_image_deref_fn
548         <
549             typename subchroma_image<Pixel, Factors>::pixel_locator_t,
550             Factors
551         >;
552
553     defer_fn_t deref_fn( y_plane.xy_at( 0, 0 )
554                        , v_plane.xy_at( 0, 0 )
555                        , u_plane.xy_at( 0, 0 )
556                        );
557
558
559     using locator_t = typename subchroma_image<Pixel, Factors>::locator_t;
560
561     locator_t locator( point_t( 0, 0 ) // p
562                      , point_t( 1, 1 ) // step
563                      , deref_fn
564                      );
565
566     using view_t = typename subchroma_image<Pixel, Factors>::view_t;
567
568     return view_t( point_t(                           y_width,                           y_height )
569                  , point_t( y_width / scaling_factors_t::ss_X, y_height / scaling_factors_t::ss_Y )
570                  , point_t( y_width / scaling_factors_t::ss_X, y_height / scaling_factors_t::ss_Y )
571                  , locator
572                  );
573 }
574
575 } // namespace gil
576 } // namespace boost
577
578 #endif