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

Initial implementation of premultiplier, which is used when saving TIFF (since by convention this uses premultiplied alpha)

This commit is contained in:
William Gallafent
2014-05-21 21:40:15 +01:00
committed by Stefan Seefeld
parent 85a02eaade
commit 271f5fdf3c
2 changed files with 101 additions and 12 deletions

View File

@@ -30,6 +30,8 @@ extern "C" {
#include <boost/static_assert.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/gil/premultiply.hpp>
#include <boost/gil/extension/io/tiff_tags.hpp>
#include <boost/gil/extension/io/detail/base.hpp>
@@ -177,12 +179,17 @@ private:
typedef typename View::x_iterator x_it_t;
x_it_t row_it = x_it_t( &(*row.begin()));
for( typename View::y_coord_t y = 0; y < view.height(); ++y )
// @todo: is there an overhead to doing this when there's no
// alpha to premultiply by? I'd hope it's optimised out.
auto pm_view = premultiply_view <typename View:: value_type> (view);
for( typename View::y_coord_t y = 0; y < pm_view.height(); ++y )
{
std::copy( view.row_begin( y )
, view.row_end( y )
, row_it
);
std::copy( pm_view.row_begin( y )
, pm_view.row_end( y )
, row_it
);
this->_io_dev.write_scaline( row
, (uint32) y
@@ -192,8 +199,8 @@ private:
// @todo: do optional bit swapping here if you need to...
}
}
template< typename View >
template< typename View>
void write_tiled_data( const View& view
, tiff_tile_width::type tw
, tiff_tile_length::type th
@@ -221,12 +228,16 @@ private:
byte_t* row_addr = reinterpret_cast< byte_t* >( &row.front() );
for( typename View::y_coord_t y = 0; y < view.height(); ++y )
// @todo: is there an overhead to doing this when there's no
// alpha to premultiply by? I'd hope it's optimised out.
auto pm_view = premultiply_view <typename View:: value_type> (view);
for( typename View::y_coord_t y = 0; y < pm_view.height(); ++y )
{
std::copy( view.row_begin( y )
, view.row_end ( y )
, row.begin()
);
std::copy( pm_view.row_begin( y )
, pm_view.row_end( y )
, row.begin()
);
this->_io_dev.write_scaline( row_addr
, (uint32) y
@@ -253,6 +264,7 @@ private:
internal_write_tiled_data(view, tw, th, row, row_it);
}
// @todo: premultiply
template< typename View,
typename IteratorType
>

View File

@@ -0,0 +1,77 @@
#ifndef PREMULTIPLY_HPP
#define PREMULTIPLY_HPP
#include <iostream>
#include <boost/gil/rgba.hpp>
#include <boost/mpl/remove.hpp>
namespace boost { namespace gil {
template <typename SrcP, typename DstP>
struct channel_premultiply {
channel_premultiply (SrcP const & src, DstP & dst)
: src_ (src), dst_ (dst)
{}
template <typename Channel>
void operator () (Channel c) const {
// @todo: need to do a “channel_convert” too, in case the channel types aren't the same?
get_color (dst_, Channel()) = channel_multiply(get_color(src_,Channel()), alpha_or_max(src_));
}
SrcP const & src_;
DstP & dst_;
};
struct premultiply {
template <typename SrcP, typename DstP>
void operator()(const SrcP& src, DstP& dst) const {
typedef typename color_space_type<SrcP>::type src_colour_space_t;
typedef typename color_space_type<DstP>::type dst_colour_space_t;
typedef typename mpl:: remove <src_colour_space_t, alpha_t>:: type src_colour_channels;
mpl:: for_each <src_colour_channels> ( channel_premultiply <SrcP, DstP> (src, dst) );
if (mpl:: contains <dst_colour_space_t, alpha_t>:: value)
get_color (dst,alpha_t()) = alpha_or_max (src);
}
};
template <typename SrcConstRefP, // const reference to the source pixel
typename DstP> // Destination pixel value (models PixelValueConcept)
class premultiply_deref_fn {
public:
typedef premultiply_deref_fn const_t;
typedef DstP value_type;
typedef value_type reference; // read-only dereferencing
typedef const value_type& const_reference;
typedef SrcConstRefP argument_type;
typedef reference result_type;
BOOST_STATIC_CONSTANT(bool, is_mutable=false);
result_type operator()(argument_type srcP) const {
result_type dstP;
premultiply () (srcP,dstP);
return dstP;
}
};
template <typename SrcView, typename DstP>
struct premultiplied_view_type {
private:
typedef typename SrcView::const_t::reference src_pix_ref; // const reference to pixel in SrcView
typedef premultiply_deref_fn<src_pix_ref, DstP> deref_t; // the dereference adaptor that performs color conversion
typedef typename SrcView::template add_deref<deref_t> add_ref_t;
public:
typedef typename add_ref_t::type type; // the color converted view type
static type make(const SrcView& sv) { return add_ref_t::make(sv, deref_t()); }
};
template <typename DstP, typename View> inline
typename premultiplied_view_type<View,DstP>::type premultiply_view(const View& src) {
return premultiplied_view_type<View,DstP>::make(src);
}
}
}
#endif