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:
committed by
Stefan Seefeld
parent
85a02eaade
commit
271f5fdf3c
@@ -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
|
||||
>
|
||||
|
||||
77
include/boost/gil/premultiply.hpp
Normal file
77
include/boost/gil/premultiply.hpp
Normal 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
|
||||
Reference in New Issue
Block a user