pixel snap raster markers and svg files loaded from the file system - partially addresses #1316

This commit is contained in:
Dane Springmeyer 2013-03-08 16:24:41 -08:00
parent 5e1a19cfda
commit 2fcd531345
2 changed files with 104 additions and 43 deletions

View file

@ -48,6 +48,7 @@
#include "agg_image_accessors.h" #include "agg_image_accessors.h"
#include "agg_pixfmt_rgba.h" #include "agg_pixfmt_rgba.h"
#include "agg_span_image_filter_rgba.h" #include "agg_span_image_filter_rgba.h"
#include "agg_span_interpolator_linear.h"
// boost // boost
#include <boost/optional.hpp> #include <boost/optional.hpp>
@ -69,7 +70,8 @@ struct vector_markers_rasterizer_dispatch
agg::trans_affine const& marker_trans, agg::trans_affine const& marker_trans,
markers_symbolizer const& sym, markers_symbolizer const& sym,
Detector & detector, Detector & detector,
double scale_factor) double scale_factor,
bool snap_to_pixels)
: buf_(render_buffer), : buf_(render_buffer),
pixf_(buf_), pixf_(buf_),
renb_(pixf_), renb_(pixf_),
@ -79,7 +81,8 @@ struct vector_markers_rasterizer_dispatch
marker_trans_(marker_trans), marker_trans_(marker_trans),
sym_(sym), sym_(sym),
detector_(detector), detector_(detector),
scale_factor_(scale_factor) scale_factor_(scale_factor),
snap_to_pixels_(snap_to_pixels)
{ {
pixf_.comp_op(static_cast<agg::comp_op_e>(sym_.comp_op())); pixf_.comp_op(static_cast<agg::comp_op_e>(sym_.comp_op()));
} }
@ -116,6 +119,12 @@ struct vector_markers_rasterizer_dispatch
if (sym_.get_allow_overlap() || if (sym_.get_allow_overlap() ||
detector_.has_placement(transformed_bbox)) detector_.has_placement(transformed_bbox))
{ {
if (snap_to_pixels_)
{
// https://github.com/mapnik/mapnik/issues/1316
matrix.tx = std::floor(matrix.tx+.5);
matrix.ty = std::floor(matrix.ty+.5);
}
svg_renderer_.render(ras_, sl_, renb_, matrix, sym_.get_opacity(), bbox_); svg_renderer_.render(ras_, sl_, renb_, matrix, sym_.get_opacity(), bbox_);
if (!sym_.get_ignore_placement()) if (!sym_.get_ignore_placement())
{ {
@ -153,6 +162,7 @@ private:
markers_symbolizer const& sym_; markers_symbolizer const& sym_;
Detector & detector_; Detector & detector_;
double scale_factor_; double scale_factor_;
bool snap_to_pixels_;
}; };
template <typename BufferType, typename Rasterizer, typename Detector> template <typename BufferType, typename Rasterizer, typename Detector>
@ -171,7 +181,8 @@ struct raster_markers_rasterizer_dispatch
agg::trans_affine const& marker_trans, agg::trans_affine const& marker_trans,
markers_symbolizer const& sym, markers_symbolizer const& sym,
Detector & detector, Detector & detector,
double scale_factor) double scale_factor,
bool snap_to_pixels)
: buf_(render_buffer), : buf_(render_buffer),
pixf_(buf_), pixf_(buf_),
renb_(pixf_), renb_(pixf_),
@ -180,7 +191,8 @@ struct raster_markers_rasterizer_dispatch
marker_trans_(marker_trans), marker_trans_(marker_trans),
sym_(sym), sym_(sym),
detector_(detector), detector_(detector),
scale_factor_(scale_factor) scale_factor_(scale_factor),
snap_to_pixels_(snap_to_pixels)
{ {
pixf_.comp_op(static_cast<agg::comp_op_e>(sym_.comp_op())); pixf_.comp_op(static_cast<agg::comp_op_e>(sym_.comp_op()));
} }
@ -245,8 +257,33 @@ struct raster_markers_rasterizer_dispatch
void render_raster_marker(agg::trans_affine const& marker_tr, void render_raster_marker(agg::trans_affine const& marker_tr,
double opacity) double opacity)
{ {
typedef agg::pixfmt_rgba32_pre pixfmt_pre;
double width = src_.width(); double width = src_.width();
double height = src_.height(); double height = src_.height();
if (std::fabs(1.0 - scale_factor_) < 0.001
&& (std::fabs(1.0 - marker_tr.sx) < agg::affine_epsilon)
&& (std::fabs(0.0 - marker_tr.shy) < agg::affine_epsilon)
&& (std::fabs(0.0 - marker_tr.shx) < agg::affine_epsilon)
&& (std::fabs(1.0 - marker_tr.sy) < agg::affine_epsilon))
{
agg::rendering_buffer src_buffer((unsigned char *)src_.getBytes(),src_.width(),src_.height(),src_.width() * 4);
pixfmt_pre pixf_mask(src_buffer);
renb_.blend_from(pixf_mask,
0,
std::floor(marker_tr.tx + .5),
std::floor(marker_tr.ty + .5),
unsigned(255*sym_.get_opacity()));
}
else
{
typedef agg::image_accessor_clone<pixfmt_pre> img_accessor_type;
typedef agg::span_interpolator_linear<> interpolator_type;
//typedef agg::span_image_filter_rgba_2x2<img_accessor_type,interpolator_type> span_gen_type;
typedef agg::span_image_resample_rgba_affine<img_accessor_type> span_gen_type;
typedef agg::renderer_scanline_aa_alpha<renderer_base,
agg::span_allocator<color_type>,
span_gen_type> renderer_type;
double p[8]; double p[8];
p[0] = 0; p[1] = 0; p[0] = 0; p[1] = 0;
p[2] = width; p[3] = 0; p[2] = width; p[3] = 0;
@ -256,31 +293,31 @@ struct raster_markers_rasterizer_dispatch
marker_tr.transform(&p[2], &p[3]); marker_tr.transform(&p[2], &p[3]);
marker_tr.transform(&p[4], &p[5]); marker_tr.transform(&p[4], &p[5]);
marker_tr.transform(&p[6], &p[7]); marker_tr.transform(&p[6], &p[7]);
ras_.move_to_d(p[0],p[1]);
ras_.line_to_d(p[2],p[3]);
ras_.line_to_d(p[4],p[5]);
ras_.line_to_d(p[6],p[7]);
agg::span_allocator<color_type> sa; agg::span_allocator<color_type> sa;
agg::image_filter_bilinear filter_kernel; agg::image_filter_lut filter;
agg::image_filter_lut filter(filter_kernel, false); filter.calculate(agg::image_filter_bilinear(), true);
agg::rendering_buffer marker_buf((unsigned char *)src_.getBytes(), agg::rendering_buffer marker_buf((unsigned char *)src_.getBytes(),
src_.width(), src_.width(),
src_.height(), src_.height(),
src_.width()*4); src_.width()*4);
agg::pixfmt_rgba32_pre pixf(marker_buf); pixfmt_pre pixf(marker_buf);
typedef agg::image_accessor_clone<agg::pixfmt_rgba32_pre> img_accessor_type;
typedef agg::span_interpolator_linear<agg::trans_affine> interpolator_type;
typedef agg::span_image_filter_rgba_2x2<img_accessor_type,
interpolator_type> span_gen_type;
typedef agg::renderer_scanline_aa_alpha<renderer_base,
agg::span_allocator<color_type>,
span_gen_type> renderer_type;
img_accessor_type ia(pixf); img_accessor_type ia(pixf);
interpolator_type interpolator(agg::trans_affine(p, 0, 0, width, height) ); agg::trans_affine final_tr(p, 0, 0, width, height);
if (snap_to_pixels_)
{
final_tr.tx = std::floor(final_tr.tx+.5);
final_tr.ty = std::floor(final_tr.ty+.5);
}
interpolator_type interpolator(final_tr);
span_gen_type sg(ia, interpolator, filter); span_gen_type sg(ia, interpolator, filter);
renderer_type rp(renb_,sa, sg, unsigned(opacity*255)); renderer_type rp(renb_,sa, sg, unsigned(opacity*255));
ras_.move_to_d(p[0],p[1]);
ras_.line_to_d(p[2],p[3]);
ras_.line_to_d(p[4],p[5]);
ras_.line_to_d(p[6],p[7]);
agg::render_scanlines(ras_, sl_, rp); agg::render_scanlines(ras_, sl_, rp);
} }
}
private: private:
agg::scanline_u8 sl_; agg::scanline_u8 sl_;
@ -293,6 +330,7 @@ private:
markers_symbolizer const& sym_; markers_symbolizer const& sym_;
Detector & detector_; Detector & detector_;
double scale_factor_; double scale_factor_;
bool snap_to_pixels_;
}; };

View file

@ -74,6 +74,9 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
std::string filename = path_processor_type::evaluate(*sym.get_filename(), feature); std::string filename = path_processor_type::evaluate(*sym.get_filename(), feature);
// https://github.com/mapnik/mapnik/issues/1316
bool snap_pixels = !mapnik::marker_cache::instance().is_uri(filename);
if (!filename.empty()) if (!filename.empty())
{ {
boost::optional<marker_ptr> mark = mapnik::marker_cache::instance().find(filename, true); boost::optional<marker_ptr> mark = mapnik::marker_cache::instance().find(filename, true);
@ -120,8 +123,15 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine_translation recenter(-center.x, -center.y);
agg::trans_affine marker_trans = recenter * tr; agg::trans_affine marker_trans = recenter * tr;
buf_type render_buffer(current_buffer_->raw_data(), width_, height_, width_ * 4); buf_type render_buffer(current_buffer_->raw_data(), width_, height_, width_ * 4);
dispatch_type rasterizer_dispatch(render_buffer,svg_renderer,*ras_ptr, dispatch_type rasterizer_dispatch(render_buffer,
bbox, marker_trans, sym, *detector_, scale_factor_); svg_renderer,
*ras_ptr,
bbox,
marker_trans,
sym,
*detector_,
scale_factor_,
snap_pixels);
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer, vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types> CoordTransform, proj_transform, agg::trans_affine, conv_types>
converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_);
@ -153,8 +163,15 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym); bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym);
svg_renderer_type svg_renderer(svg_path, result ? attributes : (*stock_vector_marker)->attributes()); svg_renderer_type svg_renderer(svg_path, result ? attributes : (*stock_vector_marker)->attributes());
buf_type render_buffer(current_buffer_->raw_data(), width_, height_, width_ * 4); buf_type render_buffer(current_buffer_->raw_data(), width_, height_, width_ * 4);
dispatch_type rasterizer_dispatch(render_buffer,svg_renderer,*ras_ptr, dispatch_type rasterizer_dispatch(render_buffer,
bbox, marker_trans, sym, *detector_, scale_factor_); svg_renderer,
*ras_ptr,
bbox,
marker_trans,
sym,
*detector_,
scale_factor_,
snap_pixels);
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer, vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types> CoordTransform, proj_transform, agg::trans_affine, conv_types>
converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_);
@ -184,8 +201,14 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
boost::optional<mapnik::image_ptr> marker = (*mark)->get_bitmap_data(); boost::optional<mapnik::image_ptr> marker = (*mark)->get_bitmap_data();
typedef raster_markers_rasterizer_dispatch<buf_type,rasterizer, detector_type> dispatch_type; typedef raster_markers_rasterizer_dispatch<buf_type,rasterizer, detector_type> dispatch_type;
buf_type render_buffer(current_buffer_->raw_data(), width_, height_, width_ * 4); buf_type render_buffer(current_buffer_->raw_data(), width_, height_, width_ * 4);
dispatch_type rasterizer_dispatch(render_buffer,*ras_ptr, **marker, dispatch_type rasterizer_dispatch(render_buffer,
marker_trans, sym, *detector_, scale_factor_); *ras_ptr,
**marker,
marker_trans,
sym,
*detector_,
scale_factor_,
true /*snap rasters no matter what*/);
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer, vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types> CoordTransform, proj_transform, agg::trans_affine, conv_types>
converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_);