diff --git a/include/mapnik/warp.hpp b/include/mapnik/warp.hpp new file mode 100644 index 000000000..32ea74445 --- /dev/null +++ b/include/mapnik/warp.hpp @@ -0,0 +1,41 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2006-2011 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 + * + *****************************************************************************/ +//$Id$ + +#ifndef WARP_HPP +#define WARP_HPP + +#include +#include + +namespace mapnik { + +void reproject_raster(raster &target, raster const& source, + proj_transform const& prj_trans, + double offset_x, double offset_y, + unsigned mesh_size, + double filter_radius, + double scale_factor, + std::string scaling_method_name); + +} +#endif //WARP_HPP diff --git a/src/agg/process_raster_symbolizer.cpp b/src/agg/process_raster_symbolizer.cpp index 0a456b36f..959a2e8be 100644 --- a/src/agg/process_raster_symbolizer.cpp +++ b/src/agg/process_raster_symbolizer.cpp @@ -24,191 +24,18 @@ // mapnik #include #include -#include #include #include #include #include +#include // stl #include -// agg -#include "agg_image_filters.h" -#include "agg_trans_bilinear.h" -#include "agg_span_interpolator_linear.h" -#include "agg_span_image_filter_rgba.h" -#include "agg_rendering_buffer.h" -#include "agg_pixfmt_rgba.h" -#include "agg_rasterizer_scanline_aa.h" -#include "agg_basics.h" -#include "agg_scanline_u.h" -#include "agg_renderer_scanline.h" -#include "agg_span_allocator.h" -#include "agg_image_accessors.h" -#include "agg_renderer_scanline.h" namespace mapnik { -static inline void resample_raster(raster &target, raster const& source, - proj_transform const& prj_trans, - double offset_x, double offset_y, - unsigned mesh_size, - double filter_radius, - double scale_factor, - std::string scaling_method_name) -{ - if (prj_trans.equal()) { - - if (scaling_method_name == "bilinear8"){ - scale_image_bilinear8(target.data_,source.data_, - offset_x, offset_y); - } else { - scaling_method_e scaling_method = get_scaling_method_by_name(scaling_method_name); - scale_image_agg(target.data_,source.data_, (scaling_method_e)scaling_method, scale_factor, offset_x, offset_y, filter_radius); - } - } else { - CoordTransform ts(source.data_.width(), source.data_.height(), - source.ext_); - CoordTransform tt(target.data_.width(), target.data_.height(), - target.ext_, offset_x, offset_y); - unsigned i, j; - unsigned mesh_nx = ceil(source.data_.width()/double(mesh_size)+1); - unsigned mesh_ny = ceil(source.data_.height()/double(mesh_size)+1); - - ImageData xs(mesh_nx, mesh_ny); - ImageData ys(mesh_nx, mesh_ny); - - // Precalculate reprojected mesh - for(j=0; j renderer_base; - typedef agg::pixfmt_rgba32_pre pixfmt_pre; - typedef agg::renderer_base renderer_base_pre; - - agg::rasterizer_scanline_aa<> rasterizer; - agg::scanline_u8 scanline; - agg::rendering_buffer buf((unsigned char*)target.data_.getData(), - target.data_.width(), - target.data_.height(), - target.data_.width()*4); - pixfmt_pre pixf_pre(buf); - renderer_base_pre rb_pre(pixf_pre); - rasterizer.clip_box(0, 0, target.data_.width(), target.data_.height()); - agg::rendering_buffer buf_tile( - (unsigned char*)source.data_.getData(), - source.data_.width(), - source.data_.height(), - source.data_.width() * 4); - - pixfmt pixf_tile(buf_tile); - - typedef agg::image_accessor_clone img_accessor_type; - img_accessor_type ia(pixf_tile); - - agg::span_allocator sa; - agg::image_filter_lut filter; - scaling_method_e scaling_method = get_scaling_method_by_name( - scaling_method_name); - switch(scaling_method) - { - case SCALING_NEAR: break; - case SCALING_BILINEAR: - filter.calculate(agg::image_filter_bilinear(), true); break; - case SCALING_BICUBIC: - filter.calculate(agg::image_filter_bicubic(), true); break; - case SCALING_SPLINE16: - filter.calculate(agg::image_filter_spline16(), true); break; - case SCALING_SPLINE36: - filter.calculate(agg::image_filter_spline36(), true); break; - case SCALING_HANNING: - filter.calculate(agg::image_filter_hanning(), true); break; - case SCALING_HAMMING: - filter.calculate(agg::image_filter_hamming(), true); break; - case SCALING_HERMITE: - filter.calculate(agg::image_filter_hermite(), true); break; - case SCALING_KAISER: - filter.calculate(agg::image_filter_kaiser(), true); break; - case SCALING_QUADRIC: - filter.calculate(agg::image_filter_quadric(), true); break; - case SCALING_CATROM: - filter.calculate(agg::image_filter_catrom(), true); break; - case SCALING_GAUSSIAN: - filter.calculate(agg::image_filter_gaussian(), true); break; - case SCALING_BESSEL: - filter.calculate(agg::image_filter_bessel(), true); break; - case SCALING_MITCHELL: - filter.calculate(agg::image_filter_mitchell(), true); break; - case SCALING_SINC: - filter.calculate(agg::image_filter_sinc(filter_radius), true); break; - case SCALING_LANCZOS: - filter.calculate(agg::image_filter_lanczos(filter_radius), true); break; - case SCALING_BLACKMAN: - filter.calculate(agg::image_filter_blackman(filter_radius), true); break; - } - - for(j=0; j - interpolator_type; - interpolator_type interpolator(tr); - - if (scaling_method == SCALING_NEAR) { - typedef agg::span_image_filter_rgba_nn - - span_gen_type; - span_gen_type sg(ia, interpolator); - agg::render_scanlines_aa(rasterizer, scanline, rb_pre, - sa, sg); - } else { - typedef agg::span_image_filter_rgba_2x2 - - span_gen_type; - - span_gen_type sg(ia, interpolator, filter); - agg::render_scanlines_aa(rasterizer, scanline, rb_pre, - sa, sg); - } - } - - } - } - } -} template void agg_renderer::process(raster_symbolizer const& sym, @@ -242,11 +69,11 @@ void agg_renderer::process(raster_symbolizer const& sym, image_data_32 target_data(raster_width,raster_height); raster target(target_ext, target_data); - resample_raster(target, *source, prj_trans, err_offs_x, err_offs_y, - sym.get_mesh_size(), - sym.calculate_filter_factor(), - scale_factor, - sym.get_scaling()); + reproject_raster(target, *source, prj_trans, err_offs_x, err_offs_y, + sym.get_mesh_size(), + sym.calculate_filter_factor(), + scale_factor, + sym.get_scaling()); if (sym.get_mode() == "normal"){ if (sym.get_opacity() == 1.0) { diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index 146e836c7..bec48966c 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -37,6 +37,7 @@ #include #include #include +#include // cairo #include @@ -1373,23 +1374,22 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym, } } -//FIXME: Port reprojection code from agg/process_raster_symbolizer.cpp void cairo_renderer_base::process(raster_symbolizer const& sym, Feature const& feature, - proj_transform const& /*prj_trans*/) + proj_transform const& prj_trans) { - // TODO -- at the moment raster_symbolizer is an empty class - // used for type dispatching, but we can have some fancy raster - // processing in a future (filters??). Just copy raster into pixmap for now. - raster_ptr const& raster = feature.get_raster(); - if (raster) + raster_ptr const& source = feature.get_raster(); + if (source) { // If there's a colorizer defined, use it to color the raster in-place raster_colorizer_ptr colorizer = sym.get_colorizer(); if (colorizer) - colorizer->colorize(raster,feature.props()); + colorizer->colorize(source,feature.props()); - box2d ext = t_.forward(raster->ext_); + box2d target_ext = box2d(source->ext_); + prj_trans.backward(target_ext, PROJ_ENVELOPE_POINTS); + + box2d ext=t_.forward(target_ext); int start_x = (int)ext.minx(); int start_y = (int)ext.miny(); int end_x = (int)ceil(ext.maxx()); @@ -1401,18 +1401,19 @@ void cairo_renderer_base::process(raster_symbolizer const& sym, if (raster_width > 0 && raster_height > 0) { - double scale_factor = ext.width() / raster->data_.width(); - image_data_32 target(raster_width, raster_height); - //TODO -- use cairo matrix transformation for scaling - if (sym.get_scaling() == "bilinear8"){ - scale_image_bilinear8(target,raster->data_, err_offs_x, err_offs_y); - } else { - scaling_method_e scaling_method = get_scaling_method_by_name(sym.get_scaling()); - scale_image_agg(target,raster->data_, scaling_method, scale_factor, err_offs_x, err_offs_y, sym.calculate_filter_factor()); - } + double scale_factor = ext.width() / source->data_.width(); + image_data_32 target_data(raster_width,raster_height); + raster target(target_ext, target_data); + + reproject_raster(target, *source, prj_trans, err_offs_x, err_offs_y, + sym.get_mesh_size(), + sym.calculate_filter_factor(), + scale_factor, + sym.get_scaling()); + cairo_context context(context_); //TODO -- support for advanced image merging - context.add_image(start_x, start_y, target, sym.get_opacity()); + context.add_image(start_x, start_y, target.data_, sym.get_opacity()); } } } diff --git a/src/warp.cpp b/src/warp.cpp new file mode 100644 index 000000000..6f4a575aa --- /dev/null +++ b/src/warp.cpp @@ -0,0 +1,204 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 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 + * + *****************************************************************************/ +//$Id$ + +// mapnik +#include +#include +#include +#include +#include + +// agg +#include "agg_image_filters.h" +#include "agg_trans_bilinear.h" +#include "agg_span_interpolator_linear.h" +#include "agg_span_image_filter_rgba.h" +#include "agg_rendering_buffer.h" +#include "agg_pixfmt_rgba.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_basics.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_span_allocator.h" +#include "agg_image_accessors.h" +#include "agg_renderer_scanline.h" + +void reproject_raster(raster &target, raster const& source, + proj_transform const& prj_trans, + double offset_x, double offset_y, + unsigned mesh_size, + double filter_radius, + double scale_factor, + std::string scaling_method_name) +{ + if (prj_trans.equal()) { + + if (scaling_method_name == "bilinear8"){ + scale_image_bilinear8(target.data_,source.data_, + offset_x, offset_y); + } else { + scaling_method_e scaling_method = get_scaling_method_by_name(scaling_method_name); + scale_image_agg(target.data_,source.data_, (scaling_method_e)scaling_method, scale_factor, offset_x, offset_y, filter_radius); + } + } else { + CoordTransform ts(source.data_.width(), source.data_.height(), + source.ext_); + CoordTransform tt(target.data_.width(), target.data_.height(), + target.ext_, offset_x, offset_y); + unsigned i, j; + unsigned mesh_nx = ceil(source.data_.width()/double(mesh_size)+1); + unsigned mesh_ny = ceil(source.data_.height()/double(mesh_size)+1); + + ImageData xs(mesh_nx, mesh_ny); + ImageData ys(mesh_nx, mesh_ny); + + // Precalculate reprojected mesh + for(j=0; j renderer_base; + typedef agg::pixfmt_rgba32_pre pixfmt_pre; + typedef agg::renderer_base renderer_base_pre; + + agg::rasterizer_scanline_aa<> rasterizer; + agg::scanline_u8 scanline; + agg::rendering_buffer buf((unsigned char*)target.data_.getData(), + target.data_.width(), + target.data_.height(), + target.data_.width()*4); + pixfmt_pre pixf_pre(buf); + renderer_base_pre rb_pre(pixf_pre); + rasterizer.clip_box(0, 0, target.data_.width(), target.data_.height()); + agg::rendering_buffer buf_tile( + (unsigned char*)source.data_.getData(), + source.data_.width(), + source.data_.height(), + source.data_.width() * 4); + + pixfmt pixf_tile(buf_tile); + + typedef agg::image_accessor_clone img_accessor_type; + img_accessor_type ia(pixf_tile); + + agg::span_allocator sa; + agg::image_filter_lut filter; + scaling_method_e scaling_method = get_scaling_method_by_name( + scaling_method_name); + switch(scaling_method) + { + case SCALING_NEAR: break; + case SCALING_BILINEAR: + filter.calculate(agg::image_filter_bilinear(), true); break; + case SCALING_BICUBIC: + filter.calculate(agg::image_filter_bicubic(), true); break; + case SCALING_SPLINE16: + filter.calculate(agg::image_filter_spline16(), true); break; + case SCALING_SPLINE36: + filter.calculate(agg::image_filter_spline36(), true); break; + case SCALING_HANNING: + filter.calculate(agg::image_filter_hanning(), true); break; + case SCALING_HAMMING: + filter.calculate(agg::image_filter_hamming(), true); break; + case SCALING_HERMITE: + filter.calculate(agg::image_filter_hermite(), true); break; + case SCALING_KAISER: + filter.calculate(agg::image_filter_kaiser(), true); break; + case SCALING_QUADRIC: + filter.calculate(agg::image_filter_quadric(), true); break; + case SCALING_CATROM: + filter.calculate(agg::image_filter_catrom(), true); break; + case SCALING_GAUSSIAN: + filter.calculate(agg::image_filter_gaussian(), true); break; + case SCALING_BESSEL: + filter.calculate(agg::image_filter_bessel(), true); break; + case SCALING_MITCHELL: + filter.calculate(agg::image_filter_mitchell(), true); break; + case SCALING_SINC: + filter.calculate(agg::image_filter_sinc(filter_radius), true); break; + case SCALING_LANCZOS: + filter.calculate(agg::image_filter_lanczos(filter_radius), true); break; + case SCALING_BLACKMAN: + filter.calculate(agg::image_filter_blackman(filter_radius), true); break; + } + + for(j=0; j + interpolator_type; + interpolator_type interpolator(tr); + + if (scaling_method == SCALING_NEAR) { + typedef agg::span_image_filter_rgba_nn + + span_gen_type; + span_gen_type sg(ia, interpolator); + agg::render_scanlines_aa(rasterizer, scanline, rb_pre, + sa, sg); + } else { + typedef agg::span_image_filter_rgba_2x2 + + span_gen_type; + + span_gen_type sg(ia, interpolator, filter); + agg::render_scanlines_aa(rasterizer, scanline, rb_pre, + sa, sg); + } + } + + } + } + } +}