123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578 |
- //
- // Copyright 2013 Christian Henning and Juan V. Puertos
- //
- // Distributed under the Boost Software License, Version 1.0
- // See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt
- //
- #ifndef BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_SUBCHROMA_IMAGE_HPP
- #define BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_SUBCHROMA_IMAGE_HPP
- #include <boost/gil/dynamic_step.hpp>
- #include <boost/gil/image.hpp>
- #include <boost/gil/image_view.hpp>
- #include <boost/gil/point.hpp>
- #include <boost/gil/virtual_locator.hpp>
- #include <boost/gil/detail/mp11.hpp>
- #include <cstddef>
- #include <memory>
- #include <type_traits>
- namespace boost { namespace gil {
- namespace detail {
- template< int J, int A, int B>
- struct scaling_factors
- {
- static_assert(std::integral_constant<int, J>::value == 4, "");
- static_assert(
- std::integral_constant<int, A>::value == 4 ||
- std::integral_constant<int, A>::value == 2 ||
- std::integral_constant<int, A>::value == 1,
- "");
- static_assert(
- std::integral_constant<int, B>::value == 4 ||
- std::integral_constant<int, B>::value == 2 ||
- std::integral_constant<int, B>::value == 1 ||
- std::integral_constant<int, B>::value == 0,
- "");
- static constexpr int ss_X =
- std::integral_constant<int, J>::value / std::integral_constant<int, A>::value;
- static constexpr int ss_Y =
- mp11::mp_if_c
- <
- std::integral_constant<int, B>::value == 0,
- std::integral_constant<int, 2>,
- mp11::mp_if_c
- <
- std::integral_constant<int, A>::value == std::integral_constant<int, B>::value,
- std::integral_constant<int, 1>,
- std::integral_constant<int, 4>
- >
- >::value;
- };
- } // namespace detail
- ////////////////////////////////////////////////////////////////////////////////////////
- /// \class subchroma_image_deref_fn
- /// \ingroup PixelLocatorModel PixelBasedModel
- /// \brief Used for virtual_2D_locator
- ///
- ////////////////////////////////////////////////////////////////////////////////////////
- template< typename Locator
- , typename Factors
- >
- struct subchroma_image_deref_fn
- {
- using plane_locator_t = gray8_view_t::locator;
- using const_t = subchroma_image_deref_fn<Locator, Factors>;
- using value_type = typename Locator::value_type;
- using reference = value_type;
- using const_reference = value_type;
- using argument_type = point_t;
- using result_type = reference;
- static const bool is_mutable = false;
- /// default constructor
- subchroma_image_deref_fn() {}
- /// constructor
- subchroma_image_deref_fn( const plane_locator_t& y_locator
- , const plane_locator_t& v_locator
- , const plane_locator_t& u_locator
- )
- : _y_locator( y_locator )
- , _v_locator( v_locator )
- , _u_locator( u_locator )
- {}
- /// operator()
- result_type operator()( const point_t& p ) const
- {
- using scaling_factors_t = detail::scaling_factors
- <
- mp11::mp_at_c<Factors, 0>::value,
- mp11::mp_at_c<Factors, 1>::value,
- mp11::mp_at_c<Factors, 2>::value
- >;
- plane_locator_t y = _y_locator.xy_at( p );
- plane_locator_t v = _v_locator.xy_at( p.x / scaling_factors_t::ss_X, p.y / scaling_factors_t::ss_X );
- plane_locator_t u = _u_locator.xy_at( p.x / scaling_factors_t::ss_X, p.y / scaling_factors_t::ss_X );
- return value_type( at_c< 0 >( *y )
- , at_c< 0 >( *v )
- , at_c< 0 >( *u )
- );
- }
- ///
- const plane_locator_t& y_locator() const { return _y_locator; }
- const plane_locator_t& v_locator() const { return _v_locator; }
- const plane_locator_t& u_locator() const { return _u_locator; }
- private:
- plane_locator_t _y_locator;
- plane_locator_t _v_locator;
- plane_locator_t _u_locator;
- };
- ////////////////////////////////////////////////////////////////////////////////////////
- /// \class subchroma_image_locator_type
- /// \ingroup PixelLocatorModel PixelBasedModel
- /// \brief
- ///
- ////////////////////////////////////////////////////////////////////////////////////////
- template< typename Locator
- , typename Factors
- >
- struct subchroma_image_locator
- {
- using type = virtual_2d_locator
- <
- subchroma_image_deref_fn<Locator, Factors>, // Deref
- false // IsTransposed
- >;
- };
- /////////////////////////////
- // PixelBasedConcept
- /////////////////////////////
- template < typename Locator, typename Factors >
- struct channel_type< subchroma_image_locator< Locator, Factors > >
- : public channel_type< typename subchroma_image_locator< Locator, Factors >::type > {};
- template < typename Locator, typename Factors >
- struct color_space_type< subchroma_image_locator< Locator, Factors > >
- : public color_space_type< typename subchroma_image_locator< Locator, Factors >::type > {};
- template < typename Locator, typename Factors >
- struct channel_mapping_type< subchroma_image_locator< Locator, Factors > >
- : public channel_mapping_type< typename subchroma_image_locator< Locator, Factors >::type > {};
- template < typename Locator, typename Factors >
- struct is_planar< subchroma_image_locator< Locator, Factors > >
- : public is_planar< typename subchroma_image_locator< Locator, Factors >::type > {};
- /////////////////////////////
- // HasDynamicXStepTypeConcept
- /////////////////////////////
- template < typename Locator, typename Factors >
- struct dynamic_x_step_type< subchroma_image_locator< Locator, Factors > >
- {
- using type = typename subchroma_image_locator<Locator, Factors>::type;
- };
- /////////////////////////////
- // HasDynamicYStepTypeConcept
- /////////////////////////////
- template < typename Locator, typename Factors >
- struct dynamic_y_step_type< subchroma_image_locator< Locator, Factors > >
- {
- using type = typename subchroma_image_locator<Locator, Factors>::type;
- };
- /////////////////////////////
- // HasTransposedTypeConcept
- /////////////////////////////
- template < typename Locator, typename Factors >
- struct transposed_type< subchroma_image_locator< Locator, Factors > >
- {
- using type = typename subchroma_image_locator<Locator, Factors>::type;
- };
- //////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////
- /// \class subchroma_image_view
- /// \ingroup ImageViewModel PixelBasedModel
- /// \brief A lightweight object that interprets a subchroma image.
- ///
- ////////////////////////////////////////////////////////////////////////////////////////
- template
- <
- typename Locator,
- typename Factors = mp11::mp_list_c<int, 4, 4, 4>
- >
- class subchroma_image_view : public image_view<Locator>
- {
- public:
- using locator = Locator;
- using deref_fn_t = typename locator::deref_fn_t;
- using plane_locator_t = typename deref_fn_t::plane_locator_t;
- using const_t = subchroma_image_view<Locator, Factors>;
- using plane_view_t = image_view<plane_locator_t>;
- /// default constructor
- subchroma_image_view()
- : image_view< Locator >()
- {}
- /// constructor
- subchroma_image_view( const point_t& y_dimensions
- , const point_t& v_dimensions
- , const point_t& u_dimensions
- , const Locator& locator
- )
- : image_view< Locator >( y_dimensions, locator )
- , _y_dimensions( y_dimensions )
- , _v_dimensions( v_dimensions )
- , _u_dimensions( u_dimensions )
- {}
- /// copy constructor
- template< typename Subchroma_View >
- subchroma_image_view( const Subchroma_View& v )
- : image_view< locator >( v )
- {}
- const point_t& v_ssfactors() const { return point_t( get_deref_fn().vx_ssfactor(), get_deref_fn().vx_ssfactor() ); }
- const point_t& u_ssfactors() const { return point_t( get_deref_fn().ux_ssfactor(), get_deref_fn().ux_ssfactor() ); }
- const point_t& y_dimension() const { return _y_dimensions; }
- const point_t& v_dimension() const { return _v_dimensions; }
- const point_t& u_dimension() const { return _u_dimensions; }
- const plane_locator_t& y_plane() const { return get_deref_fn().y_locator(); }
- const plane_locator_t& v_plane() const { return get_deref_fn().v_locator(); }
- const plane_locator_t& u_plane() const { return get_deref_fn().u_locator(); }
- const plane_view_t y_plane_view() const { return plane_view_t( _y_dimensions, y_plane() ); }
- const plane_view_t v_plane_view() const { return plane_view_t( _v_dimensions, v_plane() ); }
- const plane_view_t u_plane_view() const { return plane_view_t( _u_dimensions, u_plane() ); }
- private:
- const deref_fn_t& get_deref_fn() const { return this->pixels().deref_fn(); }
- private:
- point_t _y_dimensions;
- point_t _v_dimensions;
- point_t _u_dimensions;
- };
- /////////////////////////////
- // PixelBasedConcept
- /////////////////////////////
- template < typename Locator, typename Factors >
- struct channel_type< subchroma_image_view< Locator, Factors > >
- : public channel_type< Locator > {};
- template < typename Locator, typename Factors >
- struct color_space_type< subchroma_image_view< Locator, Factors > >
- : public color_space_type< Locator > {};
- template < typename Locator, typename Factors >
- struct channel_mapping_type< subchroma_image_view< Locator, Factors > >
- : public channel_mapping_type< Locator > {};
- template < typename Locator, typename Factors >
- struct is_planar< subchroma_image_view< Locator, Factors > >
- : public is_planar< Locator > {};
- /////////////////////////////
- // HasDynamicXStepTypeConcept
- /////////////////////////////
- template < typename Locator, typename Factors >
- struct dynamic_x_step_type< subchroma_image_view< Locator, Factors > >
- {
- using type = image_view<typename dynamic_x_step_type<Locator>::type>;
- };
- /////////////////////////////
- // HasDynamicYStepTypeConcept
- /////////////////////////////
- template < typename Locator, typename Factors >
- struct dynamic_y_step_type< subchroma_image_view< Locator, Factors > >
- {
- using type = image_view<typename dynamic_y_step_type<Locator>::type>;
- };
- /////////////////////////////
- // HasTransposedTypeConcept
- /////////////////////////////
- template < typename Locator, typename Factors >
- struct transposed_type< subchroma_image_view< Locator, Factors > >
- {
- using type = image_view<typename transposed_type<Locator>::type>;
- };
- ////////////////////////////////////////////////////////////////////////////////////////
- /// \ingroup ImageModel PixelBasedModel
- /// \brief container interface over image view. Models ImageConcept, PixelBasedConcept
- ///
- /// A subchroma image holds a bunch of planes which don't need to have the same resolution.
- ///
- ////////////////////////////////////////////////////////////////////////////////////////
- template
- <
- typename Pixel,
- typename Factors = mp11::mp_list_c<int, 4, 4, 4>,
- typename Allocator = std::allocator<unsigned char>
- >
- class subchroma_image : public detail::scaling_factors
- <
- mp11::mp_at_c<Factors, 0>::value,
- mp11::mp_at_c<Factors, 1>::value,
- mp11::mp_at_c<Factors, 2>::value
- >
- {
- private:
- using parent_t = detail::scaling_factors
- <
- mp11::mp_at_c<Factors, 0>::value,
- mp11::mp_at_c<Factors, 1>::value,
- mp11::mp_at_c<Factors, 2>::value
- >;
- public:
- using channel_t = typename channel_type<Pixel>::type;
- using pixel_t = pixel<channel_t, gray_layout_t>;
- using plane_image_t = image<pixel_t, false, Allocator>;
- using plane_view_t = typename plane_image_t::view_t;
- using plane_const_view_t = typename plane_image_t::const_view_t;
- using plane_locator_t = typename plane_view_t::locator;
- using pixel_view_t = typename view_type_from_pixel<Pixel>::type;
- using pixel_locator_t = typename pixel_view_t::locator;
- using locator_t = typename subchroma_image_locator
- <
- pixel_locator_t,
- Factors
- >::type;
- using x_coord_t = typename plane_image_t::coord_t;
- using y_coord_t = typename plane_image_t::coord_t;
- using view_t = subchroma_image_view<locator_t, Factors>;
- using const_view_t = typename view_t::const_t;
- /// constructor
- subchroma_image( const x_coord_t y_width
- , const y_coord_t y_height
- )
- : _y_plane( y_width, y_height, 0, Allocator() )
- , _v_plane( y_width / parent_t::ss_X, y_height / parent_t::ss_Y, 0, Allocator() )
- , _u_plane( y_width / parent_t::ss_X, y_height / parent_t::ss_Y, 0, Allocator() )
- {
- init();
- }
- public:
- view_t _view;
- private:
- void init()
- {
- using defer_fn_t = subchroma_image_deref_fn<pixel_locator_t, Factors>;
- defer_fn_t deref_fn( view( _y_plane ).xy_at( 0, 0 )
- , view( _v_plane ).xy_at( 0, 0 )
- , view( _u_plane ).xy_at( 0, 0 )
- );
- // init a virtual_2d_locator
- locator_t locator( point_t( 0, 0 ) // p
- , point_t( 1, 1 ) // step
- , deref_fn
- );
- _view = view_t( _y_plane.dimensions()
- , _v_plane.dimensions()
- , _u_plane.dimensions()
- , locator
- );
- }
- private:
- plane_image_t _y_plane;
- plane_image_t _v_plane;
- plane_image_t _u_plane;
- };
- /////////////////////////////
- // PixelBasedConcept
- /////////////////////////////
- template < typename Pixel, typename Factors, typename Alloc >
- struct channel_type< subchroma_image< Pixel, Factors, Alloc > >
- : channel_type< Pixel > {};
- template < typename Pixel, typename Factors, typename Alloc >
- struct color_space_type< subchroma_image< Pixel, Factors, Alloc > >
- : color_space_type< Pixel > {};
- template < typename Pixel, typename Factors, typename Alloc >
- struct channel_mapping_type< subchroma_image< Pixel, Factors, Alloc > >
- : channel_mapping_type< Pixel > {};
- template < typename Pixel, typename Factors, typename Alloc >
- struct is_planar< subchroma_image< Pixel, Factors, Alloc > >
- : std::integral_constant<bool, false>
- {};
- /////////////////////////////////////////////////////////////////////////////////////////
- /// \name view, const_view
- /// \brief Get an image view from an subchroma_image
- /// \ingroup ImageModel
- /// \brief Returns the non-constant-pixel view of an image
- /////////////////////////////////////////////////////////////////////////////////////////
- template< typename Pixel
- , typename Factors
- >
- inline
- const typename subchroma_image< Pixel, Factors >::view_t& view( subchroma_image< Pixel, Factors >& img )
- {
- return img._view;
- }
- template< typename Pixel
- , typename Factors
- >
- inline
- const typename subchroma_image< Pixel, Factors >::const_view_t const_view( subchroma_image< Pixel, Factors >& img )
- {
- return static_cast< const typename subchroma_image< Pixel, Factors >::const_view_t>( img._view );
- }
- /////////////////////////////////////////////////////////////////////////////////////////
- /// \ingroup ImageViewSTLAlgorithmsFillPixels
- /// \brief std::fill for subchroma_image views
- /////////////////////////////////////////////////////////////////////////////////////////
- template< typename Locator
- , typename Factors
- , typename Pixel
- >
- void fill_pixels( const subchroma_image_view< Locator, Factors >& view
- , const Pixel& value
- )
- {
- using channel_t = typename subchroma_image
- <
- Pixel,
- Factors
- >::plane_view_t::value_type;
- fill_pixels( view.y_plane_view(), channel_t( at_c< 0 >( value )));
- fill_pixels( view.v_plane_view(), channel_t( at_c< 1 >( value )));
- fill_pixels( view.u_plane_view(), channel_t( at_c< 2 >( value )));
- }
- /////////////////////////////////////////////////////////////////////////////////////////
- /// \ingroup ImageViewConstructors
- /// \brief Creates a subchroma view from a raw memory
- /////////////////////////////////////////////////////////////////////////////////////////
- template< typename Pixel
- , typename Factors
- >
- typename subchroma_image< Pixel
- , Factors
- >::view_t subchroma_view( std::size_t y_width
- , std::size_t y_height
- , unsigned char* y_base
- )
- {
- using scaling_factors_t = detail::scaling_factors
- <
- mp11::mp_at_c<Factors, 0>::type::value,
- mp11::mp_at_c<Factors, 1>::type::value,
- mp11::mp_at_c<Factors, 2>::type::value
- >;
- std::size_t y_channel_size = 1;
- std::size_t u_channel_size = 1;
- unsigned char* u_base = y_base + ( y_width * y_height * y_channel_size );
- unsigned char* v_base = u_base + ( y_width / scaling_factors_t::ss_X )
- * u_channel_size;
- using plane_view_t = typename subchroma_image<Pixel, Factors>::plane_view_t;
- plane_view_t y_plane = interleaved_view( y_width
- , y_height
- , (typename plane_view_t::value_type*) y_base // pixels
- , y_width // rowsize_in_bytes
- );
- plane_view_t v_plane = interleaved_view( y_width / scaling_factors_t::ss_X
- , y_height / scaling_factors_t::ss_Y
- , (typename plane_view_t::value_type*) v_base // pixels
- , y_width // rowsize_in_bytes
- );
- plane_view_t u_plane = interleaved_view( y_width / scaling_factors_t::ss_X
- , y_height / scaling_factors_t::ss_Y
- , (typename plane_view_t::value_type*) u_base // pixels
- , y_width // rowsize_in_bytes
- );
- using defer_fn_t = subchroma_image_deref_fn
- <
- typename subchroma_image<Pixel, Factors>::pixel_locator_t,
- Factors
- >;
- defer_fn_t deref_fn( y_plane.xy_at( 0, 0 )
- , v_plane.xy_at( 0, 0 )
- , u_plane.xy_at( 0, 0 )
- );
- using locator_t = typename subchroma_image<Pixel, Factors>::locator_t;
- locator_t locator( point_t( 0, 0 ) // p
- , point_t( 1, 1 ) // step
- , deref_fn
- );
- using view_t = typename subchroma_image<Pixel, Factors>::view_t;
- return view_t( point_t( y_width, y_height )
- , point_t( y_width / scaling_factors_t::ss_X, y_height / scaling_factors_t::ss_Y )
- , point_t( y_width / scaling_factors_t::ss_X, y_height / scaling_factors_t::ss_Y )
- , locator
- );
- }
- } // namespace gil
- } // namespace boost
- #endif
|