+ implement compositing for text

+ refactor image_32
This commit is contained in:
Artem Pavlenko 2012-05-09 12:39:23 +01:00
parent 36c5e348d0
commit aad7c5e384
20 changed files with 160 additions and 67 deletions

View File

@ -21,6 +21,7 @@
*****************************************************************************/
#include <mapnik/map.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/agg_renderer.hpp>
@ -250,11 +251,11 @@ int main ( int argc , char** argv)
agg_renderer<image_32> ren(m,buf);
ren.apply();
save_to_file<image_data_32>(buf.data(),"demo.jpg","jpeg");
save_to_file<image_data_32>(buf.data(),"demo.png","png");
save_to_file<image_data_32>(buf.data(),"demo256.png","png256");
save_to_file<image_data_32>(buf.data(),"demo.tif","tiff");
save_to_file(buf,"demo.jpg","jpeg");
save_to_file(buf,"demo.png","png");
save_to_file(buf,"demo256.png","png256");
save_to_file(buf,"demo.tif","tiff");
std::cout << "Three maps have been rendered using AGG in the current directory:\n"
"- demo.jpg\n"
"- demo.png\n"

View File

@ -24,6 +24,7 @@
#include <boost/bind.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/grid/grid_renderer.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/projection.hpp>

View File

@ -111,11 +111,8 @@ public:
// agg renderer doesn't support processing of multiple symbolizers.
return false;
};
void painted(bool painted)
{
pixmap_.painted(painted);
}
void painted(bool painted);
private:
buffer_type & pixmap_;

View File

@ -32,6 +32,7 @@
#include <mapnik/font_set.hpp>
#include <mapnik/char_info.hpp>
#include <mapnik/pixel_position.hpp>
#include <mapnik/image_compositing.hpp>
// freetype2
extern "C"
@ -337,7 +338,7 @@ public:
{
return stroker_;
}
private:
font_engine_type & engine_;
stroker_ptr stroker_;
@ -351,20 +352,21 @@ struct text_renderer : private boost::noncopyable
{
FT_Glyph image;
char_properties *properties;
glyph_t(FT_Glyph image_, char_properties *properties_)
glyph_t(FT_Glyph image_, char_properties *properties_)
: image(image_), properties(properties_) {}
~glyph_t () { FT_Done_Glyph(image);}
};
typedef boost::ptr_vector<glyph_t> glyphs_t;
typedef T pixmap_type;
text_renderer (pixmap_type & pixmap, face_manager<freetype_engine> &font_manager_, stroker & s);
text_renderer (pixmap_type & pixmap, face_manager<freetype_engine> &font_manager_, stroker & s, composite_mode_e comp_op = src_over);
box2d<double> prepare_glyphs(text_path *path);
void render(pixel_position pos);
void render_id(int feature_id, pixel_position pos, double min_radius=1.0);
private:
void render_bitmap(FT_Bitmap *bitmap, unsigned rgba, int x, int y, double opacity)
{
int x_max=x+bitmap->width;
@ -408,8 +410,11 @@ private:
face_manager<freetype_engine> &font_manager_;
stroker & stroker_;
glyphs_t glyphs_;
composite_mode_e comp_op_;
};
typedef face_manager<freetype_engine> face_manager_freetype;
}
#endif // MAPNIK_FONT_ENGINE_FREETYPE_HPP

View File

@ -223,7 +223,7 @@ public:
{
unsigned rgba0 = data_(x,y);
#ifdef MAPNIK_BIG_ENDIAN
unsigned a1 = (int)((rgba1 & 0xff) * opacity) & 0xff; // adjust for desired opacity
unsigned a1 = (unsigned)((rgba1 & 0xff) * opacity) & 0xff; // adjust for desired opacity
a1 = (t*a1) / 255;
if (a1 == 0) return;
unsigned r1 = (rgba1 >> 24) & 0xff;
@ -243,7 +243,7 @@ public:
a0 = a0 >> 8;
data_(x,y)= (a0)| (b0 << 8) | (g0 << 16) | (r0 << 24) ;
#else
unsigned a1 = (int)(((rgba1 >> 24) & 0xff) * opacity) & 0xff; // adjust for desired opacity
unsigned a1 = (unsigned)(((rgba1 >> 24) & 0xff) * opacity) & 0xff; // adjust for desired opacity
a1 = (t*a1) / 255;
if (a1 == 0) return;
unsigned r1 = rgba1 & 0xff;
@ -265,7 +265,9 @@ public:
#endif
}
}
void composite_pixel(unsigned op, int x,int y,unsigned c, unsigned cover, double opacity);
inline unsigned width() const
{
return width_;

View File

@ -25,7 +25,7 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/graphics.hpp>
//#include <mapnik/graphics.hpp>
#include <mapnik/palette.hpp>
// boost
@ -215,43 +215,29 @@ template <typename Image>
void scale_image_bilinear8 (Image& target,const Image& source, double x_off_f=0, double y_off_f=0);
/////////// save_to_file ////////////////////////////////////////////////
class image_32;
inline MAPNIK_DECL void save_to_file(image_32 const& image,
std::string const& file)
{
save_to_file<image_data_32>(image.data(), file);
}
MAPNIK_DECL void save_to_file(image_32 const& image,
std::string const& file);
inline MAPNIK_DECL void save_to_file (image_32 const& image,
std::string const& file,
std::string const& type)
{
save_to_file<image_data_32>(image.data(), file, type);
}
MAPNIK_DECL void save_to_file (image_32 const& image,
std::string const& file,
std::string const& type);
inline MAPNIK_DECL void save_to_file (image_32 const& image,
std::string const& file,
std::string const& type,
rgba_palette const& palette)
{
save_to_file<image_data_32>(image.data(), file, type, palette);
}
MAPNIK_DECL void save_to_file (image_32 const& image,
std::string const& file,
std::string const& type,
rgba_palette const& palette);
//////////////////////////////////////////////////////////////////////////
inline MAPNIK_DECL std::string save_to_string(image_32 const& image,
std::string const& type)
{
return save_to_string<image_data_32>(image.data(), type);
}
MAPNIK_DECL std::string save_to_string(image_32 const& image,
std::string const& type);
inline MAPNIK_DECL std::string save_to_string(image_32 const& image,
std::string const& type,
rgba_palette const& palette)
{
return save_to_string<image_data_32>(image.data(), type, palette);
}
MAPNIK_DECL std::string save_to_string(image_32 const& image,
std::string const& type,
rgba_palette const& palette);
///////////////////////////////////////////////////////////////////////////

View File

@ -28,7 +28,7 @@
#include <mapnik/palette.hpp>
#include <mapnik/octree.hpp>
#include <mapnik/hextree.hpp>
#include <mapnik/image_data.hpp>
// zlib
#include <zlib.h>

View File

@ -24,7 +24,8 @@
#define MAPNIK_RASTER_HPP
// mapnik
#include <mapnik/graphics.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/image_data.hpp>
namespace mapnik {
struct raster

View File

@ -21,6 +21,7 @@
*****************************************************************************/
// mapnik
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/agg_helpers.hpp>
@ -292,5 +293,11 @@ void agg_renderer<T>::render_marker(pixel_position const& pos, marker const& mar
}
}
template <typename T>
void agg_renderer<T>::painted(bool painted)
{
pixmap_.painted(painted);
}
template class agg_renderer<image_32>;
}

View File

@ -21,6 +21,7 @@
*****************************************************************************/
// mapnik
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/segment.hpp>

View File

@ -24,6 +24,7 @@
#include <boost/foreach.hpp>
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/agg_pattern_source.hpp>

View File

@ -23,6 +23,7 @@
// boost
#include <boost/foreach.hpp>
// mapnik
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_helpers.hpp>
#include <mapnik/agg_rasterizer.hpp>

View File

@ -22,6 +22,7 @@
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/expression_evaluator.hpp>

View File

@ -24,6 +24,7 @@
#include <boost/foreach.hpp>
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_helpers.hpp>
#include <mapnik/agg_rasterizer.hpp>

View File

@ -24,6 +24,7 @@
#include <boost/foreach.hpp>
// mapnik
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_helpers.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/polygon_symbolizer.hpp>

View File

@ -22,6 +22,7 @@
// mapnik
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image_util.hpp>

View File

@ -38,9 +38,12 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
width_, height_,
scale_factor_,
t_, font_manager_, *detector_, query_extent_);
text_renderer<T> ren(*current_buffer_, font_manager_, *(font_manager_.get_stroker()));
composite_mode_e comp_op = src_over;
if ( sym.comp_op() ) comp_op = *sym.comp_op();
text_renderer<T> ren(*current_buffer_, font_manager_, *(font_manager_.get_stroker()), comp_op);
while (helper.next()) {
placements_type &placements = helper.placements();
for (unsigned int ii = 0; ii < placements.size(); ++ii)

View File

@ -315,13 +315,11 @@ void font_face_set::get_string_info(string_info & info, UnicodeString const& ust
}
template <typename T>
text_renderer<T>::text_renderer (pixmap_type & pixmap, face_manager<freetype_engine> &font_manager_, stroker & s)
text_renderer<T>::text_renderer (pixmap_type & pixmap, face_manager<freetype_engine> &font_manager_, stroker & s, composite_mode_e comp_op)
: pixmap_(pixmap),
font_manager_(font_manager_),
stroker_(s)
{
}
stroker_(s),
comp_op_(comp_op) {}
template <typename T>
box2d<double> text_renderer<T>::prepare_glyphs(text_path *path)
@ -401,6 +399,26 @@ box2d<double> text_renderer<T>::prepare_glyphs(text_path *path)
return box2d<double>(bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax);
}
template <typename T>
void composite_bitmap(T & pixmap, FT_Bitmap *bitmap, unsigned rgba, int x, int y, double opacity, composite_mode_e comp_op)
{
int x_max=x+bitmap->width;
int y_max=y+bitmap->rows;
int i,p,j,q;
for (i=x,p=0;i<x_max;++i,++p)
{
for (j=y,q=0;j<y_max;++j,++q)
{
unsigned gray=bitmap->buffer[q*bitmap->width+p];
if (gray)
{
pixmap.composite_pixel(comp_op, i, j, rgba, gray, opacity);
}
}
}
}
template <typename T>
void text_renderer<T>::render(pixel_position pos)
{
@ -430,9 +448,12 @@ void text_renderer<T>::render(pixel_position pos)
{
FT_BitmapGlyph bit = (FT_BitmapGlyph)g;
render_bitmap(&bit->bitmap, itr->properties->halo_fill.rgba(),
bit->left,
height - bit->top, itr->properties->text_opacity);
composite_bitmap(pixmap_, &bit->bitmap, itr->properties->halo_fill.rgba(),
bit->left,
height - bit->top,
itr->properties->text_opacity,
comp_op_
);
}
}
FT_Done_Glyph(g);
@ -448,9 +469,16 @@ void text_renderer<T>::render(pixel_position pos)
{
FT_BitmapGlyph bit = (FT_BitmapGlyph)itr->image;
render_bitmap(&bit->bitmap, itr->properties->fill.rgba(),
bit->left,
height - bit->top, itr->properties->text_opacity);
//render_bitmap(&bit->bitmap, itr->properties->fill.rgba(),
// bit->left,
// height - bit->top, itr->properties->text_opacity);
composite_bitmap(pixmap_, &bit->bitmap, itr->properties->fill.rgba(),
bit->left,
height - bit->top,
itr->properties->text_opacity,
comp_op_
);
}
}
}
@ -497,10 +525,10 @@ boost::mutex freetype_engine::mutex_;
#endif
std::map<std::string,std::pair<int,std::string> > freetype_engine::name2file_;
template void text_renderer<image_32>::render(pixel_position);
template text_renderer<image_32>::text_renderer(image_32&, face_manager<freetype_engine>&, stroker&);
template text_renderer<image_32>::text_renderer(image_32&, face_manager<freetype_engine>&, stroker&, composite_mode_e);
template box2d<double>text_renderer<image_32>::prepare_glyphs(text_path*);
template void text_renderer<grid>::render_id(int, pixel_position, double);
template text_renderer<grid>::text_renderer(grid&, face_manager<freetype_engine>&, stroker&);
template void text_renderer<grid>::render_id(int, pixel_position, double );
template text_renderer<grid>::text_renderer(grid&, face_manager<freetype_engine>&, stroker&, composite_mode_e);
template box2d<double>text_renderer<grid>::prepare_glyphs(text_path*);
}

View File

@ -26,7 +26,8 @@
#include <mapnik/image_util.hpp>
#include <mapnik/global.hpp>
#include <mapnik/color.hpp>
// agg
#include "agg_pixfmt_rgba.h"
// cairo
#ifdef HAVE_CAIRO
#include <cairomm/surface.h>
@ -190,4 +191,23 @@ boost::optional<color> const& image_32::get_background() const
return background_;
}
void image_32::composite_pixel(unsigned op, int x,int y, unsigned c, unsigned cover, double opacity)
{
typedef agg::rgba8 color_type;
typedef color_type::value_type value_type;
typedef agg::order_rgba order_type;
typedef agg::comp_op_adaptor_rgba<color_type,order_type> blender_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

@ -73,6 +73,7 @@ extern "C"
namespace mapnik
{
template <typename T>
std::string save_to_string(T const& image,
std::string const& type,
@ -774,6 +775,40 @@ void scale_image_agg (Image& target,const Image& source, scaling_method_e scalin
agg::render_scanlines_aa(ras, sl, rb_dst, sa, sg);
}
void save_to_file(image_32 const& image,std::string const& file)
{
save_to_file<image_data_32>(image.data(), file);
}
void save_to_file (image_32 const& image,
std::string const& file,
std::string const& type)
{
save_to_file<image_data_32>(image.data(), file, type);
}
void save_to_file (image_32 const& image,
std::string const& file,
std::string const& type,
rgba_palette const& palette)
{
save_to_file<image_data_32>(image.data(), file, type, palette);
}
std::string save_to_string(image_32 const& image,
std::string const& type)
{
return save_to_string<image_data_32>(image.data(), type);
}
std::string save_to_string(image_32 const& image,
std::string const& type,
rgba_palette const& palette)
{
return save_to_string<image_data_32>(image.data(), type, palette);
}
template void scale_image_agg<image_data_32> (image_data_32& target,const image_data_32& source, scaling_method_e scaling_method, double scale_factor, double x_off_f, double y_off_f, double filter_radius, double ratio);
template void scale_image_bilinear_old<image_data_32> (image_data_32& target,const image_data_32& source, double x_off_f, double y_off_f);