2 // Copyright 2013 Christian Henning and Juan V. Puertos
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
8 #ifndef BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_SUBCHROMA_IMAGE_HPP
9 #define BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_SUBCHROMA_IMAGE_HPP
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>
20 #include <type_traits>
22 namespace boost { namespace gil {
26 template< int J, int A, int B>
27 struct scaling_factors
29 static_assert(std::integral_constant<int, J>::value == 4, "");
32 std::integral_constant<int, A>::value == 4 ||
33 std::integral_constant<int, A>::value == 2 ||
34 std::integral_constant<int, A>::value == 1,
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,
44 static constexpr int ss_X =
45 std::integral_constant<int, J>::value / std::integral_constant<int, A>::value;
47 static constexpr int ss_Y =
50 std::integral_constant<int, B>::value == 0,
51 std::integral_constant<int, 2>,
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>
63 ////////////////////////////////////////////////////////////////////////////////////////
64 /// \class subchroma_image_deref_fn
65 /// \ingroup PixelLocatorModel PixelBasedModel
66 /// \brief Used for virtual_2D_locator
68 ////////////////////////////////////////////////////////////////////////////////////////
69 template< typename Locator
72 struct subchroma_image_deref_fn
74 using plane_locator_t = gray8_view_t::locator;
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;
83 static const bool is_mutable = false;
85 /// default constructor
86 subchroma_image_deref_fn() {}
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
93 : _y_locator( y_locator )
94 , _v_locator( v_locator )
95 , _u_locator( u_locator )
99 result_type operator()( const point_t& p ) const
101 using scaling_factors_t = detail::scaling_factors
103 mp11::mp_at_c<Factors, 0>::value,
104 mp11::mp_at_c<Factors, 1>::value,
105 mp11::mp_at_c<Factors, 2>::value
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 );
112 return value_type( at_c< 0 >( *y )
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; }
125 plane_locator_t _y_locator;
126 plane_locator_t _v_locator;
127 plane_locator_t _u_locator;
131 ////////////////////////////////////////////////////////////////////////////////////////
132 /// \class subchroma_image_locator_type
133 /// \ingroup PixelLocatorModel PixelBasedModel
136 ////////////////////////////////////////////////////////////////////////////////////////
137 template< typename Locator
140 struct subchroma_image_locator
142 using type = virtual_2d_locator
144 subchroma_image_deref_fn<Locator, Factors>, // Deref
145 false // IsTransposed
149 /////////////////////////////
151 /////////////////////////////
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 > {};
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 > {};
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 > {};
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 > {};
169 /////////////////////////////
170 // HasDynamicXStepTypeConcept
171 /////////////////////////////
173 template < typename Locator, typename Factors >
174 struct dynamic_x_step_type< subchroma_image_locator< Locator, Factors > >
176 using type = typename subchroma_image_locator<Locator, Factors>::type;
179 /////////////////////////////
180 // HasDynamicYStepTypeConcept
181 /////////////////////////////
183 template < typename Locator, typename Factors >
184 struct dynamic_y_step_type< subchroma_image_locator< Locator, Factors > >
186 using type = typename subchroma_image_locator<Locator, Factors>::type;
189 /////////////////////////////
190 // HasTransposedTypeConcept
191 /////////////////////////////
193 template < typename Locator, typename Factors >
194 struct transposed_type< subchroma_image_locator< Locator, Factors > >
196 using type = typename subchroma_image_locator<Locator, Factors>::type;
199 //////////////////////////////////
201 ////////////////////////////////////////////////////////////////////////////////////////
202 /// \class subchroma_image_view
203 /// \ingroup ImageViewModel PixelBasedModel
204 /// \brief A lightweight object that interprets a subchroma image.
206 ////////////////////////////////////////////////////////////////////////////////////////
210 typename Factors = mp11::mp_list_c<int, 4, 4, 4>
212 class subchroma_image_view : public image_view<Locator>
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;
221 using const_t = subchroma_image_view<Locator, Factors>;
223 using plane_view_t = image_view<plane_locator_t>;
225 /// default constructor
226 subchroma_image_view()
227 : image_view< Locator >()
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
236 : image_view< Locator >( y_dimensions, locator )
237 , _y_dimensions( y_dimensions )
238 , _v_dimensions( v_dimensions )
239 , _u_dimensions( u_dimensions )
243 template< typename Subchroma_View >
244 subchroma_image_view( const Subchroma_View& v )
245 : image_view< locator >( v )
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() ); }
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; }
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(); }
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() ); }
266 const deref_fn_t& get_deref_fn() const { return this->pixels().deref_fn(); }
270 point_t _y_dimensions;
271 point_t _v_dimensions;
272 point_t _u_dimensions;
276 /////////////////////////////
278 /////////////////////////////
280 template < typename Locator, typename Factors >
281 struct channel_type< subchroma_image_view< Locator, Factors > >
282 : public channel_type< Locator > {};
284 template < typename Locator, typename Factors >
285 struct color_space_type< subchroma_image_view< Locator, Factors > >
286 : public color_space_type< Locator > {};
288 template < typename Locator, typename Factors >
289 struct channel_mapping_type< subchroma_image_view< Locator, Factors > >
290 : public channel_mapping_type< Locator > {};
292 template < typename Locator, typename Factors >
293 struct is_planar< subchroma_image_view< Locator, Factors > >
294 : public is_planar< Locator > {};
296 /////////////////////////////
297 // HasDynamicXStepTypeConcept
298 /////////////////////////////
300 template < typename Locator, typename Factors >
301 struct dynamic_x_step_type< subchroma_image_view< Locator, Factors > >
303 using type = image_view<typename dynamic_x_step_type<Locator>::type>;
306 /////////////////////////////
307 // HasDynamicYStepTypeConcept
308 /////////////////////////////
310 template < typename Locator, typename Factors >
311 struct dynamic_y_step_type< subchroma_image_view< Locator, Factors > >
313 using type = image_view<typename dynamic_y_step_type<Locator>::type>;
316 /////////////////////////////
317 // HasTransposedTypeConcept
318 /////////////////////////////
320 template < typename Locator, typename Factors >
321 struct transposed_type< subchroma_image_view< Locator, Factors > >
323 using type = image_view<typename transposed_type<Locator>::type>;
326 ////////////////////////////////////////////////////////////////////////////////////////
327 /// \ingroup ImageModel PixelBasedModel
328 /// \brief container interface over image view. Models ImageConcept, PixelBasedConcept
330 /// A subchroma image holds a bunch of planes which don't need to have the same resolution.
332 ////////////////////////////////////////////////////////////////////////////////////////
336 typename Factors = mp11::mp_list_c<int, 4, 4, 4>,
337 typename Allocator = std::allocator<unsigned char>
339 class subchroma_image : public detail::scaling_factors
341 mp11::mp_at_c<Factors, 0>::value,
342 mp11::mp_at_c<Factors, 1>::value,
343 mp11::mp_at_c<Factors, 2>::value
348 using parent_t = detail::scaling_factors
350 mp11::mp_at_c<Factors, 0>::value,
351 mp11::mp_at_c<Factors, 1>::value,
352 mp11::mp_at_c<Factors, 2>::value
357 using channel_t = typename channel_type<Pixel>::type;
358 using pixel_t = pixel<channel_t, gray_layout_t>;
360 using plane_image_t = image<pixel_t, false, Allocator>;
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;
366 using pixel_view_t = typename view_type_from_pixel<Pixel>::type;
367 using pixel_locator_t = typename pixel_view_t::locator;
369 using locator_t = typename subchroma_image_locator
375 using x_coord_t = typename plane_image_t::coord_t;
376 using y_coord_t = typename plane_image_t::coord_t;
378 using view_t = subchroma_image_view<locator_t, Factors>;
379 using const_view_t = typename view_t::const_t;
383 subchroma_image( const x_coord_t y_width
384 , const y_coord_t y_height
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() )
401 using defer_fn_t = subchroma_image_deref_fn<pixel_locator_t, Factors>;
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 )
408 // init a virtual_2d_locator
409 locator_t locator( point_t( 0, 0 ) // p
410 , point_t( 1, 1 ) // step
414 _view = view_t( _y_plane.dimensions()
415 , _v_plane.dimensions()
416 , _u_plane.dimensions()
424 plane_image_t _y_plane;
425 plane_image_t _v_plane;
426 plane_image_t _u_plane;
430 /////////////////////////////
432 /////////////////////////////
434 template < typename Pixel, typename Factors, typename Alloc >
435 struct channel_type< subchroma_image< Pixel, Factors, Alloc > >
436 : channel_type< Pixel > {};
438 template < typename Pixel, typename Factors, typename Alloc >
439 struct color_space_type< subchroma_image< Pixel, Factors, Alloc > >
440 : color_space_type< Pixel > {};
442 template < typename Pixel, typename Factors, typename Alloc >
443 struct channel_mapping_type< subchroma_image< Pixel, Factors, Alloc > >
444 : channel_mapping_type< Pixel > {};
446 template < typename Pixel, typename Factors, typename Alloc >
447 struct is_planar< subchroma_image< Pixel, Factors, Alloc > >
448 : std::integral_constant<bool, false>
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
462 const typename subchroma_image< Pixel, Factors >::view_t& view( subchroma_image< Pixel, Factors >& img )
467 template< typename Pixel
471 const typename subchroma_image< Pixel, Factors >::const_view_t const_view( subchroma_image< Pixel, Factors >& img )
473 return static_cast< const typename subchroma_image< Pixel, Factors >::const_view_t>( img._view );
476 /////////////////////////////////////////////////////////////////////////////////////////
477 /// \ingroup ImageViewSTLAlgorithmsFillPixels
478 /// \brief std::fill for subchroma_image views
479 /////////////////////////////////////////////////////////////////////////////////////////
480 template< typename Locator
484 void fill_pixels( const subchroma_image_view< Locator, Factors >& view
488 using channel_t = typename subchroma_image
492 >::plane_view_t::value_type;
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 )));
499 /////////////////////////////////////////////////////////////////////////////////////////
500 /// \ingroup ImageViewConstructors
501 /// \brief Creates a subchroma view from a raw memory
502 /////////////////////////////////////////////////////////////////////////////////////////
503 template< typename Pixel
506 typename subchroma_image< Pixel
508 >::view_t subchroma_view( std::size_t y_width
509 , std::size_t y_height
510 , unsigned char* y_base
513 using scaling_factors_t = detail::scaling_factors
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
520 std::size_t y_channel_size = 1;
521 std::size_t u_channel_size = 1;
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 )
527 using plane_view_t = typename subchroma_image<Pixel, Factors>::plane_view_t;
529 plane_view_t y_plane = interleaved_view( y_width
531 , (typename plane_view_t::value_type*) y_base // pixels
532 , y_width // rowsize_in_bytes
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
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
547 using defer_fn_t = subchroma_image_deref_fn
549 typename subchroma_image<Pixel, Factors>::pixel_locator_t,
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 )
559 using locator_t = typename subchroma_image<Pixel, Factors>::locator_t;
561 locator_t locator( point_t( 0, 0 ) // p
562 , point_t( 1, 1 ) // step
566 using view_t = typename subchroma_image<Pixel, Factors>::view_t;
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 )