Added a lot of premultiply_alpha functions to attempt to have proper premultiplication of data prior to compositing. There still seem to be some errors in the resulting images, but I am not quite sure what they are yet.

This commit is contained in:
Blake Thompson 2015-01-14 18:29:00 -06:00
parent 42c7d7ddf2
commit 202a0e8e5f
6 changed files with 32 additions and 11 deletions

View file

@ -228,6 +228,8 @@ void demultiply(image_32 & im)
void composite(image_32 & dst, image_32 & src, mapnik::composite_mode_e mode, float opacity)
{
mapnik::premultiply_alpha(dst.data());
mapnik::premultiply_alpha(src.data());
mapnik::composite(dst.data(),src.data(),mode,opacity,0,0);
}

View file

@ -192,15 +192,22 @@ struct tag_setter
throw ImageWriterException("Could not write TIFF - unknown image type provided");
}
inline void operator() (image_data_rgba8 const&) const
inline void operator() (image_data_rgba8 const& data) const
{
TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
TIFFSetField(output_, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(output_, TIFFTAG_SAMPLESPERPIXEL, 4);
//uint16 extras[] = { EXTRASAMPLE_UNASSALPHA };
uint16 extras[] = { EXTRASAMPLE_ASSOCALPHA };
TIFFSetField(output_, TIFFTAG_EXTRASAMPLES, 1, extras);
if (data.get_premultiplied())
{
uint16 extras[] = { EXTRASAMPLE_ASSOCALPHA };
TIFFSetField(output_, TIFFTAG_EXTRASAMPLES, 1, extras);
}
else
{
uint16 extras[] = { EXTRASAMPLE_UNASSALPHA };
TIFFSetField(output_, TIFFTAG_EXTRASAMPLES, 1, extras);
}
if (config_.compression == COMPRESSION_DEFLATE
|| config_.compression == COMPRESSION_ADOBE_DEFLATE
|| config_.compression == COMPRESSION_LZW)

View file

@ -145,6 +145,8 @@ void agg_renderer<T0,T1>::setup(Map const &m)
{
for (unsigned y=0;y<y_steps;++y)
{
premultiply_alpha(*bg_image);
premultiply_alpha(pixmap_.data());
composite(pixmap_.data(),*bg_image, m.background_image_comp_op(), m.background_image_opacity(), x*w, y*h);
}
}
@ -167,10 +169,7 @@ void agg_renderer<T0,T1>::start_map_processing(Map const& map)
template <typename T0, typename T1>
void agg_renderer<T0,T1>::end_map_processing(Map const& )
{
agg::rendering_buffer buf(pixmap_.raw_data(),common_.width_,common_.height_, common_.width_ * 4);
agg::pixfmt_rgba32_pre pixf(buf);
pixf.demultiply();
mapnik::demultiply_alpha(pixmap_.data());
MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: End map processing";
}
@ -280,6 +279,8 @@ void agg_renderer<T0,T1>::end_style_processing(feature_type_style const& st)
util::apply_visitor(visitor, filter_tag);
}
}
mapnik::premultiply_alpha(pixmap_.data());
mapnik::premultiply_alpha(current_buffer_->data());
if (st.comp_op())
{
composite(pixmap_.data(), current_buffer_->data(),
@ -373,6 +374,8 @@ void agg_renderer<T0,T1>::render_marker(pixel_position const& pos,
{
double cx = 0.5 * width;
double cy = 0.5 * height;
mapnik::premultiply_alpha(current_buffer_->data());
mapnik::premultiply_alpha(**marker.get_bitmap_data());
composite(current_buffer_->data(), **marker.get_bitmap_data(),
comp_op, opacity,
std::floor(pos.x - cx + .5),

View file

@ -54,6 +54,8 @@ void agg_renderer<T0,T1>::process(raster_symbolizer const& sym,
sym, feature, prj_trans, common_,
[&](image_data_rgba8 & target, composite_mode_e comp_op, double opacity,
int start_x, int start_y) {
premultiply_alpha(target);
premultiply_alpha(current_buffer_->data());
composite(current_buffer_->data(), target,
comp_op, opacity, start_x, start_y);
}

View file

@ -49,8 +49,7 @@ image_32::image_32(image_32 const& rhs)
image_32::image_32(image_data_rgba8 && data)
: data_(std::move(data)),
painted_(false),
premultiplied_(false) {}
painted_(false) {}
image_32::~image_32() {}

View file

@ -166,7 +166,15 @@ MAPNIK_DECL void composite(image_data_rgba8 & dst, image_data_rgba8 const& src,
pixfmt_type pixf(dst_buffer);
pixf.comp_op(static_cast<agg::comp_op_e>(mode));
agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32, const_rendering_buffer, agg::pixel32_type> pixf_mask(src_buffer);
if (!src.get_premultiplied()) pixf_mask.premultiply();
// DEBUGGING ONLY REMOVE
if (!src.get_premultiplied())
{
throw std::runtime_error("SOURCE MUST BE PREMULTIPLIED FOR COMPOSITING!");
}
if (!dst.get_premultiplied())
{
throw std::runtime_error("DESTINATION MUST BE PREMULTIPLIED FOR COMPOSITING!");
}
renderer_type ren(pixf);
ren.blend_from(pixf_mask,0,dx,dy,unsigned(255*opacity));
}