Merge pull request #2712 from mapnik/release/image_data_any

Release/image data any
This commit is contained in:
Blake Thompson 2015-02-19 13:56:33 -06:00
commit dc0cfef4bb
221 changed files with 8898 additions and 3168 deletions

1
.gitignore vendored
View file

@ -5,6 +5,7 @@
*.os
*.so
*.a
*.swp
*.dylib
plugins/input/*.input
plugins/input/templates/*.input

View file

@ -1,8 +1,7 @@
#ifndef __MAPNIK_COMPARE_IMAGES_HPP__
#define __MAPNIK_COMPARE_IMAGES_HPP__
#include <mapnik/graphics.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_reader.hpp>
@ -17,19 +16,15 @@ namespace benchmark {
{
throw mapnik::image_reader_exception("Failed to load: " + dest_fn);
}
std::shared_ptr<image_32> image_ptr1 = std::make_shared<image_32>(reader1->width(),reader1->height());
reader1->read(0,0,image_ptr1->data());
std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(src_fn,"png"));
if (!reader2.get())
{
throw mapnik::image_reader_exception("Failed to load: " + src_fn);
}
std::shared_ptr<image_32> image_ptr2 = std::make_shared<image_32>(reader2->width(),reader2->height());
reader2->read(0,0,image_ptr2->data());
image_data_rgba8 const& dest = image_ptr1->data();
image_data_rgba8 const& src = image_ptr2->data();
image_rgba8 const& dest = util::get<image_rgba8>(reader1->read(0,0,reader1->width(), reader1->height()));
image_rgba8 const& src = util::get<image_rgba8>(reader1->read(0,0,reader1->width(), reader1->height()));
unsigned int width = src.width();
unsigned int height = src.height();

View file

@ -1,10 +1,9 @@
#include "bench_framework.hpp"
#include <mapnik/image_util.hpp>
#include <mapnik/graphics.hpp>
class test : public benchmark::test_case
{
mapnik::image_data_rgba8 im_;
mapnik::image_rgba8 im_;
public:
test(mapnik::parameters const& params)
: test_case(params),

View file

@ -3,7 +3,7 @@
class test : public benchmark::test_case
{
std::shared_ptr<image_32> im_;
std::shared_ptr<image_rgba8> im_;
public:
test(mapnik::parameters const& params)
: test_case(params) {
@ -13,14 +13,14 @@ public:
{
throw mapnik::image_reader_exception("Failed to load: " + filename);
}
im_ = std::make_shared<image_32>(reader->width(),reader->height());
reader->read(0,0,im_->data());
im_ = std::make_shared<image_rgba8>(reader->width(),reader->height());
reader->read(0,0,*im_);
}
bool validate() const
{
std::string expected("./benchmark/data/multicolor-hextree-expected.png");
std::string actual("./benchmark/data/multicolor-hextree-actual.png");
mapnik::save_to_file(im_->data(),actual, "png8:m=h:z=1");
mapnik::save_to_file(*im_,actual, "png8:m=h:z=1");
return benchmark::compare_images(actual,expected);
}
bool operator()() const
@ -28,7 +28,7 @@ public:
std::string out;
for (std::size_t i=0;i<iterations_;++i) {
out.clear();
out = mapnik::save_to_string(im_->data(),"png8:m=h:z=1");
out = mapnik::save_to_string(*im_,"png8:m=h:z=1");
}
}
return true;

View file

@ -4,7 +4,6 @@
#include <mapnik/vertex.hpp>
#include <mapnik/transform_path_adapter.hpp>
#include <mapnik/view_transform.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/proj_transform.hpp>
@ -37,12 +36,12 @@ void render(mapnik::geometry_type const& geom,
using ren_base = agg::renderer_base<agg::pixfmt_rgba32_plain>;
using renderer = agg::renderer_scanline_aa_solid<ren_base>;
mapnik::vertex_adapter va(geom);
mapnik::image_32 im(256,256);
im.set_background(mapnik::color("white"));
mapnik::image_rgba8 im(256,256);
mapnik::fill(im, mapnik::color("white"));
mapnik::box2d<double> padded_extent = extent;
padded_extent.pad(10);
mapnik::view_transform tr(im.width(),im.height(),padded_extent,0,0);
agg::rendering_buffer buf(im.raw_data(),im.width(),im.height(), im.width() * 4);
agg::rendering_buffer buf(im.getBytes(),im.width(),im.height(), im.getRowSize());
agg::pixfmt_rgba32_plain pixf(buf);
ren_base renb(pixf);
renderer ren(renb);
@ -53,7 +52,7 @@ void render(mapnik::geometry_type const& geom,
ras.add_path(path);
agg::scanline_u8 sl;
agg::render_scanlines(ras, sl, ren);
mapnik::save_to_file(im.data(),name);
mapnik::save_to_file(im,name);
}
class test1 : public benchmark::test_case

View file

@ -1,7 +1,6 @@
#include "bench_framework.hpp"
#include <mapnik/map.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/datasource_cache.hpp>
@ -22,8 +21,8 @@ public:
mapnik::Map m(256,256);
mapnik::load_map(m,xml_);
m.zoom_to_box(extent_);
mapnik::image_32 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_32> ren(m,im);
mapnik::image_rgba8 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m,im);
ren.apply();
//mapnik::save_to_file(im.data(),"test.png");
return true;
@ -35,8 +34,8 @@ public:
m.zoom_to_box(extent_);
for (unsigned i=0;i<iterations_;++i)
{
mapnik::image_32 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_32> ren(m,im);
mapnik::image_rgba8 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m,im);
ren.apply();
}
return true;

View file

@ -2,7 +2,6 @@
#include <mapnik/map.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
@ -55,12 +54,12 @@ public:
} else {
m.zoom_all();
}
mapnik::image_32 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_32> ren(m,im,scale_factor_);
mapnik::image_rgba8 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m,im,scale_factor_);
ren.apply();
if (!preview_.empty()) {
std::clog << "preview available at " << preview_ << "\n";
mapnik::save_to_file(im.data(),preview_);
mapnik::save_to_file(im,preview_);
}
return true;
}
@ -78,8 +77,8 @@ public:
}
for (unsigned i=0;i<iterations_;++i)
{
mapnik::image_32 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_32> ren(m,im,scale_factor_);
mapnik::image_rgba8 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m,im,scale_factor_);
ren.apply();
}
return true;

View file

@ -2,7 +2,6 @@
#include <mapnik/map.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
@ -50,7 +49,7 @@ class test : public benchmark::test_case
std::shared_ptr<mapnik::Map> m_;
double scale_factor_;
std::string preview_;
mutable mapnik::image_32 im_;
mutable mapnik::image_rgba8 im_;
public:
test(mapnik::parameters const& params)
: test_case(params),
@ -94,14 +93,14 @@ public:
mapnik::projection map_proj(m_->srs(),true);
double scale_denom = mapnik::scale_denominator(m_req.scale(),map_proj.is_geographic());
scale_denom *= scale_factor_;
mapnik::agg_renderer<mapnik::image_32> ren(*m_,m_req,variables,im_,scale_factor_);
mapnik::agg_renderer<mapnik::image_rgba8> ren(*m_,m_req,variables,im_,scale_factor_);
ren.start_map_processing(*m_);
std::vector<mapnik::layer> const& layers = m_->layers();
process_layers(ren,m_req,map_proj,layers,scale_denom);
ren.end_map_processing(*m_);
if (!preview_.empty()) {
std::clog << "preview available at " << preview_ << "\n";
mapnik::save_to_file(im_.data(),preview_);
mapnik::save_to_file(im_,preview_);
}
return true;
}
@ -114,20 +113,20 @@ public:
for (unsigned i=0;i<iterations_;++i)
{
mapnik::request m_req(width_,height_,extent_);
mapnik::image_32 im(m_->width(),m_->height());
mapnik::image_rgba8 im(m_->width(),m_->height());
mapnik::attributes variables;
m_req.set_buffer_size(m_->buffer_size());
mapnik::projection map_proj(m_->srs(),true);
double scale_denom = mapnik::scale_denominator(m_req.scale(),map_proj.is_geographic());
scale_denom *= scale_factor_;
mapnik::agg_renderer<mapnik::image_32> ren(*m_,m_req,variables,im,scale_factor_);
mapnik::agg_renderer<mapnik::image_rgba8> ren(*m_,m_req,variables,im,scale_factor_);
ren.start_map_processing(*m_);
std::vector<mapnik::layer> const& layers = m_->layers();
process_layers(ren,m_req,map_proj,layers,scale_denom);
ren.end_map_processing(*m_);
bool diff = false;
mapnik::image_data_rgba8 const& dest = im.data();
mapnik::image_data_rgba8 const& src = im_.data();
mapnik::image_rgba8 const& dest = im;
mapnik::image_rgba8 const& src = im_;
for (unsigned int y = 0; y < height_; ++y)
{
const unsigned int* row_from = src.getRow(y);

View file

@ -57,17 +57,39 @@ void export_color ()
"and an alpha value.\n"
"All values between 0 and 255.\n")
)
.def(init<int,int,int,int,bool>(
( arg("r"), arg("g"), arg("b"), arg("a"), arg("premultiplied") ),
"Creates a new color from its RGB components\n"
"and an alpha value.\n"
"All values between 0 and 255.\n")
)
.def(init<int,int,int>(
( arg("r"), arg("g"), arg("b") ),
"Creates a new color from its RGB components.\n"
"All values between 0 and 255.\n")
)
.def(init<uint32_t>(
( arg("val") ),
"Creates a new color from an unsigned integer.\n"
"All values between 0 and 2^32-1\n")
)
.def(init<uint32_t, bool>(
( arg("val"), arg("premultiplied") ),
"Creates a new color from an unsigned integer.\n"
"All values between 0 and 2^32-1\n")
)
.def(init<std::string>(
( arg("color_string") ),
"Creates a new color from its CSS string representation.\n"
"The string may be a CSS color name (e.g. 'blue')\n"
"or a hex color string (e.g. '#0000ff').\n")
)
.def(init<std::string, bool>(
( arg("color_string"), arg("premultiplied") ),
"Creates a new color from its CSS string representation.\n"
"The string may be a CSS color name (e.g. 'blue')\n"
"or a hex color string (e.g. '#0000ff').\n")
)
.add_property("r",
&color::red,
&color::set_red,
@ -92,6 +114,10 @@ void export_color ()
.def(self != self)
.def_pickle(color_pickle_suite())
.def("__str__",&color::to_string)
.def("set_premultiplied",&color::set_premultiplied)
.def("get_premultiplied",&color::get_premultiplied)
.def("premultiply",&color::premultiply)
.def("demultiply",&color::demultiply)
.def("packed",&color::rgba)
.def("to_hex_string",&color::to_hex_string,
"Returns the hexadecimal representation of this color.\n"

View file

@ -35,11 +35,13 @@
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/graphics.hpp>
#include <mapnik/color.hpp>
#include <mapnik/palette.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_copy.hpp>
#include <mapnik/image_reader.hpp>
#include <mapnik/image_compositing.hpp>
#include <mapnik/image_view_any.hpp>
// cairo
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
@ -49,7 +51,7 @@
#include <cairo.h>
#endif
using mapnik::image_32;
using mapnik::image_any;
using mapnik::image_reader;
using mapnik::get_image_reader;
using mapnik::type_from_filename;
@ -58,22 +60,21 @@ using mapnik::save_to_file;
using namespace boost::python;
// output 'raw' pixels
PyObject* tostring1( image_32 const& im)
PyObject* tostring1( image_any const& im)
{
int size = im.width() * im.height() * 4;
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
#else
::PyString_FromStringAndSize
#endif
((const char*)im.raw_data(),size);
((const char*)im.getBytes(),im.getSize());
}
// encode (png,jpeg)
PyObject* tostring2(image_32 const & im, std::string const& format)
PyObject* tostring2(image_any const & im, std::string const& format)
{
std::string s = mapnik::save_to_string(im.data(), format);
std::string s = mapnik::save_to_string(im, format);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
@ -83,9 +84,9 @@ PyObject* tostring2(image_32 const & im, std::string const& format)
(s.data(),s.size());
}
PyObject* tostring3(image_32 const & im, std::string const& format, mapnik::rgba_palette const& pal)
PyObject* tostring3(image_any const & im, std::string const& format, mapnik::rgba_palette const& pal)
{
std::string s = mapnik::save_to_string(im.data(), format, pal);
std::string s = mapnik::save_to_string(im, format, pal);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
@ -96,66 +97,144 @@ PyObject* tostring3(image_32 const & im, std::string const& format, mapnik::rgba
}
void save_to_file1(mapnik::image_32 const& im, std::string const& filename)
void save_to_file1(mapnik::image_any const& im, std::string const& filename)
{
save_to_file(im.data(),filename);
save_to_file(im,filename);
}
void save_to_file2(mapnik::image_32 const& im, std::string const& filename, std::string const& type)
void save_to_file2(mapnik::image_any const& im, std::string const& filename, std::string const& type)
{
save_to_file(im.data(),filename,type);
save_to_file(im,filename,type);
}
void save_to_file3(mapnik::image_32 const& im, std::string const& filename, std::string const& type, mapnik::rgba_palette const& pal)
void save_to_file3(mapnik::image_any const& im, std::string const& filename, std::string const& type, mapnik::rgba_palette const& pal)
{
save_to_file(im.data(),filename,type,pal);
save_to_file(im,filename,type,pal);
}
bool painted(mapnik::image_32 const& im)
mapnik::image_view_any get_view(mapnik::image_any const& data,unsigned x,unsigned y, unsigned w,unsigned h)
{
return im.painted();
return mapnik::create_view(data,x,y,w,h);
}
bool is_solid(mapnik::image_32 const& im)
bool is_solid(mapnik::image_any const& im)
{
if (im.width() > 0 && im.height() > 0)
return mapnik::is_solid(im);
}
void fill_color(mapnik::image_any & im, mapnik::color const& c)
{
mapnik::fill(im, c);
}
void fill_int(mapnik::image_any & im, int val)
{
mapnik::fill(im, val);
}
void fill_double(mapnik::image_any & im, double val)
{
mapnik::fill(im, val);
}
std::shared_ptr<image_any> copy(mapnik::image_any const& im, mapnik::image_dtype type, double offset, double scaling)
{
return std::make_shared<image_any>(std::move(mapnik::image_copy(im, type, offset, scaling)));
}
unsigned compare(mapnik::image_any const& im1, mapnik::image_any const& im2, double threshold, bool alpha)
{
return mapnik::compare(im1, im2, threshold, alpha);
}
struct get_pixel_visitor
{
get_pixel_visitor(unsigned x, unsigned y)
: x_(x), y_(y) {}
PyObject* operator() (mapnik::image_null const&)
{
mapnik::image_data_rgba8 const & data = im.data();
mapnik::image_data_rgba8::pixel_type const* first_row = data.getRow(0);
mapnik::image_data_rgba8::pixel_type const first_pixel = first_row[0];
for (unsigned y = 0; y < im.height(); ++y)
{
mapnik::image_data_rgba8::pixel_type const * row = data.getRow(y);
for (unsigned x = 0; x < im.width(); ++x)
{
if (first_pixel != row[x])
{
return false;
}
}
}
throw std::runtime_error("Can not return a null image from a pixel (shouldn't have reached here)");
}
return true;
}
unsigned get_pixel(mapnik::image_32 const& im, int x, int y)
{
if (x < static_cast<int>(im.width()) && y < static_cast<int>(im.height()))
PyObject* operator() (mapnik::image_gray32f const& im)
{
mapnik::image_data_rgba8 const & data = im.data();
return data(x,y);
return PyFloat_FromDouble(mapnik::get_pixel<double>(im, x_, y_));
}
PyObject* operator() (mapnik::image_gray64f const& im)
{
return PyFloat_FromDouble(mapnik::get_pixel<double>(im, x_, y_));
}
template <typename T>
PyObject* operator() (T const& im)
{
using pixel_type = typename T::pixel_type;
return PyInt_FromLong(mapnik::get_pixel<pixel_type>(im, x_, y_));
}
private:
unsigned x_;
unsigned y_;
};
PyObject* get_pixel(mapnik::image_any const& im, unsigned x, unsigned y)
{
if (x < static_cast<unsigned>(im.width()) && y < static_cast<unsigned>(im.height()))
{
return mapnik::util::apply_visitor(get_pixel_visitor(x, y), im);
}
PyErr_SetString(PyExc_IndexError, "invalid x,y for image dimensions");
boost::python::throw_error_already_set();
return 0;
}
void set_pixel(mapnik::image_32 & im, unsigned x, unsigned y, mapnik::color const& c)
mapnik::color get_pixel_color(mapnik::image_any const& im, unsigned x, unsigned y)
{
im.setPixel(x, y, c.rgba());
if (x < static_cast<unsigned>(im.width()) && y < static_cast<unsigned>(im.height()))
{
return mapnik::get_pixel<mapnik::color>(im, x, y);
}
PyErr_SetString(PyExc_IndexError, "invalid x,y for image dimensions");
boost::python::throw_error_already_set();
return 0;
}
std::shared_ptr<image_32> open_from_file(std::string const& filename)
void set_pixel_color(mapnik::image_any & im, unsigned x, unsigned y, mapnik::color const& c)
{
if (x >= static_cast<int>(im.width()) && y >= static_cast<int>(im.height()))
{
PyErr_SetString(PyExc_IndexError, "invalid x,y for image dimensions");
boost::python::throw_error_already_set();
return;
}
mapnik::set_pixel(im, x, y, c);
}
void set_pixel_double(mapnik::image_any & im, unsigned x, unsigned y, double val)
{
if (x >= static_cast<int>(im.width()) && y >= static_cast<int>(im.height()))
{
PyErr_SetString(PyExc_IndexError, "invalid x,y for image dimensions");
boost::python::throw_error_already_set();
return;
}
mapnik::set_pixel(im, x, y, val);
}
void set_pixel_int(mapnik::image_any & im, unsigned x, unsigned y, int val)
{
if (x >= static_cast<int>(im.width()) && y >= static_cast<int>(im.height()))
{
PyErr_SetString(PyExc_IndexError, "invalid x,y for image dimensions");
boost::python::throw_error_already_set();
return;
}
mapnik::set_pixel(im, x, y, val);
}
std::shared_ptr<image_any> open_from_file(std::string const& filename)
{
boost::optional<std::string> type = type_from_filename(filename);
if (type)
@ -163,29 +242,24 @@ std::shared_ptr<image_32> open_from_file(std::string const& filename)
std::unique_ptr<image_reader> reader(get_image_reader(filename,*type));
if (reader.get())
{
std::shared_ptr<image_32> image_ptr = std::make_shared<image_32>(reader->width(),reader->height());
reader->read(0,0,image_ptr->data());
return image_ptr;
return std::make_shared<image_any>(std::move(reader->read(0,0,reader->width(),reader->height())));
}
throw mapnik::image_reader_exception("Failed to load: " + filename);
}
throw mapnik::image_reader_exception("Unsupported image format:" + filename);
}
std::shared_ptr<image_32> fromstring(std::string const& str)
std::shared_ptr<image_any> fromstring(std::string const& str)
{
std::unique_ptr<image_reader> reader(get_image_reader(str.c_str(),str.size()));
if (reader.get())
{
std::shared_ptr<image_32> image_ptr = std::make_shared<image_32>(reader->width(),reader->height());
reader->read(0,0,image_ptr->data());
return image_ptr;
return std::make_shared<image_any>(std::move(reader->read(0,0,reader->width(), reader->height())));
}
throw mapnik::image_reader_exception("Failed to load image from buffer" );
}
std::shared_ptr<image_32> frombuffer(PyObject * obj)
std::shared_ptr<image_any> frombuffer(PyObject * obj)
{
void const* buffer=0;
Py_ssize_t buffer_len;
@ -194,32 +268,74 @@ std::shared_ptr<image_32> frombuffer(PyObject * obj)
std::unique_ptr<image_reader> reader(get_image_reader(reinterpret_cast<char const*>(buffer),buffer_len));
if (reader.get())
{
std::shared_ptr<image_32> image_ptr = std::make_shared<image_32>(reader->width(),reader->height());
reader->read(0,0,image_ptr->data());
return image_ptr;
return std::make_shared<image_any>(reader->read(0,0,reader->width(),reader->height()));
}
}
throw mapnik::image_reader_exception("Failed to load image from buffer" );
}
void blend (image_32 & im, unsigned x, unsigned y, image_32 const& im2, float opacity)
void set_grayscale_to_alpha(image_any & im)
{
im.set_rectangle_alpha2(im2.data(),x,y,opacity);
mapnik::set_grayscale_to_alpha(im);
}
void composite(image_32 & dst, image_32 & src, mapnik::composite_mode_e mode, float opacity)
void set_grayscale_to_alpha_c(image_any & im, mapnik::color const& c)
{
mapnik::composite(dst.data(),src.data(),mode,opacity,0,0,false);
mapnik::set_grayscale_to_alpha(im, c);
}
void set_color_to_alpha(image_any & im, mapnik::color const& c)
{
mapnik::set_color_to_alpha(im, c);
}
void set_alpha(image_any & im, float opacity)
{
mapnik::set_alpha(im, opacity);
}
bool premultiplied(image_any &im)
{
return im.get_premultiplied();
}
bool premultiply(image_any & im)
{
return mapnik::premultiply_alpha(im);
}
bool demultiply(image_any & im)
{
return mapnik::demultiply_alpha(im);
}
void clear(image_any & im)
{
mapnik::fill(im, 0);
}
void composite(image_any & dst, image_any & src, mapnik::composite_mode_e mode, float opacity, int dx, int dy)
{
bool demultiply_dst = mapnik::premultiply_alpha(dst);
bool demultiply_src = mapnik::premultiply_alpha(src);
mapnik::composite(dst,src,mode,opacity,dx,dy);
if (demultiply_dst)
{
mapnik::demultiply_alpha(dst);
}
if (demultiply_src)
{
mapnik::demultiply_alpha(src);
}
}
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
std::shared_ptr<image_32> from_cairo(PycairoSurface* py_surface)
std::shared_ptr<image_any> from_cairo(PycairoSurface* py_surface)
{
mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer());
std::shared_ptr<image_32> image_ptr = std::make_shared<image_32>(cairo_image_surface_get_width(&*surface), cairo_image_surface_get_height(&*surface));
cairo_image_to_rgba8(image_ptr->data(), surface);
return image_ptr;
mapnik::image_rgba8 image = mapnik::image_rgba8(cairo_image_surface_get_width(&*surface), cairo_image_surface_get_height(&*surface));
cairo_image_to_rgba8(image, surface);
return std::make_shared<image_any>(std::move(image));
}
#endif
@ -266,31 +382,74 @@ void export_image()
.value("divide", mapnik::divide)
;
class_<image_32,std::shared_ptr<image_32> >("Image","This class represents a 32 bit RGBA image.",init<int,int>())
.def("width",&image_32::width)
.def("height",&image_32::height)
.def("view",&image_32::get_view)
.def("painted",&painted)
enum_<mapnik::image_dtype>("ImageType")
.value("rgba8", mapnik::image_dtype_rgba8)
.value("gray8", mapnik::image_dtype_gray8)
.value("gray8s", mapnik::image_dtype_gray8s)
.value("gray16", mapnik::image_dtype_gray16)
.value("gray16s", mapnik::image_dtype_gray16s)
.value("gray32", mapnik::image_dtype_gray32)
.value("gray32s", mapnik::image_dtype_gray32s)
.value("gray32f", mapnik::image_dtype_gray32f)
.value("gray64", mapnik::image_dtype_gray64)
.value("gray64s", mapnik::image_dtype_gray64s)
.value("gray64f", mapnik::image_dtype_gray64f)
;
class_<image_any,std::shared_ptr<image_any>, boost::noncopyable >("Image","This class represents a image.",init<int,int>())
.def(init<int,int,mapnik::image_dtype>())
.def(init<int,int,mapnik::image_dtype,bool>())
.def(init<int,int,mapnik::image_dtype,bool,bool>())
.def(init<int,int,mapnik::image_dtype,bool,bool,bool>())
.def("width",&image_any::width)
.def("height",&image_any::height)
.def("view",&get_view)
.def("painted",&image_any::painted)
.def("is_solid",&is_solid)
.add_property("background",make_function
(&image_32::get_background,return_value_policy<copy_const_reference>()),
&image_32::set_background, "The background color of the image.")
.def("set_grayscale_to_alpha",&image_32::set_grayscale_to_alpha, "Set the grayscale values to the alpha channel of the Image")
.def("set_color_to_alpha",&image_32::set_color_to_alpha, "Set a given color to the alpha channel of the Image")
.def("set_alpha",&image_32::set_alpha, "Set the overall alpha channel of the Image")
.def("blend",&blend)
.def("fill",&fill_color)
.def("fill",&fill_int)
.def("fill",&fill_double)
.def("set_grayscale_to_alpha",&set_grayscale_to_alpha, "Set the grayscale values to the alpha channel of the Image")
.def("set_grayscale_to_alpha",&set_grayscale_to_alpha_c, "Set the grayscale values to the alpha channel of the Image")
.def("set_color_to_alpha",&set_color_to_alpha, "Set a given color to the alpha channel of the Image")
.def("set_alpha",&set_alpha, "Set the overall alpha channel of the Image")
.def("composite",&composite,
( arg("self"),
arg("image"),
arg("mode")=mapnik::src_over,
arg("opacity")=1.0f
arg("opacity")=1.0f,
arg("dx")=0,
arg("dy")=0
))
.def("premultiplied",&image_32::premultiplied)
.def("premultiply",&image_32::premultiply)
.def("demultiply",&image_32::demultiply)
.def("set_pixel",&set_pixel)
.def("compare",&compare,
( arg("self"),
arg("image"),
arg("threshold")=0.0,
arg("alpha")=true
))
.def("copy",&copy,
( arg("self"),
arg("type"),
arg("offset")=0.0,
arg("scaling")=1.0
))
.add_property("offset",
&image_any::get_offset,
&image_any::set_offset,
"Gets or sets the offset component.\n")
.add_property("scaling",
&image_any::get_scaling,
&image_any::set_scaling,
"Gets or sets the offset component.\n")
.def("premultiplied",&premultiplied)
.def("premultiply",&premultiply)
.def("demultiply",&demultiply)
.def("set_pixel",&set_pixel_color)
.def("set_pixel",&set_pixel_double)
.def("set_pixel",&set_pixel_int)
.def("get_pixel",&get_pixel)
.def("clear",&image_32::clear)
.def("get_pixel_color",&get_pixel_color)
.def("clear",&clear)
//TODO(haoyu) The method name 'tostring' might be confusing since they actually return bytes in Python 3
.def("tostring",&tostring1)

View file

@ -35,26 +35,21 @@
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/image_view.hpp>
#include <mapnik/image_view_any.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/palette.hpp>
#include <mapnik/image_view.hpp>
#include <sstream>
using mapnik::image_data_rgba8;
using mapnik::image_view;
using mapnik::image_view_any;
using mapnik::save_to_file;
// output 'raw' pixels
PyObject* view_tostring1(image_view<image_data_rgba8> const& view)
PyObject* view_tostring1(image_view_any const& view)
{
std::ostringstream ss(std::ios::out|std::ios::binary);
for (unsigned i=0;i<view.height();i++)
{
ss.write(reinterpret_cast<const char*>(view.getRow(i)),
view.width() * sizeof(image_view<image_data_rgba8>::pixel_type));
}
mapnik::view_to_string(view, ss);
return
#if PY_VERSION_HEX >= 0x03000000
::PyBytes_FromStringAndSize
@ -65,7 +60,7 @@ PyObject* view_tostring1(image_view<image_data_rgba8> const& view)
}
// encode (png,jpeg)
PyObject* view_tostring2(image_view<image_data_rgba8> const & view, std::string const& format)
PyObject* view_tostring2(image_view_any const & view, std::string const& format)
{
std::string s = save_to_string(view, format);
return
@ -77,7 +72,7 @@ PyObject* view_tostring2(image_view<image_data_rgba8> const & view, std::string
(s.data(),s.size());
}
PyObject* view_tostring3(image_view<image_data_rgba8> const & view, std::string const& format, mapnik::rgba_palette const& pal)
PyObject* view_tostring3(image_view_any const & view, std::string const& format, mapnik::rgba_palette const& pal)
{
std::string s = save_to_string(view, format, pal);
return
@ -89,41 +84,25 @@ PyObject* view_tostring3(image_view<image_data_rgba8> const & view, std::string
(s.data(),s.size());
}
bool is_solid(image_view<image_data_rgba8> const& view)
bool is_solid(image_view_any const& view)
{
if (view.width() > 0 && view.height() > 0)
{
mapnik::image_view<image_data_rgba8>::pixel_type const* first_row = view.getRow(0);
mapnik::image_view<image_data_rgba8>::pixel_type const first_pixel = first_row[0];
for (unsigned y = 0; y < view.height(); ++y)
{
mapnik::image_view<image_data_rgba8>::pixel_type const * row = view.getRow(y);
for (unsigned x = 0; x < view.width(); ++x)
{
if (first_pixel != row[x])
{
return false;
}
}
}
}
return true;
return mapnik::is_solid(view);
}
void save_view1(image_view<image_data_rgba8> const& view,
void save_view1(image_view_any const& view,
std::string const& filename)
{
save_to_file(view,filename);
}
void save_view2(image_view<image_data_rgba8> const& view,
void save_view2(image_view_any const& view,
std::string const& filename,
std::string const& type)
{
save_to_file(view,filename,type);
}
void save_view3(image_view<image_data_rgba8> const& view,
void save_view3(image_view_any const& view,
std::string const& filename,
std::string const& type,
mapnik::rgba_palette const& pal)
@ -135,9 +114,9 @@ void save_view3(image_view<image_data_rgba8> const& view,
void export_image_view()
{
using namespace boost::python;
class_<image_view<image_data_rgba8> >("ImageView","A view into an image.",no_init)
.def("width",&image_view<image_data_rgba8>::width)
.def("height",&image_view<image_data_rgba8>::height)
class_<image_view_any>("ImageView","A view into an image.",no_init)
.def("width",&image_view_any::width)
.def("height",&image_view_any::height)
.def("is_solid",&is_solid)
.def("tostring",&view_tostring1)
.def("tostring",&view_tostring2)

View file

@ -99,9 +99,9 @@ void export_logger();
#include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/rule.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/value_error.hpp>
#include <mapnik/save_map.hpp>
@ -136,12 +136,16 @@ void clear_cache()
#endif
}
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
#if defined(HAVE_CAIRO)
#include <mapnik/cairo_io.hpp>
#include <mapnik/cairo/cairo_renderer.hpp>
#include <cairo.h>
#endif
#if defined(HAVE_PYCAIRO)
#include <boost/python/type_id.hpp>
#include <boost/python/converter/registry.hpp>
#include <pycairo.h>
#include <cairo.h>
static Pycairo_CAPI_t *Pycairo_CAPI;
static void *extract_surface(PyObject* op)
{
@ -188,19 +192,129 @@ bool python_thread::thread_support = true;
#endif
boost::thread_specific_ptr<PyThreadState> python_thread::state;
struct agg_renderer_visitor_1
{
agg_renderer_visitor_1(mapnik::Map const& m, double scale_factor, unsigned offset_x, unsigned offset_y)
: m_(m), scale_factor_(scale_factor), offset_x_(offset_x), offset_y_(offset_y) {}
template <typename T>
void operator() (T & pixmap)
{
throw std::runtime_error("This image type is not currently supported for rendering.");
}
private:
mapnik::Map const& m_;
double scale_factor_;
unsigned offset_x_;
unsigned offset_y_;
};
template <>
void agg_renderer_visitor_1::operator()<mapnik::image_rgba8> (mapnik::image_rgba8 & pixmap)
{
mapnik::agg_renderer<mapnik::image_rgba8> ren(m_,pixmap,scale_factor_,offset_x_, offset_y_);
ren.apply();
}
struct agg_renderer_visitor_2
{
agg_renderer_visitor_2(mapnik::Map const &m, std::shared_ptr<mapnik::label_collision_detector4> detector,
double scale_factor, unsigned offset_x, unsigned offset_y)
: m_(m), detector_(detector), scale_factor_(scale_factor), offset_x_(offset_x), offset_y_(offset_y) {}
template <typename T>
void operator() (T & pixmap)
{
throw std::runtime_error("This image type is not currently supported for rendering.");
}
private:
mapnik::Map const& m_;
std::shared_ptr<mapnik::label_collision_detector4> detector_;
double scale_factor_;
unsigned offset_x_;
unsigned offset_y_;
};
template <>
void agg_renderer_visitor_2::operator()<mapnik::image_rgba8> (mapnik::image_rgba8 & pixmap)
{
mapnik::agg_renderer<mapnik::image_rgba8> ren(m_,pixmap,detector_, scale_factor_,offset_x_, offset_y_);
ren.apply();
}
struct agg_renderer_visitor_3
{
agg_renderer_visitor_3(mapnik::Map const& m, mapnik::request const& req, mapnik::attributes const& vars,
double scale_factor, unsigned offset_x, unsigned offset_y)
: m_(m), req_(req), vars_(vars), scale_factor_(scale_factor), offset_x_(offset_x), offset_y_(offset_y) {}
template <typename T>
void operator() (T & pixmap)
{
throw std::runtime_error("This image type is not currently supported for rendering.");
}
private:
mapnik::Map const& m_;
mapnik::request const& req_;
mapnik::attributes const& vars_;
double scale_factor_;
unsigned offset_x_;
unsigned offset_y_;
};
template <>
void agg_renderer_visitor_3::operator()<mapnik::image_rgba8> (mapnik::image_rgba8 & pixmap)
{
mapnik::agg_renderer<mapnik::image_rgba8> ren(m_,req_, vars_, pixmap, scale_factor_, offset_x_, offset_y_);
ren.apply();
}
struct agg_renderer_visitor_4
{
agg_renderer_visitor_4(mapnik::Map const& m, double scale_factor, unsigned offset_x, unsigned offset_y,
mapnik::layer const& layer, std::set<std::string>& names)
: m_(m), scale_factor_(scale_factor), offset_x_(offset_x), offset_y_(offset_y),
layer_(layer), names_(names) {}
template <typename T>
void operator() (T & pixmap)
{
throw std::runtime_error("This image type is not currently supported for rendering.");
}
private:
mapnik::Map const& m_;
double scale_factor_;
unsigned offset_x_;
unsigned offset_y_;
mapnik::layer const& layer_;
std::set<std::string> & names_;
};
template <>
void agg_renderer_visitor_4::operator()<mapnik::image_rgba8> (mapnik::image_rgba8 & pixmap)
{
mapnik::agg_renderer<mapnik::image_rgba8> ren(m_,pixmap,scale_factor_,offset_x_, offset_y_);
ren.apply(layer_, names_);
}
void render(mapnik::Map const& map,
mapnik::image_32& image,
mapnik::image_any& image,
double scale_factor = 1.0,
unsigned offset_x = 0u,
unsigned offset_y = 0u)
{
python_unblock_auto_block b;
mapnik::agg_renderer<mapnik::image_32> ren(map,image,scale_factor,offset_x, offset_y);
ren.apply();
mapnik::util::apply_visitor(agg_renderer_visitor_1(map, scale_factor, offset_x, offset_y), image);
}
void render_with_vars(mapnik::Map const& map,
mapnik::image_32& image,
mapnik::image_any& image,
boost::python::dict const& d,
double scale_factor = 1.0,
unsigned offset_x = 0u,
@ -210,25 +324,23 @@ void render_with_vars(mapnik::Map const& map,
mapnik::request req(map.width(),map.height(),map.get_current_extent());
req.set_buffer_size(map.buffer_size());
python_unblock_auto_block b;
mapnik::agg_renderer<mapnik::image_32> ren(map,req,vars,image,scale_factor,offset_x,offset_y);
ren.apply();
mapnik::util::apply_visitor(agg_renderer_visitor_3(map, req, vars, scale_factor, offset_x, offset_y), image);
}
void render_with_detector(
mapnik::Map const& map,
mapnik::image_32 &image,
mapnik::image_any &image,
std::shared_ptr<mapnik::label_collision_detector4> detector,
double scale_factor = 1.0,
unsigned offset_x = 0u,
unsigned offset_y = 0u)
{
python_unblock_auto_block b;
mapnik::agg_renderer<mapnik::image_32> ren(map,image,detector,scale_factor,offset_x,offset_y);
ren.apply();
mapnik::util::apply_visitor(agg_renderer_visitor_2(map, detector, scale_factor, offset_x, offset_y), image);
}
void render_layer2(mapnik::Map const& map,
mapnik::image_32& image,
mapnik::image_any& image,
unsigned layer_idx,
double scale_factor,
unsigned offset_x,
@ -245,9 +357,8 @@ void render_layer2(mapnik::Map const& map,
python_unblock_auto_block b;
mapnik::layer const& layer = layers[layer_idx];
mapnik::agg_renderer<mapnik::image_32> ren(map,image,scale_factor,offset_x,offset_y);
std::set<std::string> names;
ren.apply(layer,names);
mapnik::util::apply_visitor(agg_renderer_visitor_4(map, scale_factor, offset_x, offset_y, layer, names), image);
}
#if defined(HAVE_CAIRO) && defined(HAVE_PYCAIRO)
@ -350,9 +461,9 @@ void render_tile_to_file(mapnik::Map const& map,
std::string const& file,
std::string const& format)
{
mapnik::image_32 image(width,height);
mapnik::image_any image(width,height);
render(map,image,1.0,offset_x, offset_y);
mapnik::save_to_file(image.data(),file,format);
mapnik::save_to_file(image,file,format);
}
void render_to_file1(mapnik::Map const& map,
@ -385,9 +496,9 @@ void render_to_file1(mapnik::Map const& map,
}
else
{
mapnik::image_32 image(map.width(),map.height());
mapnik::image_any image(map.width(),map.height());
render(map,image,1.0,0,0);
mapnik::save_to_file(image.data(),filename,format);
mapnik::save_to_file(image,filename,format);
}
}
@ -404,9 +515,9 @@ void render_to_file2(mapnik::Map const& map,std::string const& filename)
}
else
{
mapnik::image_32 image(map.width(),map.height());
mapnik::image_any image(map.width(),map.height());
render(map,image,1.0,0,0);
mapnik::save_to_file(image.data(),filename);
mapnik::save_to_file(image,filename);
}
}
@ -442,9 +553,9 @@ void render_to_file3(mapnik::Map const& map,
}
else
{
mapnik::image_32 image(map.width(),map.height());
mapnik::image_any image(map.width(),map.height());
render(map,image,scale_factor,0,0);
mapnik::save_to_file(image.data(),filename,format);
mapnik::save_to_file(image,filename,format);
}
}
@ -724,7 +835,7 @@ BOOST_PYTHON_MODULE(_mapnik)
def("render", &render, render_overloads(
"\n"
"Render Map to an AGG image_32 using offsets\n"
"Render Map to an AGG image_any using offsets\n"
"\n"
"Usage:\n"
">>> from mapnik import Map, Image, render, load_map\n"
@ -741,7 +852,7 @@ BOOST_PYTHON_MODULE(_mapnik)
def("render_with_detector", &render_with_detector, render_with_detector_overloads(
"\n"
"Render Map to an AGG image_32 using a pre-constructed detector.\n"
"Render Map to an AGG image_any using a pre-constructed detector.\n"
"\n"
"Usage:\n"
">>> from mapnik import Map, Image, LabelCollisionDetector, render_with_detector, load_map\n"

View file

@ -43,7 +43,6 @@
#include <mapnik/path_expression.hpp>
#include "mapnik_enumeration.hpp"
#include "mapnik_svg.hpp"
#include <mapnik/graphics.hpp>
#include <mapnik/expression_node.hpp>
#include <mapnik/value_error.hpp>
#include <mapnik/marker_cache.hpp> // for known_svg_prefix_

View file

@ -24,7 +24,6 @@
#include <mapnik/layer.hpp>
#include <mapnik/rule.hpp>
#include <mapnik/feature_type_style.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/text/placements/dummy.hpp>
#include <mapnik/text/text_properties.hpp>
@ -37,6 +36,7 @@
#include <mapnik/image_util.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/save_map.hpp>
#include <mapnik/cairo_io.hpp>
#if defined(HAVE_CAIRO)
#include <mapnik/cairo/cairo_renderer.hpp>
@ -305,26 +305,26 @@ int main ( int, char** )
m.zoom_to_box(box2d<double>(-8024477.28459,5445190.38849,-7381388.20071,5662941.44855));
image_32 buf(m.width(),m.height());
agg_renderer<image_32> ren(m,buf);
image_rgba8 buf(m.width(),m.height());
agg_renderer<image_rgba8> ren(m,buf);
ren.apply();
std::string msg("These maps have been rendered using AGG in the current directory:\n");
#ifdef HAVE_JPEG
save_to_file(buf.data(),"demo.jpg","jpeg");
save_to_file(buf,"demo.jpg","jpeg");
msg += "- demo.jpg\n";
#endif
#ifdef HAVE_PNG
save_to_file(buf.data(),"demo.png","png");
save_to_file(buf.data(),"demo256.png","png8");
save_to_file(buf,"demo.png","png");
save_to_file(buf,"demo256.png","png8");
msg += "- demo.png\n";
msg += "- demo256.png\n";
#endif
#ifdef HAVE_TIFF
save_to_file(buf.data(),"demo.tif","tiff");
save_to_file(buf,"demo.tif","tiff");
msg += "- demo.tif\n";
#endif
#ifdef HAVE_WEBP
save_to_file(buf.data(),"demo.webp","webp");
save_to_file(buf,"demo.webp","webp");
msg += "- demo.webp\n";
#endif
msg += "Have a look!\n";
@ -353,7 +353,7 @@ int main ( int, char** )
cairo_surface_write_to_png(&*image_surface, "cairo-demo.png");
// but we can also benefit from quantization by converting
// to a mapnik image object and then saving that
mapnik::image_data_rgba8 im_data(cairo_image_surface_get_width(&*image_surface), cairo_image_surface_get_height(&*image_surface));
mapnik::image_rgba8 im_data(cairo_image_surface_get_width(&*image_surface), cairo_image_surface_get_height(&*image_surface));
cairo_image_to_rgba8(im_data, image_surface);
save_to_file(im_data, "cairo-demo256.png","png8");
cairo_surface_finish(&*image_surface);

View file

@ -22,7 +22,6 @@
#include <boost/bind.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>
@ -42,7 +41,7 @@
#include "mapwidget.hpp"
#include "info_dialog.hpp"
using mapnik::image_32;
using mapnik::image_rgba8;
using mapnik::Map;
using mapnik::layer;
using mapnik::box2d;
@ -480,7 +479,7 @@ void MapWidget::zoomToLevel(int level)
void MapWidget::export_to_file(unsigned ,unsigned ,std::string const&,std::string const&)
{
//image_32 image(width,height);
//image_rgba8 image(width,height);
//agg_renderer renderer(map,image);
//renderer.apply();
//image.saveToFile(filename,type);
@ -497,8 +496,8 @@ void render_agg(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
unsigned width=map.width();
unsigned height=map.height();
image_32 buf(width,height);
mapnik::agg_renderer<image_32> ren(map,buf,scaling_factor);
image_rgba8 buf(width,height);
mapnik::agg_renderer<image_rgba8> ren(map,buf,scaling_factor);
try
{
@ -541,10 +540,9 @@ void render_cairo(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
mapnik::cairo_renderer<mapnik::cairo_ptr> renderer(map, cairo, scaling_factor);
renderer.apply();
}
mapnik::image_data_rgba8 data(map.width(), map.height());
mapnik::image_rgba8 data(map.width(), map.height());
mapnik::cairo_image_to_rgba8(data, image_surface);
image_32 buf(std::move(data));
QImage image((uchar*)buf.raw_data(),buf.width(),buf.height(),QImage::Format_ARGB32);
QImage image((uchar*)data.getBytes(),data.width(),data.height(),QImage::Format_ARGB32);
pix = QPixmap::fromImage(image.rgbSwapped());
#endif
}

View file

@ -201,7 +201,7 @@ struct symbolizer_icon
{
// FIXME!
/*
std::shared_ptr<mapnik::image_data_rgba8> symbol = sym.get_image();
std::shared_ptr<mapnik::image_rgba8> symbol = sym.get_image();
if (symbol)
{
QImage image(symbol->getBytes(),

View file

@ -24,7 +24,7 @@
#define MAPNIK_AGG_PATTERN_SOURCE_HPP
// mapnik
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/util/noncopyable.hpp>
// agg
@ -36,7 +36,7 @@ namespace mapnik
class pattern_source : private util::noncopyable
{
public:
pattern_source(image_data_rgba8 const& pattern, double opacity = 1.0)
pattern_source(image_rgba8 const& pattern, double opacity = 1.0)
: pattern_(pattern),
opacity_(opacity) {}
@ -57,7 +57,7 @@ public:
static_cast<unsigned>(((c >> 24) & 0xff) * opacity_));
}
private:
image_data_rgba8 const& pattern_;
image_rgba8 const& pattern_;
double opacity_;
};
}

View file

@ -66,7 +66,7 @@ void render_vector_marker(SvgRenderer & svg_renderer, RasterizerType & ras, Rend
}
template <typename RendererType, typename RasterizerType>
void render_raster_marker(RendererType renb, RasterizerType & ras, image_data_rgba8 const& src,
void render_raster_marker(RendererType renb, RasterizerType & ras, image_rgba8 const& src,
agg::trans_affine const& tr, double opacity,
float scale_factor, bool snap_to_pixels)
{
@ -81,7 +81,7 @@ void render_raster_marker(RendererType renb, RasterizerType & ras, image_data_rg
&& (std::fabs(0.0 - tr.shx) < agg::affine_epsilon)
&& (std::fabs(1.0 - tr.sy) < agg::affine_epsilon))
{
agg::rendering_buffer src_buffer((unsigned char *)src.getBytes(),src.width(),src.height(),src.width() * 4);
agg::rendering_buffer src_buffer((unsigned char *)src.getBytes(),src.width(),src.height(),src.getRowSize());
pixfmt_pre pixf_mask(src_buffer);
if (snap_to_pixels)
{
@ -125,7 +125,7 @@ void render_raster_marker(RendererType renb, RasterizerType & ras, image_data_rg
agg::rendering_buffer marker_buf((unsigned char *)src.getBytes(),
src.width(),
src.height(),
src.width()*4);
src.getRowSize());
pixfmt_pre pixf(marker_buf);
img_accessor_type ia(pixf);
agg::trans_affine final_tr(p, 0, 0, width, height);

View file

@ -36,7 +36,8 @@
#include <mapnik/request.hpp>
#include <mapnik/symbolizer_enumerations.hpp>
#include <mapnik/renderer_common.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/image_any.hpp>
// stl
#include <memory>
@ -50,10 +51,9 @@ namespace mapnik {
class feature_type_style;
class label_collision_detector4;
class layer;
class marker;
struct marker;
class proj_transform;
struct rasterizer;
class image_32;
}
namespace mapnik {
@ -171,7 +171,7 @@ private:
void setup(Map const& m);
};
extern template class MAPNIK_DECL agg_renderer<image_32>;
extern template class MAPNIK_DECL agg_renderer<image_rgba8>;
} // namespace mapnik

View file

@ -27,7 +27,8 @@
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/color.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/image_compositing.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/gradient.hpp>
@ -121,7 +122,7 @@ private:
class cairo_pattern : private util::noncopyable
{
public:
explicit cairo_pattern(image_data_rgba8 const& data, double opacity = 1.0)
explicit cairo_pattern(image_rgba8 const& data, double opacity = 1.0)
{
int pixels = data.width() * data.height();
const unsigned int *in_ptr = data.getData();
@ -279,7 +280,6 @@ inline cairo_ptr create_context(cairo_surface_ptr const& surface)
class cairo_context : private util::noncopyable
{
public:
cairo_context(cairo_ptr const& cairo);
inline ErrorStatus get_status() const
@ -308,8 +308,8 @@ public:
void paint();
void set_pattern(cairo_pattern const& pattern);
void set_gradient(cairo_gradient const& pattern, box2d<double> const& bbox);
void add_image(double x, double y, image_data_rgba8 & data, double opacity = 1.0);
void add_image(agg::trans_affine const& tr, image_data_rgba8 & data, double opacity = 1.0);
void add_image(double x, double y, image_rgba8 const& data, double opacity = 1.0);
void add_image(agg::trans_affine const& tr, image_rgba8 const& data, double opacity = 1.0);
void set_font_face(cairo_face_manager & manager, face_ptr face);
void set_font_matrix(cairo_matrix_t const& matrix);
void set_matrix(cairo_matrix_t const& matrix);

View file

@ -25,7 +25,7 @@
#define MAPNIK_CAIRO_IMAGE_UTIL_HPP
// mapnik
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/cairo/cairo_context.hpp> // for cairo_surface_ptr
// stl
@ -33,7 +33,7 @@
namespace mapnik {
static inline void cairo_image_to_rgba8(mapnik::image_data_rgba8 & data,
static inline void cairo_image_to_rgba8(mapnik::image_rgba8 & data,
cairo_surface_ptr const& surface)
{
if (cairo_image_surface_get_format(&*surface) != CAIRO_FORMAT_ARGB32)

View file

@ -47,7 +47,7 @@ class feature_impl;
class feature_type_style;
class label_collision_detector4;
class layer;
class marker;
struct marker;
class proj_transform;
class request;
struct pixel_position;

View file

@ -0,0 +1,49 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_CAIRO_IO_HPP
#define MAPNIK_CAIRO_IO_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/map.hpp>
// stl
#include <string>
namespace mapnik {
#if defined(HAVE_CAIRO)
MAPNIK_DECL void save_to_cairo_file(mapnik::Map const& map,
std::string const& filename,
double scale_factor=1.0,
double scale_denominator=0.0);
MAPNIK_DECL void save_to_cairo_file(mapnik::Map const& map,
std::string const& filename,
std::string const& type,
double scale_factor=1.0,
double scale_denominator=0.0);
#endif
} // end ns
#endif // MAPNIK_CAIRO_IO_HPP

View file

@ -44,29 +44,39 @@ private:
std::uint8_t green_;
std::uint8_t blue_;
std::uint8_t alpha_;
bool premultiplied_;
public:
// default ctor
color()
: red_(0xff),
green_(0xff),
blue_(0xff),
alpha_(0xff)
alpha_(0xff),
premultiplied_(false)
{}
color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, std::uint8_t alpha = 0xff)
color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, std::uint8_t alpha = 0xff, bool premultiplied = false)
: red_(red),
green_(green),
blue_(blue),
alpha_(alpha)
alpha_(alpha),
premultiplied_(premultiplied)
{}
color(std::uint32_t rgba, bool premultiplied = false)
: red_(rgba & 0xff),
green_((rgba >> 8) & 0xff),
blue_((rgba >> 16) & 0xff),
alpha_((rgba >> 24) & 0xff),
premultiplied_(premultiplied) {}
// copy ctor
color(const color& rhs)
: red_(rhs.red_),
green_(rhs.green_),
blue_(rhs.blue_),
alpha_(rhs.alpha_)
alpha_(rhs.alpha_),
premultiplied_(rhs.premultiplied_)
{}
// move ctor
@ -74,14 +84,15 @@ public:
: red_(std::move(rhs.red_)),
green_(std::move(rhs.green_)),
blue_(std::move(rhs.blue_)),
alpha_(std::move(rhs.alpha_)) {}
alpha_(std::move(rhs.alpha_)),
premultiplied_(std::move(rhs.premultiplied_)) {}
color( std::string const& str);
color( std::string const& str, bool premultiplied = false);
std::string to_string() const;
std::string to_hex_string() const;
void premultiply();
void demultiply();
bool premultiply();
bool demultiply();
color& operator=(color rhs)
{
@ -135,6 +146,14 @@ public:
{
alpha_ = alpha;
}
inline bool get_premultiplied() const
{
return premultiplied_;
}
inline void set_premultiplied(bool status)
{
premultiplied_ = status;
}
inline unsigned rgba() const
{

View file

@ -1,304 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_GRAPHICS_HPP
#define MAPNIK_GRAPHICS_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/color.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/image_view.hpp>
#include <mapnik/global.hpp>
// stl
#include <algorithm>
#include <string>
#include <memory>
// boost
#include <boost/optional/optional.hpp>
namespace mapnik
{
class MAPNIK_DECL image_32
{
private:
image_data_rgba8 data_;
boost::optional<color> background_;
bool painted_;
bool premultiplied_;
public:
image_32(int width,int height);
image_32(image_32 const& rhs);
image_32(image_data_rgba8 && data);
~image_32();
void painted(bool painted)
{
painted_ = painted;
}
bool painted() const
{
return painted_;
}
bool premultiplied() const
{
return premultiplied_;
}
inline void clear()
{
std::fill(data_.getData(), data_.getData() + data_.width() * data_.height(), 0);
}
boost::optional<color> const& get_background() const;
void set_background(const color& c);
void premultiply();
void demultiply();
void set_grayscale_to_alpha();
void set_color_to_alpha(color const& c);
void set_alpha(float opacity);
inline const image_data_rgba8& data() const
{
return data_;
}
inline image_data_rgba8& data()
{
return data_;
}
inline const unsigned char* raw_data() const
{
return data_.getBytes();
}
inline unsigned char* raw_data()
{
return data_.getBytes();
}
inline image_view<image_data_rgba8> get_view(unsigned x,unsigned y, unsigned w,unsigned h)
{
return image_view<image_data_rgba8>(x,y,w,h,data_);
}
private:
inline bool checkBounds(int x, int y) const
{
return (x >= 0 && x < static_cast<int>(data_.width()) && y >= 0 && y < static_cast<int>(data_.height()));
}
public:
inline void setPixel(int x,int y,unsigned int rgba)
{
if (checkBounds(x,y))
{
data_(x,y)=rgba;
}
}
void composite_pixel(unsigned op, int x,int y,unsigned c, unsigned cover, double opacity);
inline unsigned width() const
{
return data_.width();
}
inline unsigned height() const
{
return data_.height();
}
inline void set_rectangle(int x0,int y0,image_data_rgba8 const& data)
{
box2d<int> ext0(0,0,data_.width(),data_.height());
box2d<int> ext1(x0,y0,x0+data.width(),y0+data.height());
if (ext0.intersects(ext1))
{
box2d<int> box = ext0.intersect(ext1);
for (int y = box.miny(); y < box.maxy(); ++y)
{
unsigned int* row_to = data_.getRow(y);
unsigned int const * row_from = data.getRow(y-y0);
for (int x = box.minx(); x < box.maxx(); ++x)
{
if (row_from[x-x0] & 0xff000000)
{
row_to[x] = row_from[x-x0];
}
}
}
}
}
inline void set_rectangle_alpha(int x0,int y0,const image_data_rgba8& data)
{
box2d<int> ext0(0,0,data_.width(),data_.height());
box2d<int> ext1(x0,y0,x0 + data.width(),y0 + data.height());
if (ext0.intersects(ext1))
{
box2d<int> box = ext0.intersect(ext1);
for (int y = box.miny(); y < box.maxy(); ++y)
{
unsigned int* row_to = data_.getRow(y);
unsigned int const * row_from = data.getRow(y-y0);
for (int x = box.minx(); x < box.maxx(); ++x)
{
unsigned rgba0 = row_to[x];
unsigned rgba1 = row_from[x-x0];
unsigned a1 = (rgba1 >> 24) & 0xff;
if (a1 == 0) continue;
if (a1 == 0xff)
{
row_to[x] = rgba1;
continue;
}
unsigned r1 = rgba1 & 0xff;
unsigned g1 = (rgba1 >> 8 ) & 0xff;
unsigned b1 = (rgba1 >> 16) & 0xff;
unsigned a0 = (rgba0 >> 24) & 0xff;
unsigned r0 = (rgba0 & 0xff) * a0;
unsigned g0 = ((rgba0 >> 8 ) & 0xff) * a0;
unsigned b0 = ((rgba0 >> 16) & 0xff) * a0;
a0 = ((a1 + a0) << 8) - a0*a1;
r0 = ((((r1 << 8) - r0) * a1 + (r0 << 8)) / a0);
g0 = ((((g1 << 8) - g0) * a1 + (g0 << 8)) / a0);
b0 = ((((b1 << 8) - b0) * a1 + (b0 << 8)) / a0);
a0 = a0 >> 8;
row_to[x] = (a0 << 24)| (b0 << 16) | (g0 << 8) | (r0) ;
}
}
}
}
inline void set_rectangle_alpha2(image_data_rgba8 const& data, unsigned x0, unsigned y0, float opacity)
{
box2d<int> ext0(0,0,data_.width(),data_.height());
box2d<int> ext1(x0,y0,x0 + data.width(),y0 + data.height());
if (ext0.intersects(ext1))
{
box2d<int> box = ext0.intersect(ext1);
for (int y = box.miny(); y < box.maxy(); ++y)
{
unsigned int* row_to = data_.getRow(y);
unsigned int const * row_from = data.getRow(y-y0);
for (int x = box.minx(); x < box.maxx(); ++x)
{
unsigned rgba0 = row_to[x];
unsigned rgba1 = row_from[x-x0];
unsigned a1 = int( ((rgba1 >> 24) & 0xff) * opacity );
if (a1 == 0) continue;
if (a1 == 0xff)
{
row_to[x] = rgba1;
continue;
}
unsigned r1 = rgba1 & 0xff;
unsigned g1 = (rgba1 >> 8 ) & 0xff;
unsigned b1 = (rgba1 >> 16) & 0xff;
unsigned a0 = (rgba0 >> 24) & 0xff;
unsigned r0 = rgba0 & 0xff ;
unsigned g0 = (rgba0 >> 8 ) & 0xff;
unsigned b0 = (rgba0 >> 16) & 0xff;
unsigned atmp = a1 + a0 - ((a1 * a0 + 255) >> 8);
if (atmp)
{
r0 = byte((r1 * a1 + (r0 * a0) - ((r0 * a0 * a1 + 255) >> 8)) / atmp);
g0 = byte((g1 * a1 + (g0 * a0) - ((g0 * a0 * a1 + 255) >> 8)) / atmp);
b0 = byte((b1 * a1 + (b0 * a0) - ((b0 * a0 * a1 + 255) >> 8)) / atmp);
}
a0 = byte(atmp);
row_to[x] = (a0 << 24)| (b0 << 16) | (g0 << 8) | (r0) ;
}
}
}
}
template <typename MergeMethod>
inline void merge_rectangle(image_data_rgba8 const& data, unsigned x0, unsigned y0, float opacity)
{
box2d<int> ext0(0,0,data_.width(),data_.height());
box2d<int> ext1(x0,y0,x0 + data.width(),y0 + data.height());
if (ext0.intersects(ext1))
{
box2d<int> box = ext0.intersect(ext1);
for (int y = box.miny(); y < box.maxy(); ++y)
{
unsigned int* row_to = data_.getRow(y);
unsigned int const * row_from = data.getRow(y-y0);
for (int x = box.minx(); x < box.maxx(); ++x)
{
unsigned rgba0 = row_to[x];
unsigned rgba1 = row_from[x-x0];
unsigned a1 = int( ((rgba1 >> 24) & 0xff) * opacity );
if (a1 == 0) continue;
unsigned r1 = rgba1 & 0xff;
unsigned g1 = (rgba1 >> 8 ) & 0xff;
unsigned b1 = (rgba1 >> 16) & 0xff;
unsigned a0 = (rgba0 >> 24) & 0xff;
unsigned r0 = rgba0 & 0xff ;
unsigned g0 = (rgba0 >> 8 ) & 0xff;
unsigned b0 = (rgba0 >> 16) & 0xff;
unsigned a = (a1 * 255 + (255 - a1) * a0 + 127)/255;
MergeMethod::mergeRGB(r0,g0,b0,r1,g1,b1);
r0 = (r1*a1 + (((255 - a1) * a0 + 127)/255) * r0 + 127)/a;
g0 = (g1*a1 + (((255 - a1) * a0 + 127)/255) * g0 + 127)/a;
b0 = (b1*a1 + (((255 - a1) * a0 + 127)/255) * b0 + 127)/a;
row_to[x] = (a << 24)| (b0 << 16) | (g0 << 8) | (r0) ;
}
}
}
}
};
}
#endif // MAPNIK_GRAPHICS_HPP

View file

@ -25,7 +25,7 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/grid/grid_view.hpp>
#include <mapnik/global.hpp>
@ -35,7 +35,6 @@
#include <mapnik/util/conversions.hpp>
// stl
#include <cstdint>
#include <map>
#include <set>
#include <cmath>
@ -49,8 +48,8 @@ template <typename T>
class MAPNIK_DECL hit_grid
{
public:
using value_type = T;
using data_type = mapnik::image_data<value_type>;
using value_type = typename T::type;
using data_type = mapnik::image<T>;
using lookup_type = std::string;
// mapping between pixel id and key
using feature_key_type = std::map<value_type, lookup_type>;
@ -147,12 +146,12 @@ public:
return data_;
}
inline T const * raw_data() const
inline value_type const * raw_data() const
{
return data_.getData();
}
inline T* raw_data()
inline value_type* raw_data()
{
return data_.getData();
}
@ -195,7 +194,7 @@ public:
return height_;
}
inline void set_rectangle(value_type id,image_data_rgba8 const& data,int x0,int y0)
inline void set_rectangle(value_type id,image_rgba8 const& data,int x0,int y0)
{
box2d<int> ext0(0,0,width_,height_);
box2d<int> ext1(x0,y0,x0+data.width(),y0+data.height());
@ -222,10 +221,9 @@ public:
}
}
}
};
using grid = hit_grid<mapnik::value_integer>;
using grid = hit_grid<mapnik::value_integer_pixel>;
}
#endif //MAPNIK_GRID_HPP

View file

@ -41,7 +41,7 @@ namespace mapnik {
template <typename RendererType, typename RasterizerType>
void render_raster_marker(RendererType ren,
RasterizerType & ras,
image_data_rgba8 & src,
image_rgba8 const& src,
mapnik::feature_impl const& feature,
agg::trans_affine const& marker_tr,
double opacity)

View file

@ -49,7 +49,7 @@ namespace mapnik {
class feature_type_style;
class label_collision_detector4;
class layer;
class marker;
struct marker;
class proj_transform;
struct grid_rasterizer;
class request;

View file

@ -23,7 +23,7 @@
#ifndef MAPNIK_GRID_VIEW_HPP
#define MAPNIK_GRID_VIEW_HPP
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/global.hpp>
#include <mapnik/value.hpp>
@ -196,7 +196,7 @@ private:
feature_type const& features_;
};
using grid_view = hit_grid_view<mapnik::image_data<mapnik::value_integer> >;
using grid_view = hit_grid_view<mapnik::image<mapnik::value_integer_pixel> >;
}

View file

@ -25,10 +25,13 @@
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/pixel_types.hpp>
// stl
#include <algorithm>
#include <cassert>
#include <stdexcept>
#include <iostream>
namespace mapnik {
@ -116,45 +119,70 @@ struct image_dimensions
}
template <typename T, std::size_t max_size = 65535>
class image_data
class image
{
public:
using pixel_type = T;
using pixel = T;
using pixel_type = typename T::type;
static constexpr std::size_t pixel_size = sizeof(pixel_type);
image_data(int width, int height, bool initialize = true)
private:
detail::image_dimensions<max_size> dimensions_;
detail::buffer buffer_;
pixel_type *pData_;
double offset_;
double scaling_;
bool premultiplied_alpha_;
bool painted_;
public:
image(int width, int height, bool initialize = true, bool premultiplied = false, bool painted = false)
: dimensions_(width, height),
buffer_(dimensions_.width() * dimensions_.height() * pixel_size),
pData_(reinterpret_cast<pixel_type*>(buffer_.data()))
pData_(reinterpret_cast<pixel_type*>(buffer_.data())),
offset_(0.0),
scaling_(1.0),
premultiplied_alpha_(premultiplied),
painted_(painted)
{
if (pData_ && initialize) std::fill(pData_, pData_ + dimensions_.width() * dimensions_.height(), 0);
}
image_data(image_data<pixel_type> const& rhs)
image(image<T> const& rhs)
: dimensions_(rhs.dimensions_),
buffer_(rhs.buffer_),
pData_(reinterpret_cast<pixel_type*>(buffer_.data()))
pData_(reinterpret_cast<pixel_type*>(buffer_.data())),
offset_(rhs.offset_),
scaling_(rhs.scaling_),
premultiplied_alpha_(rhs.premultiplied_alpha_),
painted_(rhs.painted_)
{}
image_data(image_data<pixel_type> && rhs) noexcept
image(image<T> && rhs) noexcept
: dimensions_(std::move(rhs.dimensions_)),
buffer_(std::move(rhs.buffer_)),
pData_(reinterpret_cast<pixel_type*>(buffer_.data()))
buffer_(std::move(rhs.buffer_)),
pData_(reinterpret_cast<pixel_type*>(buffer_.data())),
offset_(rhs.offset_),
scaling_(rhs.scaling_),
premultiplied_alpha_(rhs.premultiplied_alpha_),
painted_(rhs.painted_)
{
rhs.dimensions_ = { 0, 0 };
rhs.pData_ = nullptr;
}
image_data<pixel_type>& operator=(image_data<pixel_type> rhs)
image<T>& operator=(image<T> rhs)
{
swap(rhs);
return *this;
}
void swap(image_data<pixel_type> & rhs)
void swap(image<T> & rhs)
{
std::swap(dimensions_, rhs.dimensions_);
std::swap(buffer_, rhs.buffer_);
std::swap(offset_, rhs.offset_);
std::swap(scaling_, rhs.scaling_);
std::swap(premultiplied_alpha_, rhs.premultiplied_alpha_);
std::swap(painted_, rhs.painted_);
}
inline pixel_type& operator() (std::size_t i, std::size_t j)
@ -241,16 +269,80 @@ public:
std::copy(buf, buf + (x1 - x0), pData_ + row * dimensions_.width() + x0);
}
private:
detail::image_dimensions<max_size> dimensions_;
detail::buffer buffer_;
pixel_type *pData_;
inline double get_offset() const
{
return offset_;
}
inline void set_offset(double set)
{
offset_ = set;
}
inline double get_scaling() const
{
return scaling_;
}
inline void set_scaling(double set)
{
if (set != 0.0)
{
scaling_ = set;
return;
}
std::clog << "Can not set scaling to 0.0, offset not set." << std::endl;
}
inline bool get_premultiplied() const
{
return premultiplied_alpha_;
}
inline void set_premultiplied(bool set)
{
premultiplied_alpha_ = set;
}
inline void painted(bool painted)
{
painted_ = painted;
}
inline bool painted() const
{
return painted_;
}
};
using image_data_rgba8 = image_data<std::uint32_t>;
using image_data_gray8 = image_data<std::uint8_t> ;
using image_data_gray16 = image_data<std::int16_t>;
using image_data_gray32f = image_data<float>;
}
using image_rgba8 = image<rgba8_t>;
using image_gray8 = image<gray8_t>;
using image_gray8s = image<gray8s_t>;
using image_gray16 = image<gray16_t>;
using image_gray16s = image<gray16s_t>;
using image_gray32 = image<gray32_t>;
using image_gray32s = image<gray32s_t>;
using image_gray32f = image<gray32f_t>;
using image_gray64 = image<gray64_t>;
using image_gray64s = image<gray64s_t>;
using image_gray64f = image<gray64f_t>;
enum image_dtype : std::uint8_t
{
image_dtype_rgba8 = 0,
image_dtype_gray8,
image_dtype_gray8s,
image_dtype_gray16,
image_dtype_gray16s,
image_dtype_gray32,
image_dtype_gray32s,
image_dtype_gray32f,
image_dtype_gray64,
image_dtype_gray64s,
image_dtype_gray64f,
image_dtype_null
};
} // end ns
#endif // MAPNIK_IMAGE_DATA_HPP

View file

@ -0,0 +1,316 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_IMAGE_DATA_ANY_HPP
#define MAPNIK_IMAGE_DATA_ANY_HPP
#include <mapnik/image.hpp>
#include <mapnik/util/variant.hpp>
namespace mapnik {
struct image_null
{
using pixel_type = uint8_t;
unsigned char const* getBytes() const { return nullptr; }
unsigned char* getBytes() { return nullptr;}
unsigned getSize() const { return 0; }
unsigned getRowSize() const { return 0; }
std::size_t width() const { return 0; }
std::size_t height() const { return 0; }
bool painted() const { return false; }
double get_offset() const { return 0.0; }
void set_offset(double) {}
double get_scaling() const { return 1.0; }
void set_scaling(double) {}
bool get_premultiplied() const { return false; }
void set_premultiplied(bool) {}
void set(pixel_type const&) { throw std::runtime_error("Can not set values for null image"); }
pixel_type& operator() (std::size_t, std::size_t)
{
throw std::runtime_error("Can not set or get values for null image");
}
pixel_type const& operator() (std::size_t, std::size_t) const
{
throw std::runtime_error("Can not set or get values for null image");
}
};
using image_base = util::variant<image_null,
image_rgba8,
image_gray8,
image_gray8s,
image_gray16,
image_gray16s,
image_gray32,
image_gray32s,
image_gray32f,
image_gray64,
image_gray64s,
image_gray64f>;
// Forward declaring
struct image_any;
image_any create_image_any(int width,
int height,
image_dtype type = image_dtype_rgba8,
bool initialize = true,
bool premultiplied = false,
bool painted = false);
namespace detail {
struct get_bytes_visitor
{
template <typename T>
unsigned char* operator()(T & data)
{
return data.getBytes();
}
};
struct get_bytes_visitor_const
{
template <typename T>
unsigned char const* operator()(T const& data) const
{
return data.getBytes();
}
};
struct get_width_visitor
{
template <typename T>
std::size_t operator()(T const& data) const
{
return data.width();
}
};
struct get_height_visitor
{
template <typename T>
std::size_t operator()(T const& data) const
{
return data.height();
}
};
struct get_premultiplied_visitor
{
template <typename T>
bool operator()(T const& data) const
{
return data.get_premultiplied();
}
};
struct get_painted_visitor
{
template <typename T>
bool operator()(T const& data) const
{
return data.painted();
}
};
struct get_any_size_visitor
{
template <typename T>
unsigned operator()(T const& data) const
{
return data.getSize();
}
};
struct get_any_row_size_visitor
{
template <typename T>
unsigned operator()(T const& data) const
{
return data.getRowSize();
}
};
struct get_offset_visitor
{
template <typename T>
double operator() (T const& data) const
{
return data.get_offset();
}
};
struct get_scaling_visitor
{
template <typename T>
double operator() (T const& data) const
{
return data.get_scaling();
}
};
struct set_offset_visitor
{
set_offset_visitor(double val)
: val_(val) {}
template <typename T>
void operator() (T & data)
{
data.set_offset(val_);
}
private:
double val_;
};
struct set_scaling_visitor
{
set_scaling_visitor(double val)
: val_(val) {}
template <typename T>
void operator() (T & data)
{
data.set_scaling(val_);
}
private:
double val_;
};
} // namespace detail
struct image_any : image_base
{
image_any() = default;
image_any(int width,
int height,
image_dtype type = image_dtype_rgba8,
bool initialize = true,
bool premultiplied = false,
bool painted = false)
: image_base(std::move(create_image_any(width, height, type, initialize, premultiplied, painted))) {}
template <typename T>
image_any(T && data) noexcept
: image_base(std::move(data)) {}
unsigned char const* getBytes() const
{
return util::apply_visitor(detail::get_bytes_visitor_const(),*this);
}
unsigned char* getBytes()
{
return util::apply_visitor(detail::get_bytes_visitor(),*this);
}
std::size_t width() const
{
return util::apply_visitor(detail::get_width_visitor(),*this);
}
std::size_t height() const
{
return util::apply_visitor(detail::get_height_visitor(),*this);
}
bool get_premultiplied() const
{
return util::apply_visitor(detail::get_premultiplied_visitor(),*this);
}
bool painted() const
{
return util::apply_visitor(detail::get_painted_visitor(),*this);
}
unsigned getSize() const
{
return util::apply_visitor(detail::get_any_size_visitor(),*this);
}
unsigned getRowSize() const
{
return util::apply_visitor(detail::get_any_row_size_visitor(),*this);
}
double get_offset() const
{
return util::apply_visitor(detail::get_offset_visitor(),*this);
}
double get_scaling() const
{
return util::apply_visitor(detail::get_scaling_visitor(),*this);
}
void set_offset(double val)
{
util::apply_visitor(detail::set_offset_visitor(val),*this);
}
void set_scaling(double val)
{
util::apply_visitor(detail::set_scaling_visitor(val),*this);
}
};
inline image_any create_image_any(int width,
int height,
image_dtype type,
bool initialize,
bool premultiplied,
bool painted)
{
switch (type)
{
case image_dtype_gray8:
return image_any(std::move(image_gray8(width, height, initialize, premultiplied, painted)));
case image_dtype_gray8s:
return image_any(std::move(image_gray8s(width, height, initialize, premultiplied, painted)));
case image_dtype_gray16:
return image_any(std::move(image_gray16(width, height, initialize, premultiplied, painted)));
case image_dtype_gray16s:
return image_any(std::move(image_gray16s(width, height, initialize, premultiplied, painted)));
case image_dtype_gray32:
return image_any(std::move(image_gray32(width, height, initialize, premultiplied, painted)));
case image_dtype_gray32s:
return image_any(std::move(image_gray32s(width, height, initialize, premultiplied, painted)));
case image_dtype_gray32f:
return image_any(std::move(image_gray32f(width, height, initialize, premultiplied, painted)));
case image_dtype_gray64:
return image_any(std::move(image_gray64(width, height, initialize, premultiplied, painted)));
case image_dtype_gray64s:
return image_any(std::move(image_gray64s(width, height, initialize, premultiplied, painted)));
case image_dtype_gray64f:
return image_any(std::move(image_gray64f(width, height, initialize, premultiplied, painted)));
case image_dtype_null:
return image_any(std::move(image_null()));
case image_dtype_rgba8:
default:
return image_any(std::move(image_rgba8(width, height, initialize, premultiplied, painted)));
}
}
} // end mapnik ns
#endif // MAPNIK_IMAGE_DATA_ANY_HPP

View file

@ -24,7 +24,7 @@
#define MAPNIK_IMAGE_COMPOSITING_HPP
#include <mapnik/config.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
// boost
#include <boost/optional.hpp>
@ -87,8 +87,7 @@ MAPNIK_DECL void composite(T & dst, T const& src,
composite_mode_e mode,
float opacity=1,
int dx=0,
int dy=0,
bool premultiply_src=false);
int dy=0);
}
#endif // MAPNIK_IMAGE_COMPOSITING_HPP

View file

@ -0,0 +1,72 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_IMAGE_COPY_HPP
#define MAPNIK_IMAGE_COPY_HPP
#include <mapnik/image_any.hpp>
#include <mapnik/config.hpp>
namespace mapnik
{
template <typename T>
MAPNIK_DECL T image_copy(image_any const&, double offset = 0.0, double scaling = 1.0);
template <typename T>
MAPNIK_DECL T image_copy(image_rgba8 const&, double offset = 0.0, double scaling = 1.0);
template <typename T>
MAPNIK_DECL T image_copy(image_gray8 const&, double offset = 0.0, double scaling = 1.0);
template <typename T>
MAPNIK_DECL T image_copy(image_gray8s const&, double offset = 0.0, double scaling = 1.0);
template <typename T>
MAPNIK_DECL T image_copy(image_gray16 const&, double offset = 0.0, double scaling = 1.0);
template <typename T>
MAPNIK_DECL T image_copy(image_gray16s const&, double offset = 0.0, double scaling = 1.0);
template <typename T>
MAPNIK_DECL T image_copy(image_gray32 const&, double offset = 0.0, double scaling = 1.0);
template <typename T>
MAPNIK_DECL T image_copy(image_gray32s const&, double offset = 0.0, double scaling = 1.0);
template <typename T>
MAPNIK_DECL T image_copy(image_gray32f const&, double offset = 0.0, double scaling = 1.0);
template <typename T>
MAPNIK_DECL T image_copy(image_gray64 const&, double offset = 0.0, double scaling = 1.0);
template <typename T>
MAPNIK_DECL T image_copy(image_gray64s const&, double offset = 0.0, double scaling = 1.0);
template <typename T>
MAPNIK_DECL T image_copy(image_gray64f const&, double offset = 0.0, double scaling = 1.0);
MAPNIK_DECL image_any image_copy(image_any const&, image_dtype type, double offset = 0.0, double scaling = 1.0);
} // end mapnik ns
#endif // MAPNIK_IMAGE_COPY_HPP

View file

@ -1,112 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_IMAGE_DATA_ANY_HPP
#define MAPNIK_IMAGE_DATA_ANY_HPP
#include <mapnik/image_data.hpp>
#include <mapnik/util/variant.hpp>
namespace mapnik {
struct image_data_null
{
unsigned char const* getBytes() const { return nullptr; }
unsigned char* getBytes() { return nullptr;}
std::size_t width() const { return 0; }
std::size_t height() const { return 0; }
};
using image_data_base = util::variant<image_data_null, image_data_rgba8, image_data_gray8, image_data_gray16, image_data_gray32f>;
namespace detail {
struct get_bytes_visitor
{
template <typename T>
unsigned char* operator()(T & data)
{
return data.getBytes();
}
};
struct get_bytes_visitor_const
{
template <typename T>
unsigned char const* operator()(T const& data) const
{
return data.getBytes();
}
};
struct get_width_visitor
{
template <typename T>
std::size_t operator()(T const& data) const
{
return data.width();
}
};
struct get_height_visitor
{
template <typename T>
std::size_t operator()(T const& data) const
{
return data.height();
}
};
} // namespace detail
struct image_data_any : image_data_base
{
image_data_any() = default;
template <typename T>
image_data_any(T && data) noexcept
: image_data_base(std::move(data)) {}
unsigned char const* getBytes() const
{
return util::apply_visitor(detail::get_bytes_visitor_const(),*this);
}
unsigned char* getBytes()
{
return util::apply_visitor(detail::get_bytes_visitor(),*this);
}
std::size_t width() const
{
return util::apply_visitor(detail::get_width_visitor(),*this);
}
std::size_t height() const
{
return util::apply_visitor(detail::get_height_visitor(),*this);
}
};
}
#endif // MAPNIK_IMAGE_DATA_ANY_HPP

View file

@ -139,7 +139,7 @@ boost::gil::rgba8_view_t rgba8_view(Image & img)
using boost::gil::interleaved_view;
using boost::gil::rgba8_pixel_t;
return interleaved_view(img.width(), img.height(),
reinterpret_cast<rgba8_pixel_t*>(img.raw_data()),
reinterpret_cast<rgba8_pixel_t*>(img.getBytes()),
img.width() * sizeof(rgba8_pixel_t));
}
@ -391,17 +391,17 @@ template <typename Src, typename Filter>
void apply_filter(Src & src, Filter const& filter)
{
{
src.demultiply();
demultiply_alpha(src);
double_buffer<Src> tb(src);
apply_convolution_3x3(tb.src_view, tb.dst_view, filter);
} // ensure ~double_buffer() is called before premultiplying
src.premultiply();
premultiply_alpha(src);
}
template <typename Src>
void apply_filter(Src & src, agg_stack_blur const& op)
{
agg::rendering_buffer buf(src.raw_data(),src.width(),src.height(), src.width() * 4);
agg::rendering_buffer buf(src.getBytes(),src.width(),src.height(), src.getRowSize());
agg::pixfmt_rgba32_pre pixf(buf);
agg::stack_blur_rgba32(pixf,op.rx,op.ry);
}

View file

@ -24,7 +24,7 @@
#define MAPNIK_IMAGE_READER_HPP
// mapnik
#include <mapnik/image_data_any.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/config.hpp>
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/factory.hpp>
@ -59,10 +59,9 @@ struct MAPNIK_DECL image_reader : private util::noncopyable
virtual unsigned width() const = 0;
virtual unsigned height() const = 0;
virtual bool has_alpha() const = 0;
virtual bool premultiplied_alpha() const = 0;
virtual boost::optional<box2d<double> > bounding_box() const = 0;
virtual void read(unsigned x,unsigned y,image_data_rgba8& image) = 0;
virtual image_data_any read(unsigned x, unsigned y, unsigned width, unsigned height) = 0;
virtual void read(unsigned x,unsigned y,image_rgba8& image) = 0;
virtual image_any read(unsigned x, unsigned y, unsigned width, unsigned height) = 0;
virtual ~image_reader() {}
};

View file

@ -25,7 +25,7 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
// stl
#include <iosfwd>

View file

@ -38,7 +38,7 @@ template <typename T>
struct agg_scaling_traits {};
template <>
struct agg_scaling_traits<image_data_rgba8>
struct agg_scaling_traits<image_rgba8>
{
using pixfmt_pre = agg::pixfmt_rgba32_pre;
using color_type = agg::rgba8;
@ -50,7 +50,7 @@ struct agg_scaling_traits<image_data_rgba8>
};
template <>
struct agg_scaling_traits<image_data_gray8>
struct agg_scaling_traits<image_gray8>
{
using pixfmt_pre = agg::pixfmt_gray8_pre;
using color_type = agg::gray8;
@ -61,7 +61,18 @@ struct agg_scaling_traits<image_data_gray8>
};
template <>
struct agg_scaling_traits<image_data_gray16>
struct agg_scaling_traits<image_gray8s>
{
using pixfmt_pre = agg::pixfmt_gray8_pre;
using color_type = agg::gray8;
using interpolator_type = agg::span_interpolator_linear<>;
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
using span_image_filter = agg::span_image_filter_gray_nn<img_src_type,interpolator_type>;
using span_image_resample_affine = agg::span_image_resample_gray_affine<img_src_type>;
};
template <>
struct agg_scaling_traits<image_gray16>
{
using pixfmt_pre = agg::pixfmt_gray16_pre;
using color_type = agg::gray16;
@ -72,7 +83,73 @@ struct agg_scaling_traits<image_data_gray16>
};
template <>
struct agg_scaling_traits<image_data_gray32f>
struct agg_scaling_traits<image_gray16s>
{
using pixfmt_pre = agg::pixfmt_gray16_pre;
using color_type = agg::gray16;
using interpolator_type = agg::span_interpolator_linear<>;
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
using span_image_filter = agg::span_image_filter_gray_nn<img_src_type,interpolator_type>;
using span_image_resample_affine = agg::span_image_resample_gray_affine<img_src_type>;
};
template <>
struct agg_scaling_traits<image_gray32>
{
using pixfmt_pre = agg::pixfmt_gray32_pre;
using color_type = agg::gray32;
using interpolator_type = agg::span_interpolator_linear<>;
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
using span_image_filter = agg::span_image_filter_gray_nn<img_src_type,interpolator_type>;
using span_image_resample_affine = agg::span_image_resample_gray_affine<img_src_type>;
};
template <>
struct agg_scaling_traits<image_gray32s>
{
using pixfmt_pre = agg::pixfmt_gray32_pre;
using color_type = agg::gray32;
using interpolator_type = agg::span_interpolator_linear<>;
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
using span_image_filter = agg::span_image_filter_gray_nn<img_src_type,interpolator_type>;
using span_image_resample_affine = agg::span_image_resample_gray_affine<img_src_type>;
};
template <>
struct agg_scaling_traits<image_gray32f>
{
using pixfmt_pre = agg::pixfmt_gray32_pre;
using color_type = agg::gray32;
using interpolator_type = agg::span_interpolator_linear<>;
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
using span_image_filter = agg::span_image_filter_gray_nn<img_src_type,interpolator_type>;
using span_image_resample_affine = agg::span_image_resample_gray_affine<img_src_type>;
};
template <>
struct agg_scaling_traits<image_gray64>
{
using pixfmt_pre = agg::pixfmt_gray32_pre;
using color_type = agg::gray32;
using interpolator_type = agg::span_interpolator_linear<>;
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
using span_image_filter = agg::span_image_filter_gray_nn<img_src_type,interpolator_type>;
using span_image_resample_affine = agg::span_image_resample_gray_affine<img_src_type>;
};
template <>
struct agg_scaling_traits<image_gray64s>
{
using pixfmt_pre = agg::pixfmt_gray32_pre;
using color_type = agg::gray32;
using interpolator_type = agg::span_interpolator_linear<>;
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
using span_image_filter = agg::span_image_filter_gray_nn<img_src_type,interpolator_type>;
using span_image_resample_affine = agg::span_image_resample_gray_affine<img_src_type>;
};
template <>
struct agg_scaling_traits<image_gray64f>
{
using pixfmt_pre = agg::pixfmt_gray32_pre;
using color_type = agg::gray32;

View file

@ -25,8 +25,11 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/image_view.hpp>
#include <mapnik/image_view_any.hpp>
#include <mapnik/color.hpp>
// boost
#pragma GCC diagnostic push
@ -37,13 +40,11 @@
// stl
#include <string>
#include <cmath>
#include <exception>
namespace mapnik {
// fwd declares
class Map;
class rgba_palette;
class ImageWriterException : public std::exception
@ -62,18 +63,6 @@ public:
}
};
#if defined(HAVE_CAIRO)
MAPNIK_DECL void save_to_cairo_file(mapnik::Map const& map,
std::string const& filename,
double scale_factor=1.0,
double scale_denominator=0.0);
MAPNIK_DECL void save_to_cairo_file(mapnik::Map const& map,
std::string const& filename,
std::string const& type,
double scale_factor=1.0,
double scale_denominator=0.0);
#endif
template <typename T>
MAPNIK_DECL void save_to_file(T const& image,
std::string const& filename,
@ -121,17 +110,228 @@ MAPNIK_DECL void save_to_stream
std::string const& type
);
template <typename T>
void save_as_png(T const& image,
std::string const& filename,
rgba_palette const& palette);
// PREMULTIPLY ALPHA
MAPNIK_DECL bool premultiply_alpha(image_any & image);
#if defined(HAVE_JPEG)
template <typename T>
void save_as_jpeg(std::string const& filename,
int quality,
T const& image);
#endif
MAPNIK_DECL bool premultiply_alpha(T & image);
// DEMULTIPLY ALPHA
MAPNIK_DECL bool demultiply_alpha(image_any & image);
template <typename T>
MAPNIK_DECL bool demultiply_alpha(T & image);
// SET PREMULTIPLIED ALPHA
MAPNIK_DECL void set_premultiplied_alpha(image_any & image, bool status);
template <typename T>
MAPNIK_DECL void set_premultiplied_alpha(T & image, bool status);
// IS SOLID
MAPNIK_DECL bool is_solid (image_any const& image);
MAPNIK_DECL bool is_solid (image_view_any const& image);
template <typename T>
MAPNIK_DECL bool is_solid (T const& image);
// SET ALPHA
MAPNIK_DECL void set_alpha (image_any & image, float opacity);
template <typename T>
MAPNIK_DECL void set_alpha (T & image, float opacity);
// SET GRAYSCALE TO ALPHA
MAPNIK_DECL void set_grayscale_to_alpha (image_any & image);
MAPNIK_DECL void set_grayscale_to_alpha (image_any & image, color const& c);
template <typename T>
MAPNIK_DECL void set_grayscale_to_alpha (T & image);
template <typename T>
MAPNIK_DECL void set_grayscale_to_alpha (T & image, color const& c);
// SET COLOR TO ALPHA
MAPNIK_DECL void set_color_to_alpha (image_any & image, color const& c);
template <typename T>
MAPNIK_DECL void set_color_to_alpha (T & image, color const& c);
// FILL
template <typename T>
MAPNIK_DECL void fill (image_any & data, T const&);
template <typename T>
MAPNIK_DECL void fill (image_rgba8 & data, T const&);
template <typename T>
MAPNIK_DECL void fill (image_gray8 & data, T const&);
template <typename T>
MAPNIK_DECL void fill (image_gray8s & data, T const&);
template <typename T>
MAPNIK_DECL void fill (image_gray16 & data, T const&);
template <typename T>
MAPNIK_DECL void fill (image_gray16s & data, T const&);
template <typename T>
MAPNIK_DECL void fill (image_gray32 & data, T const&);
template <typename T>
MAPNIK_DECL void fill (image_gray32s & data, T const&);
template <typename T>
MAPNIK_DECL void fill (image_gray32f & data, T const&);
template <typename T>
MAPNIK_DECL void fill (image_gray64 & data, T const&);
template <typename T>
MAPNIK_DECL void fill (image_gray64s & data, T const&);
template <typename T>
MAPNIK_DECL void fill (image_gray64f & data, T const&);
// SET RECTANGLE
MAPNIK_DECL void set_rectangle (image_any & dst, image_any const& src, int x = 0, int y = 0);
template <typename T>
MAPNIK_DECL void set_rectangle (T & dst, T const& src, int x = 0, int y = 0);
// CHECK BOUNDS
template <typename T>
inline bool check_bounds (T const& data, std::size_t x, std::size_t y)
{
return (x < static_cast<int>(data.width()) && y < static_cast<int>(data.height()));
}
// COMPOSITE_PIXEL
MAPNIK_DECL void composite_pixel(image_any & data, unsigned op, int x, int y, unsigned c, unsigned cover, double opacity );
template <typename T>
MAPNIK_DECL void composite_pixel(T & data, unsigned op, int x, int y, unsigned c, unsigned cover, double opacity );
// SET PIXEL
template <typename T>
MAPNIK_DECL void set_pixel(image_any & data, std::size_t x, std::size_t y, T const& val);
template <typename T>
MAPNIK_DECL void set_pixel(image_rgba8 & data, std::size_t x, std::size_t y, T const& val);
template <typename T>
MAPNIK_DECL void set_pixel(image_gray8 & data, std::size_t x, std::size_t y, T const& val);
template <typename T>
MAPNIK_DECL void set_pixel(image_gray8s & data, std::size_t x, std::size_t y, T const& val);
template <typename T>
MAPNIK_DECL void set_pixel(image_gray16 & data, std::size_t x, std::size_t y, T const& val);
template <typename T>
MAPNIK_DECL void set_pixel(image_gray16s & data, std::size_t x, std::size_t y, T const& val);
template <typename T>
MAPNIK_DECL void set_pixel(image_gray32 & data, std::size_t x, std::size_t y, T const& val);
template <typename T>
MAPNIK_DECL void set_pixel(image_gray32s & data, std::size_t x, std::size_t y, T const& val);
template <typename T>
MAPNIK_DECL void set_pixel(image_gray32f & data, std::size_t x, std::size_t y, T const& val);
template <typename T>
MAPNIK_DECL void set_pixel(image_gray64 & data, std::size_t x, std::size_t y, T const& val);
template <typename T>
MAPNIK_DECL void set_pixel(image_gray64s & data, std::size_t x, std::size_t y, T const& val);
template <typename T>
MAPNIK_DECL void set_pixel(image_gray64f & data, std::size_t x, std::size_t y, T const& val);
// GET PIXEL
template <typename T>
MAPNIK_DECL T get_pixel(image_any const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_view_any const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_rgba8 const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_gray8 const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_gray8s const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_gray16 const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_gray16s const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_gray32 const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_gray32s const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_gray32f const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_gray64 const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_gray64s const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_gray64f const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_view_rgba8 const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_view_gray8 const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_view_gray8s const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_view_gray16 const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_view_gray16s const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_view_gray32 const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_view_gray32s const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_view_gray32f const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_view_gray64 const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_view_gray64s const& data, std::size_t x, std::size_t y);
template <typename T>
MAPNIK_DECL T get_pixel(image_view_gray64f const& data, std::size_t x, std::size_t y);
// VIEW TO STRING
MAPNIK_DECL void view_to_string (image_view_any const& view, std::ostringstream & ss);
// CREATE VIEW
MAPNIK_DECL image_view_any create_view (image_any const& data, unsigned x, unsigned y, unsigned w, unsigned h);
// COMPARE
template <typename T>
MAPNIK_DECL unsigned compare(T const& im1, T const& im2, double threshold = 0, bool alpha = true);
inline bool is_png(std::string const& filename)
{
@ -209,82 +409,6 @@ void add_border(T & image)
}
}
extern template MAPNIK_DECL void save_to_file<image_data_rgba8>(image_data_rgba8 const&,
std::string const&,
std::string const&,
rgba_palette const&);
extern template MAPNIK_DECL void save_to_file<image_data_rgba8>(image_data_rgba8 const&,
std::string const&,
std::string const&);
extern template MAPNIK_DECL void save_to_file<image_data_rgba8>(image_data_rgba8 const&,
std::string const&,
rgba_palette const&);
extern template MAPNIK_DECL void save_to_file<image_data_rgba8>(image_data_rgba8 const&,
std::string const&);
extern template MAPNIK_DECL void save_to_file<image_view<image_data_rgba8> > (image_view<image_data_rgba8> const&,
std::string const&,
std::string const&,
rgba_palette const&);
extern template MAPNIK_DECL void save_to_file<image_view<image_data_rgba8> > (image_view<image_data_rgba8> const&,
std::string const&,
std::string const&);
extern template MAPNIK_DECL void save_to_file<image_view<image_data_rgba8> > (image_view<image_data_rgba8> const&,
std::string const&,
rgba_palette const&);
extern template MAPNIK_DECL void save_to_file<image_view<image_data_rgba8> > (image_view<image_data_rgba8> const&,
std::string const&);
extern template MAPNIK_DECL std::string save_to_string<image_data_rgba8>(image_data_rgba8 const&,
std::string const&);
extern template MAPNIK_DECL std::string save_to_string<image_data_rgba8>(image_data_rgba8 const&,
std::string const&,
rgba_palette const&);
extern template MAPNIK_DECL std::string save_to_string<image_view<image_data_rgba8> > (image_view<image_data_rgba8> const&,
std::string const&);
extern template MAPNIK_DECL std::string save_to_string<image_view<image_data_rgba8> > (image_view<image_data_rgba8> const&,
std::string const&,
rgba_palette const&);
#ifdef _MSC_VER
template MAPNIK_DECL void save_to_stream<image_data_rgba8>(
image_data_rgba8 const& image,
std::ostream & stream,
std::string const& type,
rgba_palette const& palette
);
template MAPNIK_DECL void save_to_stream<image_data_rgba8>(
image_data_rgba8 const& image,
std::ostream & stream,
std::string const& type
);
template MAPNIK_DECL void save_to_stream<image_view<image_data_rgba8> > (
image_view<image_data_rgba8> const& image,
std::ostream & stream,
std::string const& type,
rgba_palette const& palette
);
template MAPNIK_DECL void save_to_stream<image_view<image_data_rgba8> > (
image_view<image_data_rgba8> const& image,
std::ostream & stream,
std::string const& type
);
#endif
}
#endif // MAPNIK_IMAGE_UTIL_HPP

View file

@ -0,0 +1,44 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_IMAGE_UTIL_JPEG_HPP
#define MAPNIK_IMAGE_UTIL_JPEG_HPP
// stl
#include <string>
#include <iostream>
namespace mapnik {
struct jpeg_saver
{
jpeg_saver(std::ostream &, std::string const&);
template <typename T>
void operator() (T const&) const;
private:
std::ostream & stream_;
std::string const& t_;
};
} // end ns
#endif // MAPNIK_IMAGE_UTIL_JPEG_HPP

View file

@ -0,0 +1,55 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_IMAGE_UTIL_PNG_HPP
#define MAPNIK_IMAGE_UTIL_PNG_HPP
// stl
#include <string>
#include <iostream>
namespace mapnik {
struct png_saver_pal
{
png_saver_pal(std::ostream &, std::string const&, rgba_palette const&);
template <typename T>
void operator() (T const&) const;
private:
std::ostream & stream_;
std::string const& t_;
rgba_palette const& pal_;
};
struct png_saver
{
png_saver(std::ostream &, std::string const&);
template <typename T>
void operator() (T const&) const;
private:
std::ostream & stream_;
std::string const& t_;
};
} // end ns
#endif // MAPNIK_IMAGE_UTIL_PNG_HPP

View file

@ -0,0 +1,44 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_IMAGE_UTIL_TIFF_HPP
#define MAPNIK_IMAGE_UTIL_TIFF_HPP
// stl
#include <string>
#include <iostream>
namespace mapnik {
struct tiff_saver
{
tiff_saver(std::ostream &, std::string const&);
template <typename T>
void operator() (T const&) const;
private:
std::ostream & stream_;
std::string const& t_;
};
} // end ns
#endif // MAPNIK_IMAGE_UTIL_TIFF_HPP

View file

@ -0,0 +1,44 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_IMAGE_UTIL_WEBP_HPP
#define MAPNIK_IMAGE_UTIL_WEBP_HPP
// stl
#include <string>
#include <iostream>
namespace mapnik {
struct webp_saver
{
webp_saver(std::ostream &, std::string const&);
template <typename T>
void operator() (T const&) const;
private:
std::ostream & stream_;
std::string const& t_;
};
} // end ns
#endif // MAPNIK_IMAGE_UTIL_WEBP_HPP

View file

@ -23,12 +23,15 @@
#ifndef MAPNIK_IMAGE_VIEW_HPP
#define MAPNIK_IMAGE_VIEW_HPP
#include <mapnik/image.hpp>
namespace mapnik {
template <typename T>
class image_view
{
public:
using pixel = typename T::pixel;
using pixel_type = typename T::pixel_type;
static constexpr std::size_t pixel_size = sizeof(pixel_type);
@ -84,6 +87,10 @@ public:
{
return height_;
}
inline const pixel_type& operator() (std::size_t i, std::size_t j) const
{
return data_(i,j);
}
inline unsigned getSize() const
{
@ -110,6 +117,21 @@ public:
return data_;
}
inline bool get_premultiplied() const
{
return data_.get_premultiplied();
}
inline double get_offset() const
{
return data_.get_offset();
}
inline double get_scaling() const
{
return data_.get_scaling();
}
private:
unsigned x_;
unsigned y_;
@ -117,6 +139,19 @@ private:
unsigned height_;
T const& data_;
};
}
using image_view_rgba8 = image_view<image_rgba8>;
using image_view_gray8 = image_view<image_gray8>;
using image_view_gray8s = image_view<image_gray8s>;
using image_view_gray16 = image_view<image_gray16>;
using image_view_gray16s = image_view<image_gray16s>;
using image_view_gray32 = image_view<image_gray32>;
using image_view_gray32s = image_view<image_gray32s>;
using image_view_gray32f = image_view<image_gray32f>;
using image_view_gray64 = image_view<image_gray64>;
using image_view_gray64s = image_view<image_gray64s>;
using image_view_gray64f = image_view<image_gray64f>;
} // end ns
#endif // MAPNIK_IMAGE_VIEW_HPP

View file

@ -0,0 +1,155 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_IMAGE_VIEW_ANY_HPP
#define MAPNIK_IMAGE_VIEW_ANY_HPP
#include <mapnik/image_view.hpp>
#include <mapnik/util/variant.hpp>
namespace mapnik {
using image_view_base = util::variant<image_view_rgba8,
image_view_gray8,
image_view_gray8s,
image_view_gray16,
image_view_gray16s,
image_view_gray32,
image_view_gray32s,
image_view_gray32f,
image_view_gray64,
image_view_gray64s,
image_view_gray64f>;
namespace detail {
struct get_view_width_visitor
{
template <typename T>
std::size_t operator()(T const& data) const
{
return data.width();
}
};
struct get_view_height_visitor
{
template <typename T>
std::size_t operator()(T const& data) const
{
return data.height();
}
};
struct get_view_size_visitor
{
template <typename T>
unsigned operator()(T const& data) const
{
return data.getSize();
}
};
struct get_view_row_size_visitor
{
template <typename T>
unsigned operator()(T const& data) const
{
return data.getRowSize();
}
};
struct get_view_premultiplied_visitor
{
template <typename T>
bool operator()(T const& data) const
{
return data.get_premultiplied();
}
};
struct get_view_offset_visitor
{
template <typename T>
double operator()(T const& data) const
{
return data.get_offset();
}
};
struct get_view_scaling_visitor
{
template <typename T>
double operator()(T const& data) const
{
return data.get_scaling();
}
};
} // namespace detail
struct image_view_any : image_view_base
{
image_view_any() = default;
template <typename T>
image_view_any(T && data) noexcept
: image_view_base(std::move(data)) {}
std::size_t width() const
{
return util::apply_visitor(detail::get_view_width_visitor(),*this);
}
std::size_t height() const
{
return util::apply_visitor(detail::get_view_height_visitor(),*this);
}
unsigned getSize() const
{
return util::apply_visitor(detail::get_view_size_visitor(),*this);
}
unsigned getRowSize() const
{
return util::apply_visitor(detail::get_view_row_size_visitor(),*this);
}
bool get_premultiplied() const
{
return util::apply_visitor(detail::get_view_premultiplied_visitor(),*this);
}
double get_offset() const
{
return util::apply_visitor(detail::get_view_offset_visitor(),*this);
}
double get_scaling() const
{
return util::apply_visitor(detail::get_view_scaling_visitor(),*this);
}
};
}
#endif // MAPNIK_IMAGE_VIEW_ANY_HPP

View file

@ -24,11 +24,13 @@
#define MAPNIK_MARKER_HPP
// mapnik
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/svg/svg_storage.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/util/variant.hpp>
// agg
#include "agg_array.h"
@ -45,97 +47,169 @@ namespace mapnik
using attr_storage = agg::pod_bvector<mapnik::svg::path_attributes>;
using svg_storage_type = mapnik::svg::svg_storage<mapnik::svg::svg_path_storage,attr_storage>;
using svg_path_ptr = std::shared_ptr<svg_storage_type>;
using image_ptr = std::shared_ptr<image_data_rgba8>;
/**
* A class to hold either vector or bitmap marker data. This allows these to be treated equally
* in the image caches and most of the render paths.
*/
class marker: private util::noncopyable
using image_ptr = std::shared_ptr<image_any>;
struct marker_rgba8
{
public:
marker()
marker_rgba8()
: bitmap_data_(4,4,true,true)
{
// create default OGC 4x4 black pixel
bitmap_data_ = boost::optional<mapnik::image_ptr>(std::make_shared<image_data_rgba8>(4,4));
(*bitmap_data_)->set(0xff000000);
bitmap_data_.set(0xff000000);
}
marker(boost::optional<mapnik::image_ptr> const& data)
marker_rgba8(image_rgba8 const & data)
: bitmap_data_(data) {}
marker(boost::optional<mapnik::svg_path_ptr> const& data)
: vector_data_(data) {}
marker_rgba8(image_rgba8 && data)
: bitmap_data_(std::move(data)) {}
marker(marker const& rhs)
: bitmap_data_(rhs.bitmap_data_),
vector_data_(rhs.vector_data_) {}
marker_rgba8(marker_rgba8 const& rhs)
: bitmap_data_(rhs.bitmap_data_) {}
marker_rgba8(marker_rgba8 && rhs) noexcept
: bitmap_data_(std::move(rhs.bitmap_data_)) {}
box2d<double> bounding_box() const
{
if (is_vector())
{
return (*vector_data_)->bounding_box();
}
if (is_bitmap())
{
double width = (*bitmap_data_)->width();
double height = (*bitmap_data_)->height();
return box2d<double>(0, 0, width, height);
}
return box2d<double>();
double width = bitmap_data_.width();
double height = bitmap_data_.height();
return box2d<double>(0, 0, width, height);
}
inline double width() const
inline std::size_t width() const
{
if (is_bitmap())
{
return (*bitmap_data_)->width();
}
else if (is_vector())
{
return (*vector_data_)->bounding_box().width();
}
return 0;
}
inline double height() const
{
if (is_bitmap())
{
return (*bitmap_data_)->height();
}
else if (is_vector())
{
return (*vector_data_)->bounding_box().height();
}
return 0;
return bitmap_data_.width();
}
inline bool is_bitmap() const
inline std::size_t height() const
{
return !!bitmap_data_;
return bitmap_data_.height();
}
inline bool is_vector() const
{
return !!vector_data_;
}
boost::optional<mapnik::image_ptr> get_bitmap_data() const
image_rgba8 const& get_data() const
{
return bitmap_data_;
}
boost::optional<mapnik::svg_path_ptr> get_vector_data() const
private:
image_rgba8 bitmap_data_;
};
struct marker_svg
{
public:
marker_svg() { }
marker_svg(mapnik::svg_path_ptr data)
: vector_data_(data) {}
marker_svg(marker_svg const& rhs)
: vector_data_(rhs.vector_data_) {}
marker_svg(marker_svg && rhs) noexcept
: vector_data_(rhs.vector_data_) {}
box2d<double> bounding_box() const
{
return vector_data_->bounding_box();
}
inline double width() const
{
return vector_data_->bounding_box().width();
}
inline double height() const
{
return vector_data_->bounding_box().height();
}
mapnik::svg_path_ptr get_data() const
{
return vector_data_;
}
private:
boost::optional<mapnik::image_ptr> bitmap_data_;
boost::optional<mapnik::svg_path_ptr> vector_data_;
mapnik::svg_path_ptr vector_data_;
};
}
struct marker_null
{
public:
box2d<double> bounding_box() const
{
return box2d<double>();
}
inline double width() const
{
return 0;
}
inline double height() const
{
return 0;
}
};
using marker_base = util::variant<marker_svg,
marker_rgba8,
marker_null>;
namespace detail {
struct get_marker_bbox_visitor
{
template <typename T>
box2d<double> operator()(T & data) const
{
return data.bounding_box();
}
};
struct get_marker_width_visitor
{
template <typename T>
double operator()(T const& data) const
{
return static_cast<double>(data.width());
}
};
struct get_marker_height_visitor
{
template <typename T>
double operator()(T const& data) const
{
return static_cast<double>(data.height());
}
};
} // end detail ns
struct marker : marker_base
{
marker() = default;
template <typename T>
marker(T && data) noexcept
: marker_base(std::move(data)) {}
double width() const
{
return util::apply_visitor(detail::get_marker_width_visitor(),*this);
}
double height() const
{
return util::apply_visitor(detail::get_marker_height_visitor(),*this);
}
box2d<double> bounding_box() const
{
return util::apply_visitor(detail::get_marker_bbox_visitor(),*this);
}
};
} // end mapnik ns
#endif // MAPNIK_MARKER_HPP

View file

@ -36,10 +36,7 @@
namespace mapnik
{
class marker;
using marker_ptr = std::shared_ptr<marker>;
struct marker;
class MAPNIK_DECL marker_cache :
public singleton <marker_cache, CreateUsingNew>,
@ -49,8 +46,8 @@ class MAPNIK_DECL marker_cache :
private:
marker_cache();
~marker_cache();
bool insert_marker(std::string const& key, marker_ptr path);
boost::unordered_map<std::string,marker_ptr> marker_cache_;
bool insert_marker(std::string const& key, marker && path);
boost::unordered_map<std::string, mapnik::marker> marker_cache_;
bool insert_svg(std::string const& name, std::string const& svg_string);
boost::unordered_map<std::string,std::string> svg_cache_;
public:
@ -59,7 +56,7 @@ public:
inline bool is_uri(std::string const& path) { return is_svg_uri(path) || is_image_uri(path); }
bool is_svg_uri(std::string const& path);
bool is_image_uri(std::string const& path);
boost::optional<marker_ptr> find(std::string const& key, bool update_cache = false);
marker const& find(std::string const& key, bool update_cache = false);
void clear();
};

View file

@ -118,7 +118,7 @@ protected:
template <typename Detector>
struct raster_markers_dispatch : util::noncopyable
{
raster_markers_dispatch(image_data_rgba8 & src,
raster_markers_dispatch(image_rgba8 const& src,
agg::trans_affine const& marker_trans,
symbolizer_base const& sym,
Detector & detector,
@ -163,7 +163,7 @@ struct raster_markers_dispatch : util::noncopyable
virtual void render_marker(agg::trans_affine const& marker_tr, double opacity) = 0;
protected:
image_data_rgba8 & src_;
image_rgba8 const& src_;
agg::trans_affine const& marker_trans_;
symbolizer_base const& sym_;
Detector & detector_;

View file

@ -32,7 +32,7 @@
#include <iostream>
#include <stdexcept>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/image_view.hpp>
/* miniz.c porting issues:
@ -83,12 +83,12 @@ private:
static const unsigned char IEND_tpl[];
};
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_data_gray8>(image_data_gray8 const& image);
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_view<image_data_gray8> >(image_view<image_data_gray8> const& image);
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_data_rgba8>(image_data_rgba8 const& image);
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_view<image_data_rgba8> >(image_view<image_data_rgba8> const& image);
extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha<image_data_rgba8>(image_data_rgba8 const& image);
extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha<image_view<image_data_rgba8> >(image_view<image_data_rgba8> const& image);
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_gray8>(image_gray8 const& image);
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_view_gray8>(image_view_gray8 const& image);
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_rgba8>(image_rgba8 const& image);
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_view_rgba8>(image_view_rgba8 const& image);
extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha<image_rgba8>(image_rgba8 const& image);
extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha<image_view_rgba8>(image_view_rgba8 const& image);
}}

View file

@ -0,0 +1,40 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_PIXEL_TYPES_HPP
#define MAPNIK_PIXEL_TYPES_HPP
#include <mapnik/global.hpp>
struct rgba8_t { using type = std::uint32_t; };
struct gray8_t { using type = std::uint8_t; };
struct gray8s_t { using type = std::int8_t; };
struct gray16_t { using type = std::uint16_t; };
struct gray16s_t { using type = std::int16_t; };
struct gray32_t { using type = std::uint32_t; };
struct gray32s_t { using type = std::int32_t; };
struct gray32f_t { using type = float; };
struct gray64_t { using type = std::uint64_t; };
struct gray64s_t { using type = std::int64_t; };
struct gray64f_t { using type = double; };
#endif // MAPNIK_PIXEL_TYPES_HPP

View file

@ -28,7 +28,7 @@
#include <mapnik/octree.hpp>
#include <mapnik/hextree.hpp>
#include <mapnik/miniz_png.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
// zlib
#include <zlib.h> // for Z_DEFAULT_COMPRESSION
@ -149,7 +149,7 @@ void save_as_png(T1 & file,
template <typename T>
void reduce_8(T const& in,
image_data_gray8 & out,
image_gray8 & out,
octree<rgb> trees[],
unsigned limits[],
unsigned levels,
@ -166,8 +166,8 @@ void reduce_8(T const& in,
}
for (unsigned y = 0; y < height; ++y)
{
mapnik::image_data_rgba8::pixel_type const * row = in.getRow(y);
mapnik::image_data_gray8::pixel_type * row_out = out.getRow(y);
mapnik::image_rgba8::pixel_type const * row = in.getRow(y);
mapnik::image_gray8::pixel_type * row_out = out.getRow(y);
for (unsigned x = 0; x < width; ++x)
{
unsigned val = row[x];
@ -200,7 +200,7 @@ void reduce_8(T const& in,
template <typename T>
void reduce_4(T const& in,
image_data_gray8 & out,
image_gray8 & out,
octree<rgb> trees[],
unsigned limits[],
unsigned levels,
@ -217,8 +217,8 @@ void reduce_4(T const& in,
}
for (unsigned y = 0; y < height; ++y)
{
mapnik::image_data_rgba8::pixel_type const * row = in.getRow(y);
mapnik::image_data_gray8::pixel_type * row_out = out.getRow(y);
mapnik::image_rgba8::pixel_type const * row = in.getRow(y);
mapnik::image_gray8::pixel_type * row_out = out.getRow(y);
for (unsigned x = 0; x < width; ++x)
{
unsigned val = row[x];
@ -256,7 +256,7 @@ void reduce_4(T const& in,
// 1-bit but only one color.
template <typename T>
void reduce_1(T const&,
image_data_gray8 & out,
image_gray8 & out,
octree<rgb> /*trees*/[],
unsigned /*limits*/[],
std::vector<unsigned> & /*alpha*/)
@ -266,7 +266,7 @@ void reduce_1(T const&,
template <typename T>
void save_as_png(T & file, std::vector<mapnik::rgb> const& palette,
mapnik::image_data_gray8 const& image,
mapnik::image_gray8 const& image,
unsigned width,
unsigned height,
unsigned color_depth,
@ -556,7 +556,7 @@ void save_as_png8_oct(T1 & file,
if (palette.size() > 16 )
{
// >16 && <=256 colors -> write 8-bit color depth
image_data_gray8 reduced_image(width,height);
image_gray8 reduced_image(width,height);
reduce_8(image, reduced_image, trees, limits, TRANSPARENCY_LEVELS, alphaTable);
save_as_png(file,palette,reduced_image,width,height,8,alphaTable,opts);
}
@ -565,7 +565,7 @@ void save_as_png8_oct(T1 & file,
// 1 color image -> write 1-bit color depth PNG
unsigned image_width = ((width + 15) >> 3) & ~1U; // 1-bit image, round up to 16-bit boundary
unsigned image_height = height;
image_data_gray8 reduced_image(image_width,image_height);
image_gray8 reduced_image(image_width,image_height);
reduce_1(image,reduced_image,trees, limits, alphaTable);
if (meanAlpha<255 && cols[0]==0)
{
@ -579,7 +579,7 @@ void save_as_png8_oct(T1 & file,
// <=16 colors -> write 4-bit color depth PNG
unsigned image_width = ((width + 7) >> 1) & ~3U; // 4-bit image, round up to 32-bit boundary
unsigned image_height = height;
image_data_gray8 reduced_image(image_width,image_height);
image_gray8 reduced_image(image_width,image_height);
reduce_4(image, reduced_image, trees, limits, TRANSPARENCY_LEVELS, alphaTable);
save_as_png(file,palette,reduced_image,width,height,4,alphaTable,opts);
}
@ -600,11 +600,11 @@ void save_as_png8(T1 & file,
if (palette.size() > 16 )
{
// >16 && <=256 colors -> write 8-bit color depth
image_data_gray8 reduced_image(width, height);
image_gray8 reduced_image(width, height);
for (unsigned y = 0; y < height; ++y)
{
mapnik::image_data_rgba8::pixel_type const * row = image.getRow(y);
mapnik::image_data_gray8::pixel_type * row_out = reduced_image.getRow(y);
mapnik::image_rgba8::pixel_type const * row = image.getRow(y);
mapnik::image_gray8::pixel_type * row_out = reduced_image.getRow(y);
for (unsigned x = 0; x < width; ++x)
{
row_out[x] = tree.quantize(row[x]);
@ -617,7 +617,7 @@ void save_as_png8(T1 & file,
// 1 color image -> write 1-bit color depth PNG
unsigned image_width = ((width + 15) >> 3) & ~1U; // 1-bit image, round up to 16-bit boundary
unsigned image_height = height;
image_data_gray8 reduced_image(image_width, image_height);
image_gray8 reduced_image(image_width, image_height);
reduced_image.set(0);
save_as_png(file, palette, reduced_image, width, height, 1, alphaTable, opts);
}
@ -626,11 +626,11 @@ void save_as_png8(T1 & file,
// <=16 colors -> write 4-bit color depth PNG
unsigned image_width = ((width + 7) >> 1) & ~3U; // 4-bit image, round up to 32-bit boundary
unsigned image_height = height;
image_data_gray8 reduced_image(image_width, image_height);
image_gray8 reduced_image(image_width, image_height);
for (unsigned y = 0; y < height; ++y)
{
mapnik::image_data_rgba8::pixel_type const * row = image.getRow(y);
mapnik::image_data_gray8::pixel_type * row_out = reduced_image.getRow(y);
mapnik::image_rgba8::pixel_type const * row = image.getRow(y);
mapnik::image_gray8::pixel_type * row_out = reduced_image.getRow(y);
byte index = 0;
for (unsigned x = 0; x < width; ++x)
{

View file

@ -25,7 +25,7 @@
// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/image_data_any.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/util/variant.hpp>
// boost
@ -37,20 +37,17 @@ class raster : private util::noncopyable
{
public:
box2d<double> ext_;
image_data_any data_;
image_any data_;
double filter_factor_;
bool premultiplied_alpha_;
boost::optional<double> nodata_;
template <typename ImageData>
raster(box2d<double> const& ext,
ImageData && data,
double filter_factor,
bool premultiplied_alpha = false)
double filter_factor)
: ext_(ext),
data_(std::move(data)),
filter_factor_(filter_factor),
premultiplied_alpha_(premultiplied_alpha) {}
filter_factor_(filter_factor) {}
void set_nodata(double nodata)
{

View file

@ -40,7 +40,7 @@
#include <mapnik/config.hpp>
#include <mapnik/color.hpp>
#include <mapnik/enumeration.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
// boost
#include <boost/optional.hpp>
// boost
@ -198,7 +198,7 @@ public:
colorizer_stops const& get_stops() const { return stops_; }
template <typename T>
void colorize(image_data_rgba8 & out, T const& in, boost::optional<double>const& nodata, feature_impl const& f) const;
void colorize(image_rgba8 & out, T const& in, boost::optional<double>const& nodata, feature_impl const& f) const;
//! \brief Perform the translation of input to output
//!

View file

@ -42,7 +42,6 @@
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/graphics.hpp>
// agg
#include <agg_trans_affine.h>
@ -130,13 +129,13 @@ struct vector_marker_render_thunk : util::noncopyable
struct raster_marker_render_thunk : util::noncopyable
{
image_data_rgba8 & src_;
image_rgba8 const& src_;
agg::trans_affine tr_;
double opacity_;
composite_mode_e comp_op_;
bool snap_to_pixels_;
raster_marker_render_thunk(image_data_rgba8 & src,
raster_marker_render_thunk(image_rgba8 const& src,
agg::trans_affine const& marker_trans,
double opacity,
composite_mode_e comp_op,

View file

@ -32,6 +32,230 @@
namespace mapnik {
template <typename VD, typename RD, typename RendererType, typename ContextType>
struct render_marker_symbolizer_visitor
{
using vector_dispatch_type = VD;
using raster_dispatch_type = RD;
using buffer_type = typename std::tuple_element<0,ContextType>::type;
render_marker_symbolizer_visitor(std::string const& filename,
markers_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans,
RendererType const& common,
box2d<double> const& clip_box,
ContextType const& renderer_context)
: filename_(filename),
sym_(sym),
feature_(feature),
prj_trans_(prj_trans),
common_(common),
clip_box_(clip_box),
renderer_context_(renderer_context) {}
void operator() (marker_null const&) {}
void operator() (marker_svg const& mark)
{
using namespace mapnik::svg;
bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
double offset = get<value_double, keys::offset>(sym_, feature_, common_.vars_);
double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);
// https://github.com/mapnik/mapnik/issues/1316
bool snap_to_pixels = !mapnik::marker_cache::instance().is_uri(filename_);
agg::trans_affine geom_tr;
auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
if (transform) evaluate_transform(geom_tr, feature_, common_.vars_, *transform, common_.scale_factor_);
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
boost::optional<svg_path_ptr> const& stock_vector_marker = mark.get_data();
// special case for simple ellipse markers
// to allow for full control over rx/ry dimensions
if (filename_ == "shape://ellipse"
&& (has_key(sym_,keys::width) || has_key(sym_,keys::height)))
{
svg_path_ptr marker_ellipse = std::make_shared<svg_storage_type>();
vertex_stl_adapter<svg_path_storage> stl_storage(marker_ellipse->source());
svg_path_adapter svg_path(stl_storage);
build_ellipse(sym_, feature_, common_.vars_, *marker_ellipse, svg_path);
svg_attribute_type attributes;
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym_, feature_, common_.vars_);
auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform);
vector_dispatch_type rasterizer_dispatch(marker_ellipse,
svg_path,
result ? attributes : (*stock_vector_marker)->attributes(),
image_tr,
sym_,
*common_.detector_,
common_.scale_factor_,
feature_,
common_.vars_,
snap_to_pixels,
renderer_context_);
using vertex_converter_type = vertex_converter<vector_dispatch_type,clip_line_tag,
clip_poly_tag,
transform_tag,
affine_transform_tag,
simplify_tag, smooth_tag,
offset_transform_tag>;
vertex_converter_type converter(clip_box_,
rasterizer_dispatch,
sym_,
common_.t_,
prj_trans_,
geom_tr,
feature_,
common_.vars_,
common_.scale_factor_);
if (clip && feature_.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature_.paths()[0].type();
if (type == geometry_type::types::Polygon)
converter.template set<clip_poly_tag>();
else if (type == geometry_type::types::LineString)
converter.template set<clip_line_tag>();
}
converter.template set<transform_tag>(); //always transform
if (std::fabs(offset) > 0.0) converter.template set<offset_transform_tag>(); // parallel offset
converter.template set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature_, common_.vars_, converter, sym_);
}
else
{
box2d<double> const& bbox = mark.bounding_box();
setup_transform_scaling(image_tr, bbox.width(), bbox.height(), feature_, common_.vars_, sym_);
auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform);
vertex_stl_adapter<svg_path_storage> stl_storage((*stock_vector_marker)->source());
svg_path_adapter svg_path(stl_storage);
svg_attribute_type attributes;
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym_, feature_, common_.vars_);
vector_dispatch_type rasterizer_dispatch(*stock_vector_marker,
svg_path,
result ? attributes : (*stock_vector_marker)->attributes(),
image_tr,
sym_,
*common_.detector_,
common_.scale_factor_,
feature_,
common_.vars_,
snap_to_pixels,
renderer_context_);
using vertex_converter_type = vertex_converter<vector_dispatch_type,clip_line_tag,
clip_poly_tag,
transform_tag,
affine_transform_tag,
simplify_tag, smooth_tag,
offset_transform_tag>;
vertex_converter_type converter(clip_box_,
rasterizer_dispatch,
sym_,
common_.t_,
prj_trans_,
geom_tr,
feature_,
common_.vars_,
common_.scale_factor_);
if (clip && feature_.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature_.paths()[0].type();
if (type == geometry_type::types::Polygon)
converter.template set<clip_poly_tag>();
else if (type == geometry_type::types::LineString)
converter.template set<clip_line_tag>();
}
converter.template set<transform_tag>(); //always transform
if (std::fabs(offset) > 0.0) converter.template set<offset_transform_tag>(); // parallel offset
converter.template set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature_, common_.vars_, converter, sym_);
}
}
void operator() (marker_rgba8 const& mark)
{
using namespace mapnik::svg;
bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
double offset = get<value_double, keys::offset>(sym_, feature_, common_.vars_);
double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);
agg::trans_affine geom_tr;
auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
if (transform) evaluate_transform(geom_tr, feature_, common_.vars_, *transform, common_.scale_factor_);
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
setup_transform_scaling(image_tr, mark.width(), mark.height(), feature_, common_.vars_, sym_);
auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform);
box2d<double> const& bbox = mark.bounding_box();
mapnik::image_rgba8 const& marker = mark.get_data();
// - clamp sizes to > 4 pixels of interactivity
coord2d center = bbox.center();
agg::trans_affine_translation recenter(-center.x, -center.y);
agg::trans_affine marker_trans = recenter * image_tr;
raster_dispatch_type rasterizer_dispatch(marker,
marker_trans,
sym_,
*common_.detector_,
common_.scale_factor_,
feature_,
common_.vars_,
renderer_context_);
using vertex_converter_type = vertex_converter<raster_dispatch_type,clip_line_tag,
clip_poly_tag,
transform_tag,
affine_transform_tag,
simplify_tag, smooth_tag,
offset_transform_tag>;
vertex_converter_type converter(clip_box_,
rasterizer_dispatch,
sym_,
common_.t_,
prj_trans_,
geom_tr,
feature_,
common_.vars_,
common_.scale_factor_);
if (clip && feature_.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature_.paths()[0].type();
if (type == geometry_type::types::Polygon)
converter.template set<clip_poly_tag>();
else if (type == geometry_type::types::LineString)
converter.template set<clip_line_tag>();
}
converter.template set<transform_tag>(); //always transform
if (std::fabs(offset) > 0.0) converter.template set<offset_transform_tag>(); // parallel offset
converter.template set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature_, common_.vars_, converter, sym_);
}
private:
std::string const& filename_;
markers_symbolizer const& sym_;
mapnik::feature_impl & feature_;
proj_transform const& prj_trans_;
RendererType const& common_;
box2d<double> const& clip_box_;
ContextType const& renderer_context_;
};
template <typename VD, typename RD, typename RendererType, typename ContextType>
void render_markers_symbolizer(markers_symbolizer const& sym,
mapnik::feature_impl & feature,
@ -41,167 +265,18 @@ void render_markers_symbolizer(markers_symbolizer const& sym,
ContextType const& renderer_context)
{
using namespace mapnik::svg;
using vector_dispatch_type = VD;
using raster_dispatch_type = RD;
std::string filename = get<std::string>(sym, keys::file, feature, common.vars_, "shape://ellipse");
bool clip = get<value_bool, keys::clip>(sym, feature, common.vars_);
double offset = get<value_double, keys::offset>(sym, feature, common.vars_);
double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym, feature, common.vars_);
double smooth = get<value_double, keys::smooth>(sym, feature, common.vars_);
// https://github.com/mapnik/mapnik/issues/1316
bool snap_to_pixels = !mapnik::marker_cache::instance().is_uri(filename);
if (!filename.empty())
{
boost::optional<marker_ptr> mark = mapnik::marker_cache::instance().find(filename, true);
if (mark && *mark)
{
agg::trans_affine geom_tr;
auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
if (transform) evaluate_transform(geom_tr, feature, common.vars_, *transform, common.scale_factor_);
agg::trans_affine image_tr = agg::trans_affine_scaling(common.scale_factor_);
if ((*mark)->is_vector())
{
boost::optional<svg_path_ptr> const& stock_vector_marker = (*mark)->get_vector_data();
// special case for simple ellipse markers
// to allow for full control over rx/ry dimensions
if (filename == "shape://ellipse"
&& (has_key(sym,keys::width) || has_key(sym,keys::height)))
{
svg_path_ptr marker_ellipse = std::make_shared<svg_storage_type>();
vertex_stl_adapter<svg_path_storage> stl_storage(marker_ellipse->source());
svg_path_adapter svg_path(stl_storage);
build_ellipse(sym, feature, common.vars_, *marker_ellipse, svg_path);
svg_attribute_type attributes;
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym, feature, common.vars_);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature, common.vars_, *image_transform);
vector_dispatch_type rasterizer_dispatch(marker_ellipse,
svg_path,
result ? attributes : (*stock_vector_marker)->attributes(),
image_tr,
sym,
*common.detector_,
common.scale_factor_,
feature,
common.vars_,
snap_to_pixels,
renderer_context);
using vertex_converter_type = vertex_converter<vector_dispatch_type,clip_line_tag,
clip_poly_tag,
transform_tag,
affine_transform_tag,
simplify_tag, smooth_tag,
offset_transform_tag>;
vertex_converter_type converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,geom_tr,feature,common.vars_,common.scale_factor_);
if (clip && feature.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature.paths()[0].type();
if (type == geometry_type::types::Polygon)
converter.template set<clip_poly_tag>();
else if (type == geometry_type::types::LineString)
converter.template set<clip_line_tag>();
}
converter.template set<transform_tag>(); //always transform
if (std::fabs(offset) > 0.0) converter.template set<offset_transform_tag>(); // parallel offset
converter.template set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature, common.vars_, converter, sym);
}
else
{
box2d<double> const& bbox = (*mark)->bounding_box();
setup_transform_scaling(image_tr, bbox.width(), bbox.height(), feature, common.vars_, sym);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature, common.vars_, *image_transform);
vertex_stl_adapter<svg_path_storage> stl_storage((*stock_vector_marker)->source());
svg_path_adapter svg_path(stl_storage);
svg_attribute_type attributes;
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym, feature, common.vars_);
vector_dispatch_type rasterizer_dispatch(*stock_vector_marker,
svg_path,
result ? attributes : (*stock_vector_marker)->attributes(),
image_tr,
sym,
*common.detector_,
common.scale_factor_,
feature,
common.vars_,
snap_to_pixels,
renderer_context);
using vertex_converter_type = vertex_converter<vector_dispatch_type,clip_line_tag,
clip_poly_tag,
transform_tag,
affine_transform_tag,
simplify_tag, smooth_tag,
offset_transform_tag>;
vertex_converter_type converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,geom_tr,feature,common.vars_,common.scale_factor_);
if (clip && feature.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature.paths()[0].type();
if (type == geometry_type::types::Polygon)
converter.template set<clip_poly_tag>();
else if (type == geometry_type::types::LineString)
converter.template set<clip_line_tag>();
}
converter.template set<transform_tag>(); //always transform
if (std::fabs(offset) > 0.0) converter.template set<offset_transform_tag>(); // parallel offset
converter.template set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature, common.vars_, converter, sym);
}
}
else // raster markers
{
setup_transform_scaling(image_tr, (*mark)->width(), (*mark)->height(), feature, common.vars_, sym);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature, common.vars_, *image_transform);
box2d<double> const& bbox = (*mark)->bounding_box();
boost::optional<mapnik::image_ptr> marker = (*mark)->get_bitmap_data();
// - clamp sizes to > 4 pixels of interactivity
coord2d center = bbox.center();
agg::trans_affine_translation recenter(-center.x, -center.y);
agg::trans_affine marker_trans = recenter * image_tr;
raster_dispatch_type rasterizer_dispatch(**marker,
marker_trans,
sym,
*common.detector_,
common.scale_factor_,
feature,
common.vars_,
renderer_context);
using vertex_converter_type = vertex_converter<raster_dispatch_type,clip_line_tag,
clip_poly_tag,
transform_tag,
affine_transform_tag,
simplify_tag, smooth_tag,
offset_transform_tag>;
vertex_converter_type converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,geom_tr,feature,common.vars_,common.scale_factor_);
if (clip && feature.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature.paths()[0].type();
if (type == geometry_type::types::Polygon)
converter.template set<clip_poly_tag>();
else if (type == geometry_type::types::LineString)
converter.template set<clip_line_tag>();
}
converter.template set<transform_tag>(); //always transform
if (std::fabs(offset) > 0.0) converter.template set<offset_transform_tag>(); // parallel offset
converter.template set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature, common.vars_, converter, sym);
}
}
mapnik::marker const& mark = mapnik::marker_cache::instance().find(filename, true);
render_marker_symbolizer_visitor<VD,RD,RendererType,ContextType> visitor(filename,
sym,
feature,
prj_trans,
common,
clip_box,
renderer_context);
util::apply_visitor(visitor, mark);
}
}

View file

@ -41,18 +41,18 @@ void render_point_symbolizer(point_symbolizer const &sym,
F render_marker)
{
std::string filename = get<std::string,keys::file>(sym,feature, common.vars_);
boost::optional<mapnik::marker_ptr> marker = filename.empty()
? std::make_shared<mapnik::marker>()
mapnik::marker const& mark = filename.empty()
? mapnik::marker(std::move(mapnik::marker_rgba8()))
: marker_cache::instance().find(filename, true);
if (marker)
if (!mark.is<mapnik::marker_null>())
{
value_double opacity = get<value_double,keys::opacity>(sym, feature, common.vars_);
value_bool allow_overlap = get<value_bool, keys::allow_overlap>(sym, feature, common.vars_);
value_bool ignore_placement = get<value_bool, keys::ignore_placement>(sym, feature, common.vars_);
point_placement_enum placement= get<point_placement_enum, keys::point_placement_type>(sym, feature, common.vars_);
box2d<double> const& bbox = (*marker)->bounding_box();
box2d<double> const& bbox = mark.bounding_box();
coord2d center = bbox.center();
agg::trans_affine tr;
@ -89,7 +89,7 @@ void render_point_symbolizer(point_symbolizer const &sym,
{
render_marker(pixel_position(x, y),
**marker,
mark,
tr,
opacity);

View file

@ -24,6 +24,7 @@
#define MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP
// mapnik
#include <mapnik/image_util.hpp>
#include <mapnik/warp.hpp>
#include <mapnik/raster.hpp>
#include <mapnik/symbolizer.hpp>
@ -44,10 +45,10 @@ namespace mapnik {
namespace detail {
template <typename F>
struct image_data_dispatcher
struct image_dispatcher
{
using composite_function = F;
image_data_dispatcher(int start_x, int start_y,
image_dispatcher(int start_x, int start_y,
int width, int height,
double scale_x, double scale_y,
scaling_method_e method, double filter_factor,
@ -68,10 +69,10 @@ struct image_data_dispatcher
composite_(composite),
nodata_(nodata) {}
void operator() (image_data_null const& data_in) const {} //no-op
void operator() (image_data_rgba8 const& data_in) const
void operator() (image_null const& data_in) const {} //no-op
void operator() (image_rgba8 const& data_in) const
{
image_data_rgba8 data_out(width_, height_);
image_rgba8 data_out(width_, height_, true, true);
scale_image_agg(data_out, data_in, method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_);
composite_(data_out, comp_op_, opacity_, start_x_, start_y_);
}
@ -79,12 +80,13 @@ struct image_data_dispatcher
template <typename T>
void operator() (T const& data_in) const
{
using image_data_type = T;
image_data_type data_out(width_, height_);
using image_type = T;
image_type data_out(width_, height_);
scale_image_agg(data_out, data_in, method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_);
image_data_rgba8 dst(width_, height_);
image_rgba8 dst(width_, height_);
raster_colorizer_ptr colorizer = get<raster_colorizer_ptr>(sym_, keys::colorizer);
if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_);
premultiply_alpha(dst);
composite_(dst, comp_op_, opacity_, start_x_, start_y_);
}
private:
@ -105,10 +107,10 @@ private:
};
template <typename F>
struct image_data_warp_dispatcher
struct image_warp_dispatcher
{
using composite_function = F;
image_data_warp_dispatcher(proj_transform const& prj_trans,
image_warp_dispatcher(proj_transform const& prj_trans,
int start_x, int start_y, int width, int height,
box2d<double> const& target_ext, box2d<double> const& source_ext,
double offset_x, double offset_y, unsigned mesh_size, scaling_method_e scaling_method,
@ -133,11 +135,11 @@ struct image_data_warp_dispatcher
composite_(composite),
nodata_(nodata) {}
void operator() (image_data_null const& data_in) const {} //no-op
void operator() (image_null const& data_in) const {} //no-op
void operator() (image_data_rgba8 const& data_in) const
void operator() (image_rgba8 const& data_in) const
{
image_data_rgba8 data_out(width_, height_);
image_rgba8 data_out(width_, height_, true, true);
warp_image(data_out, data_in, prj_trans_, target_ext_, source_ext_, offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_);
composite_(data_out, comp_op_, opacity_, start_x_, start_y_);
}
@ -145,13 +147,14 @@ struct image_data_warp_dispatcher
template <typename T>
void operator() (T const& data_in) const
{
using image_data_type = T;
image_data_type data_out(width_, height_);
using image_type = T;
image_type data_out(width_, height_);
if (nodata_) data_out.set(*nodata_);
warp_image(data_out, data_in, prj_trans_, target_ext_, source_ext_, offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_);
image_data_rgba8 dst(width_, height_);
image_rgba8 dst(width_, height_);
raster_colorizer_ptr colorizer = get<raster_colorizer_ptr>(sym_, keys::colorizer);
if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_);
premultiply_alpha(dst);
composite_(dst, comp_op_, opacity_, start_x_, start_y_);
}
private:
@ -202,24 +205,14 @@ void render_raster_symbolizer(raster_symbolizer const& sym,
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, common.vars_, src_over);
double opacity = get<double>(sym,keys::opacity,feature, common.vars_, 1.0);
// only premultiply rgba8 images
if (source->data_.is<image_data_rgba8>())
if (source->data_.is<image_rgba8>())
{
bool premultiply_source = !source->premultiplied_alpha_;
auto is_premultiplied = get_optional<bool>(sym, keys::premultiplied, feature, common.vars_);
if (is_premultiplied)
if (is_premultiplied && *is_premultiplied)
{
if (*is_premultiplied) premultiply_source = false;
else premultiply_source = true;
}
if (premultiply_source)
{
agg::rendering_buffer buffer(source->data_.getBytes(),
source->data_.width(),
source->data_.height(),
source->data_.width() * 4);
agg::pixfmt_rgba32 pixf(buffer);
pixf.premultiply();
mapnik::set_premultiplied_alpha(source->data_, true);
}
mapnik::premultiply_alpha(source->data_);
}
if (!prj_trans.equal())
@ -227,7 +220,7 @@ void render_raster_symbolizer(raster_symbolizer const& sym,
double offset_x = ext.minx() - start_x;
double offset_y = ext.miny() - start_y;
unsigned mesh_size = static_cast<unsigned>(get<value_integer>(sym,keys::mesh_size,feature, common.vars_, 16));
detail::image_data_warp_dispatcher<F> dispatcher(prj_trans, start_x, start_y, raster_width, raster_height,
detail::image_warp_dispatcher<F> dispatcher(prj_trans, start_x, start_y, raster_width, raster_height,
target_ext, source->ext_, offset_x, offset_y, mesh_size,
scaling_method, source->get_filter_factor(),
opacity, comp_op, sym, feature, composite, source->nodata());
@ -243,14 +236,14 @@ void render_raster_symbolizer(raster_symbolizer const& sym,
(std::abs(start_x) <= eps) &&
(std::abs(start_y) <= eps) )
{
if (source->data_.is<image_data_rgba8>())
if (source->data_.is<image_rgba8>())
{
composite(util::get<image_data_rgba8>(source->data_), comp_op, opacity, start_x, start_y);
composite(util::get<image_rgba8>(source->data_), comp_op, opacity, start_x, start_y);
}
}
else
{
detail::image_data_dispatcher<F> dispatcher(start_x, start_y, raster_width, raster_height,
detail::image_dispatcher<F> dispatcher(start_x, start_y, raster_width, raster_height,
image_ratio_x, image_ratio_y,
scaling_method, source->get_filter_factor(),
opacity, comp_op, sym, feature, composite, source->nodata());

View file

@ -23,7 +23,7 @@
#ifndef MAPNIK_RENDER_PATTERN_HPP
#define MAPNIK_RENDER_PATTERN_HPP
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <memory>
// fwd decl
@ -35,12 +35,14 @@ namespace mapnik {
// fwd decl
struct rasterizer;
class marker;
struct marker_svg;
std::shared_ptr<image_data_rgba8> render_pattern(rasterizer & ras,
marker const& marker,
agg::trans_affine const& tr,
double opacity);
template <typename T>
void render_pattern(rasterizer & ras,
marker_svg const& marker,
agg::trans_affine const& tr,
double opacity,
T & image);
} // namespace mapnik

156
include/mapnik/sse.hpp Normal file
View file

@ -0,0 +1,156 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_SSE_HPP
#define MAPNIK_SSE_HPP
#include <emmintrin.h>
#include <xmmintrin.h>
#define ROUND_DOWN(x, s) ((x) & ~((s)-1))
typedef union
{
__m128i v;
int32_t i32[4];
uint32_t u32[4];
uint16_t u16[8];
uint8_t u8[16];
} m128_int;
static inline __m128i
_mm_cmple_epu16 (__m128i x, __m128i y)
{
// Returns 0xFFFF where x <= y:
return _mm_cmpeq_epi16(_mm_subs_epu16(x, y), _mm_setzero_si128());
}
static inline __m128i
_mm_cmple_epu8 (__m128i x, __m128i y)
{
// Returns 0xFF where x <= y:
return _mm_cmpeq_epi8(_mm_min_epu8(x, y), x);
}
static inline __m128i
_mm_cmpgt_epu16 (__m128i x, __m128i y)
{
// Returns 0xFFFF where x > y:
return _mm_andnot_si128(_mm_cmpeq_epi16(x, y), _mm_cmple_epu16(y, x));
}
static inline __m128i
_mm_cmpgt_epu8 (__m128i x, __m128i y)
{
// Returns 0xFF where x > y:
return _mm_andnot_si128(
_mm_cmpeq_epi8(x, y),
_mm_cmpeq_epi8(_mm_max_epu8(x, y), x)
);
}
static inline __m128i
_mm_cmplt_epu16 (__m128i x, __m128i y)
{
// Returns 0xFFFF where x < y:
return _mm_cmpgt_epu16(y, x);
}
static inline __m128i
_mm_cmplt_epu8 (__m128i x, __m128i y)
{
// Returns 0xFF where x < y:
return _mm_cmpgt_epu8(y, x);
}
static inline __m128i
_mm_cmpge_epu16 (__m128i x, __m128i y)
{
// Returns 0xFFFF where x >= y:
return _mm_cmple_epu16(y, x);
}
static inline __m128i
_mm_cmpge_epu8 (__m128i x, __m128i y)
{
// Returns 0xFF where x >= y:
return _mm_cmple_epu8(y, x);
}
// Its not often that you want to use this!
static inline __m128i
_mm_not_si128 (__m128i x)
{
// Returns ~x, the bitwise complement of x:
return _mm_xor_si128(x, _mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()));
}
static inline __m128i
_mm_absdiff_epu16 (__m128i x, __m128i y)
{
// Calculate absolute difference: abs(x - y):
return _mm_or_si128(_mm_subs_epu16(x, y), _mm_subs_epu16(y, x));
}
static inline __m128i
_mm_absdiff_epu8 (__m128i x, __m128i y)
{
// Calculate absolute difference: abs(x - y):
return _mm_or_si128(_mm_subs_epu8(x, y), _mm_subs_epu8(y, x));
}
static inline __m128i
_mm_div255_epu16 (__m128i x)
{
// Divide 8 16-bit uints by 255:
// x := ((x + 1) + (x >> 8)) >> 8:
return _mm_srli_epi16(_mm_adds_epu16(
_mm_adds_epu16(x, _mm_set1_epi16(1)),
_mm_srli_epi16(x, 8)), 8);
}
static __m128i
_mm_scale_epu8 (__m128i x, __m128i y)
{
// Returns an "alpha blend" of x scaled by y/255;
// x := x * (y / 255)
// Reorder: x := (x * y) / 255
// Unpack x and y into 16-bit uints:
__m128i xlo = _mm_unpacklo_epi8(x, _mm_setzero_si128());
__m128i ylo = _mm_unpacklo_epi8(y, _mm_setzero_si128());
__m128i xhi = _mm_unpackhi_epi8(x, _mm_setzero_si128());
__m128i yhi = _mm_unpackhi_epi8(y, _mm_setzero_si128());
// Multiply x with y, keeping the low 16 bits:
xlo = _mm_mullo_epi16(xlo, ylo);
xhi = _mm_mullo_epi16(xhi, yhi);
// Divide by 255:
xlo = _mm_div255_epu16(xlo);
xhi = _mm_div255_epu16(xhi);
// Repack the 16-bit uints to clamped 8-bit values:
return _mm_packus_epi16(xlo, xhi);
}
#endif // MAPNIK_SSE_HPP

View file

@ -53,7 +53,7 @@ namespace mapnik {
class feature_type_style;
class label_collision_detector4;
class layer;
class marker;
struct marker;
class proj_transform;
}

View file

@ -50,18 +50,20 @@ struct glyph_position
struct marker_info
{
marker_info() : marker(), transform() {}
marker_info(marker_ptr _marker, agg::trans_affine const& _transform) :
//marker_info() : marker(), transform() {}
marker_info(marker const& _marker, agg::trans_affine const& _transform) :
marker(_marker), transform(_transform) {}
marker_ptr marker;
marker const& marker;
agg::trans_affine transform;
};
using marker_info_ptr = std::shared_ptr<marker_info>;
/** Stores positions of glphys.
*
* The actual glyphs and their format are stored in text_layout.
*/
class glyph_positions
{
public:

View file

@ -25,7 +25,7 @@
#include <mapnik/global.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_data_any.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/util/variant.hpp>
extern "C"
@ -35,12 +35,13 @@ extern "C"
#define RealTIFFClose TIFFClose
}
//std
#include <memory>
#define TIFF_WRITE_SCANLINE 0
#define TIFF_WRITE_STRIPPED 1
#define TIFF_WRITE_TILED 2
#include <iostream>
namespace mapnik {
static inline tsize_t tiff_write_proc(thandle_t fd, tdata_t buf, tsize_t size)
@ -181,7 +182,7 @@ struct tiff_config
struct tag_setter
{
tag_setter(TIFF * output, tiff_config & config)
tag_setter(TIFF * output, tiff_config const& config)
: output_(output),
config_(config) {}
@ -192,15 +193,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_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)
@ -209,7 +217,76 @@ struct tag_setter
}
}
inline void operator() (image_data_gray32f const&) const
inline void operator() (image_gray64 const&) const
{
TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
TIFFSetField(output_, TIFFTAG_BITSPERSAMPLE, 64);
TIFFSetField(output_, TIFFTAG_SAMPLESPERPIXEL, 1);
if (config_.compression == COMPRESSION_DEFLATE
|| config_.compression == COMPRESSION_ADOBE_DEFLATE
|| config_.compression == COMPRESSION_LZW)
{
TIFFSetField(output_, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL);
}
}
inline void operator() (image_gray64s const&) const
{
TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
TIFFSetField(output_, TIFFTAG_BITSPERSAMPLE, 64);
TIFFSetField(output_, TIFFTAG_SAMPLESPERPIXEL, 1);
if (config_.compression == COMPRESSION_DEFLATE
|| config_.compression == COMPRESSION_ADOBE_DEFLATE
|| config_.compression == COMPRESSION_LZW)
{
TIFFSetField(output_, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL);
}
}
inline void operator() (image_gray64f const&) const
{
TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
TIFFSetField(output_, TIFFTAG_BITSPERSAMPLE, 64);
TIFFSetField(output_, TIFFTAG_SAMPLESPERPIXEL, 1);
if (config_.compression == COMPRESSION_DEFLATE
|| config_.compression == COMPRESSION_ADOBE_DEFLATE
|| config_.compression == COMPRESSION_LZW)
{
TIFFSetField(output_, TIFFTAG_PREDICTOR, PREDICTOR_FLOATINGPOINT);
}
}
inline void operator() (image_gray32 const&) const
{
TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
TIFFSetField(output_, TIFFTAG_BITSPERSAMPLE, 32);
TIFFSetField(output_, TIFFTAG_SAMPLESPERPIXEL, 1);
if (config_.compression == COMPRESSION_DEFLATE
|| config_.compression == COMPRESSION_ADOBE_DEFLATE
|| config_.compression == COMPRESSION_LZW)
{
TIFFSetField(output_, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL);
}
}
inline void operator() (image_gray32s const&) const
{
TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
TIFFSetField(output_, TIFFTAG_BITSPERSAMPLE, 32);
TIFFSetField(output_, TIFFTAG_SAMPLESPERPIXEL, 1);
if (config_.compression == COMPRESSION_DEFLATE
|| config_.compression == COMPRESSION_ADOBE_DEFLATE
|| config_.compression == COMPRESSION_LZW)
{
TIFFSetField(output_, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL);
}
}
inline void operator() (image_gray32f const&) const
{
TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
@ -222,7 +299,7 @@ struct tag_setter
TIFFSetField(output_, TIFFTAG_PREDICTOR, PREDICTOR_FLOATINGPOINT);
}
}
inline void operator() (image_data_gray16 const&) const
inline void operator() (image_gray16 const&) const
{
TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
@ -236,7 +313,21 @@ struct tag_setter
}
}
inline void operator() (image_data_gray8 const&) const
inline void operator() (image_gray16s const&) const
{
TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
TIFFSetField(output_, TIFFTAG_BITSPERSAMPLE, 16);
TIFFSetField(output_, TIFFTAG_SAMPLESPERPIXEL, 1);
if (config_.compression == COMPRESSION_DEFLATE
|| config_.compression == COMPRESSION_ADOBE_DEFLATE
|| config_.compression == COMPRESSION_LZW)
{
TIFFSetField(output_, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL);
}
}
inline void operator() (image_gray8 const&) const
{
TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
@ -250,7 +341,21 @@ struct tag_setter
}
}
inline void operator() (image_data_null const&) const
inline void operator() (image_gray8s const&) const
{
TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
TIFFSetField(output_, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(output_, TIFFTAG_SAMPLESPERPIXEL, 1);
if (config_.compression == COMPRESSION_DEFLATE
|| config_.compression == COMPRESSION_ADOBE_DEFLATE
|| config_.compression == COMPRESSION_LZW)
{
TIFFSetField(output_, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL);
}
}
inline void operator() (image_null const&) const
{
// Assume this would be null type
throw ImageWriterException("Could not write TIFF - Null image provided");
@ -258,10 +363,10 @@ struct tag_setter
private:
TIFF * output_;
tiff_config config_;
tiff_config const& config_;
};
void set_tiff_config(TIFF* output, tiff_config & config)
inline void set_tiff_config(TIFF* output, tiff_config const& config)
{
// Set some constant tiff information that doesn't vary based on type of data
// or image size
@ -282,7 +387,7 @@ void set_tiff_config(TIFF* output, tiff_config & config)
}
template <typename T1, typename T2>
void save_as_tiff(T1 & file, T2 const& image, tiff_config & config)
void save_as_tiff(T1 & file, T2 const& image, tiff_config const& config)
{
using pixel_type = typename T2::pixel_type;
@ -312,7 +417,6 @@ void save_as_tiff(T1 & file, T2 const& image, tiff_config & config)
// Set tags that vary based on the type of data being provided.
tag_setter set(output, config);
set(image);
//util::apply_visitor(set, image);
// Use specific types of writing methods.
if (TIFF_WRITE_SCANLINE == config.method)
@ -339,9 +443,7 @@ void save_as_tiff(T1 & file, T2 const& image, tiff_config & config)
TIFFSetField(output, TIFFTAG_ROWSPERSTRIP, rows_per_strip);
std::size_t strip_size = width * rows_per_strip;
std::unique_ptr<pixel_type[]> strip_buffer(new pixel_type[strip_size]);
int end_y=(height/rows_per_strip+1)*rows_per_strip;
for (int y=0; y < end_y; y+=rows_per_strip)
for (int y=0; y < height; y+=rows_per_strip)
{
int ty1 = std::min(height, static_cast<int>(y + rows_per_strip)) - y;
int row = y;
@ -380,7 +482,7 @@ void save_as_tiff(T1 & file, T2 const& image, tiff_config & config)
TIFFSetField(output, TIFFTAG_TILELENGTH, tile_height);
TIFFSetField(output, TIFFTAG_TILEDEPTH, 1);
std::size_t tile_size = tile_width * tile_height;
std::unique_ptr<pixel_type[]> image_data_out (new pixel_type[tile_size]);
std::unique_ptr<pixel_type[]> image_out (new pixel_type[tile_size]);
int end_y = (height / tile_height + 1) * tile_height;
int end_x = (width / tile_width + 1) * tile_width;
end_y = std::min(end_y, height);
@ -393,14 +495,14 @@ void save_as_tiff(T1 & file, T2 const& image, tiff_config & config)
for (int x = 0; x < end_x; x += tile_width)
{
// Prefill the entire array with zeros.
std::fill(image_data_out.get(), image_data_out.get() + tile_size, 0);
std::fill(image_out.get(), image_out.get() + tile_size, 0);
int tx1 = std::min(width, x + tile_width);
int row = y;
for (int ty = 0; ty < ty1; ++ty, ++row)
{
std::copy(image.getRow(row, x), image.getRow(row, tx1), image_data_out.get() + ty * tile_width);
std::copy(image.getRow(row, x), image.getRow(row, tx1), image_out.get() + ty * tile_width);
}
if (TIFFWriteEncodedTile(output, TIFFComputeTile(output, x, y, 0, 0), image_data_out.get(), tile_size * sizeof(pixel_type)) == -1)
if (TIFFWriteEncodedTile(output, TIFFComputeTile(output, x, y, 0, 0), image_out.get(), tile_size * sizeof(pixel_type)) == -1)
{
throw ImageWriterException("Could not write TIFF - TIFF Tile Write failed");
}

View file

@ -25,6 +25,7 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/pixel_types.hpp>
// icu
#include <unicode/uversion.h> // for U_NAMESPACE_QUALIFIER
@ -42,9 +43,13 @@ namespace mapnik {
#ifdef BIGINT
//using value_integer = boost::long_long_type;
using value_integer = long long;
//using value_integer = long long;
using value_integer = std::int64_t;
using value_integer_pixel = gray64s_t;
#else
using value_integer = int;
//using value_integer = int;
using value_integer = std::int32_t;
using value_integer_pixel = gray32s_t;
#endif
using value_double = double;

View file

@ -24,7 +24,7 @@
#define MAPNIK_WEBP_IO_HPP
// mapnik
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/util/conversions.hpp>
// webp
@ -73,14 +73,14 @@ std::string webp_encoding_error(WebPEncodingError error)
}
template <typename T2>
inline int import_image_data(T2 const& image,
inline int import_image(T2 const& im_in,
WebPPicture & pic,
bool alpha)
{
image_data<typename T2::pixel_type> const& data = image.data();
int stride = sizeof(typename T2::pixel_type) * image.width();
if (data.width() == image.width() &&
data.height() == image.height())
image<typename T2::pixel> const& data = im_in.data();
int stride = sizeof(typename T2::pixel_type) * im_in.width();
if (data.width() == im_in.width() &&
data.height() == im_in.height())
{
if (alpha)
{
@ -98,11 +98,11 @@ inline int import_image_data(T2 const& image,
else
{
// need to copy: https://github.com/mapnik/mapnik/issues/2024
image_data_rgba8 im(image.width(),image.height());
for (unsigned y = 0; y < image.height(); ++y)
image_rgba8 im(im_in.width(),im_in.height());
for (unsigned y = 0; y < im_in.height(); ++y)
{
typename T2::pixel_type const * row_from = image.getRow(y);
image_data_rgba8::pixel_type * row_to = im.getRow(y);
typename T2::pixel_type const * row_from = im_in.getRow(y);
image_rgba8::pixel_type * row_to = im.getRow(y);
std::copy(row_from, row_from + stride, row_to);
}
if (alpha)
@ -121,11 +121,11 @@ inline int import_image_data(T2 const& image,
}
template <>
inline int import_image_data(image_data_rgba8 const& im,
inline int import_image(image_rgba8 const& im,
WebPPicture & pic,
bool alpha)
{
int stride = sizeof(image_data_rgba8::pixel_type) * im.width();
int stride = sizeof(image_rgba8::pixel_type) * im.width();
if (alpha)
{
return WebPPictureImportRGBA(&pic, im.getBytes(), stride);
@ -187,10 +187,10 @@ void save_as_webp(T1& file,
{
// different approach for lossy since ImportYUVAFromRGBA is needed
// to prepare WebPPicture and working with view pixels is not viable
ok = import_image_data(image,pic,alpha);
ok = import_image(image,pic,alpha);
}
#else
ok = import_image_data(image,pic,alpha);
ok = import_image(image,pic,alpha);
#endif
if (!ok)
{

View file

@ -25,6 +25,7 @@
//mapnik
#include <mapnik/debug.hpp>
#include <mapnik/value_types.hpp>
#include <mapnik/xml_tree.hpp>
#include <mapnik/enumeration.hpp>
#include <mapnik/boolean.hpp>
@ -87,14 +88,14 @@ struct do_xml_attribute_cast<int>
#ifdef BIGINT
// specialization for long long
template <>
struct do_xml_attribute_cast<long long>
struct do_xml_attribute_cast<mapnik::value_integer>
{
static inline boost::optional<long long> xml_attribute_cast_impl(xml_tree const& /*tree*/, std::string const& source)
static inline boost::optional<mapnik::value_integer> xml_attribute_cast_impl(xml_tree const& /*tree*/, std::string const& source)
{
int result;
if (mapnik::util::string2int(source, result))
return boost::optional<long long>(result);
return boost::optional<long long>();
return boost::optional<mapnik::value_integer>(result);
return boost::optional<mapnik::value_integer>();
}
};

View file

@ -24,7 +24,7 @@
#include <mapnik/make_unique.hpp>
#include <mapnik/global.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/raster.hpp>
#include <mapnik/view_transform.hpp>
#include <mapnik/feature.hpp>
@ -203,33 +203,99 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Reading band=" << band_;
if (band_ > 0) // we are querying a single band
{
mapnik::image_data_gray16 image(im_width, im_height);
image.set(std::numeric_limits<std::int16_t>::max());
GDALRasterBand * band = dataset_.GetRasterBand(band_);
if (band_ > nbands_)
{
std::ostringstream s;
s << "GDAL Plugin: " << band_ << " is an invalid band, dataset only has " << nbands_ << "bands";
throw datasource_exception(s.str());
}
GDALRasterBand * band = dataset_.GetRasterBand(band_);
raster_nodata = band->GetNoDataValue(&raster_has_nodata);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
image.getData(), image.width(), image.height(),
GDT_Int16, 0, 0);
if (raster_io_error == CE_Failure)
GDALDataType band_type = band->GetRasterDataType();
switch (band_type)
{
throw datasource_exception(CPLGetLastErrorMsg());
case GDT_Byte:
{
mapnik::image_gray8 image(im_width, im_height);
image.set(std::numeric_limits<std::uint8_t>::max());
raster_nodata = band->GetNoDataValue(&raster_has_nodata);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
image.getData(), image.width(), image.height(),
GDT_Byte, 0, 0);
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);
// set nodata value to be used in raster colorizer
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
break;
}
case GDT_Float64:
case GDT_Float32:
{
mapnik::image_gray32f image(im_width, im_height);
image.set(std::numeric_limits<float>::max());
raster_nodata = band->GetNoDataValue(&raster_has_nodata);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
image.getData(), image.width(), image.height(),
GDT_Float32, 0, 0);
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);
// set nodata value to be used in raster colorizer
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
break;
}
case GDT_UInt16:
{
mapnik::image_gray16 image(im_width, im_height);
image.set(std::numeric_limits<std::uint16_t>::max());
raster_nodata = band->GetNoDataValue(&raster_has_nodata);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
image.getData(), image.width(), image.height(),
GDT_UInt16, 0, 0);
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);
// set nodata value to be used in raster colorizer
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
break;
}
default:
case GDT_Int16:
{
mapnik::image_gray16s image(im_width, im_height);
image.set(std::numeric_limits<std::int16_t>::max());
raster_nodata = band->GetNoDataValue(&raster_has_nodata);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
image.getData(), image.width(), image.height(),
GDT_Int16, 0, 0);
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);
// set nodata value to be used in raster colorizer
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
break;
}
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);
// set nodata value to be used in raster colorizer
if (nodata_value_) raster->set_nodata(*nodata_value_);
else raster->set_nodata(raster_nodata);
feature->set_raster(raster);
}
else // working with all bands
{
mapnik::image_data_rgba8 image(im_width, im_height);
mapnik::image_rgba8 image(im_width, im_height);
image.set(std::numeric_limits<std::uint32_t>::max());
for (int i = 0; i < nbands_; ++i)
{

View file

@ -38,7 +38,7 @@
#include <mapnik/feature_factory.hpp>
#include <mapnik/view_transform.hpp>
#include <mapnik/raster.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/util/conversions.hpp>
#include <mapnik/util/trim.hpp>
#include <mapnik/global.hpp> // for int2net

View file

@ -32,7 +32,7 @@
#include <mapnik/debug.hpp>
#include <mapnik/view_transform.hpp>
#include <mapnik/raster.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/util/conversions.hpp>
#include <mapnik/util/trim.hpp>
#include <mapnik/box2d.hpp> // for box2d
@ -183,12 +183,7 @@ mapnik::raster_ptr read_data_band(mapnik::box2d<double> const& bbox,
uint16_t width, uint16_t height,
bool hasnodata, T reader)
{
mapnik::image_data_gray32f image(width, height);
//image.set(std::numeric_limits<float>::max());
// Start with plain white (ABGR or RGBA depending on endiannes)
// TODO: set to transparent instead?
image.set(0xffffffff);
mapnik::image_gray32f image(width, height);
float* data = image.getData();
double val;
val = reader(); // nodata value, need to read anyway
@ -199,7 +194,7 @@ mapnik::raster_ptr read_data_band(mapnik::box2d<double> const& bbox,
data[off] = val;
}
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(bbox, image, 1.0, true);
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(bbox, image, 1.0);
if ( hasnodata ) raster->set_nodata(val);
return raster;
}
@ -271,7 +266,7 @@ mapnik::raster_ptr read_grayscale_band(mapnik::box2d<double> const& bbox,
uint16_t width, uint16_t height,
bool hasnodata, T reader)
{
mapnik::image_data_rgba8 image(width,height);
mapnik::image_rgba8 image(width,height, true, true);
// Start with plain white (ABGR or RGBA depending on endiannes)
// TODO: set to transparent instead?
image.set(0xffffffff);
@ -279,7 +274,7 @@ mapnik::raster_ptr read_grayscale_band(mapnik::box2d<double> const& bbox,
int val;
uint8_t * data = image.getBytes();
int ps = 4; // sizeof(image_data::pixel_type)
int ps = 4; // sizeof(image::pixel_type)
int off;
val = reader(); // nodata value, need to read anyway
for (int y=0; y<height; ++y) {
@ -292,7 +287,7 @@ mapnik::raster_ptr read_grayscale_band(mapnik::box2d<double> const& bbox,
data[off+2] = val;
}
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(bbox, image, 1.0, true);
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(bbox, image, 1.0);
if ( hasnodata ) raster->set_nodata(val);
return raster;
}
@ -352,9 +347,9 @@ mapnik::raster_ptr pgraster_wkb_reader::read_grayscale(mapnik::box2d<double> con
mapnik::raster_ptr pgraster_wkb_reader::read_rgba(mapnik::box2d<double> const& bbox,
uint16_t width, uint16_t height)
{
mapnik::image_data_rgba8 image(width, height);
mapnik::image_rgba8 im(width, height, true, true);
// Start with plain white (ABGR or RGBA depending on endiannes)
image.set(0xffffffff);
im.set(0xffffffff);
uint8_t nodataval;
for (int bn=0; bn<numBands_; ++bn) {
@ -387,8 +382,8 @@ mapnik::raster_ptr pgraster_wkb_reader::read_rgba(mapnik::box2d<double> const& b
<< " nodataval " << tmp << " != band 0 nodataval " << nodataval;
}
int ps = 4; // sizeof(image_data::pixel_type)
uint8_t * image_data = image.getBytes();
int ps = 4; // sizeof(image::pixel_type)
uint8_t * image_data = im.getBytes();
for (int y=0; y<height_; ++y) {
for (int x=0; x<width_; ++x) {
uint8_t val = read_uint8(&ptr_);
@ -400,7 +395,7 @@ mapnik::raster_ptr pgraster_wkb_reader::read_rgba(mapnik::box2d<double> const& b
}
}
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(bbox, image, 1.0, true);
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(bbox, im, 1.0);
raster->set_nodata(0xffffffff);
return raster;
}

View file

@ -22,7 +22,7 @@
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/raster.hpp>
#include <mapnik/view_transform.hpp>
#include <mapnik/image_reader.hpp>
@ -43,7 +43,7 @@
using mapnik::query;
using mapnik::image_reader;
using mapnik::feature_ptr;
using mapnik::image_data_rgba8;
using mapnik::image_rgba8;
using mapnik::raster;
using mapnik::feature_factory;
@ -114,9 +114,8 @@ feature_ptr raster_featureset<LookupPolicy>::next()
rem.maxx() + x_off + width,
rem.maxy() + y_off + height);
intersect = t.backward(feature_raster_extent);
mapnik::image_data_any data = reader->read(x_off, y_off, width, height);
mapnik::image_any data = reader->read(x_off, y_off, width, height);
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, std::move(data), 1.0);
raster->premultiplied_alpha_ = reader->premultiplied_alpha();
feature->set_raster(raster);
}
}

View file

@ -24,7 +24,7 @@
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/query.hpp>
#include <mapnik/raster.hpp>
@ -114,10 +114,9 @@ feature_ptr rasterlite_featureset::get_feature(mapnik::query const& q)
{
if (size > 0)
{
mapnik::image_data_rgba8 image(width,height);
mapnik::image_rgba8 image(width,height);
unsigned char* raster_data = static_cast<unsigned char*>(raster);
unsigned char* image_data = image.getBytes();
std::memcpy(image_data, raster_data, size);
std::memcpy(image.getBytes(), raster_data, size);
feature->set_raster(std::make_shared<mapnik::raster>(intersect, std::move(image), 1.0));
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_featureset: Done";
}

View file

@ -24,7 +24,6 @@
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/agg_helpers.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/rule.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/layer.hpp>
@ -43,6 +42,7 @@
#include <mapnik/image_compositing.hpp>
#include <mapnik/image_filter.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_any.hpp>
// agg
#include "agg_rendering_buffer.h"
#include "agg_pixfmt_rgba.h"
@ -108,9 +108,52 @@ agg_renderer<T0,T1>::agg_renderer(Map const& m, T0 & pixmap, std::shared_ptr<T1>
setup(m);
}
template <typename buffer_type>
struct setup_agg_bg_visitor
{
setup_agg_bg_visitor(buffer_type & pixmap,
renderer_common const& common,
composite_mode_e mode,
double opacity)
: pixmap_(pixmap),
common_(common),
mode_(mode),
opacity_(opacity) {}
void operator() (marker_null const&) {}
void operator() (marker_svg const&) {}
void operator() (marker_rgba8 const& marker)
{
mapnik::image_rgba8 const& bg_image = marker.get_data();
int w = bg_image.width();
int h = bg_image.height();
if ( w > 0 && h > 0)
{
// repeat background-image both vertically and horizontally
unsigned x_steps = static_cast<unsigned>(std::ceil(common_.width_/double(w)));
unsigned y_steps = static_cast<unsigned>(std::ceil(common_.height_/double(h)));
for (unsigned x=0;x<x_steps;++x)
{
for (unsigned y=0;y<y_steps;++y)
{
composite(pixmap_, bg_image, mode_, opacity_, x*w, y*h);
}
}
}
}
private:
buffer_type & pixmap_;
renderer_common const& common_;
composite_mode_e mode_;
double opacity_;
};
template <typename T0, typename T1>
void agg_renderer<T0,T1>::setup(Map const &m)
{
mapnik::set_premultiplied_alpha(pixmap_, true);
boost::optional<color> const& bg = m.background();
if (bg)
{
@ -118,11 +161,13 @@ void agg_renderer<T0,T1>::setup(Map const &m)
{
mapnik::color bg_color = *bg;
bg_color.premultiply();
pixmap_.set_background(bg_color);
mapnik::fill(pixmap_, bg_color);
}
else
{
pixmap_.set_background(*bg);
mapnik::color bg_color = *bg;
bg_color.set_premultiplied(true);
mapnik::fill(pixmap_,bg_color);
}
}
@ -130,26 +175,12 @@ void agg_renderer<T0,T1>::setup(Map const &m)
if (image_filename)
{
// NOTE: marker_cache returns premultiplied image, if needed
boost::optional<mapnik::marker_ptr> bg_marker = mapnik::marker_cache::instance().find(*image_filename,true);
if (bg_marker && (*bg_marker)->is_bitmap())
{
mapnik::image_ptr bg_image = *(*bg_marker)->get_bitmap_data();
int w = bg_image->width();
int h = bg_image->height();
if ( w > 0 && h > 0)
{
// repeat background-image both vertically and horizontally
unsigned x_steps = static_cast<unsigned>(std::ceil(common_.width_/double(w)));
unsigned y_steps = static_cast<unsigned>(std::ceil(common_.height_/double(h)));
for (unsigned x=0;x<x_steps;++x)
{
for (unsigned y=0;y<y_steps;++y)
{
composite(pixmap_.data(),*bg_image, m.background_image_comp_op(), m.background_image_opacity(), x*w, y*h, false);
}
}
}
}
mapnik::marker const& bg_marker = mapnik::marker_cache::instance().find(*image_filename,true);
setup_agg_bg_visitor<buffer_type> visitor(pixmap_,
common_,
m.background_image_comp_op(),
m.background_image_opacity());
util::apply_visitor(visitor, bg_marker);
}
MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Scale=" << m.scale();
}
@ -167,10 +198,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_);
MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: End map processing";
}
@ -239,7 +267,7 @@ void agg_renderer<T0,T1>::start_style_processing(feature_type_style const& st)
}
else
{
internal_buffer_->set_background(color(0,0,0,0)); // fill with transparent colour
mapnik::fill(*internal_buffer_, 0); // fill with transparent colour
}
}
else
@ -250,12 +278,13 @@ void agg_renderer<T0,T1>::start_style_processing(feature_type_style const& st)
}
else
{
internal_buffer_->set_background(color(0,0,0,0)); // fill with transparent colour
mapnik::fill(*internal_buffer_, 0); // fill with transparent colour
}
common_.t_.set_offset(0);
ras_ptr->clip_box(0,0,common_.width_,common_.height_);
}
current_buffer_ = internal_buffer_.get();
set_premultiplied_alpha(*current_buffer_,true);
}
else
{
@ -274,7 +303,7 @@ void agg_renderer<T0,T1>::end_style_processing(feature_type_style const& st)
if (st.image_filters().size() > 0)
{
blend_from = true;
mapnik::filter::filter_visitor<image_32> visitor(*current_buffer_);
mapnik::filter::filter_visitor<buffer_type> visitor(*current_buffer_);
for (mapnik::filter::filter_type const& filter_tag : st.image_filters())
{
util::apply_visitor(visitor, filter_tag);
@ -282,21 +311,21 @@ void agg_renderer<T0,T1>::end_style_processing(feature_type_style const& st)
}
if (st.comp_op())
{
composite(pixmap_.data(), current_buffer_->data(),
composite(pixmap_, *current_buffer_,
*st.comp_op(), st.get_opacity(),
-common_.t_.offset(),
-common_.t_.offset(), false);
-common_.t_.offset());
}
else if (blend_from || st.get_opacity() < 1.0)
{
composite(pixmap_.data(), current_buffer_->data(),
composite(pixmap_, *current_buffer_,
src_over, st.get_opacity(),
-common_.t_.offset(),
-common_.t_.offset(), false);
-common_.t_.offset());
}
}
// apply any 'direct' image filters
mapnik::filter::filter_visitor<image_32> visitor(pixmap_);
mapnik::filter::filter_visitor<buffer_type> visitor(pixmap_);
for (mapnik::filter::filter_type const& filter_tag : st.direct_image_filters())
{
util::apply_visitor(visitor, filter_tag);
@ -304,87 +333,128 @@ void agg_renderer<T0,T1>::end_style_processing(feature_type_style const& st)
MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: End processing style";
}
template <typename T0, typename T1>
void agg_renderer<T0,T1>::render_marker(pixel_position const& pos,
marker const& marker,
agg::trans_affine const& tr,
double opacity,
composite_mode_e comp_op)
template <typename buffer_type>
struct agg_render_marker_visitor
{
using color_type = agg::rgba8;
using order_type = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color_type, order_type>; // comp blender
using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
using renderer_type = agg::renderer_scanline_aa_solid<renderer_base>;
using svg_attribute_type = agg::pod_bvector<mapnik::svg::path_attributes>;
agg_render_marker_visitor(renderer_common & common,
buffer_type * current_buffer,
std::unique_ptr<rasterizer> const& ras_ptr,
gamma_method_enum & gamma_method,
double & gamma,
pixel_position const& pos,
agg::trans_affine const& tr,
double opacity,
composite_mode_e comp_op)
: common_(common),
current_buffer_(current_buffer),
ras_ptr_(ras_ptr),
gamma_method_(gamma_method),
gamma_(gamma),
pos_(pos),
tr_(tr),
opacity_(opacity),
comp_op_(comp_op) {}
ras_ptr->reset();
if (gamma_method_ != GAMMA_POWER || gamma_ != 1.0)
{
ras_ptr->gamma(agg::gamma_power());
gamma_method_ = GAMMA_POWER;
gamma_ = 1.0;
}
agg::scanline_u8 sl;
agg::rendering_buffer buf(current_buffer_->raw_data(),
current_buffer_->width(),
current_buffer_->height(),
current_buffer_->width() * 4);
pixfmt_comp_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(comp_op));
renderer_base renb(pixf);
void operator() (marker_null const&) {}
if (marker.is_vector())
void operator() (marker_svg const& marker)
{
box2d<double> const& bbox = (*marker.get_vector_data())->bounding_box();
using color_type = agg::rgba8;
using order_type = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color_type, order_type>; // comp blender
using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
using renderer_type = agg::renderer_scanline_aa_solid<renderer_base>;
using svg_attribute_type = agg::pod_bvector<mapnik::svg::path_attributes>;
ras_ptr_->reset();
if (gamma_method_ != GAMMA_POWER || gamma_ != 1.0)
{
ras_ptr_->gamma(agg::gamma_power());
gamma_method_ = GAMMA_POWER;
gamma_ = 1.0;
}
agg::scanline_u8 sl;
agg::rendering_buffer buf(current_buffer_->getBytes(),
current_buffer_->width(),
current_buffer_->height(),
current_buffer_->getRowSize());
pixfmt_comp_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(comp_op_));
renderer_base renb(pixf);
box2d<double> const& bbox = marker.get_data()->bounding_box();
coord<double,2> c = bbox.center();
// center the svg marker on '0,0'
agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y);
// apply symbol transformation to get to map space
mtx *= tr;
mtx *= tr_;
mtx *= agg::trans_affine_scaling(common_.scale_factor_);
// render the marker at the center of the marker box
mtx.translate(pos.x, pos.y);
mtx.translate(pos_.x, pos_.y);
using namespace mapnik::svg;
vertex_stl_adapter<svg_path_storage> stl_storage((*marker.get_vector_data())->source());
vertex_stl_adapter<svg_path_storage> stl_storage(marker.get_data()->source());
svg_path_adapter svg_path(stl_storage);
svg_renderer_agg<svg_path_adapter,
svg_attribute_type,
renderer_type,
pixfmt_comp_type> svg_renderer(svg_path,
(*marker.get_vector_data())->attributes());
marker.get_data()->attributes());
// https://github.com/mapnik/mapnik/issues/1316
// https://github.com/mapnik/mapnik/issues/1866
mtx.tx = std::floor(mtx.tx+.5);
mtx.ty = std::floor(mtx.ty+.5);
svg_renderer.render(*ras_ptr, sl, renb, mtx, opacity, bbox);
svg_renderer.render(*ras_ptr_, sl, renb, mtx, opacity_, bbox);
}
else
void operator() (marker_rgba8 const& marker)
{
double width = (*marker.get_bitmap_data())->width();
double height = (*marker.get_bitmap_data())->height();
using color_type = agg::rgba8;
using order_type = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color_type, order_type>; // comp blender
using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
using renderer_type = agg::renderer_scanline_aa_solid<renderer_base>;
using svg_attribute_type = agg::pod_bvector<mapnik::svg::path_attributes>;
ras_ptr_->reset();
if (gamma_method_ != GAMMA_POWER || gamma_ != 1.0)
{
ras_ptr_->gamma(agg::gamma_power());
gamma_method_ = GAMMA_POWER;
gamma_ = 1.0;
}
agg::scanline_u8 sl;
agg::rendering_buffer buf(current_buffer_->getBytes(),
current_buffer_->width(),
current_buffer_->height(),
current_buffer_->getRowSize());
pixfmt_comp_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(comp_op_));
renderer_base renb(pixf);
double width = marker.width();
double height = marker.height();
if (std::fabs(1.0 - common_.scale_factor_) < 0.001
&& (std::fabs(1.0 - tr.sx) < agg::affine_epsilon)
&& (std::fabs(0.0 - tr.shy) < agg::affine_epsilon)
&& (std::fabs(0.0 - tr.shx) < agg::affine_epsilon)
&& (std::fabs(1.0 - tr.sy) < agg::affine_epsilon))
&& (std::fabs(1.0 - tr_.sx) < agg::affine_epsilon)
&& (std::fabs(0.0 - tr_.shy) < agg::affine_epsilon)
&& (std::fabs(0.0 - tr_.shx) < agg::affine_epsilon)
&& (std::fabs(1.0 - tr_.sy) < agg::affine_epsilon))
{
double cx = 0.5 * width;
double cy = 0.5 * height;
composite(current_buffer_->data(), **marker.get_bitmap_data(),
comp_op, opacity,
std::floor(pos.x - cx + .5),
std::floor(pos.y - cy + .5),
false);
composite(*current_buffer_, marker.get_data(),
comp_op_, opacity_,
std::floor(pos_.x - cx + .5),
std::floor(pos_.y - cy + .5));
}
else
{
double p[8];
double x0 = pos.x - 0.5 * width;
double y0 = pos.y - 0.5 * height;
double x0 = pos_.x - 0.5 * width;
double y0 = pos_.y - 0.5 * height;
p[0] = x0; p[1] = y0;
p[2] = x0 + width; p[3] = y0;
p[4] = x0 + width; p[5] = y0 + height;
@ -392,31 +462,31 @@ void agg_renderer<T0,T1>::render_marker(pixel_position const& pos,
agg::trans_affine marker_tr;
marker_tr *= agg::trans_affine_translation(-pos.x,-pos.y);
marker_tr *= tr;
marker_tr *= agg::trans_affine_translation(-pos_.x,-pos_.y);
marker_tr *= tr_;
marker_tr *= agg::trans_affine_scaling(common_.scale_factor_);
marker_tr *= agg::trans_affine_translation(pos.x,pos.y);
marker_tr *= agg::trans_affine_translation(pos_.x,pos_.y);
marker_tr.transform(&p[0], &p[1]);
marker_tr.transform(&p[2], &p[3]);
marker_tr.transform(&p[4], &p[5]);
marker_tr.transform(&p[6], &p[7]);
ras_ptr->move_to_d(p[0],p[1]);
ras_ptr->line_to_d(p[2],p[3]);
ras_ptr->line_to_d(p[4],p[5]);
ras_ptr->line_to_d(p[6],p[7]);
ras_ptr_->move_to_d(p[0],p[1]);
ras_ptr_->line_to_d(p[2],p[3]);
ras_ptr_->line_to_d(p[4],p[5]);
ras_ptr_->line_to_d(p[6],p[7]);
agg::span_allocator<color_type> sa;
agg::image_filter_bilinear filter_kernel;
agg::image_filter_lut filter(filter_kernel, false);
image_data_rgba8 const& src = **marker.get_bitmap_data();
buffer_type const& src = marker.get_data();
agg::rendering_buffer marker_buf((unsigned char *)src.getBytes(),
src.width(),
src.height(),
src.width()*4);
src.getRowSize());
agg::pixfmt_rgba32_pre marker_pixf(marker_buf);
using img_accessor_type = agg::image_accessor_clone<agg::pixfmt_rgba32_pre>;
using interpolator_type = agg::span_interpolator_linear<agg::trans_affine>;
@ -431,10 +501,41 @@ void agg_renderer<T0,T1>::render_marker(pixel_position const& pos,
final_tr.ty = std::floor(final_tr.ty+.5);
interpolator_type interpolator(final_tr);
span_gen_type sg(ia, interpolator, filter);
renderer_type rp(renb,sa, sg, unsigned(opacity*255));
agg::render_scanlines(*ras_ptr, sl, rp);
renderer_type rp(renb,sa, sg, unsigned(opacity_*255));
agg::render_scanlines(*ras_ptr_, sl, rp);
}
}
private:
renderer_common & common_;
buffer_type * current_buffer_;
std::unique_ptr<rasterizer> const& ras_ptr_;
gamma_method_enum & gamma_method_;
double & gamma_;
pixel_position const& pos_;
agg::trans_affine const& tr_;
double opacity_;
composite_mode_e comp_op_;
};
template <typename T0, typename T1>
void agg_renderer<T0,T1>::render_marker(pixel_position const& pos,
marker const& marker,
agg::trans_affine const& tr,
double opacity,
composite_mode_e comp_op)
{
agg_render_marker_visitor<buffer_type> visitor(common_,
current_buffer_,
ras_ptr,
gamma_method_,
gamma_,
pos,
tr,
opacity,
comp_op);
util::apply_visitor(visitor, marker);
}
template <typename T0, typename T1>
@ -453,10 +554,10 @@ template <typename T0, typename T1>
void agg_renderer<T0,T1>::debug_draw_box(box2d<double> const& box,
double x, double y, double angle)
{
agg::rendering_buffer buf(current_buffer_->raw_data(),
agg::rendering_buffer buf(current_buffer_->getBytes(),
current_buffer_->width(),
current_buffer_->height(),
current_buffer_->width() * 4);
current_buffer_->getRowSize());
debug_draw_box(buf, box, x, y, angle);
}
@ -509,19 +610,19 @@ void agg_renderer<T0,T1>::draw_geo_extent(box2d<double> const& extent, mapnik::c
unsigned rgba = color.rgba();
for (double x=x0; x<x1; x++)
{
pixmap_.setPixel(x, y0, rgba);
pixmap_.setPixel(x, y1, rgba);
mapnik::set_pixel(pixmap_, x, y0, rgba);
mapnik::set_pixel(pixmap_, x, y1, rgba);
}
for (double y=y0; y<y1; y++)
{
pixmap_.setPixel(x0, y, rgba);
pixmap_.setPixel(x1, y, rgba);
mapnik::set_pixel(pixmap_, x0, y, rgba);
mapnik::set_pixel(pixmap_, x1, y, rgba);
}
}
template class agg_renderer<image_32>;
template void agg_renderer<image_32>::debug_draw_box<agg::rendering_buffer>(
template class agg_renderer<image_rgba8>;
template void agg_renderer<image_rgba8>::debug_draw_box<agg::rendering_buffer>(
agg::rendering_buffer& buf,
box2d<double> const& box,
double x, double y, double angle);
}
} // end ns

View file

@ -22,7 +22,7 @@
// mapnik
#include <mapnik/make_unique.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
@ -58,7 +58,7 @@ void agg_renderer<T0,T1>::process(building_symbolizer const& sym,
using ren_base = agg::renderer_base<agg::pixfmt_rgba32_pre>;
using renderer = agg::renderer_scanline_aa_solid<ren_base>;
agg::rendering_buffer buf(current_buffer_->raw_data(),current_buffer_->width(),current_buffer_->height(), current_buffer_->width() * 4);
agg::rendering_buffer buf(current_buffer_->getBytes(),current_buffer_->width(),current_buffer_->height(), current_buffer_->getRowSize());
agg::pixfmt_rgba32_pre pixf(buf);
ren_base renb(pixf);
@ -115,8 +115,7 @@ void agg_renderer<T0,T1>::process(building_symbolizer const& sym,
});
}
template void agg_renderer<image_32>::process(building_symbolizer const&,
template void agg_renderer<image_rgba8>::process(building_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);
}

View file

@ -23,13 +23,15 @@
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/image_util.hpp>
namespace mapnik {
void draw_rect(image_32 &pixmap, box2d<double> const& box)
template <typename T>
void draw_rect(T &pixmap, box2d<double> const& box)
{
int x0 = static_cast<int>(box.minx());
int x1 = static_cast<int>(box.maxx());
@ -38,13 +40,13 @@ void draw_rect(image_32 &pixmap, box2d<double> const& box)
unsigned color1 = 0xff0000ff;
for (int x=x0; x<x1; x++)
{
pixmap.setPixel(x, y0, color1);
pixmap.setPixel(x, y1, color1);
mapnik::set_pixel(pixmap, x, y0, color1);
mapnik::set_pixel(pixmap, x, y1, color1);
}
for (int y=y0; y<y1; y++)
{
pixmap.setPixel(x0, y, color1);
pixmap.setPixel(x1, y, color1);
mapnik::set_pixel(pixmap, x0, y, color1);
mapnik::set_pixel(pixmap, x1, y, color1);
}
}
@ -80,17 +82,17 @@ void agg_renderer<T0,T1>::process(debug_symbolizer const& sym,
if (cmd == SEG_CLOSE) continue;
prj_trans.backward(x,y,z);
common_.t_.forward(&x,&y);
pixmap_.setPixel(x,y,0xff0000ff);
pixmap_.setPixel(x-1,y-1,0xff0000ff);
pixmap_.setPixel(x+1,y+1,0xff0000ff);
pixmap_.setPixel(x-1,y+1,0xff0000ff);
pixmap_.setPixel(x+1,y-1,0xff0000ff);
mapnik::set_pixel(pixmap_,x,y,0xff0000ff);
mapnik::set_pixel(pixmap_,x-1,y-1,0xff0000ff);
mapnik::set_pixel(pixmap_,x+1,y+1,0xff0000ff);
mapnik::set_pixel(pixmap_,x-1,y+1,0xff0000ff);
mapnik::set_pixel(pixmap_,x+1,y-1,0xff0000ff);
}
}
}
}
template void agg_renderer<image_32>::process(debug_symbolizer const&,
template void agg_renderer<image_rgba8>::process(debug_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);
}

View file

@ -26,7 +26,7 @@
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/symbolizer_keys.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/image.hpp>
#include <mapnik/vertex.hpp>
#include <mapnik/renderer_common.hpp>
#include <mapnik/proj_transform.hpp>
@ -70,7 +70,7 @@ void agg_renderer<T0,T1>::process(dot_symbolizer const& sym,
double opacity = get<double>(sym, keys::opacity, feature, common_.vars_, 1.0);
color const& fill = get<mapnik::color>(sym, keys::fill, feature, common_.vars_, mapnik::color(128,128,128));
ras_ptr->reset();
agg::rendering_buffer buf(current_buffer_->raw_data(),current_buffer_->width(),current_buffer_->height(),current_buffer_->width() * 4);
agg::rendering_buffer buf(current_buffer_->getBytes(),current_buffer_->width(),current_buffer_->height(),current_buffer_->getRowSize());
using blender_type = agg::comp_op_adaptor_rgba_pre<agg::rgba8, agg::order_rgba>;
using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
@ -102,7 +102,7 @@ void agg_renderer<T0,T1>::process(dot_symbolizer const& sym,
}
}
template void agg_renderer<image_32>::process(dot_symbolizer const&,
template void agg_renderer<image_rgba8>::process(dot_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);

View file

@ -26,6 +26,7 @@
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/agg_render_marker.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image.hpp>
#include <mapnik/util/variant.hpp>
#include <mapnik/text/renderer.hpp>
#include <mapnik/geom_util.hpp>
@ -48,9 +49,14 @@ namespace mapnik {
* to render it, and the boxes themselves should already be
* in the detector from the placement_finder.
*/
struct thunk_renderer
template <typename T>
struct thunk_renderer;
template <>
struct thunk_renderer<image_rgba8>
{
using renderer_type = agg_renderer<image_32>;
using renderer_type = agg_renderer<image_rgba8>;
using buffer_type = renderer_type::buffer_type;
using text_renderer_type = agg_text_renderer<buffer_type>;
@ -75,7 +81,7 @@ struct thunk_renderer
renderer_type,
pixfmt_comp_type>;
ras_ptr_->reset();
buf_type render_buffer(buf_->raw_data(), buf_->width(), buf_->height(), buf_->width() * 4);
buf_type render_buffer(buf_->getBytes(), buf_->width(), buf_->height(), buf_->getRowSize());
pixfmt_comp_type pixf(render_buffer);
pixf.comp_op(static_cast<agg::comp_op_e>(thunk.comp_op_));
renderer_base renb(pixf);
@ -96,7 +102,7 @@ struct thunk_renderer
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
ras_ptr_->reset();
buf_type render_buffer(buf_->raw_data(), buf_->width(), buf_->height(), buf_->width() * 4);
buf_type render_buffer(buf_->getBytes(), buf_->width(), buf_->height(), buf_->getRowSize());
pixfmt_comp_type pixf(render_buffer);
pixf.comp_op(static_cast<agg::comp_op_e>(thunk.comp_op_));
renderer_base renb(pixf);
@ -119,7 +125,7 @@ struct thunk_renderer
if (glyphs->marker())
{
ren_.render_marker(glyphs->marker_pos(),
*(glyphs->marker()->marker),
glyphs->marker()->marker,
glyphs->marker()->transform,
thunk.opacity_, thunk.comp_op_);
}
@ -130,7 +136,7 @@ struct thunk_renderer
template <typename T>
void operator()(T const &) const
{
// TODO: warning if unimplemented?
throw std::runtime_error("Rendering of this data type is not supported currently by the renderer");
}
private:
@ -150,7 +156,7 @@ void agg_renderer<T0,T1>::process(group_symbolizer const& sym,
sym, feature, common_.vars_, prj_trans, clipping_extent(common_), common_,
[&](render_thunk_list const& thunks, pixel_position const& render_offset)
{
thunk_renderer ren(*this, ras_ptr, current_buffer_, common_, render_offset);
thunk_renderer<buffer_type> ren(*this, ras_ptr, current_buffer_, common_, render_offset);
for (render_thunk_ptr const& thunk : thunks)
{
util::apply_visitor(ren, *thunk);
@ -158,7 +164,7 @@ void agg_renderer<T0,T1>::process(group_symbolizer const& sym,
});
}
template void agg_renderer<image_32>::process(group_symbolizer const&,
template void agg_renderer<image_rgba8>::process(group_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);

View file

@ -23,7 +23,7 @@
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/agg_pattern_source.hpp>
@ -52,100 +52,204 @@
namespace mapnik {
template <typename buffer_type>
struct agg_renderer_process_visitor_l
{
agg_renderer_process_visitor_l(renderer_common & common,
buffer_type & pixmap,
buffer_type * current_buffer,
std::unique_ptr<rasterizer> const& ras_ptr,
line_pattern_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
: common_(common),
pixmap_(pixmap),
current_buffer_(current_buffer),
ras_ptr_(ras_ptr),
sym_(sym),
feature_(feature),
prj_trans_(prj_trans) {}
void operator() (marker_null const&) {}
void operator() (marker_svg const& marker)
{
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pattern_filter_type = agg::pattern_filter_bilinear_rgba8;
using pattern_type = agg::line_image_pattern<pattern_filter_type>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using renderer_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_outline_image<renderer_base, pattern_type>;
using rasterizer_type = agg::rasterizer_outline_aa<renderer_type>;
value_double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_);
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform);
mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr;
image_rgba8 image(bbox_image.width(), bbox_image.height());
render_pattern<buffer_type>(*ras_ptr_, marker, image_tr, 1.0, image);
value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
value_double offset = get<value_double, keys::offset>(sym_, feature_, common_.vars_);
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
value_double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);
agg::rendering_buffer buf(current_buffer_->getBytes(),current_buffer_->width(),current_buffer_->height(), current_buffer_->getRowSize());
pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
renderer_base ren_base(pixf);
agg::pattern_filter_bilinear_rgba8 filter;
pattern_source source(image, opacity);
pattern_type pattern (filter,source);
renderer_type ren(ren_base, pattern);
rasterizer_type ras(ren);
agg::trans_affine tr;
auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_);
box2d<double> clip_box = clipping_extent(common_);
if (clip)
{
double padding = (double)(common_.query_extent_.width()/pixmap_.width());
double half_stroke = marker.width()/2.0;
if (half_stroke > 1)
padding *= half_stroke;
if (std::fabs(offset) > 0)
padding *= std::fabs(offset) * 1.2;
padding *= common_.scale_factor_;
clip_box.pad(padding);
}
vertex_converter<rasterizer_type, clip_line_tag, transform_tag,
affine_transform_tag,
simplify_tag,smooth_tag,
offset_transform_tag>
converter(clip_box,ras,sym_,common_.t_,prj_trans_,tr,feature_,common_.vars_,common_.scale_factor_);
if (clip) converter.set<clip_line_tag>(); //optional clip (default: true)
converter.set<transform_tag>(); //always transform
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
converter.set<affine_transform_tag>(); // optional affine transform
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
for (geometry_type const& geom : feature_.paths())
{
if (geom.size() > 1)
{
vertex_adapter va(geom);
converter.apply(va);
}
}
}
void operator() (marker_rgba8 const& marker)
{
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pattern_filter_type = agg::pattern_filter_bilinear_rgba8;
using pattern_type = agg::line_image_pattern<pattern_filter_type>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using renderer_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_outline_image<renderer_base, pattern_type>;
using rasterizer_type = agg::rasterizer_outline_aa<renderer_type>;
value_double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_);
mapnik::image_rgba8 const& image = marker.get_data();
value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
value_double offset = get<value_double, keys::offset>(sym_, feature_, common_.vars_);
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
value_double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);
agg::rendering_buffer buf(current_buffer_->getBytes(),current_buffer_->width(),current_buffer_->height(), current_buffer_->getRowSize());
pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
renderer_base ren_base(pixf);
agg::pattern_filter_bilinear_rgba8 filter;
pattern_source source(image, opacity);
pattern_type pattern (filter,source);
renderer_type ren(ren_base, pattern);
rasterizer_type ras(ren);
agg::trans_affine tr;
auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_);
box2d<double> clip_box = clipping_extent(common_);
if (clip)
{
double padding = (double)(common_.query_extent_.width()/pixmap_.width());
double half_stroke = marker.width()/2.0;
if (half_stroke > 1)
padding *= half_stroke;
if (std::fabs(offset) > 0)
padding *= std::fabs(offset) * 1.2;
padding *= common_.scale_factor_;
clip_box.pad(padding);
}
vertex_converter<rasterizer_type, clip_line_tag, transform_tag,
affine_transform_tag,
simplify_tag,smooth_tag,
offset_transform_tag>
converter(clip_box,ras,sym_,common_.t_,prj_trans_,tr,feature_,common_.vars_,common_.scale_factor_);
if (clip) converter.set<clip_line_tag>(); //optional clip (default: true)
converter.set<transform_tag>(); //always transform
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
converter.set<affine_transform_tag>(); // optional affine transform
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
for (geometry_type const& geom : feature_.paths())
{
if (geom.size() > 1)
{
vertex_adapter va(geom);
converter.apply(va);
}
}
}
private:
renderer_common & common_;
buffer_type & pixmap_;
buffer_type * current_buffer_;
std::unique_ptr<rasterizer> const& ras_ptr_;
line_pattern_symbolizer const& sym_;
mapnik::feature_impl & feature_;
proj_transform const& prj_trans_;
};
template <typename T0, typename T1>
void agg_renderer<T0,T1>::process(line_pattern_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
{
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pattern_filter_type = agg::pattern_filter_bilinear_rgba8;
using pattern_type = agg::line_image_pattern<pattern_filter_type>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using renderer_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_outline_image<renderer_base, pattern_type>;
using rasterizer_type = agg::rasterizer_outline_aa<renderer_type>;
std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_);
if (filename.empty()) return;
boost::optional<mapnik::marker_ptr> marker_ptr = marker_cache::instance().find(filename, true);
if (!marker_ptr || !(*marker_ptr)) return;
boost::optional<image_ptr> pat;
// TODO - re-implement at renderer level like polygon_pattern symbolizer
value_double opacity = get<value_double, keys::opacity>(sym, feature, common_.vars_);
if ((*marker_ptr)->is_bitmap())
{
pat = (*marker_ptr)->get_bitmap_data();
}
else
{
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform);
pat = render_pattern(*ras_ptr, **marker_ptr, image_tr, 1.0);
}
if (!pat) return;
value_bool clip = get<value_bool, keys::clip>(sym, feature, common_.vars_);
value_double offset = get<value_double, keys::offset>(sym, feature, common_.vars_);
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym, feature, common_.vars_);
value_double smooth = get<value_double, keys::smooth>(sym, feature, common_.vars_);
agg::rendering_buffer buf(current_buffer_->raw_data(),current_buffer_->width(),current_buffer_->height(), current_buffer_->width() * 4);
pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym, feature, common_.vars_)));
renderer_base ren_base(pixf);
agg::pattern_filter_bilinear_rgba8 filter;
pattern_source source(*(*pat), opacity);
pattern_type pattern (filter,source);
renderer_type ren(ren_base, pattern);
rasterizer_type ras(ren);
agg::trans_affine tr;
auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_);
box2d<double> clip_box = clipping_extent(common_);
if (clip)
{
double padding = (double)(common_.query_extent_.width()/pixmap_.width());
double half_stroke = (*marker_ptr)->width()/2.0;
if (half_stroke > 1)
padding *= half_stroke;
if (std::fabs(offset) > 0)
padding *= std::fabs(offset) * 1.2;
padding *= common_.scale_factor_;
clip_box.pad(padding);
}
vertex_converter<rasterizer_type, clip_line_tag, transform_tag,
affine_transform_tag,
simplify_tag,smooth_tag,
offset_transform_tag>
converter(clip_box,ras,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);
if (clip) converter.set<clip_line_tag>(); //optional clip (default: true)
converter.set<transform_tag>(); //always transform
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
converter.set<affine_transform_tag>(); // optional affine transform
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
for (geometry_type const& geom : feature.paths())
{
if (geom.size() > 1)
{
vertex_adapter va(geom);
converter.apply(va);
}
}
mapnik::marker const & marker = marker_cache::instance().find(filename, true);
agg_renderer_process_visitor_l<buffer_type> visitor(common_,
pixmap_,
current_buffer_,
ras_ptr,
sym,
feature,
prj_trans);
util::apply_visitor(visitor, marker);
}
template void agg_renderer<image_32>::process(line_pattern_symbolizer const&,
template void agg_renderer<image_rgba8>::process(line_pattern_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);

View file

@ -22,7 +22,7 @@
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/agg_helpers.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
@ -109,7 +109,7 @@ void agg_renderer<T0,T1>::process(line_symbolizer const& sym,
gamma_ = gamma;
}
agg::rendering_buffer buf(current_buffer_->raw_data(),current_buffer_->width(),current_buffer_->height(), current_buffer_->width() * 4);
agg::rendering_buffer buf(current_buffer_->getBytes(),current_buffer_->width(),current_buffer_->height(), current_buffer_->getRowSize());
using color_type = agg::rgba8;
using order_type = agg::order_rgba;
@ -225,7 +225,7 @@ void agg_renderer<T0,T1>::process(line_symbolizer const& sym,
}
template void agg_renderer<image_32>::process(line_symbolizer const&,
template void agg_renderer<image_rgba8>::process(line_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);

View file

@ -21,7 +21,6 @@
*****************************************************************************/
// mapnik
#include <mapnik/graphics.hpp>
#include <mapnik/agg_helpers.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
@ -125,7 +124,7 @@ struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch<Detec
using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, BufferType>;
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
raster_markers_rasterizer_dispatch(image_data_rgba8 & src,
raster_markers_rasterizer_dispatch(image_rgba8 const& src,
agg::trans_affine const& marker_trans,
symbolizer_base const& sym,
Detector & detector,
@ -148,6 +147,8 @@ struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch<Detec
void render_marker(agg::trans_affine const& marker_tr, double opacity)
{
// In the long term this should be a visitor pattern based on the type of render this->src_ provided that converts
// the destination pixel type required.
render_raster_marker(renb_, ras_, this->src_, marker_tr, opacity, this->scale_factor_, snap_to_pixels_);
}
@ -191,7 +192,7 @@ void agg_renderer<T0,T1>::process(markers_symbolizer const& sym,
gamma_ = gamma;
}
buf_type render_buffer(current_buffer_->raw_data(), current_buffer_->width(), current_buffer_->height(), current_buffer_->width() * 4);
buf_type render_buffer(current_buffer_->getBytes(), current_buffer_->width(), current_buffer_->height(), current_buffer_->getRowSize());
box2d<double> clip_box = clipping_extent(common_);
auto renderer_context = std::tie(render_buffer,*ras_ptr,pixmap_);
@ -203,7 +204,7 @@ void agg_renderer<T0,T1>::process(markers_symbolizer const& sym,
sym, feature, prj_trans, common_, clip_box, renderer_context);
}
template void agg_renderer<image_32>::process(markers_symbolizer const&,
template void agg_renderer<image_rgba8>::process(markers_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);
}

View file

@ -25,6 +25,7 @@
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/marker.hpp>
@ -59,7 +60,7 @@ void agg_renderer<T0,T1>::process(point_symbolizer const& sym,
});
}
template void agg_renderer<image_32>::process(point_symbolizer const&,
template void agg_renderer<image_rgba8>::process(point_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);

View file

@ -23,7 +23,6 @@
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_helpers.hpp>
#include <mapnik/agg_rasterizer.hpp>
@ -54,6 +53,254 @@
namespace mapnik {
template <typename buffer_type>
struct agg_renderer_process_visitor_p
{
agg_renderer_process_visitor_p(renderer_common & common,
buffer_type * current_buffer,
std::unique_ptr<rasterizer> const& ras_ptr,
gamma_method_enum & gamma_method,
double & gamma,
polygon_pattern_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
: common_(common),
current_buffer_(current_buffer),
ras_ptr_(ras_ptr),
gamma_method_(gamma_method),
gamma_(gamma),
sym_(sym),
feature_(feature),
prj_trans_(prj_trans) {}
void operator() (marker_null const&) {}
void operator() (marker_svg const& marker)
{
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform);
mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr;
mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
render_pattern<buffer_type>(*ras_ptr_, marker, image_tr, 1.0, image);
using clipped_geometry_type = agg::conv_clip_polygon<vertex_adapter>;
using path_type = transform_path_adapter<view_transform,clipped_geometry_type>;
agg::rendering_buffer buf(current_buffer_->getBytes(), current_buffer_->width(),
current_buffer_->height(), current_buffer_->getRowSize());
ras_ptr_->reset();
value_double gamma = get<value_double, keys::gamma>(sym_, feature_, common_.vars_);
gamma_method_enum gamma_method = get<gamma_method_enum, keys::gamma_method>(sym_, feature_, common_.vars_);
if (gamma != gamma_ || gamma_method != gamma_method_)
{
set_gamma_method(ras_ptr_, gamma, gamma_method);
gamma_method_ = gamma_method;
gamma_ = gamma;
}
value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
value_double opacity = get<double, keys::opacity>(sym_, feature_, common_.vars_);
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
value_double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);
box2d<double> clip_box = clipping_extent(common_);
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using wrap_x_type = agg::wrap_mode_repeat;
using wrap_y_type = agg::wrap_mode_repeat;
using img_source_type = agg::image_accessor_wrap<agg::pixfmt_rgba32_pre,
wrap_x_type,
wrap_y_type>;
using span_gen_type = agg::span_pattern_rgba<img_source_type>;
using ren_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_scanline_aa_alpha<ren_base,
agg::span_allocator<agg::rgba8>,
span_gen_type>;
pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
ren_base renb(pixf);
unsigned w = image.width();
unsigned h = image.height();
agg::rendering_buffer pattern_rbuf((agg::int8u*)image.getBytes(),w,h,w*4);
agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
img_source_type img_src(pixf_pattern);
pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym_, feature_, common_.vars_);
unsigned offset_x=0;
unsigned offset_y=0;
if (alignment == LOCAL_ALIGNMENT)
{
double x0 = 0;
double y0 = 0;
if (feature_.num_geometries() > 0)
{
vertex_adapter va(feature_.get_geometry(0));
clipped_geometry_type clipped(va);
clipped.clip_box(clip_box.minx(),clip_box.miny(),clip_box.maxx(),clip_box.maxy());
path_type path(common_.t_,clipped,prj_trans_);
path.vertex(&x0,&y0);
}
offset_x = unsigned(current_buffer_->width() - x0);
offset_y = unsigned(current_buffer_->height() - y0);
}
span_gen_type sg(img_src, offset_x, offset_y);
agg::span_allocator<agg::rgba8> sa;
renderer_type rp(renb,sa, sg, unsigned(opacity * 255));
agg::trans_affine tr;
auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_);
vertex_converter<rasterizer, clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag>
converter(clip_box,*ras_ptr_,sym_,common_.t_,prj_trans_,tr,feature_,common_.vars_,common_.scale_factor_);
if (prj_trans_.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true)
converter.set<transform_tag>(); //always transform
converter.set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
for ( geometry_type const& geom : feature_.paths())
{
if (geom.size() > 2)
{
vertex_adapter va(geom);
converter.apply(va);
}
}
agg::scanline_u8 sl;
ras_ptr_->filling_rule(agg::fill_even_odd);
agg::render_scanlines(*ras_ptr_, sl, rp);
}
void operator() (marker_rgba8 const& marker)
{
using clipped_geometry_type = agg::conv_clip_polygon<vertex_adapter>;
using path_type = transform_path_adapter<view_transform,clipped_geometry_type>;
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using wrap_x_type = agg::wrap_mode_repeat;
using wrap_y_type = agg::wrap_mode_repeat;
using img_source_type = agg::image_accessor_wrap<agg::pixfmt_rgba32_pre,
wrap_x_type,
wrap_y_type>;
using span_gen_type = agg::span_pattern_rgba<img_source_type>;
using ren_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_scanline_aa_alpha<ren_base,
agg::span_allocator<agg::rgba8>,
span_gen_type>;
mapnik::image_rgba8 const& image = marker.get_data();
agg::rendering_buffer buf(current_buffer_->getBytes(), current_buffer_->width(),
current_buffer_->height(), current_buffer_->getRowSize());
ras_ptr_->reset();
value_double gamma = get<value_double, keys::gamma>(sym_, feature_, common_.vars_);
gamma_method_enum gamma_method = get<gamma_method_enum, keys::gamma_method>(sym_, feature_, common_.vars_);
if (gamma != gamma_ || gamma_method != gamma_method_)
{
set_gamma_method(ras_ptr_, gamma, gamma_method);
gamma_method_ = gamma_method;
gamma_ = gamma;
}
value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
value_double opacity = get<double, keys::opacity>(sym_, feature_, common_.vars_);
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
value_double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);
box2d<double> clip_box = clipping_extent(common_);
pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
ren_base renb(pixf);
unsigned w = image.width();
unsigned h = image.height();
agg::rendering_buffer pattern_rbuf((agg::int8u*)image.getBytes(),w,h,w*4);
agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
img_source_type img_src(pixf_pattern);
pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym_, feature_, common_.vars_);
unsigned offset_x=0;
unsigned offset_y=0;
if (alignment == LOCAL_ALIGNMENT)
{
double x0 = 0;
double y0 = 0;
if (feature_.num_geometries() > 0)
{
vertex_adapter va(feature_.get_geometry(0));
clipped_geometry_type clipped(va);
clipped.clip_box(clip_box.minx(),clip_box.miny(),clip_box.maxx(),clip_box.maxy());
path_type path(common_.t_,clipped,prj_trans_);
path.vertex(&x0,&y0);
}
offset_x = unsigned(current_buffer_->width() - x0);
offset_y = unsigned(current_buffer_->height() - y0);
}
span_gen_type sg(img_src, offset_x, offset_y);
agg::span_allocator<agg::rgba8> sa;
renderer_type rp(renb,sa, sg, unsigned(opacity * 255));
agg::trans_affine tr;
auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_);
vertex_converter<rasterizer, clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag>
converter(clip_box,*ras_ptr_,sym_,common_.t_,prj_trans_,tr,feature_,common_.vars_,common_.scale_factor_);
if (prj_trans_.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true)
converter.set<transform_tag>(); //always transform
converter.set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
for ( geometry_type const& geom : feature_.paths())
{
if (geom.size() > 2)
{
vertex_adapter va(geom);
converter.apply(va);
}
}
agg::scanline_u8 sl;
ras_ptr_->filling_rule(agg::fill_even_odd);
agg::render_scanlines(*ras_ptr_, sl, rp);
}
private:
renderer_common & common_;
buffer_type * current_buffer_;
std::unique_ptr<rasterizer> const& ras_ptr_;
gamma_method_enum & gamma_method_;
double & gamma_;
polygon_pattern_symbolizer const& sym_;
mapnik::feature_impl & feature_;
proj_transform const& prj_trans_;
};
template <typename T0, typename T1>
void agg_renderer<T0,T1>::process(polygon_pattern_symbolizer const& sym,
mapnik::feature_impl & feature,
@ -61,128 +308,20 @@ void agg_renderer<T0,T1>::process(polygon_pattern_symbolizer const& sym,
{
std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_);
if (filename.empty()) return;
boost::optional<mapnik::marker_ptr> marker_ptr = marker_cache::instance().find(filename, true);
if (!marker_ptr || !(*marker_ptr)) return;
boost::optional<image_ptr> pat;
if ((*marker_ptr)->is_bitmap())
{
pat = (*marker_ptr)->get_bitmap_data();
}
else
{
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform);
pat = render_pattern(*ras_ptr, **marker_ptr, image_tr, 1.0);
}
if (!pat) return;
using clipped_geometry_type = agg::conv_clip_polygon<vertex_adapter>;
using path_type = transform_path_adapter<view_transform,clipped_geometry_type>;
agg::rendering_buffer buf(current_buffer_->raw_data(), current_buffer_->width(),
current_buffer_->height(), current_buffer_->width() * 4);
ras_ptr->reset();
value_double gamma = get<value_double, keys::gamma>(sym, feature, common_.vars_);
gamma_method_enum gamma_method = get<gamma_method_enum, keys::gamma_method>(sym, feature, common_.vars_);
if (gamma != gamma_ || gamma_method != gamma_method_)
{
set_gamma_method(ras_ptr, gamma, gamma_method);
gamma_method_ = gamma_method;
gamma_ = gamma;
}
value_bool clip = get<value_bool, keys::clip>(sym, feature, common_.vars_);
value_double opacity = get<double, keys::opacity>(sym, feature, common_.vars_);
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym, feature, common_.vars_);
value_double smooth = get<value_double, keys::smooth>(sym, feature, common_.vars_);
box2d<double> clip_box = clipping_extent(common_);
using color = agg::rgba8;
using order = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using wrap_x_type = agg::wrap_mode_repeat;
using wrap_y_type = agg::wrap_mode_repeat;
using img_source_type = agg::image_accessor_wrap<agg::pixfmt_rgba32_pre,
wrap_x_type,
wrap_y_type>;
using span_gen_type = agg::span_pattern_rgba<img_source_type>;
using ren_base = agg::renderer_base<pixfmt_type>;
using renderer_type = agg::renderer_scanline_aa_alpha<ren_base,
agg::span_allocator<agg::rgba8>,
span_gen_type>;
pixfmt_type pixf(buf);
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym, feature, common_.vars_)));
ren_base renb(pixf);
unsigned w=(*pat)->width();
unsigned h=(*pat)->height();
agg::rendering_buffer pattern_rbuf((agg::int8u*)(*pat)->getBytes(),w,h,w*4);
agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
img_source_type img_src(pixf_pattern);
pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym, feature, common_.vars_);
unsigned offset_x=0;
unsigned offset_y=0;
if (alignment == LOCAL_ALIGNMENT)
{
double x0 = 0;
double y0 = 0;
if (feature.num_geometries() > 0)
{
vertex_adapter va(feature.get_geometry(0));
clipped_geometry_type clipped(va);
clipped.clip_box(clip_box.minx(),clip_box.miny(),clip_box.maxx(),clip_box.maxy());
path_type path(common_.t_,clipped,prj_trans);
path.vertex(&x0,&y0);
}
offset_x = unsigned(current_buffer_->width() - x0);
offset_y = unsigned(current_buffer_->height() - y0);
}
span_gen_type sg(img_src, offset_x, offset_y);
agg::span_allocator<agg::rgba8> sa;
renderer_type rp(renb,sa, sg, unsigned(opacity * 255));
agg::trans_affine tr;
auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_);
vertex_converter<rasterizer, clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag>
converter(clip_box,*ras_ptr,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);
if (prj_trans.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true)
converter.set<transform_tag>(); //always transform
converter.set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
for ( geometry_type const& geom : feature.paths())
{
if (geom.size() > 2)
{
vertex_adapter va(geom);
converter.apply(va);
}
}
agg::scanline_u8 sl;
ras_ptr->filling_rule(agg::fill_even_odd);
agg::render_scanlines(*ras_ptr, sl, rp);
mapnik::marker const& marker = marker_cache::instance().find(filename, true);
agg_renderer_process_visitor_p<buffer_type> visitor(common_,
current_buffer_,
ras_ptr,
gamma_method_,
gamma_,
sym,
feature,
prj_trans);
util::apply_visitor(visitor, marker);
}
template void agg_renderer<image_32>::process(polygon_pattern_symbolizer const&,
template void agg_renderer<image_rgba8>::process(polygon_pattern_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);

View file

@ -26,7 +26,6 @@
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_helpers.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/symbolizer.hpp>
@ -62,7 +61,7 @@ void agg_renderer<T0,T1>::process(polygon_symbolizer const& sym,
}
box2d<double> clip_box = clipping_extent(common_);
agg::rendering_buffer buf(current_buffer_->raw_data(),current_buffer_->width(),current_buffer_->height(), current_buffer_->width() * 4);
agg::rendering_buffer buf(current_buffer_->getBytes(),current_buffer_->width(),current_buffer_->height(), current_buffer_->getRowSize());
render_polygon_symbolizer<vertex_converter_type>(
sym, feature, prj_trans, common_, clip_box, *ras_ptr,
@ -88,7 +87,7 @@ void agg_renderer<T0,T1>::process(polygon_symbolizer const& sym,
});
}
template void agg_renderer<image_32>::process(polygon_symbolizer const&,
template void agg_renderer<image_rgba8>::process(polygon_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);

View file

@ -25,11 +25,10 @@
#include <mapnik/agg_renderer.hpp>
#include <mapnik/image_scaling.hpp>
#include <mapnik/image_compositing.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/raster_colorizer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/raster.hpp>
#include <mapnik/box2d.hpp>
@ -52,15 +51,15 @@ void agg_renderer<T0,T1>::process(raster_symbolizer const& sym,
{
render_raster_symbolizer(
sym, feature, prj_trans, common_,
[&](image_data_rgba8 & target, composite_mode_e comp_op, double opacity,
[&](image_rgba8 & target, composite_mode_e comp_op, double opacity,
int start_x, int start_y) {
composite(current_buffer_->data(), target,
comp_op, opacity, start_x, start_y, false);
composite(*current_buffer_, target,
comp_op, opacity, start_x, start_y);
}
);
}
template void agg_renderer<image_32>::process(raster_symbolizer const&,
template void agg_renderer<image_rgba8>::process(raster_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);

View file

@ -23,7 +23,6 @@
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/text/symbolizer_helpers.hpp>
#include <mapnik/pixel_position.hpp>
@ -65,7 +64,7 @@ void agg_renderer<T0,T1>::process(shield_symbolizer const& sym,
{
if (glyphs->marker())
render_marker(glyphs->marker_pos(),
*(glyphs->marker()->marker),
glyphs->marker()->marker,
glyphs->marker()->transform,
opacity, comp_op);
ren.render(*glyphs);
@ -73,7 +72,7 @@ void agg_renderer<T0,T1>::process(shield_symbolizer const& sym,
}
template void agg_renderer<image_32>::process(shield_symbolizer const&,
template void agg_renderer<image_rgba8>::process(shield_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);

View file

@ -23,7 +23,7 @@
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/text/symbolizer_helpers.hpp>
#include <mapnik/text/renderer.hpp>
@ -75,7 +75,7 @@ void agg_renderer<T0,T1>::process(text_symbolizer const& sym,
}
}
template void agg_renderer<image_32>::process(text_symbolizer const&,
template void agg_renderer<image_rgba8>::process(text_symbolizer const&,
mapnik::feature_impl &,
proj_transform const&);

View file

@ -152,6 +152,7 @@ source = Split(
miniz_png.cpp
color.cpp
conversions.cpp
image_copy.cpp
image_compositing.cpp
image_scaling.cpp
box2d.cpp
@ -170,10 +171,14 @@ source = Split(
font_set.cpp
function_call.cpp
gradient.cpp
graphics.cpp
parse_path.cpp
image_reader.cpp
cairo_io.cpp
image_util.cpp
image_util_jpeg.cpp
image_util_png.cpp
image_util_tiff.cpp
image_util_webp.cpp
layer.cpp
map.cpp
load_map.cpp

View file

@ -337,7 +337,7 @@ void cairo_context::set_gradient(cairo_gradient const& pattern, const box2d<doub
check_object_status_and_throw_exception(*this);
}
void cairo_context::add_image(double x, double y, image_data_rgba8 & data, double opacity)
void cairo_context::add_image(double x, double y, image_rgba8 const& data, double opacity)
{
cairo_pattern pattern(data);
pattern.set_origin(x, y);
@ -348,7 +348,7 @@ void cairo_context::add_image(double x, double y, image_data_rgba8 & data, doubl
check_object_status_and_throw_exception(*this);
}
void cairo_context::add_image(agg::trans_affine const& tr, image_data_rgba8 & data, double opacity)
void cairo_context::add_image(agg::trans_affine const& tr, image_rgba8 const& data, double opacity)
{
cairo_pattern pattern(data);
if (!tr.is_identity())

View file

@ -99,6 +99,42 @@ cairo_renderer<T>::cairo_renderer(Map const& m,
template <typename T>
cairo_renderer<T>::~cairo_renderer() {}
struct setup_marker_visitor
{
setup_marker_visitor(cairo_context & context, renderer_common const& common)
: context_(context), common_(common) {}
void operator() (marker_null const &) {}
void operator() (marker_svg const &) {}
void operator() (marker_rgba8 const& marker)
{
mapnik::image_rgba8 const& bg_image = marker.get_data();
int w = bg_image.width();
int h = bg_image.height();
if ( w > 0 && h > 0)
{
// repeat background-image both vertically and horizontally
unsigned x_steps = unsigned(std::ceil(common_.width_/double(w)));
unsigned y_steps = unsigned(std::ceil(common_.height_/double(h)));
for (unsigned x=0;x<x_steps;++x)
{
for (unsigned y=0;y<y_steps;++y)
{
agg::trans_affine matrix = agg::trans_affine_translation(
x*w,
y*h);
context_.add_image(matrix, bg_image, 1.0f);
}
}
}
}
private:
cairo_context & context_;
renderer_common const& common_;
};
template <typename T>
void cairo_renderer<T>::setup(Map const& map)
{
@ -113,29 +149,8 @@ void cairo_renderer<T>::setup(Map const& map)
if (image_filename)
{
// NOTE: marker_cache returns premultiplied image, if needed
boost::optional<mapnik::marker_ptr> bg_marker = mapnik::marker_cache::instance().find(*image_filename,true);
if (bg_marker && (*bg_marker)->is_bitmap())
{
mapnik::image_ptr bg_image = *(*bg_marker)->get_bitmap_data();
int w = bg_image->width();
int h = bg_image->height();
if ( w > 0 && h > 0)
{
// repeat background-image both vertically and horizontally
unsigned x_steps = unsigned(std::ceil(common_.width_/double(w)));
unsigned y_steps = unsigned(std::ceil(common_.height_/double(h)));
for (unsigned x=0;x<x_steps;++x)
{
for (unsigned y=0;y<y_steps;++y)
{
agg::trans_affine matrix = agg::trans_affine_translation(
x*w,
y*h);
context_.add_image(matrix, *bg_image, 1.0f);
}
}
}
}
mapnik::marker const& bg_marker = mapnik::marker_cache::instance().find(*image_filename,true);
util::apply_visitor(setup_marker_visitor(context_, common_), bg_marker);
}
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: Scale=" << map.scale();
}
@ -187,6 +202,68 @@ void cairo_renderer<T>::end_style_processing(feature_type_style const& st)
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer:end style processing";
}
struct cairo_render_marker_visitor
{
cairo_render_marker_visitor(cairo_context & context,
renderer_common const& common,
pixel_position const& pos,
agg::trans_affine const& tr,
double opacity,
bool recenter)
: context_(context),
common_(common),
pos_(pos),
tr_(tr),
opacity_(opacity),
recenter_(recenter) {}
void operator() (marker_null const&) {}
void operator() (marker_svg const& marker)
{
mapnik::svg_path_ptr vmarker = marker.get_data();
if (vmarker)
{
box2d<double> bbox = vmarker->bounding_box();
agg::trans_affine marker_tr = tr_;
if (recenter_)
{
coord<double,2> c = bbox.center();
marker_tr = agg::trans_affine_translation(-c.x,-c.y);
marker_tr *= tr_;
}
marker_tr *= agg::trans_affine_scaling(common_.scale_factor_);
agg::pod_bvector<svg::path_attributes> const & attributes = vmarker->attributes();
svg::vertex_stl_adapter<svg::svg_path_storage> stl_storage(vmarker->source());
svg::svg_path_adapter svg_path(stl_storage);
marker_tr.translate(pos_.x, pos_.y);
render_vector_marker(context_, svg_path, attributes, bbox, marker_tr, opacity_);
}
}
void operator() (marker_rgba8 const& marker)
{
double width = marker.get_data().width();
double height = marker.get_data().height();
double cx = 0.5 * width;
double cy = 0.5 * height;
agg::trans_affine marker_tr;
marker_tr *= agg::trans_affine_translation(-cx,-cy);
marker_tr *= tr_;
marker_tr *= agg::trans_affine_scaling(common_.scale_factor_);
marker_tr *= agg::trans_affine_translation(pos_.x,pos_.y);
context_.add_image(marker_tr, marker.get_data(), opacity_);
}
private:
cairo_context & context_;
renderer_common const& common_;
pixel_position const& pos_;
agg::trans_affine const& tr_;
double opacity_;
bool recenter_;
};
template <typename T>
void cairo_renderer<T>::render_marker(pixel_position const& pos,
marker const& marker,
@ -196,40 +273,13 @@ void cairo_renderer<T>::render_marker(pixel_position const& pos,
{
cairo_save_restore guard(context_);
if (marker.is_vector())
{
mapnik::svg_path_ptr vmarker = *marker.get_vector_data();
if (vmarker)
{
box2d<double> bbox = vmarker->bounding_box();
agg::trans_affine marker_tr = tr;
if (recenter)
{
coord<double,2> c = bbox.center();
marker_tr = agg::trans_affine_translation(-c.x,-c.y);
marker_tr *= tr;
}
marker_tr *= agg::trans_affine_scaling(common_.scale_factor_);
agg::pod_bvector<svg::path_attributes> const & attributes = vmarker->attributes();
svg::vertex_stl_adapter<svg::svg_path_storage> stl_storage(vmarker->source());
svg::svg_path_adapter svg_path(stl_storage);
marker_tr.translate(pos.x, pos.y);
render_vector_marker(context_, svg_path, attributes, bbox, marker_tr, opacity);
}
}
else if (marker.is_bitmap())
{
double width = (*marker.get_bitmap_data())->width();
double height = (*marker.get_bitmap_data())->height();
double cx = 0.5 * width;
double cy = 0.5 * height;
agg::trans_affine marker_tr;
marker_tr *= agg::trans_affine_translation(-cx,-cy);
marker_tr *= tr;
marker_tr *= agg::trans_affine_scaling(common_.scale_factor_);
marker_tr *= agg::trans_affine_translation(pos.x,pos.y);
context_.add_image(marker_tr, **marker.get_bitmap_data(), opacity);
}
cairo_render_marker_visitor visitor(context_,
common_,
pos,
tr,
opacity,
recenter);
util::apply_visitor(visitor, marker);
}
template class cairo_renderer<cairo_ptr>;

View file

@ -77,7 +77,7 @@ struct thunk_renderer
thunk.opacity_);
}
void operator()(raster_marker_render_thunk const &thunk) const
void operator()(raster_marker_render_thunk const& thunk) const
{
cairo_save_restore guard(context_);
context_.set_operator(thunk.comp_op_);
@ -100,7 +100,7 @@ struct thunk_renderer
if (glyphs->marker())
{
ren_.render_marker(glyphs->marker_pos(),
*(glyphs->marker()->marker),
glyphs->marker()->marker,
glyphs->marker()->transform,
thunk.opacity_, thunk.comp_op_);
}
@ -111,7 +111,7 @@ struct thunk_renderer
template <typename T0>
void operator()(T0 const &) const
{
// TODO: warning if unimplemented?
throw std::runtime_error("Rendering of this type is not supported by the cairo renderer.");
}
private:

View file

@ -36,6 +36,53 @@
namespace mapnik
{
struct cairo_renderer_process_visitor_l
{
cairo_renderer_process_visitor_l(renderer_common const& common,
line_pattern_symbolizer const& sym,
mapnik::feature_impl & feature,
unsigned & width,
unsigned & height)
: common_(common),
sym_(sym),
feature_(feature),
width_(width),
height_(height) {}
std::shared_ptr<cairo_pattern> operator() (mapnik::marker_null const&)
{
throw std::runtime_error("This should not have been reached.");
}
std::shared_ptr<cairo_pattern> operator() (mapnik::marker_svg const& marker)
{
double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_);
mapnik::rasterizer ras;
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform);
mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr;
mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
render_pattern<image_rgba8>(ras, marker, image_tr, 1.0, image);
width_ = image.width();
height_ = image.height();
return std::make_shared<cairo_pattern>(image, opacity);
}
std::shared_ptr<cairo_pattern> operator() (mapnik::marker_rgba8 const& marker)
{
double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_);
return std::make_shared<cairo_pattern>(marker.get_data(), opacity);
}
private:
renderer_common const& common_;
line_pattern_symbolizer const& sym_;
mapnik::feature_impl & feature_;
unsigned & width_;
unsigned & height_;
};
template <typename T>
void cairo_renderer<T>::process(line_pattern_symbolizer const& sym,
mapnik::feature_impl & feature,
@ -48,39 +95,29 @@ void cairo_renderer<T>::process(line_pattern_symbolizer const& sym,
value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym, feature, common_.vars_);
value_double smooth = get<value_double, keys::smooth>(sym, feature, common_.vars_);
boost::optional<marker_ptr> marker;
if ( !filename.empty() )
if (filename.empty())
{
marker = marker_cache::instance().find(filename, true);
return;
}
if (!marker || !(*marker)) return;
unsigned width = (*marker)->width();
unsigned height = (*marker)->height();
mapnik::marker const& marker = marker_cache::instance().find(filename, true);
if (marker.is<mapnik::marker_null>()) return;
unsigned width = marker.width();
unsigned height = marker.height();
cairo_save_restore guard(context_);
context_.set_operator(comp_op);
std::shared_ptr<cairo_pattern> pattern;
image_ptr image = nullptr;
// TODO - re-implement at renderer level like polygon_pattern symbolizer
double opacity = get<value_double, keys::opacity>(sym, feature, common_.vars_);
if ((*marker)->is_bitmap())
{
pattern = std::make_unique<cairo_pattern>(**((*marker)->get_bitmap_data()), opacity);
context_.set_line_width(height);
}
else
{
mapnik::rasterizer ras;
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform);
image = render_pattern(ras, **marker, image_tr, 1.0);
pattern = std::make_unique<cairo_pattern>(*image, opacity);
width = image->width();
height = image->height();
context_.set_line_width(height);
}
cairo_renderer_process_visitor_l visit(common_,
sym,
feature,
width,
height);
std::shared_ptr<cairo_pattern> pattern = util::apply_visitor(visit, marker);
context_.set_line_width(height);
pattern->set_extend(CAIRO_EXTEND_REPEAT);
pattern->set_filter(CAIRO_FILTER_BILINEAR);

View file

@ -86,7 +86,7 @@ private:
template <typename RendererContext, typename Detector>
struct raster_markers_dispatch_cairo : public raster_markers_dispatch<Detector>
{
raster_markers_dispatch_cairo(mapnik::image_data_rgba8 & src,
raster_markers_dispatch_cairo(image_rgba8 const& src,
agg::trans_affine const& marker_trans,
markers_symbolizer const& sym,
Detector & detector,

View file

@ -37,6 +37,49 @@
namespace mapnik
{
struct cairo_renderer_process_visitor_p
{
cairo_renderer_process_visitor_p(cairo_context & context,
agg::trans_affine & image_tr,
unsigned offset_x,
unsigned offset_y,
float opacity)
: context_(context),
image_tr_(image_tr),
offset_x_(offset_x),
offset_y_(offset_y),
opacity_(opacity) {}
void operator() (marker_null const&) {}
void operator() (marker_svg const& marker)
{
mapnik::rasterizer ras;
mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr_;
mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
render_pattern<image_rgba8>(ras, marker, image_tr_, 1.0, image);
cairo_pattern pattern(image, opacity_);
pattern.set_extend(CAIRO_EXTEND_REPEAT);
pattern.set_origin(offset_x_, offset_y_);
context_.set_pattern(pattern);
}
void operator() (marker_rgba8 const& marker)
{
cairo_pattern pattern(marker.get_data(), opacity_);
pattern.set_extend(CAIRO_EXTEND_REPEAT);
pattern.set_origin(offset_x_, offset_y_);
context_.set_pattern(pattern);
}
private:
cairo_context & context_;
agg::trans_affine & image_tr_;
unsigned offset_x_;
unsigned offset_y_;
float opacity_;
};
template <typename T>
void cairo_renderer<T>::process(polygon_pattern_symbolizer const& sym,
mapnik::feature_impl & feature,
@ -55,8 +98,8 @@ void cairo_renderer<T>::process(polygon_pattern_symbolizer const& sym,
cairo_save_restore guard(context_);
context_.set_operator(comp_op);
boost::optional<mapnik::marker_ptr> marker = mapnik::marker_cache::instance().find(filename,true);
if (!marker || !(*marker)) return;
mapnik::marker const& marker = mapnik::marker_cache::instance().find(filename,true);
if (marker.is<mapnik::marker_null>()) return;
unsigned offset_x=0;
unsigned offset_y=0;
@ -82,22 +125,7 @@ void cairo_renderer<T>::process(polygon_pattern_symbolizer const& sym,
offset_y = std::abs(clip_box.height() - y0);
}
if ((*marker)->is_bitmap())
{
cairo_pattern pattern(**((*marker)->get_bitmap_data()), opacity);
pattern.set_extend(CAIRO_EXTEND_REPEAT);
pattern.set_origin(offset_x, offset_y);
context_.set_pattern(pattern);
}
else
{
mapnik::rasterizer ras;
image_ptr image = render_pattern(ras, **marker, image_tr, 1.0); //
cairo_pattern pattern(*image, opacity);
pattern.set_extend(CAIRO_EXTEND_REPEAT);
pattern.set_origin(offset_x, offset_y);
context_.set_pattern(pattern);
}
util::apply_visitor(cairo_renderer_process_visitor_p(context_, image_tr, offset_x, offset_y, opacity), marker);
agg::trans_affine tr;
auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform);

View file

@ -43,7 +43,7 @@ void cairo_renderer<T>::process(raster_symbolizer const& sym,
cairo_save_restore guard(context_);
render_raster_symbolizer(
sym, feature, prj_trans, common_,
[&](image_data_rgba8 &target, composite_mode_e comp_op, double opacity,
[&](image_rgba8 &target, composite_mode_e comp_op, double opacity,
int start_x, int start_y) {
context_.set_operator(comp_op);
context_.add_image(start_x, start_y, target, opacity);

View file

@ -60,7 +60,7 @@ void cairo_renderer<T>::process(shield_symbolizer const& sym,
if (glyphs->marker()) {
pixel_position pos = glyphs->marker_pos();
render_marker(pos,
*(glyphs->marker()->marker),
glyphs->marker()->marker,
glyphs->marker()->transform,
opacity);
}

131
src/cairo_io.cpp Normal file
View file

@ -0,0 +1,131 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// mapnik
#include <mapnik/cairo_io.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/map.hpp>
#ifdef HAVE_CAIRO
#include <mapnik/cairo/cairo_renderer.hpp>
#include <cairo.h>
#ifdef CAIRO_HAS_PDF_SURFACE
#include <cairo-pdf.h>
#endif
#ifdef CAIRO_HAS_PS_SURFACE
#include <cairo-ps.h>
#endif
#ifdef CAIRO_HAS_SVG_SURFACE
#include <cairo-svg.h>
#endif
#endif
// stl
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
namespace mapnik {
#if defined(HAVE_CAIRO)
void save_to_cairo_file(mapnik::Map const& map, std::string const& filename, double scale_factor, double scale_denominator)
{
boost::optional<std::string> type = type_from_filename(filename);
if (type)
{
save_to_cairo_file(map,filename,*type,scale_factor,scale_denominator);
}
else throw ImageWriterException("Could not write file to " + filename );
}
void save_to_cairo_file(mapnik::Map const& map,
std::string const& filename,
std::string const& type,
double scale_factor,
double scale_denominator)
{
std::ofstream file (filename.c_str(), std::ios::out|std::ios::trunc|std::ios::binary);
if (file)
{
cairo_surface_ptr surface;
unsigned width = map.width();
unsigned height = map.height();
if (type == "pdf")
{
#ifdef CAIRO_HAS_PDF_SURFACE
surface = cairo_surface_ptr(cairo_pdf_surface_create(filename.c_str(),width,height),cairo_surface_closer());
#else
throw ImageWriterException("PDFSurface not supported in the cairo backend");
#endif
}
#ifdef CAIRO_HAS_SVG_SURFACE
else if (type == "svg")
{
surface = cairo_surface_ptr(cairo_svg_surface_create(filename.c_str(),width,height),cairo_surface_closer());
}
#endif
#ifdef CAIRO_HAS_PS_SURFACE
else if (type == "ps")
{
surface = cairo_surface_ptr(cairo_ps_surface_create(filename.c_str(),width,height),cairo_surface_closer());
}
#endif
#ifdef CAIRO_HAS_IMAGE_SURFACE
else if (type == "ARGB32")
{
surface = cairo_surface_ptr(cairo_image_surface_create(CAIRO_FORMAT_ARGB32,width,height),cairo_surface_closer());
}
else if (type == "RGB24")
{
surface = cairo_surface_ptr(cairo_image_surface_create(CAIRO_FORMAT_RGB24,width,height),cairo_surface_closer());
}
#endif
else
{
throw ImageWriterException("unknown file type: " + type);
}
//cairo_t * ctx = cairo_create(surface);
// TODO - expose as user option
/*
if (type == "ARGB32" || type == "RGB24")
{
context->set_antialias(Cairo::ANTIALIAS_NONE);
}
*/
mapnik::cairo_renderer<cairo_ptr> ren(map, create_context(surface), scale_factor);
ren.apply(scale_denominator);
if (type == "ARGB32" || type == "RGB24")
{
cairo_surface_write_to_png(&*surface, filename.c_str());
}
cairo_surface_finish(&*surface);
}
}
#endif
} // end ns

View file

@ -45,9 +45,10 @@
namespace mapnik {
color::color(std::string const& str)
color::color(std::string const& str, bool premultiplied)
{
*this = parse_color(str);
premultiplied_ = premultiplied;
}
std::string color::to_string() const
@ -95,23 +96,28 @@ std::string color::to_hex_string() const
return str;
}
void color::premultiply()
bool color::premultiply()
{
if (premultiplied_) return false;
agg::rgba8 pre_c = agg::rgba8(red_,green_,blue_,alpha_);
pre_c.premultiply();
red_ = pre_c.r;
green_ = pre_c.g;
blue_ = pre_c.b;
premultiplied_ = true;
return true;
}
void color::demultiply()
bool color::demultiply()
{
// note: this darkens too much: https://github.com/mapnik/mapnik/issues/1519
if (!premultiplied_) return false;
agg::rgba8 pre_c = agg::rgba8(red_,green_,blue_,alpha_);
pre_c.demultiply();
red_ = pre_c.r;
green_ = pre_c.g;
blue_ = pre_c.b;
premultiplied_ = false;
return true;
}
}

View file

@ -24,7 +24,7 @@
#include <mapnik/feature_style_processor_impl.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/image_any.hpp>
#if defined(GRID_RENDERER)
#include <mapnik/grid/grid_renderer.hpp>
@ -44,17 +44,17 @@ namespace mapnik
{
#if defined(HAVE_CAIRO)
template class feature_style_processor<cairo_renderer<cairo_ptr> >;
template class MAPNIK_DECL feature_style_processor<cairo_renderer<cairo_ptr> >;
#endif
#if defined(SVG_RENDERER)
template class feature_style_processor<svg_renderer<std::ostream_iterator<char> > >;
template class MAPNIK_DECL feature_style_processor<svg_renderer<std::ostream_iterator<char> > >;
#endif
#if defined(GRID_RENDERER)
template class feature_style_processor<grid_renderer<grid> >;
template class MAPNIK_DECL feature_style_processor<grid_renderer<grid> >;
#endif
template class feature_style_processor<agg_renderer<image_32> >;
template class MAPNIK_DECL feature_style_processor<agg_renderer<image_rgba8> >;
}

View file

@ -1,166 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/global.hpp>
#include <mapnik/color.hpp>
// agg
#include "agg_rendering_buffer.h"
#include "agg_pixfmt_rgba.h"
#include "agg_color_rgba.h"
#ifdef HAVE_CAIRO
#include <mapnik/cairo/cairo_context.hpp>
#endif
namespace mapnik
{
image_32::image_32(int width,int height)
: data_(width,height),
painted_(false),
premultiplied_(false) {}
image_32::image_32(image_32 const& rhs)
: data_(rhs.data_),
painted_(rhs.painted_),
premultiplied_(rhs.premultiplied_) {}
image_32::image_32(image_data_rgba8 && data)
: data_(std::move(data)),
painted_(false),
premultiplied_(false) {}
image_32::~image_32() {}
void image_32::set_grayscale_to_alpha()
{
for (unsigned int y = 0; y < data_.height(); ++y)
{
unsigned int* row_from = data_.getRow(y);
for (unsigned int x = 0; x < data_.width(); ++x)
{
unsigned rgba = row_from[x];
unsigned r = rgba & 0xff;
unsigned g = (rgba >> 8 ) & 0xff;
unsigned b = (rgba >> 16) & 0xff;
// magic numbers for grayscale
unsigned a = static_cast<unsigned>(std::ceil((r * .3) + (g * .59) + (b * .11)));
row_from[x] = (a << 24)| (255 << 16) | (255 << 8) | (255) ;
}
}
}
void image_32::set_color_to_alpha(const color& c)
{
for (unsigned y = 0; y < data_.height(); ++y)
{
unsigned int* row_from = data_.getRow(y);
for (unsigned x = 0; x < data_.width(); ++x)
{
unsigned rgba = row_from[x];
unsigned r = rgba & 0xff;
unsigned g = (rgba >> 8 ) & 0xff;
unsigned b = (rgba >> 16) & 0xff;
if (r == c.red() && g == c.green() && b == c.blue())
{
row_from[x] = 0;
}
}
}
}
void image_32::set_alpha(float opacity)
{
for (unsigned int y = 0; y < data_.height(); ++y)
{
unsigned int* row_to = data_.getRow(y);
for (unsigned int x = 0; x < data_.width(); ++x)
{
unsigned rgba = row_to[x];
unsigned a0 = (rgba >> 24) & 0xff;
unsigned a1 = int( ((rgba >> 24) & 0xff) * opacity );
//unsigned a1 = opacity;
if (a0 == a1) continue;
unsigned r = rgba & 0xff;
unsigned g = (rgba >> 8 ) & 0xff;
unsigned b = (rgba >> 16) & 0xff;
row_to[x] = (a1 << 24)| (b << 16) | (g << 8) | (r) ;
}
}
}
void image_32::set_background(const color& c)
{
background_=c;
data_.set(background_->rgba());
}
boost::optional<color> const& image_32::get_background() const
{
return background_;
}
void image_32::premultiply()
{
agg::rendering_buffer buffer(data_.getBytes(),data_.width(),data_.height(),data_.width() * 4);
agg::pixfmt_rgba32 pixf(buffer);
pixf.premultiply();
premultiplied_ = true;
}
void image_32::demultiply()
{
agg::rendering_buffer buffer(data_.getBytes(),data_.width(),data_.height(),data_.width() * 4);
agg::pixfmt_rgba32_pre pixf(buffer);
pixf.demultiply();
premultiplied_ = false;
}
void image_32::composite_pixel(unsigned op, int x,int y, unsigned c, unsigned cover, double opacity)
{
using color_type = agg::rgba8;
using value_type = color_type::value_type;
using order_type = agg::order_rgba;
using blender_type = agg::comp_op_adaptor_rgba<color_type,order_type>;
if (checkBounds(x,y))
{
unsigned rgba = data_(x,y);
unsigned ca = (unsigned)(((c >> 24) & 0xff) * opacity);
unsigned cb = (c >> 16 ) & 0xff;
unsigned cg = (c >> 8) & 0xff;
unsigned cr = (c & 0xff);
blender_type::blend_pix(op, (value_type*)&rgba, cr, cg, cb, ca, cover);
data_(x,y) = rgba;
}
}
}

View file

@ -34,7 +34,7 @@ namespace mapnik
{
template <typename T>
const typename hit_grid<T>::value_type hit_grid<T>::base_mask = std::numeric_limits<T>::min();
const typename hit_grid<T>::value_type hit_grid<T>::base_mask = std::numeric_limits<typename T::type>::min();
template <typename T>
hit_grid<T>::hit_grid(int width, int height, std::string const& key, unsigned int resolution)
@ -146,7 +146,7 @@ void hit_grid<T>::add_feature(mapnik::feature_impl const& feature)
}
template class hit_grid<mapnik::value_integer>;
template class MAPNIK_DECL hit_grid<mapnik::value_integer_pixel>;
}

View file

@ -125,10 +125,27 @@ void grid_renderer<T>::end_layer_processing(layer const&)
MAPNIK_LOG_DEBUG(grid_renderer) << "grid_renderer: End layer processing";
}
template <typename T>
void grid_renderer<T>::render_marker(mapnik::feature_impl const& feature, pixel_position const& pos, marker const& marker, agg::trans_affine const& tr, double opacity, composite_mode_e /*comp_op*/)
template <typename buffer_type>
struct grid_render_marker_visitor
{
if (marker.is_vector())
grid_render_marker_visitor(buffer_type & pixmap,
std::unique_ptr<grid_rasterizer> const& ras_ptr,
renderer_common const& common,
mapnik::feature_impl const& feature,
pixel_position const& pos,
agg::trans_affine const& tr,
double opacity)
: pixmap_(pixmap),
ras_ptr_(ras_ptr),
common_(common),
feature_(feature),
pos_(pos),
tr_(tr),
opacity_(opacity) {}
void operator() (marker_null const&) {}
void operator() (marker_svg const& marker)
{
using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>;
@ -140,61 +157,88 @@ void grid_renderer<T>::render_marker(mapnik::feature_impl const& feature, pixel_
grid_renderer_base_type renb(pixf);
renderer_type ren(renb);
ras_ptr->reset();
ras_ptr_->reset();
box2d<double> const& bbox = (*marker.get_vector_data())->bounding_box();
box2d<double> const& bbox = marker.get_data()->bounding_box();
coord<double,2> c = bbox.center();
// center the svg marker on '0,0'
agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y);
// apply symbol transformation to get to map space
mtx *= tr;
mtx *= tr_;
mtx *= agg::trans_affine_scaling(common_.scale_factor_);
// render the marker at the center of the marker box
mtx.translate(pos.x, pos.y);
mtx.translate(pos_.x, pos_.y);
using namespace mapnik::svg;
vertex_stl_adapter<svg_path_storage> stl_storage((*marker.get_vector_data())->source());
vertex_stl_adapter<svg_path_storage> stl_storage(marker.get_data()->source());
svg_path_adapter svg_path(stl_storage);
svg_renderer_agg<svg_path_adapter,
agg::pod_bvector<path_attributes>,
renderer_type,
pixfmt_type> svg_renderer(svg_path,
(*marker.get_vector_data())->attributes());
svg_renderer.render_id(*ras_ptr, sl, renb, feature.id(), mtx, opacity, bbox);
marker.get_data()->attributes());
svg_renderer.render_id(*ras_ptr_, sl, renb, feature_.id(), mtx, opacity_, bbox);
}
else
void operator() (marker_rgba8 const& marker)
{
image_data_rgba8 const& data = **marker.get_bitmap_data();
image_rgba8 const& data = marker.get_data();
double width = data.width();
double height = data.height();
double cx = 0.5 * width;
double cy = 0.5 * height;
if ((std::fabs(1.0 - common_.scale_factor_) < 0.001 && tr.is_identity()))
if ((std::fabs(1.0 - common_.scale_factor_) < 0.001 && tr_.is_identity()))
{
// TODO - support opacity
pixmap_.set_rectangle(feature.id(), data,
boost::math::iround(pos.x - cx),
boost::math::iround(pos.y - cy));
pixmap_.set_rectangle(feature_.id(), data,
boost::math::iround(pos_.x - cx),
boost::math::iround(pos_.y - cy));
}
else
{
image_data_rgba8 target(data.width(), data.height());
image_rgba8 target(data.width(), data.height());
mapnik::scale_image_agg(target,
data,
SCALING_NEAR,
1,
1,
0.0, 0.0, 1.0); // TODO: is 1.0 a valid default here, and do we even care in grid_renderer what the image looks like?
pixmap_.set_rectangle(feature.id(), target,
boost::math::iround(pos.x - cx),
boost::math::iround(pos.y - cy));
pixmap_.set_rectangle(feature_.id(), target,
boost::math::iround(pos_.x - cx),
boost::math::iround(pos_.y - cy));
}
}
private:
buffer_type & pixmap_;
std::unique_ptr<grid_rasterizer> const& ras_ptr_;
renderer_common const& common_;
mapnik::feature_impl const& feature_;
pixel_position const& pos_;
agg::trans_affine const& tr_;
double opacity_;
};
template <typename T>
void grid_renderer<T>::render_marker(mapnik::feature_impl const& feature,
pixel_position const& pos,
marker const& marker,
agg::trans_affine const& tr,
double opacity,
composite_mode_e /*comp_op*/)
{
grid_render_marker_visitor<buffer_type> visitor(pixmap_,
ras_ptr,
common_,
feature,
pos,
tr,
opacity);
util::apply_visitor(visitor, marker);
pixmap_.add_feature(feature);
}
template class grid_renderer<grid>;
template class MAPNIK_DECL grid_renderer<grid>;
}

View file

@ -135,7 +135,7 @@ struct thunk_renderer
{
ren_.render_marker(feature_,
glyphs->marker_pos(),
*(glyphs->marker()->marker),
glyphs->marker()->marker,
glyphs->marker()->transform,
thunk.opacity_, thunk.comp_op_);
}

Some files were not shown because too many files have changed in this diff Show more