+ use pre-multiplied pixel format in agg_renderer

(de-multiply in end_map_processing())
+ support for compositing at style level
+ image blur (TODO)
This commit is contained in:
Artem Pavlenko 2012-04-03 13:10:30 +01:00
parent c9a83837a1
commit 81566a8f80
16 changed files with 211 additions and 82 deletions

View file

@ -55,6 +55,8 @@ class MAPNIK_DECL agg_renderer : public feature_style_processor<agg_renderer<T>
{
public:
typedef T buffer_type;
// create with default, empty placement detector
agg_renderer(Map const& m, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
// create with external placement detector, possibly non-empty
@ -65,6 +67,10 @@ public:
void end_map_processing(Map const& map);
void start_layer_processing(layer const& lay, box2d<double> const& query_extent);
void end_layer_processing(layer const& lay);
void start_style_processing(feature_type_style const& st);
void end_style_processing(feature_type_style const& st);
void render_marker(pixel_position const& pos, marker const& marker, agg::trans_affine const& tr, double opacity);
void process(point_symbolizer const& sym,
@ -113,9 +119,13 @@ public:
pixmap_.painted(painted);
}
private:
T & pixmap_;
boost::scoped_ptr<aa_renderer> renderer_;
buffer_type & pixmap_;
buffer_type internal_buffer_;
buffer_type * current_buffer_;
//boost::scoped_ptr<aa_renderer> renderer_;
unsigned width_;
unsigned height_;
double scale_factor_;
@ -127,6 +137,9 @@ private:
box2d<double> query_extent_;
void setup(Map const &m);
void set_current_buffer(bool per_layer = false);
};
}

View file

@ -50,7 +50,11 @@ class MAPNIK_DECL feature_type_style
private:
rules rules_;
filter_mode_e filter_mode_;
// blur
unsigned blur_radius_x_;
unsigned blur_radius_y_;
// comp-op
composite_mode_e comp_op_;
// The rule_ptrs vectors are only valid for the scale_denom_validity_.
double scale_denom_validity_;
rule_ptrs if_rules_;
@ -75,11 +79,19 @@ public:
void set_filter_mode(filter_mode_e mode);
filter_mode_e get_filter_mode() const;
void set_blur_radius_x(unsigned );
void set_blur_radius_y(unsigned );
unsigned blur_radius_x() const;
unsigned blur_radius_y() const;
// compositing
void set_comp_op(composite_mode_e comp_op);
composite_mode_e comp_op() const;
~feature_type_style() {}
private:
void update_rule_cache(double scale_denom);
};
}

View file

@ -65,6 +65,8 @@ public:
void end_map_processing(Map const& map);
void start_layer_processing(layer const& lay, box2d<double> const& query_extent);
void end_layer_processing(layer const& lay);
void start_style_processing(feature_type_style const& st) {}
void end_style_processing(feature_type_style const& st) {}
void render_marker(mapnik::feature_ptr const& feature, unsigned int step, pixel_position const& pos, marker const& marker, const agg::trans_affine & tr, double opacity);
void process(point_symbolizer const& sym,

View file

@ -34,7 +34,7 @@
#include <mapnik/svg/svg_converter.hpp>
#include <mapnik/svg/svg_renderer.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/image_compositing.hpp>
// agg
#define AGG_RENDERING_BUFFER row_ptr_cache<int8u>
#include "agg_rendering_buffer.h"
@ -68,7 +68,7 @@
#include "agg_renderer_outline_image.h"
#include "agg_vpgen_clip_polyline.h"
#include "agg_arrowhead.h"
#include "agg_blur.h"
// boost
#include <boost/utility.hpp>
@ -115,7 +115,8 @@ template <typename T>
agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y)
: feature_style_processor<agg_renderer>(m, scale_factor),
pixmap_(pixmap),
renderer_(new aa_renderer),
internal_buffer_(pixmap_.width(),pixmap_.height()),
current_buffer_(&pixmap),
width_(pixmap_.width()),
height_(pixmap_.height()),
scale_factor_(scale_factor),
@ -133,7 +134,8 @@ agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, boost::shared_ptr<label_
double scale_factor, unsigned offset_x, unsigned offset_y)
: feature_style_processor<agg_renderer>(m, scale_factor),
pixmap_(pixmap),
renderer_(),
internal_buffer_(pixmap_.width(),pixmap_.height()),
current_buffer_(&pixmap),
width_(pixmap_.width()),
height_(pixmap_.height()),
scale_factor_(scale_factor),
@ -197,6 +199,9 @@ void agg_renderer<T>::start_map_processing(Map const& map)
template <typename T>
void agg_renderer<T>::end_map_processing(Map const& )
{
agg::rendering_buffer buf(current_buffer_->raw_data(),width_,height_, width_ * 4);
aa_renderer::pixel_format_type pixf(buf);
pixf.demultiply();
#ifdef MAPNIK_DEBUG
std::clog << "end map processing\n";
#endif
@ -210,6 +215,8 @@ void agg_renderer<T>::start_layer_processing(layer const& lay, box2d<double> con
std::clog << "datasource = " << lay.datasource().get() << "\n";
std::clog << "query_extent = " << query_extent << "\n";
#endif
// set current_buffer
if (lay.clear_label_cache())
{
detector_->clear();
@ -219,18 +226,58 @@ void agg_renderer<T>::start_layer_processing(layer const& lay, box2d<double> con
template <typename T>
void agg_renderer<T>::end_layer_processing(layer const&)
{
{
#ifdef MAPNIK_DEBUG
std::clog << "end layer processing\n";
#endif
}
template <typename T>
void agg_renderer<T>::start_style_processing(feature_type_style const& st)
{
#ifdef MAPNIK_DEBUG
std::clog << "start style processing\n";
#endif
if (st.comp_op() != clear || st.blur_radius_x() > 0 || st.blur_radius_y() > 0)
{
internal_buffer_.set_background(color(0,0,0,0));//
current_buffer_ = &internal_buffer_;
}
else
{
current_buffer_ = &pixmap_;
}
}
template <typename T>
void agg_renderer<T>::end_style_processing(feature_type_style const& st)
{
if (st.blur_radius_x() > 0 || st.blur_radius_y() > 0)
{
agg::rendering_buffer buf(current_buffer_->raw_data(),width_,height_, width_ * 4);
aa_renderer::pixel_format_type pixf(buf);
agg::stack_blur_rgba32(pixf,st.blur_radius_x(),st.blur_radius_y());
composite(pixmap_.data(),current_buffer_->data(), st.comp_op());
}
else if (st.comp_op() != clear)
{
// compositing
composite(pixmap_.data(),current_buffer_->data(), st.comp_op());
}
#ifdef MAPNIK_DEBUG
std::clog << "end style processing\n";
#endif
}
template <typename T>
void agg_renderer<T>::render_marker(pixel_position const& pos, marker const& marker, agg::trans_affine const& tr, double opacity)
{
if (marker.is_vector())
{
typedef agg::pixfmt_rgba32_plain pixfmt;
typedef agg::pixfmt_rgba32 pixfmt;
typedef agg::renderer_base<pixfmt> renderer_base;
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid;
@ -256,11 +303,11 @@ void agg_renderer<T>::render_marker(pixel_position const& pos, marker const& mar
svg_renderer<svg_path_adapter,
agg::pod_bvector<path_attributes>,
renderer_solid,
agg::pixfmt_rgba32_plain> svg_renderer(svg_path,
agg::pixfmt_rgba32> svg_renderer(svg_path,
(*marker.get_vector_data())->attributes());
svg_renderer.render(*ras_ptr, sl, renb, mtx, opacity, bbox);
}
else

View file

@ -48,11 +48,11 @@ void agg_renderer<T>::process(building_symbolizer const& sym,
proj_transform const& prj_trans)
{
typedef coord_transform2<CoordTransform,geometry_type> path_type;
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base;
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
agg::pixfmt_rgba32_plain pixf(buf);
agg::pixfmt_rgba32 pixf(buf);
ren_base renb(pixf);
color const& fill_ = sym.get_fill();

View file

@ -51,16 +51,15 @@ void agg_renderer<T>::process(compositing_symbolizer const& sym,
typedef agg::rgba8 color_type;
typedef agg::order_rgba order_type;
typedef agg::pixel32_type pixel_type;
typedef agg::comp_op_adaptor_rgba<color_type, order_type> blender_type;
typedef agg::comp_op_adaptor_rgba<color_type, order_type> blender_type; // comp blender
typedef agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixfmt_type;
typedef agg::renderer_base<pixfmt_type> renderer_base;
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_type;
color const& fill_ = sym.get_fill();
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
agg::rendering_buffer buf(current_buffer_->raw_data(),width_,height_, width_ * 4);
pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(sym.comp_op()));

View file

@ -55,12 +55,12 @@ void agg_renderer<T>::process(line_pattern_symbolizer const& sym,
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
typedef agg::line_image_pattern<agg::pattern_filter_bilinear_rgba8> pattern_type;
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> renderer_base;
typedef agg::renderer_base<agg::pixfmt_rgba32> renderer_base;
typedef agg::renderer_outline_image<renderer_base, pattern_type> renderer_type;
typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
agg::pixfmt_rgba32_plain pixf(buf);
agg::pixfmt_rgba32 pixf(buf);
std::string filename = path_processor_type::evaluate( *sym.get_filename(), *feature);

View file

@ -60,13 +60,14 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
unsigned b=col.blue();
unsigned a=col.alpha();
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
agg::pixfmt_rgba32_plain pixf(buf);
agg::rendering_buffer buf(current_buffer_->raw_data(),width_,height_, width_ * 4);
//agg::pixfmt_rgba32 pixf(buf);
aa_renderer::pixel_format_type pixf(buf);
box2d<double> ext = query_extent_ * 1.1;
if (sym.get_rasterizer() == RASTERIZER_FAST)
{
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
typedef agg::renderer_base<aa_renderer::pixel_format_type> ren_base;
typedef agg::renderer_outline_aa<ren_base> renderer_type;
typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
@ -98,7 +99,8 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
{
ras_ptr->reset();
set_gamma_method(stroke_, ras_ptr);
renderer_->attach(pixf);
aa_renderer ren;
ren.attach(pixf);
//metawriter_with_properties writer = sym.get_metawriter();
@ -194,8 +196,8 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
}
}
renderer_->color(agg::rgba8(r, g, b, int(a*stroke_.get_opacity())));
renderer_->render(*ras_ptr);
ren.color(agg::rgba8(r, g, b, int(a*stroke_.get_opacity())));
ren.render(*ras_ptr);
}
}

View file

@ -54,7 +54,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
typedef agg::pixfmt_rgba32_plain pixfmt;
typedef agg::pixfmt_rgba32 pixfmt;
typedef agg::renderer_base<pixfmt> renderer_base;
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid;
@ -103,7 +103,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
svg_renderer<svg_path_adapter,
agg::pod_bvector<path_attributes>,
renderer_solid,
agg::pixfmt_rgba32_plain > svg_renderer(svg_path,(*marker)->attributes());
agg::pixfmt_rgba32 > svg_renderer(svg_path,(*marker)->attributes());
for (unsigned i=0; i<feature->num_geometries(); ++i)
{

View file

@ -51,7 +51,7 @@ void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym,
{
typedef agg::conv_clip_polygon<geometry_type> clipped_geometry_type;
typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base;
typedef agg::wrap_mode_repeat wrap_x_type;
typedef agg::wrap_mode_repeat wrap_y_type;
typedef agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32_plain,
@ -68,7 +68,7 @@ void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym,
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
agg::pixfmt_rgba32_plain pixf(buf);
agg::pixfmt_rgba32 pixf(buf);
ren_base renb(pixf);
agg::scanline_u8 sl;

View file

@ -26,6 +26,7 @@
#include <mapnik/agg_helpers.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/polygon_symbolizer.hpp>
#include <mapnik/vertex_converters.hpp>
// agg
#include "agg_basics.h"
@ -33,12 +34,13 @@
#include "agg_pixfmt_rgba.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_u.h"
// for polygon_symbolizer
#include "agg_renderer_scanline.h"
#include "agg_conv_clip_polygon.h"
#include "agg_conv_smooth_poly1.h"
//#include "agg_renderer_scanline.h"
//#include "agg_conv_clip_polygon.h"
//#include "agg_conv_smooth_poly1.h"
// stl
#include <string>
//#include <string>
namespace mapnik {
@ -47,52 +49,47 @@ void agg_renderer<T>::process(polygon_symbolizer const& sym,
mapnik::feature_ptr const& feature,
proj_transform const& prj_trans)
{
color const& fill_ = sym.get_fill();
agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
agg::pixfmt_rgba32_plain pixf(buf);
agg::rendering_buffer buf(current_buffer_->raw_data(),width_,height_, width_ * 4);
aa_renderer::pixel_format_type pixf(buf);
unsigned r=fill_.red();
unsigned g=fill_.green();
unsigned b=fill_.blue();
unsigned a=fill_.alpha();
ras_ptr->reset();
set_gamma_method(sym,ras_ptr);
renderer_->attach(pixf);
aa_renderer ren;
ren.attach(pixf);
//metawriter_with_properties writer = sym.get_metawriter();
box2d<double> inflated_extent = query_extent_ * 1.1;
typedef boost::mpl::vector<smooth> conv_types;
vertex_converter<rasterizer,polygon_symbolizer,conv_types> converter(*ras_ptr,sym);
if (sym.smooth() > 0.0) converter.set<smooth>();
//converter.set<clip_poly>(); //always clip
for (unsigned i=0;i<feature->num_geometries();++i)
{
geometry_type & geom=feature->get_geometry(i);
if (geom.num_points() > 2)
{
if (sym.smooth() > 0.0)
{
typedef agg::conv_clip_polygon<geometry_type> clipped_geometry_type;
typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
typedef agg::conv_smooth_poly1_curve<path_type> smooth_type;
clipped_geometry_type clipped(geom);
clipped.clip_box(inflated_extent.minx(),inflated_extent.miny(),inflated_extent.maxx(),inflated_extent.maxy());
path_type path(t_,clipped,prj_trans);
smooth_type smooth(path);
smooth.smooth_value(sym.smooth());
ras_ptr->add_path(smooth);
}
else
{
typedef agg::conv_clip_polygon<geometry_type> clipped_geometry_type;
typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
clipped_geometry_type clipped(geom);
clipped.clip_box(inflated_extent.minx(),inflated_extent.miny(),inflated_extent.maxx(),inflated_extent.maxy());
path_type path(t_,clipped,prj_trans);
ras_ptr->add_path(path);
}
//if (writer.first) writer.first->add_polygon(path, *feature, t_, writer.second);
typedef agg::conv_clip_polygon<geometry_type> clipped_geometry_type;
typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
clipped_geometry_type clipped(geom);
clipped.clip_box(inflated_extent.minx(),inflated_extent.miny(),inflated_extent.maxx(),inflated_extent.maxy());
path_type path(t_,clipped,prj_trans);
converter.apply(path);
}
}
renderer_->color(agg::rgba8(r, g, b, int(a * sym.get_opacity())));
renderer_->render(*ras_ptr);
color const& fill_ = sym.get_fill();
unsigned r=fill_.red();
unsigned g=fill_.green();
unsigned b=fill_.blue();
unsigned a=fill_.alpha();
ren.color(agg::rgba8(r, g, b, int(a * sym.get_opacity())));
ren.render(*ras_ptr);
}
template void agg_renderer<image_32>::process(polygon_symbolizer const&,

View file

@ -40,7 +40,7 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
scale_factor_,
t_, font_manager_, *detector_, query_extent_);
text_renderer<T> ren(pixmap_, font_manager_, *(font_manager_.get_stroker()));
text_renderer<T> ren(*current_buffer_, font_manager_, *(font_manager_.get_stroker()));
while (helper.next()) {
placements_type &placements = helper.placements();

View file

@ -36,11 +36,18 @@ IMPLEMENT_ENUM( filter_mode_e, filter_mode_strings )
feature_type_style::feature_type_style()
: filter_mode_(FILTER_ALL),
scale_denom_validity_(-1) {}
scale_denom_validity_(-1),
blur_radius_x_(0),
blur_radius_y_(0),
comp_op_(clear)
{}
feature_type_style::feature_type_style(feature_type_style const& rhs, bool deep_copy)
: filter_mode_(rhs.filter_mode_),
scale_denom_validity_(-1)
scale_denom_validity_(-1),
blur_radius_x_(rhs.blur_radius_x_),
blur_radius_y_(rhs.blur_radius_y_),
comp_op_(rhs.comp_op_)
{
if (!deep_copy) {
rules_ = rhs.rules_;
@ -56,8 +63,11 @@ feature_type_style::feature_type_style(feature_type_style const& rhs, bool deep_
feature_type_style& feature_type_style::operator=(feature_type_style const& rhs)
{
if (this == &rhs) return *this;
rules_=rhs.rules_;
rules_=rhs.rules_;
scale_denom_validity_ = -1;
blur_radius_x_ = rhs.blur_radius_x_;
blur_radius_y_ = rhs.blur_radius_y_;
comp_op_ = rhs.comp_op_;
return *this;
}
@ -87,6 +97,35 @@ filter_mode_e feature_type_style::get_filter_mode() const
return filter_mode_;
}
void feature_type_style::set_blur_radius_x(unsigned x)
{
blur_radius_x_= x;
}
void feature_type_style::set_blur_radius_y(unsigned y)
{
blur_radius_y_= y;
}
unsigned feature_type_style::blur_radius_x() const
{
return blur_radius_x_;
}
unsigned feature_type_style::blur_radius_y() const
{
return blur_radius_y_;
}
void feature_type_style::set_comp_op(composite_mode_e comp_op)
{
comp_op_ = comp_op;
}
composite_mode_e feature_type_style::comp_op() const
{
return comp_op_;
}
void feature_type_style::update_rule_cache(double scale_denom)
{

View file

@ -88,18 +88,16 @@ void composite(T1 & im, T2 & im2, composite_mode_e mode)
typedef agg::comp_op_adaptor_rgba<color, order> blender_type;
typedef agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixfmt_type;
typedef agg::renderer_base<pixfmt_type> renderer_type;
agg::rendering_buffer source(im.getBytes(),im.width(),im.height(),im.width() * 4);
agg::rendering_buffer mask(im2.getBytes(),im2.width(),im2.height(),im2.width() * 4);
agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixf(source);
pixf.premultiply();
agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixf_mask(mask);
pixf.comp_op(static_cast<agg::comp_op_e>(mode));
//agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixf_mask(mask);
agg::pixfmt_rgba32 pixf_mask(mask);
renderer_type ren(pixf);
agg::renderer_base<pixfmt_type> rb(pixf);
rb.blend_from(pixf_mask,0,0,0,255);
ren.blend_from(pixf_mask,0,0,0,255);
}

View file

@ -689,7 +689,7 @@ void scale_image_bilinear8 (Image& target,const Image& source, double x_off_f, d
template <typename Image>
void scale_image_agg (Image& target,const Image& source, scaling_method_e scaling_method, double scale_factor, double x_off_f, double y_off_f, double filter_radius, double ratio)
{
typedef agg::pixfmt_rgba32_plain pixfmt;
typedef agg::pixfmt_rgba32 pixfmt;
typedef agg::renderer_base<pixfmt> renderer_base;
// define some stuff we'll use soon

View file

@ -414,7 +414,27 @@ void map_parser::parse_style(Map & map, xml_node const& sty)
filter_mode_e filter_mode = sty.get_attr<filter_mode_e>("filter-mode", FILTER_ALL);
style.set_filter_mode(filter_mode);
// compositing
optional<std::string> comp_op_name = sty.get_opt_attr<std::string>("comp-op");
if (comp_op_name)
{
composite_mode_e comp_op = comp_op_from_string(*comp_op_name);
style.set_comp_op(comp_op);
}
// blur-x
optional<unsigned> blur_x = sty.get_opt_attr<unsigned>("blur-radius-x");
if (blur_x)
{
style.set_blur_radius_x(*blur_x);
}
// blur-y
optional<unsigned> blur_y = sty.get_opt_attr<unsigned>("blur-radius-y");
if (blur_y)
{
style.set_blur_radius_y(*blur_y);
}
xml_node::const_iterator ruleIter = sty.begin();
xml_node::const_iterator endRule = sty.end();
@ -551,7 +571,7 @@ void map_parser::parse_layer(Map & map, xml_node const& lay)
{
lyr.set_group_by(* group_by);
}
xml_node::const_iterator child = lay.begin();
xml_node::const_iterator end = lay.end();