2
0
mirror of https://github.com/boostorg/gil.git synced 2026-02-18 14:12:10 +00:00

* Added integer optimization for bit8 channels.

* fixed compiler error

[SVN r83605]
This commit is contained in:
Christian Henning
2013-03-27 18:55:31 +00:00
committed by Stefan Seefeld
parent 5a3313d048
commit b844bc1f85
2 changed files with 127 additions and 76 deletions

View File

@@ -25,6 +25,8 @@
#include <boost/mpl/vector_c.hpp>
#include <boost/gil/gil_all.hpp>
#include <boost/gil/extension/toolbox/metafunctions/get_num_bits.hpp>
namespace boost{ namespace gil {
/// \addtogroup ColorNameModel
@@ -41,13 +43,13 @@ struct cr_t {};
/// \}
/// \ingroup ColorSpaceModel
typedef boost::mpl::vector3<ycbcr_color_space::y_t, ycbcr_color_space::cb_t, ycbcr_color_space::cr_t> ycbcr_t;
typedef boost::mpl::vector3<ycbcr_color_space::y_t, ycbcr_color_space::cb_t, ycbcr_color_space::cr_t> ycbcr_601__t;
/// \ingroup LayoutModel
typedef boost::gil::layout<ycbcr_t> ycbcr_layout_t;
typedef boost::gil::layout<ycbcr_601__t> ycbcr_601__layout_t;
//The channel depth is ALWAYS 8bits ofr YCbCr!
GIL_DEFINE_ALL_TYPEDEFS(8, ycbcr)
GIL_DEFINE_ALL_TYPEDEFS(8, ycbcr_601_)
/*
* Source: http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
@@ -58,12 +60,61 @@ GIL_DEFINE_ALL_TYPEDEFS(8, ycbcr)
* @brief Convert YCbCr ITU.BT-601 to RGB.
*/
template<>
struct default_color_converter_impl<ycbcr_t, rgb_t>
struct default_color_converter_impl<ycbcr_601__t, rgb_t>
{
// Note: the RGB_t channels range can be set later on by the users. We dont want to cast to bits8 or anything here.
template < typename SRCP, typename DSTP >
void operator()( const SRCP& src, DSTP& dst ) const
{
typedef channel_type< DSTP >::type dst_channel_t;
convert( src, dst
, boost::is_same< mpl::int_<8>::type, mpl::int_<8>::type >::type()
);
}
private:
// optimization for bit8 channels
template< typename Src_Pixel
, typename Dst_Pixel
>
void convert( const Src_Pixel& src
, Dst_Pixel& dst
, mpl::true_ // is 8 bit channel
) const
{
using namespace boost::algorithm;
using namespace boost::gil::ycbcr_color_space;
typedef channel_type< Src_Pixel >::type src_channel_t;
typedef channel_type< Dst_Pixel >::type dst_channel_t;
src_channel_t y = channel_convert<src_channel_t>( get_color(src, y_t()));
src_channel_t cb = channel_convert<src_channel_t>( get_color(src, cb_t()));
src_channel_t cr = channel_convert<src_channel_t>( get_color(src, cr_t()));
// The intermediate results of the formulas require at least 16bits of precission.
boost::int_fast16_t c = y - 16;
boost::int_fast16_t d = cb - 128;
boost::int_fast16_t e = cr - 128;
boost::int_fast16_t red = clamp((( 298 * c + 409 * e + 128) >> 8), 0, 255);
boost::int_fast16_t green = clamp((( 298 * c - 100 * d - 208 * e + 128) >> 8), 0, 255);
boost::int_fast16_t blue = clamp((( 298 * c + 516 * d + 128) >> 8), 0, 255);
get_color( dst, red_t() ) = (dst_channel_t) red;
get_color( dst, green_t() ) = (dst_channel_t) green;
get_color( dst, blue_t() ) = (dst_channel_t) blue;
}
template< typename Src_Pixel
, typename Dst_Pixel
>
void convert( const Src_Pixel& s
, Dst_Pixel& d
, mpl::false_ // is 8 bit channel
) const
{
using namespace boost::algorithm;
using namespace boost::gil::ycbcr_color_space;
@@ -87,7 +138,7 @@ struct default_color_converter_impl<ycbcr_t, rgb_t>
, 0.0
, 255.0
);
}
}
};
/*
@@ -99,7 +150,7 @@ struct default_color_converter_impl<ycbcr_t, rgb_t>
* @brief Convert RGB to YCbCr ITU.BT-601.
*/
template<>
struct default_color_converter_impl<rgb_t, ycbcr_t>
struct default_color_converter_impl<rgb_t, ycbcr_601__t>
{
template < typename SRCP, typename DSTP >
void operator()( const SRCP& src, DSTP& dst ) const
@@ -120,12 +171,11 @@ struct default_color_converter_impl<rgb_t, ycbcr_t>
get_color( dst, y_t() ) = (dst_channel_t) y;
get_color( dst, cb_t() ) = (dst_channel_t) cb;
get_color( dst, cr_t() ) = (dst_channel_t) cr;
get_color( dst, cr_t() ) = (dst_channel_t) cr;
}
};
} // namespace gil
} // namespace boost
#endif

View File

@@ -69,13 +69,13 @@ struct subsampled_image_deref_fn
/// operator()
typename result_type operator()( const point_t& p ) const
{
auto y = *_y_locator.xy_at( p );
auto v = *_v_locator.xy_at( p.x / _ux_ssfactor, p.y / _uy_ssfactor );
auto u = *_u_locator.xy_at( p.x / _vx_ssfactor, p.y / _vy_ssfactor );
plane_locator_t y = _y_locator.xy_at( p );
plane_locator_t v = _v_locator.xy_at( p.x / _ux_ssfactor, p.y / _uy_ssfactor );
plane_locator_t u = _u_locator.xy_at( p.x / _vx_ssfactor, p.y / _vy_ssfactor );
return value_type( at_c<0>( y )
, at_c<0>( v )
, at_c<0>( u )
return value_type( at_c<0>( *y )
, at_c<0>( *v )
, at_c<0>( *u )
);
}
@@ -212,7 +212,9 @@ public:
typedef typename plane_view_t::locator plane_locator_t;
typedef typename view_type_from_pixel< Pixel >::type pixel_view_t;
typedef typename subsampled_image_locator< typename pixel_view_t::locator >::type locator_t;
typedef typename pixel_view_t::locator pixel_locator_t;
typedef typename subsampled_image_locator< pixel_locator_t >::type locator_t;
typedef typename plane_image_t::coord_t x_coord_t;
typedef typename plane_image_t::coord_t y_coord_t;
@@ -254,7 +256,7 @@ private:
, const std::size_t uy_ssfactor
)
{
typedef subsampled_image_deref_fn< locator_t > defer_fn_t;
typedef subsampled_image_deref_fn< pixel_locator_t > defer_fn_t;
defer_fn_t deref_fn( view( _y_plane ).xy_at( 0, 0 )
, view( _v_plane ).xy_at( 0, 0 )
@@ -328,67 +330,66 @@ void fill_pixels( const subsampled_image_view< Locator >& view
/// \ingroup ImageViewConstructors
/// \brief Creates a subsampled view from a raw memory
/////////////////////////////////////////////////////////////////////////////////////////
//template< typename Pixel >
//typename subsampled_image< Pixel >::view_t subsampled_view( std::size_t y_width
// , std::size_t y_height
// , unsigned char* y_base
// , std::size_t vx_ssfactor = 2
// , std::size_t vy_ssfactor = 2
// , std::size_t ux_ssfactor = 2
// , std::size_t uy_ssfactor = 2
// )
//{
// 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 / ux_ssfactor ) * ( y_height / uy_ssfactor ) * u_channel_size;
//
// typedef subsampled_image< Pixel >::plane_view_t plane_view_t;
//
// plane_view_t y_plane = interleaved_view( y_width
// , y_height
// , (plane_view_t::value_type*) y_base // pixels
// , y_width // rowsize_in_bytes
// );
//
// plane_view_t v_plane = interleaved_view( y_width / vx_ssfactor
// , y_height / vy_ssfactor
// , (plane_view_t::value_type*) v_base // pixels
// , y_width // rowsize_in_bytes
// );
//
// plane_view_t u_plane = interleaved_view( y_width / ux_ssfactor
// , y_height / uy_ssfactor
// , (plane_view_t::value_type*) u_base // pixels
// , y_width // rowsize_in_bytes
// );
//
// typedef subsampled_image_deref_fn< subsampled_image< Pixel >::locator_t > defer_fn_t;
// defer_fn_t deref_fn( y_plane.xy_at( 0, 0 )
// , v_plane.xy_at( 0, 0 )
// , u_plane.xy_at( 0, 0 )
// , vx_ssfactor
// , vy_ssfactor
// , ux_ssfactor
// , uy_ssfactor
// );
//
//
// typedef subsampled_image< Pixel >::locator_t locator_t;
// locator_t locator( point_t( 0, 0 ) // p
// , point_t( 1, 1 ) // step
// , deref_fn
// );
//
// typedef subsampled_image< Pixel >::view_t view_t;
// return view_t( point_t( y_width, y_height )
// , point_t( y_width / vx_ssfactor, y_height / vy_ssfactor )
// , point_t( y_width / ux_ssfactor, y_height / uy_ssfactor )
// , locator
// );
//}
template< typename Pixel >
typename subsampled_image< Pixel >::view_t subsampled_view( std::size_t y_width
, std::size_t y_height
, unsigned char* y_base
, std::size_t vx_ssfactor = 2
, std::size_t vy_ssfactor = 2
, std::size_t ux_ssfactor = 2
, std::size_t uy_ssfactor = 2
)
{
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 / ux_ssfactor ) * ( y_height / uy_ssfactor ) * u_channel_size;
typedef subsampled_image< Pixel >::plane_view_t plane_view_t;
plane_view_t y_plane = interleaved_view( y_width
, y_height
, (plane_view_t::value_type*) y_base // pixels
, y_width // rowsize_in_bytes
);
plane_view_t v_plane = interleaved_view( y_width / vx_ssfactor
, y_height / vy_ssfactor
, (plane_view_t::value_type*) v_base // pixels
, y_width // rowsize_in_bytes
);
plane_view_t u_plane = interleaved_view( y_width / ux_ssfactor
, y_height / uy_ssfactor
, (plane_view_t::value_type*) u_base // pixels
, y_width // rowsize_in_bytes
);
typedef subsampled_image_deref_fn< typename subsampled_image< Pixel >::pixel_locator_t > defer_fn_t;
defer_fn_t deref_fn( y_plane.xy_at( 0, 0 )
, v_plane.xy_at( 0, 0 )
, u_plane.xy_at( 0, 0 )
, vx_ssfactor
, vy_ssfactor
, ux_ssfactor
, uy_ssfactor
);
typedef subsampled_image< Pixel >::locator_t locator_t;
locator_t locator( point_t( 0, 0 ) // p
, point_t( 1, 1 ) // step
, deref_fn
);
typedef subsampled_image< Pixel >::view_t view_t;
return view_t( point_t( y_width, y_height )
, point_t( y_width / vx_ssfactor, y_height / vy_ssfactor )
, point_t( y_width / ux_ssfactor, y_height / uy_ssfactor )
, locator
);
}
} // namespace gil
} // namespace boost