rollback 34c3128b0c
, move 'scaling' to proper enum, and move image_scaling functions to new cpp/hpp
This commit is contained in:
parent
b365923772
commit
3823890b40
14 changed files with 686 additions and 555 deletions
|
@ -37,6 +37,7 @@ void export_palette();
|
|||
void export_image();
|
||||
void export_image_view();
|
||||
void export_gamma_method();
|
||||
void export_scaling_method();
|
||||
void export_grid();
|
||||
void export_grid_view();
|
||||
void export_map();
|
||||
|
@ -362,6 +363,7 @@ BOOST_PYTHON_MODULE(_mapnik)
|
|||
export_image();
|
||||
export_image_view();
|
||||
export_gamma_method();
|
||||
export_scaling_method();
|
||||
export_grid();
|
||||
export_grid_view();
|
||||
export_expression();
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
// mapnik
|
||||
#include <mapnik/raster_symbolizer.hpp>
|
||||
#include <mapnik/image_scaling.hpp>
|
||||
|
||||
using mapnik::raster_symbolizer;
|
||||
|
||||
|
@ -39,13 +40,13 @@ struct raster_symbolizer_pickle_suite : boost::python::pickle_suite
|
|||
*/
|
||||
|
||||
static boost::python::tuple
|
||||
getstate(const raster_symbolizer& r)
|
||||
getstate(raster_symbolizer const& r)
|
||||
{
|
||||
return boost::python::make_tuple(r.get_mode(),r.get_scaling(),r.get_opacity(),r.get_filter_factor(),r.get_mesh_size());
|
||||
return boost::python::make_tuple(r.get_mode(),r.get_scaling_method(),r.get_opacity(),r.get_filter_factor(),r.get_mesh_size());
|
||||
}
|
||||
|
||||
static void
|
||||
setstate (raster_symbolizer& r, boost::python::tuple state)
|
||||
setstate (raster_symbolizer & r, boost::python::tuple state)
|
||||
{
|
||||
using namespace boost::python;
|
||||
if (len(state) != 5)
|
||||
|
@ -58,7 +59,7 @@ struct raster_symbolizer_pickle_suite : boost::python::pickle_suite
|
|||
}
|
||||
|
||||
r.set_mode(extract<std::string>(state[0]));
|
||||
r.set_scaling(extract<std::string>(state[1]));
|
||||
r.set_scaling_method(extract<mapnik::scaling_method_e>(state[1]));
|
||||
r.set_opacity(extract<float>(state[2]));
|
||||
r.set_filter_factor(extract<float>(state[3]));
|
||||
r.set_mesh_size(extract<unsigned>(state[4]));
|
||||
|
@ -91,17 +92,15 @@ void export_raster_symbolizer()
|
|||
)
|
||||
|
||||
.add_property("scaling",
|
||||
make_function(&raster_symbolizer::get_scaling,return_value_policy<copy_const_reference>()),
|
||||
&raster_symbolizer::set_scaling,
|
||||
&raster_symbolizer::get_scaling_method,
|
||||
&raster_symbolizer::set_scaling_method,
|
||||
"Get/Set scaling algorithm.\n"
|
||||
"Possible values are:\n"
|
||||
"fast, bilinear, and bilinear8\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
"\n"
|
||||
">>> from mapnik import RasterSymbolizer\n"
|
||||
">>> r = RasterSymbolizer()\n"
|
||||
">>> r.scaling = 'bilinear8'\n"
|
||||
">>> r.scaling = 'mapnik.scaling_method.GAUSSIAN'\n"
|
||||
)
|
||||
|
||||
.add_property("opacity",
|
||||
|
|
83
include/mapnik/image_scaling.hpp
Normal file
83
include/mapnik/image_scaling.hpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef MAPNIK_IMAGE_SCALING_HPP
|
||||
#define MAPNIK_IMAGE_SCALING_HPP
|
||||
|
||||
// stl
|
||||
#include <string>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <mapnik/config.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
enum scaling_method_e
|
||||
{
|
||||
SCALING_NEAR=0,
|
||||
SCALING_BILINEAR,
|
||||
SCALING_BICUBIC,
|
||||
SCALING_SPLINE16,
|
||||
SCALING_SPLINE36,
|
||||
SCALING_HANNING,
|
||||
SCALING_HAMMING,
|
||||
SCALING_HERMITE,
|
||||
SCALING_KAISER,
|
||||
SCALING_QUADRIC,
|
||||
SCALING_CATROM,
|
||||
SCALING_GAUSSIAN,
|
||||
SCALING_BESSEL,
|
||||
SCALING_MITCHELL,
|
||||
SCALING_SINC,
|
||||
SCALING_LANCZOS,
|
||||
SCALING_BLACKMAN,
|
||||
SCALING_BILINEAR8
|
||||
};
|
||||
|
||||
boost::optional<scaling_method_e> scaling_method_from_string(std::string const& name);
|
||||
boost::optional<std::string> scaling_method_to_string(scaling_method_e scaling_method);
|
||||
|
||||
template <typename Image>
|
||||
void scale_image_agg(Image & target,
|
||||
Image const& source,
|
||||
scaling_method_e scaling_method,
|
||||
double scale_factor,
|
||||
double x_off_f=0,
|
||||
double y_off_f=0,
|
||||
double filter_radius=2,
|
||||
double ratio=1);
|
||||
|
||||
template <typename Image>
|
||||
void scale_image_bilinear_old(Image & target,
|
||||
Image const& source,
|
||||
double x_off_f=0,
|
||||
double y_off_f=0);
|
||||
|
||||
template <typename Image>
|
||||
void scale_image_bilinear8(Image & target,
|
||||
Image const& source,
|
||||
double x_off_f=0,
|
||||
double y_off_f=0);
|
||||
|
||||
}
|
||||
#endif // MAPNIK_IMAGE_SCALING_HPP
|
|
@ -61,7 +61,7 @@ public:
|
|||
MAPNIK_DECL void save_to_cairo_file(mapnik::Map const& map,
|
||||
std::string const& filename,
|
||||
std::string const& type,
|
||||
double scale_factor);
|
||||
double scale_factor=1.0);
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
|
@ -185,38 +185,7 @@ void add_border(T & image)
|
|||
}
|
||||
}
|
||||
|
||||
// IMAGE SCALING
|
||||
enum scaling_method_e
|
||||
{
|
||||
SCALING_NEAR=0,
|
||||
SCALING_BILINEAR=1,
|
||||
SCALING_BICUBIC=2,
|
||||
SCALING_SPLINE16=3,
|
||||
SCALING_SPLINE36=4,
|
||||
SCALING_HANNING=5,
|
||||
SCALING_HAMMING=6,
|
||||
SCALING_HERMITE=7,
|
||||
SCALING_KAISER=8,
|
||||
SCALING_QUADRIC=9,
|
||||
SCALING_CATROM=10,
|
||||
SCALING_GAUSSIAN=11,
|
||||
SCALING_BESSEL=12,
|
||||
SCALING_MITCHELL=13,
|
||||
SCALING_SINC=14,
|
||||
SCALING_LANCZOS=15,
|
||||
SCALING_BLACKMAN=16
|
||||
};
|
||||
|
||||
scaling_method_e get_scaling_method_by_name (std::string name);
|
||||
|
||||
template <typename Image>
|
||||
void scale_image_agg (Image& target,const Image& source, scaling_method_e scaling_method, double scale_factor, double x_off_f=0, double y_off_f=0, double filter_radius=2, double ratio=1);
|
||||
|
||||
template <typename Image>
|
||||
void scale_image_bilinear_old (Image& target,const Image& source, double x_off_f=0, double y_off_f=0);
|
||||
|
||||
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;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <mapnik/symbolizer.hpp>
|
||||
#include <mapnik/image_util.hpp>
|
||||
#include <mapnik/image_compositing.hpp>
|
||||
#include <mapnik/image_scaling.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
@ -39,7 +40,7 @@ struct MAPNIK_DECL raster_symbolizer : public symbolizer_base
|
|||
raster_symbolizer()
|
||||
: symbolizer_base(),
|
||||
mode_("normal"),
|
||||
scaling_("fast"),
|
||||
scaling_(SCALING_NEAR),
|
||||
opacity_(1.0),
|
||||
colorizer_(),
|
||||
filter_factor_(-1),
|
||||
|
@ -47,9 +48,9 @@ struct MAPNIK_DECL raster_symbolizer : public symbolizer_base
|
|||
|
||||
raster_symbolizer(const raster_symbolizer &rhs)
|
||||
: symbolizer_base(rhs),
|
||||
mode_(rhs.get_mode()),
|
||||
scaling_(rhs.get_scaling()),
|
||||
opacity_(rhs.get_opacity()),
|
||||
mode_(rhs.mode_),
|
||||
scaling_(rhs.scaling_),
|
||||
opacity_(rhs.opacity_),
|
||||
colorizer_(rhs.colorizer_),
|
||||
filter_factor_(rhs.filter_factor_),
|
||||
mesh_size_(rhs.mesh_size_) {}
|
||||
|
@ -76,11 +77,11 @@ struct MAPNIK_DECL raster_symbolizer : public symbolizer_base
|
|||
MAPNIK_LOG_ERROR(raster_symbolizer) << "could not convert mode into comp-op";
|
||||
}
|
||||
}
|
||||
std::string const& get_scaling() const
|
||||
scaling_method_e get_scaling_method() const
|
||||
{
|
||||
return scaling_;
|
||||
}
|
||||
void set_scaling(std::string const& scaling)
|
||||
void set_scaling_method(scaling_method_e scaling)
|
||||
{
|
||||
scaling_ = scaling;
|
||||
}
|
||||
|
@ -115,13 +116,9 @@ struct MAPNIK_DECL raster_symbolizer : public symbolizer_base
|
|||
// respect explicitly specified values
|
||||
return filter_factor_;
|
||||
} else {
|
||||
// No filter factor specified, calculate a sensible default value
|
||||
// based on the scaling algorithm being employed.
|
||||
scaling_method_e scaling = get_scaling_method_by_name (scaling_);
|
||||
|
||||
double ff = 1.0;
|
||||
|
||||
switch(scaling)
|
||||
switch(scaling_)
|
||||
{
|
||||
case SCALING_NEAR:
|
||||
ff = 1.0;
|
||||
|
@ -130,6 +127,7 @@ struct MAPNIK_DECL raster_symbolizer : public symbolizer_base
|
|||
// TODO potentially some of these algorithms would use filter_factor >2.0.
|
||||
// Contributions welcome from someone who knows more about them.
|
||||
case SCALING_BILINEAR:
|
||||
case SCALING_BILINEAR8:
|
||||
case SCALING_BICUBIC:
|
||||
case SCALING_SPLINE16:
|
||||
case SCALING_SPLINE36:
|
||||
|
@ -163,7 +161,7 @@ struct MAPNIK_DECL raster_symbolizer : public symbolizer_base
|
|||
|
||||
private:
|
||||
std::string mode_;
|
||||
std::string scaling_;
|
||||
scaling_method_e scaling_;
|
||||
float opacity_;
|
||||
raster_colorizer_ptr colorizer_;
|
||||
double filter_factor_;
|
||||
|
|
|
@ -26,16 +26,17 @@
|
|||
// mapnik
|
||||
#include <mapnik/raster.hpp>
|
||||
#include <mapnik/proj_transform.hpp>
|
||||
#include <mapnik/image_scaling.hpp>
|
||||
|
||||
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);
|
||||
void reproject_and_scale_raster(raster & target,
|
||||
raster const& source,
|
||||
proj_transform const& prj_trans,
|
||||
double offset_x, double offset_y,
|
||||
unsigned mesh_size,
|
||||
double filter_radius,
|
||||
scaling_method_e scaling_method);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
// mapnik
|
||||
#include <mapnik/agg_renderer.hpp>
|
||||
#include <mapnik/image_scaling.hpp>
|
||||
#include <mapnik/image_compositing.hpp>
|
||||
#include <mapnik/graphics.hpp>
|
||||
#include <mapnik/agg_rasterizer.hpp>
|
||||
|
@ -44,7 +45,7 @@ void agg_renderer<T>::process(raster_symbolizer const& sym,
|
|||
mapnik::feature_impl & feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
raster_ptr const& source=feature.get_raster();
|
||||
raster_ptr const& source = feature.get_raster();
|
||||
if (source)
|
||||
{
|
||||
// If there's a colorizer defined, use it to color the raster in-place
|
||||
|
@ -54,28 +55,44 @@ void agg_renderer<T>::process(raster_symbolizer const& sym,
|
|||
|
||||
box2d<double> target_ext = box2d<double>(source->ext_);
|
||||
prj_trans.backward(target_ext, PROJ_ENVELOPE_POINTS);
|
||||
|
||||
box2d<double> ext=t_.forward(target_ext);
|
||||
int start_x = (int)ext.minx();
|
||||
int start_y = (int)ext.miny();
|
||||
int end_x = (int)ceil(ext.maxx());
|
||||
int end_y = (int)ceil(ext.maxy());
|
||||
box2d<double> ext = t_.forward(target_ext);
|
||||
int start_x = static_cast<int>(ext.minx());
|
||||
int start_y = static_cast<int>(ext.miny());
|
||||
int end_x = static_cast<int>(ceil(ext.maxx()));
|
||||
int end_y = static_cast<int>(ceil(ext.maxy()));
|
||||
int raster_width = end_x - start_x;
|
||||
int raster_height = end_y - start_y;
|
||||
double err_offs_x = ext.minx() - start_x;
|
||||
double err_offs_y = ext.miny() - start_y;
|
||||
|
||||
if (raster_width > 0 && raster_height > 0)
|
||||
{
|
||||
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());
|
||||
|
||||
scaling_method_e scaling_method = sym.get_scaling_method();
|
||||
double filter_radius = sym.calculate_filter_factor();
|
||||
double offset_x = ext.minx() - start_x;
|
||||
double offset_y = ext.miny() - start_y;
|
||||
if (!prj_trans.equal())
|
||||
{
|
||||
reproject_and_scale_raster(target, *source, prj_trans,
|
||||
offset_x, offset_y,
|
||||
sym.get_mesh_size(),
|
||||
filter_radius,
|
||||
scaling_method);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scaling_method == SCALING_BILINEAR8){
|
||||
scale_image_bilinear8<image_data_32>(target.data_,source->data_, offset_x, offset_y);
|
||||
} else {
|
||||
double scaling_ratio = ext.width() / source->data_.width();
|
||||
scale_image_agg<image_data_32>(target.data_,
|
||||
source->data_,
|
||||
scaling_method,
|
||||
scaling_ratio,
|
||||
offset_x,
|
||||
offset_y,
|
||||
filter_radius);
|
||||
}
|
||||
}
|
||||
composite(current_buffer_->data(), target.data_, sym.comp_op(), sym.get_opacity(), start_x, start_y, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,6 +103,7 @@ source = Split(
|
|||
color.cpp
|
||||
conversions.cpp
|
||||
image_compositing.cpp
|
||||
image_scaling.cpp
|
||||
box2d.cpp
|
||||
building_symbolizer.cpp
|
||||
datasource_cache.cpp
|
||||
|
|
|
@ -1344,32 +1344,46 @@ void cairo_renderer_base::process(raster_symbolizer const& sym,
|
|||
|
||||
box2d<double> target_ext = box2d<double>(source->ext_);
|
||||
prj_trans.backward(target_ext, PROJ_ENVELOPE_POINTS);
|
||||
|
||||
box2d<double> ext=t_.forward(target_ext);
|
||||
int start_x = (int)ext.minx();
|
||||
int start_y = (int)ext.miny();
|
||||
int end_x = (int)ceil(ext.maxx());
|
||||
int end_y = (int)ceil(ext.maxy());
|
||||
box2d<double> ext = t_.forward(target_ext);
|
||||
int start_x = static_cast<int>(ext.minx());
|
||||
int start_y = static_cast<int>(ext.miny());
|
||||
int end_x = static_cast<int>(ceil(ext.maxx()));
|
||||
int end_y = static_cast<int>(ceil(ext.maxy()));
|
||||
int raster_width = end_x - start_x;
|
||||
int raster_height = end_y - start_y;
|
||||
double err_offs_x = ext.minx() - start_x;
|
||||
double err_offs_y = ext.miny() - start_y;
|
||||
|
||||
if (raster_width > 0 && raster_height > 0)
|
||||
{
|
||||
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());
|
||||
|
||||
scaling_method_e scaling_method = sym.get_scaling_method();
|
||||
double filter_radius = sym.calculate_filter_factor();
|
||||
double offset_x = ext.minx() - start_x;
|
||||
double offset_y = ext.miny() - start_y;
|
||||
if (!prj_trans.equal())
|
||||
{
|
||||
reproject_and_scale_raster(target, *source, prj_trans,
|
||||
offset_x, offset_y,
|
||||
sym.get_mesh_size(),
|
||||
filter_radius,
|
||||
scaling_method);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scaling_method == SCALING_BILINEAR8){
|
||||
scale_image_bilinear8<image_data_32>(target.data_,source->data_, offset_x, offset_y);
|
||||
} else {
|
||||
double scaling_ratio = ext.width() / source->data_.width();
|
||||
scale_image_agg<image_data_32>(target.data_,
|
||||
source->data_,
|
||||
scaling_method,
|
||||
scaling_ratio,
|
||||
offset_x,
|
||||
offset_y,
|
||||
filter_radius);
|
||||
}
|
||||
}
|
||||
cairo_context context(context_);
|
||||
context.set_operator(sym.comp_op());
|
||||
//TODO -- support for advanced image merging
|
||||
context.add_image(start_x, start_y, target.data_, sym.get_opacity());
|
||||
}
|
||||
}
|
||||
|
|
359
src/image_scaling.cpp
Normal file
359
src/image_scaling.cpp
Normal file
|
@ -0,0 +1,359 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/image_data.hpp>
|
||||
#include <mapnik/image_scaling.hpp>
|
||||
#include <mapnik/span_image_filter.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/assign/list_of.hpp>
|
||||
#include <boost/bimap.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_image_accessors.h"
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
#include "agg_scanline_u.h"
|
||||
#include "agg_span_allocator.h"
|
||||
#include "agg_span_image_filter_rgba.h"
|
||||
#include "agg_span_interpolator_linear.h"
|
||||
#include "agg_trans_affine.h"
|
||||
#include "agg_image_filters.h"
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
typedef boost::bimap<scaling_method_e, std::string> scaling_method_lookup_type;
|
||||
static const scaling_method_lookup_type scaling_lookup = boost::assign::list_of<scaling_method_lookup_type::relation>
|
||||
(SCALING_NEAR,"near")
|
||||
(SCALING_BILINEAR,"bilinear")
|
||||
(SCALING_BICUBIC,"bicubic")
|
||||
(SCALING_SPLINE16,"spline16")
|
||||
(SCALING_SPLINE36,"spline36")
|
||||
(SCALING_HANNING,"hanning")
|
||||
(SCALING_HAMMING,"hamming")
|
||||
(SCALING_HERMITE,"hermite")
|
||||
(SCALING_KAISER,"kaiser")
|
||||
(SCALING_QUADRIC,"quadric")
|
||||
(SCALING_CATROM,"catrom")
|
||||
(SCALING_GAUSSIAN,"gaussian")
|
||||
(SCALING_BESSEL,"bessel")
|
||||
(SCALING_MITCHELL,"mitchell")
|
||||
(SCALING_SINC,"sinc")
|
||||
(SCALING_LANCZOS,"lanczos")
|
||||
(SCALING_BLACKMAN,"blackman")
|
||||
(SCALING_BILINEAR8,"bilinear8")
|
||||
;
|
||||
|
||||
boost::optional<scaling_method_e> scaling_method_from_string(std::string const& name)
|
||||
{
|
||||
boost::optional<scaling_method_e> mode;
|
||||
scaling_method_lookup_type::right_const_iterator right_iter = scaling_lookup.right.find(name);
|
||||
if (right_iter != scaling_lookup.right.end())
|
||||
{
|
||||
mode.reset(right_iter->second);
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
boost::optional<std::string> scaling_method_to_string(scaling_method_e scaling_method)
|
||||
{
|
||||
boost::optional<std::string> mode;
|
||||
scaling_method_lookup_type::left_const_iterator left_iter = scaling_lookup.left.find(scaling_method);
|
||||
if (left_iter != scaling_lookup.left.end())
|
||||
{
|
||||
mode.reset(left_iter->second);
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
// this has been replaced by agg impl - see https://trac.mapnik.org/ticket/656
|
||||
template <typename Image>
|
||||
void scale_image_bilinear_old (Image & target,Image const& source, double x_off_f, double y_off_f)
|
||||
{
|
||||
|
||||
int source_width=source.width();
|
||||
int source_height=source.height();
|
||||
|
||||
int target_width=target.width();
|
||||
int target_height=target.height();
|
||||
|
||||
if (source_width<1 || source_height<1 ||
|
||||
target_width<1 || target_height<1) return;
|
||||
int x=0,y=0,xs=0,ys=0;
|
||||
int tw2 = target_width/2;
|
||||
int th2 = target_height/2;
|
||||
int offs_x = rint((source_width-target_width-x_off_f*2*source_width)/2);
|
||||
int offs_y = rint((source_height-target_height-y_off_f*2*source_height)/2);
|
||||
unsigned yprt, yprt1, xprt, xprt1;
|
||||
|
||||
//no scaling or subpixel offset
|
||||
if (target_height == source_height && target_width == source_width && offs_x == 0 && offs_y == 0){
|
||||
for (y=0;y<target_height;++y)
|
||||
target.setRow(y,source.getRow(y),target_width);
|
||||
return;
|
||||
}
|
||||
|
||||
for (y=0;y<target_height;++y)
|
||||
{
|
||||
ys = (y*source_height+offs_y)/target_height;
|
||||
int ys1 = ys+1;
|
||||
if (ys1>=source_height)
|
||||
ys1--;
|
||||
if (ys<0)
|
||||
ys=ys1=0;
|
||||
if (source_height/2<target_height)
|
||||
yprt = (y*source_height+offs_y)%target_height;
|
||||
else
|
||||
yprt = th2;
|
||||
yprt1 = target_height-yprt;
|
||||
for (x=0;x<target_width;++x)
|
||||
{
|
||||
xs = (x*source_width+offs_x)/target_width;
|
||||
if (source_width/2<target_width)
|
||||
xprt = (x*source_width+offs_x)%target_width;
|
||||
else
|
||||
xprt = tw2;
|
||||
xprt1 = target_width-xprt;
|
||||
int xs1 = xs+1;
|
||||
if (xs1>=source_width)
|
||||
xs1--;
|
||||
if (xs<0)
|
||||
xs=xs1=0;
|
||||
|
||||
unsigned a = source(xs,ys);
|
||||
unsigned b = source(xs1,ys);
|
||||
unsigned c = source(xs,ys1);
|
||||
unsigned d = source(xs1,ys1);
|
||||
unsigned out=0;
|
||||
unsigned t = 0;
|
||||
|
||||
for(int i=0; i<4; i++){
|
||||
unsigned p,r,s;
|
||||
// X axis
|
||||
p = a&0xff;
|
||||
r = b&0xff;
|
||||
if (p!=r)
|
||||
r = (r*xprt+p*xprt1+tw2)/target_width;
|
||||
p = c&0xff;
|
||||
s = d&0xff;
|
||||
if (p!=s)
|
||||
s = (s*xprt+p*xprt1+tw2)/target_width;
|
||||
// Y axis
|
||||
if (r!=s)
|
||||
r = (s*yprt+r*yprt1+th2)/target_height;
|
||||
// channel up
|
||||
out |= r << t;
|
||||
t += 8;
|
||||
a >>= 8;
|
||||
b >>= 8;
|
||||
c >>= 8;
|
||||
d >>= 8;
|
||||
}
|
||||
target(x,y)=out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename Image>
|
||||
void scale_image_bilinear8 (Image & target,Image const& source, double x_off_f, double y_off_f)
|
||||
{
|
||||
|
||||
int source_width=source.width();
|
||||
int source_height=source.height();
|
||||
|
||||
int target_width=target.width();
|
||||
int target_height=target.height();
|
||||
|
||||
if (source_width<1 || source_height<1 ||
|
||||
target_width<1 || target_height<1) return;
|
||||
int x=0,y=0,xs=0,ys=0;
|
||||
int tw2 = target_width/2;
|
||||
int th2 = target_height/2;
|
||||
int offs_x = rint((source_width-target_width-x_off_f*2*source_width)/2);
|
||||
int offs_y = rint((source_height-target_height-y_off_f*2*source_height)/2);
|
||||
unsigned yprt, yprt1, xprt, xprt1;
|
||||
|
||||
//no scaling or subpixel offset
|
||||
if (target_height == source_height && target_width == source_width && offs_x == 0 && offs_y == 0){
|
||||
for (y=0;y<target_height;++y)
|
||||
target.setRow(y,source.getRow(y),target_width);
|
||||
return;
|
||||
}
|
||||
|
||||
for (y=0;y<target_height;++y)
|
||||
{
|
||||
ys = (y*source_height+offs_y)/target_height;
|
||||
int ys1 = ys+1;
|
||||
if (ys1>=source_height)
|
||||
ys1--;
|
||||
if (ys<0)
|
||||
ys=ys1=0;
|
||||
if (source_height/2<target_height)
|
||||
yprt = (y*source_height+offs_y)%target_height;
|
||||
else
|
||||
yprt = th2;
|
||||
yprt1 = target_height-yprt;
|
||||
for (x=0;x<target_width;++x)
|
||||
{
|
||||
xs = (x*source_width+offs_x)/target_width;
|
||||
if (source_width/2<target_width)
|
||||
xprt = (x*source_width+offs_x)%target_width;
|
||||
else
|
||||
xprt = tw2;
|
||||
xprt1 = target_width-xprt;
|
||||
int xs1 = xs+1;
|
||||
if (xs1>=source_width)
|
||||
xs1--;
|
||||
if (xs<0)
|
||||
xs=xs1=0;
|
||||
|
||||
unsigned a = source(xs,ys);
|
||||
unsigned b = source(xs1,ys);
|
||||
unsigned c = source(xs,ys1);
|
||||
unsigned d = source(xs1,ys1);
|
||||
unsigned p,r,s;
|
||||
// X axis
|
||||
p = a&0xff;
|
||||
r = b&0xff;
|
||||
if (p!=r)
|
||||
r = (r*xprt+p*xprt1+tw2)/target_width;
|
||||
p = c&0xff;
|
||||
s = d&0xff;
|
||||
if (p!=s)
|
||||
s = (s*xprt+p*xprt1+tw2)/target_width;
|
||||
// Y axis
|
||||
if (r!=s)
|
||||
r = (s*yprt+r*yprt1+th2)/target_height;
|
||||
target(x,y)=(0xff<<24) | (r<<16) | (r<<8) | r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Image>
|
||||
void scale_image_agg(Image & target,
|
||||
Image const& source,
|
||||
scaling_method_e scaling_method,
|
||||
double image_ratio,
|
||||
double x_off_f,
|
||||
double y_off_f,
|
||||
double filter_radius,
|
||||
double ratio)
|
||||
{
|
||||
typedef agg::pixfmt_rgba32 pixfmt;
|
||||
typedef agg::pixfmt_rgba32_pre pixfmt_pre;
|
||||
typedef agg::renderer_base<pixfmt_pre> renderer_base;
|
||||
|
||||
// define some stuff we'll use soon
|
||||
agg::rasterizer_scanline_aa<> ras;
|
||||
agg::scanline_u8 sl;
|
||||
agg::span_allocator<agg::rgba8> sa;
|
||||
agg::image_filter_lut filter;
|
||||
|
||||
// initialize source AGG buffer
|
||||
agg::rendering_buffer rbuf_src((unsigned char*)source.getBytes(), source.width(), source.height(), source.width() * 4);
|
||||
pixfmt pixf_src(rbuf_src);
|
||||
typedef agg::image_accessor_clone<pixfmt> img_src_type;
|
||||
img_src_type img_src(pixf_src);
|
||||
|
||||
// initialise destination AGG buffer (with transparency)
|
||||
agg::rendering_buffer rbuf_dst((unsigned char*)target.getBytes(), target.width(), target.height(), target.width() * 4);
|
||||
pixfmt_pre pixf_dst(rbuf_dst);
|
||||
renderer_base rb_dst(pixf_dst);
|
||||
rb_dst.clear(agg::rgba(0, 0, 0, 0));
|
||||
|
||||
// create a scaling matrix
|
||||
agg::trans_affine img_mtx;
|
||||
img_mtx /= agg::trans_affine_scaling(image_ratio * ratio, image_ratio * ratio);
|
||||
|
||||
// create a linear interpolator for our scaling matrix
|
||||
typedef agg::span_interpolator_linear<> interpolator_type;
|
||||
interpolator_type interpolator(img_mtx);
|
||||
|
||||
// draw an anticlockwise polygon to render our image into
|
||||
double scaled_width = source.width() * image_ratio;
|
||||
double scaled_height = source.height() * image_ratio;
|
||||
ras.reset();
|
||||
ras.move_to_d(x_off_f, y_off_f);
|
||||
ras.line_to_d(x_off_f + scaled_width, y_off_f);
|
||||
ras.line_to_d(x_off_f + scaled_width, y_off_f + scaled_height);
|
||||
ras.line_to_d(x_off_f, y_off_f + scaled_height);
|
||||
|
||||
switch(scaling_method)
|
||||
{
|
||||
case SCALING_NEAR:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_nn<img_src_type, interpolator_type> span_gen_type;
|
||||
span_gen_type sg(img_src, interpolator);
|
||||
agg::render_scanlines_aa(ras, sl, rb_dst, sa, sg);
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
typedef mapnik::span_image_resample_rgba_affine<img_src_type> span_gen_type;
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
agg::render_scanlines_aa(ras, sl, rb_dst, sa, sg);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
template void scale_image_bilinear8<image_data_32> (image_data_32& target,const image_data_32& source, double x_off_f, double y_off_f);
|
||||
|
||||
|
||||
}
|
|
@ -35,7 +35,6 @@ extern "C"
|
|||
#include <mapnik/palette.hpp>
|
||||
#include <mapnik/map.hpp>
|
||||
#include <mapnik/util/conversions.hpp>
|
||||
#include <mapnik/span_image_filter.hpp>
|
||||
// jpeg
|
||||
#if defined(HAVE_JPEG)
|
||||
#include <mapnik/jpeg_io.hpp>
|
||||
|
@ -56,20 +55,6 @@ extern "C"
|
|||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
// agg
|
||||
#include "agg_image_accessors.h"
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
#include "agg_scanline_u.h"
|
||||
//#include "agg_scanline_p.h"
|
||||
#include "agg_span_allocator.h"
|
||||
#include "agg_span_image_filter_rgba.h"
|
||||
#include "agg_span_interpolator_linear.h"
|
||||
#include "agg_trans_affine.h"
|
||||
#include "agg_image_filters.h"
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
|
@ -477,306 +462,6 @@ template std::string save_to_string<image_view<image_data_32> > (image_view<imag
|
|||
std::string const&,
|
||||
rgba_palette const& palette);
|
||||
|
||||
|
||||
|
||||
// Image scaling functions
|
||||
|
||||
scaling_method_e get_scaling_method_by_name (std::string name)
|
||||
{
|
||||
// TODO - make into proper ENUMS
|
||||
if (name == "fast" || name == "near")
|
||||
return SCALING_NEAR;
|
||||
else if (name == "bilinear")
|
||||
return SCALING_BILINEAR;
|
||||
else if (name == "cubic" || name == "bicubic")
|
||||
return SCALING_BICUBIC;
|
||||
else if (name == "spline16")
|
||||
return SCALING_SPLINE16;
|
||||
else if (name == "spline36")
|
||||
return SCALING_SPLINE36;
|
||||
else if (name == "hanning")
|
||||
return SCALING_HANNING;
|
||||
else if (name == "hamming")
|
||||
return SCALING_HAMMING;
|
||||
else if (name == "hermite")
|
||||
return SCALING_HERMITE;
|
||||
else if (name == "kaiser")
|
||||
return SCALING_KAISER;
|
||||
else if (name == "quadric")
|
||||
return SCALING_QUADRIC;
|
||||
else if (name == "catrom")
|
||||
return SCALING_CATROM;
|
||||
else if (name == "gaussian")
|
||||
return SCALING_GAUSSIAN;
|
||||
else if (name == "bessel")
|
||||
return SCALING_BESSEL;
|
||||
else if (name == "mitchell")
|
||||
return SCALING_MITCHELL;
|
||||
else if (name == "sinc")
|
||||
return SCALING_SINC;
|
||||
else if (name == "lanczos")
|
||||
return SCALING_LANCZOS;
|
||||
else if (name == "blackman")
|
||||
return SCALING_BLACKMAN;
|
||||
else
|
||||
return SCALING_NEAR;
|
||||
}
|
||||
|
||||
// this has been replaced by agg impl - see https://trac.mapnik.org/ticket/656
|
||||
|
||||
template <typename Image>
|
||||
void scale_image_bilinear_old (Image& target,const Image& source, double x_off_f, double y_off_f)
|
||||
{
|
||||
|
||||
int source_width=source.width();
|
||||
int source_height=source.height();
|
||||
|
||||
int target_width=target.width();
|
||||
int target_height=target.height();
|
||||
|
||||
if (source_width<1 || source_height<1 ||
|
||||
target_width<1 || target_height<1) return;
|
||||
int x=0,y=0,xs=0,ys=0;
|
||||
int tw2 = target_width/2;
|
||||
int th2 = target_height/2;
|
||||
int offs_x = rint((source_width-target_width-x_off_f*2*source_width)/2);
|
||||
int offs_y = rint((source_height-target_height-y_off_f*2*source_height)/2);
|
||||
unsigned yprt, yprt1, xprt, xprt1;
|
||||
|
||||
//no scaling or subpixel offset
|
||||
if (target_height == source_height && target_width == source_width && offs_x == 0 && offs_y == 0){
|
||||
for (y=0;y<target_height;++y)
|
||||
target.setRow(y,source.getRow(y),target_width);
|
||||
return;
|
||||
}
|
||||
|
||||
for (y=0;y<target_height;++y)
|
||||
{
|
||||
ys = (y*source_height+offs_y)/target_height;
|
||||
int ys1 = ys+1;
|
||||
if (ys1>=source_height)
|
||||
ys1--;
|
||||
if (ys<0)
|
||||
ys=ys1=0;
|
||||
if (source_height/2<target_height)
|
||||
yprt = (y*source_height+offs_y)%target_height;
|
||||
else
|
||||
yprt = th2;
|
||||
yprt1 = target_height-yprt;
|
||||
for (x=0;x<target_width;++x)
|
||||
{
|
||||
xs = (x*source_width+offs_x)/target_width;
|
||||
if (source_width/2<target_width)
|
||||
xprt = (x*source_width+offs_x)%target_width;
|
||||
else
|
||||
xprt = tw2;
|
||||
xprt1 = target_width-xprt;
|
||||
int xs1 = xs+1;
|
||||
if (xs1>=source_width)
|
||||
xs1--;
|
||||
if (xs<0)
|
||||
xs=xs1=0;
|
||||
|
||||
unsigned a = source(xs,ys);
|
||||
unsigned b = source(xs1,ys);
|
||||
unsigned c = source(xs,ys1);
|
||||
unsigned d = source(xs1,ys1);
|
||||
unsigned out=0;
|
||||
unsigned t = 0;
|
||||
|
||||
for(int i=0; i<4; i++){
|
||||
unsigned p,r,s;
|
||||
// X axis
|
||||
p = a&0xff;
|
||||
r = b&0xff;
|
||||
if (p!=r)
|
||||
r = (r*xprt+p*xprt1+tw2)/target_width;
|
||||
p = c&0xff;
|
||||
s = d&0xff;
|
||||
if (p!=s)
|
||||
s = (s*xprt+p*xprt1+tw2)/target_width;
|
||||
// Y axis
|
||||
if (r!=s)
|
||||
r = (s*yprt+r*yprt1+th2)/target_height;
|
||||
// channel up
|
||||
out |= r << t;
|
||||
t += 8;
|
||||
a >>= 8;
|
||||
b >>= 8;
|
||||
c >>= 8;
|
||||
d >>= 8;
|
||||
}
|
||||
target(x,y)=out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename Image>
|
||||
void scale_image_bilinear8 (Image& target,const Image& source, double x_off_f, double y_off_f)
|
||||
{
|
||||
|
||||
int source_width=source.width();
|
||||
int source_height=source.height();
|
||||
|
||||
int target_width=target.width();
|
||||
int target_height=target.height();
|
||||
|
||||
if (source_width<1 || source_height<1 ||
|
||||
target_width<1 || target_height<1) return;
|
||||
int x=0,y=0,xs=0,ys=0;
|
||||
int tw2 = target_width/2;
|
||||
int th2 = target_height/2;
|
||||
int offs_x = rint((source_width-target_width-x_off_f*2*source_width)/2);
|
||||
int offs_y = rint((source_height-target_height-y_off_f*2*source_height)/2);
|
||||
unsigned yprt, yprt1, xprt, xprt1;
|
||||
|
||||
//no scaling or subpixel offset
|
||||
if (target_height == source_height && target_width == source_width && offs_x == 0 && offs_y == 0){
|
||||
for (y=0;y<target_height;++y)
|
||||
target.setRow(y,source.getRow(y),target_width);
|
||||
return;
|
||||
}
|
||||
|
||||
for (y=0;y<target_height;++y)
|
||||
{
|
||||
ys = (y*source_height+offs_y)/target_height;
|
||||
int ys1 = ys+1;
|
||||
if (ys1>=source_height)
|
||||
ys1--;
|
||||
if (ys<0)
|
||||
ys=ys1=0;
|
||||
if (source_height/2<target_height)
|
||||
yprt = (y*source_height+offs_y)%target_height;
|
||||
else
|
||||
yprt = th2;
|
||||
yprt1 = target_height-yprt;
|
||||
for (x=0;x<target_width;++x)
|
||||
{
|
||||
xs = (x*source_width+offs_x)/target_width;
|
||||
if (source_width/2<target_width)
|
||||
xprt = (x*source_width+offs_x)%target_width;
|
||||
else
|
||||
xprt = tw2;
|
||||
xprt1 = target_width-xprt;
|
||||
int xs1 = xs+1;
|
||||
if (xs1>=source_width)
|
||||
xs1--;
|
||||
if (xs<0)
|
||||
xs=xs1=0;
|
||||
|
||||
unsigned a = source(xs,ys);
|
||||
unsigned b = source(xs1,ys);
|
||||
unsigned c = source(xs,ys1);
|
||||
unsigned d = source(xs1,ys1);
|
||||
unsigned p,r,s;
|
||||
// X axis
|
||||
p = a&0xff;
|
||||
r = b&0xff;
|
||||
if (p!=r)
|
||||
r = (r*xprt+p*xprt1+tw2)/target_width;
|
||||
p = c&0xff;
|
||||
s = d&0xff;
|
||||
if (p!=s)
|
||||
s = (s*xprt+p*xprt1+tw2)/target_width;
|
||||
// Y axis
|
||||
if (r!=s)
|
||||
r = (s*yprt+r*yprt1+th2)/target_height;
|
||||
target(x,y)=(0xff<<24) | (r<<16) | (r<<8) | r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Image>
|
||||
void scale_image_agg (Image& target,const Image& source, scaling_method_e scaling_method, double scale_factor, double x_off_f, double y_off_f, double filter_radius, double ratio)
|
||||
{
|
||||
typedef agg::pixfmt_rgba32 pixfmt;
|
||||
typedef agg::pixfmt_rgba32_pre pixfmt_pre;
|
||||
typedef agg::renderer_base<pixfmt_pre> renderer_base;
|
||||
|
||||
// define some stuff we'll use soon
|
||||
agg::rasterizer_scanline_aa<> ras;
|
||||
agg::scanline_u8 sl;
|
||||
agg::span_allocator<agg::rgba8> sa;
|
||||
agg::image_filter_lut filter;
|
||||
|
||||
// initialize source AGG buffer
|
||||
agg::rendering_buffer rbuf_src((unsigned char*)source.getBytes(), source.width(), source.height(), source.width() * 4);
|
||||
pixfmt pixf_src(rbuf_src);
|
||||
typedef agg::image_accessor_clone<pixfmt> img_src_type;
|
||||
img_src_type img_src(pixf_src);
|
||||
|
||||
// initialise destination AGG buffer (with transparency)
|
||||
agg::rendering_buffer rbuf_dst((unsigned char*)target.getBytes(), target.width(), target.height(), target.width() * 4);
|
||||
pixfmt_pre pixf_dst(rbuf_dst);
|
||||
renderer_base rb_dst(pixf_dst);
|
||||
rb_dst.clear(agg::rgba(0, 0, 0, 0));
|
||||
|
||||
// create a scaling matrix
|
||||
agg::trans_affine img_mtx;
|
||||
img_mtx /= agg::trans_affine_scaling(scale_factor * ratio, scale_factor * ratio);
|
||||
|
||||
// create a linear interpolator for our scaling matrix
|
||||
typedef agg::span_interpolator_linear<> interpolator_type;
|
||||
interpolator_type interpolator(img_mtx);
|
||||
|
||||
// draw an anticlockwise polygon to render our image into
|
||||
double scaled_width = source.width() * scale_factor;
|
||||
double scaled_height = source.height() * scale_factor;
|
||||
ras.reset();
|
||||
ras.move_to_d(x_off_f, y_off_f);
|
||||
ras.line_to_d(x_off_f + scaled_width, y_off_f);
|
||||
ras.line_to_d(x_off_f + scaled_width, y_off_f + scaled_height);
|
||||
ras.line_to_d(x_off_f, y_off_f + scaled_height);
|
||||
|
||||
switch(scaling_method)
|
||||
{
|
||||
case SCALING_NEAR:
|
||||
{
|
||||
typedef agg::span_image_filter_rgba_nn<img_src_type, interpolator_type> span_gen_type;
|
||||
span_gen_type sg(img_src, interpolator);
|
||||
agg::render_scanlines_aa(ras, sl, rb_dst, sa, sg);
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
typedef mapnik::span_image_resample_rgba_affine<img_src_type> span_gen_type;
|
||||
span_gen_type sg(img_src, interpolator, filter);
|
||||
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);
|
||||
|
@ -810,10 +495,4 @@ std::string save_to_string(image_32 const& image,
|
|||
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);
|
||||
|
||||
template void scale_image_bilinear8<image_data_32> (image_data_32& target,const image_data_32& source, double x_off_f, double y_off_f);
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <mapnik/xml_tree.hpp>
|
||||
#include <mapnik/version.hpp>
|
||||
#include <mapnik/image_compositing.hpp>
|
||||
#include <mapnik/image_scaling.hpp>
|
||||
#include <mapnik/color.hpp>
|
||||
#include <mapnik/color_factory.hpp>
|
||||
#include <mapnik/symbolizer.hpp>
|
||||
|
@ -1468,7 +1469,27 @@ void map_parser::parse_raster_symbolizer(rule & rule, xml_node const & sym)
|
|||
|
||||
// scaling
|
||||
optional<std::string> scaling = sym.get_opt_attr<std::string>("scaling");
|
||||
if (scaling) raster_sym.set_scaling(*scaling);
|
||||
if (scaling)
|
||||
{
|
||||
std::string scaling_method = *scaling;
|
||||
if (scaling_method == "fast")
|
||||
{
|
||||
MAPNIK_LOG_ERROR(raster_symbolizer) << "'scaling' value of 'fast' is deprecated and will be removed in Mapnik 3.x, use 'near' with Mapnik >= 2.1.x";
|
||||
raster_sym.set_scaling_method(SCALING_NEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::optional<scaling_method_e> method = scaling_method_from_string(scaling_method);
|
||||
if (method)
|
||||
{
|
||||
raster_sym.set_scaling_method(*method);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw config_error("failed to parse 'scaling': '" + *scaling + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// opacity
|
||||
optional<double> opacity = sym.get_opt_attr<double>("opacity");
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <mapnik/text_placements/list.hpp>
|
||||
#include <mapnik/text_placements/dummy.hpp>
|
||||
#include <mapnik/image_compositing.hpp>
|
||||
#include <mapnik/image_scaling.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
@ -158,9 +159,9 @@ public:
|
|||
ptree::value_type("RasterSymbolizer", ptree()))->second;
|
||||
raster_symbolizer dfl;
|
||||
|
||||
if ( sym.get_scaling() != dfl.get_scaling() || explicit_defaults_ )
|
||||
if ( sym.get_scaling_method() != dfl.get_scaling_method() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( sym_node, "scaling", sym.get_scaling() );
|
||||
set_attr( sym_node, "scaling", *scaling_method_to_string(sym.get_scaling_method()) );
|
||||
}
|
||||
|
||||
if ( sym.get_opacity() != dfl.get_opacity() || explicit_defaults_ )
|
||||
|
|
259
src/warp.cpp
259
src/warp.cpp
|
@ -46,162 +46,149 @@
|
|||
|
||||
namespace mapnik {
|
||||
|
||||
void reproject_raster(raster &target, raster const& source,
|
||||
void reproject_and_scale_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)
|
||||
scaling_method_e scaling_method)
|
||||
{
|
||||
if (prj_trans.equal()) {
|
||||
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);
|
||||
|
||||
if (scaling_method_name == "bilinear8"){
|
||||
scale_image_bilinear8<image_data_32>(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<image_data_32>(target.data_,source.data_, (scaling_method_e)scaling_method, scale_factor, offset_x, offset_y, filter_radius);
|
||||
ImageData<double> xs(mesh_nx, mesh_ny);
|
||||
ImageData<double> ys(mesh_nx, mesh_ny);
|
||||
|
||||
// Precalculate reprojected mesh
|
||||
for(j=0; j<mesh_ny; j++) {
|
||||
for (i=0; i<mesh_nx; i++) {
|
||||
xs(i,j) = i*mesh_size;
|
||||
ys(i,j) = j*mesh_size;
|
||||
ts.backward(&xs(i,j), &ys(i,j));
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
prj_trans.backward(xs.getData(), ys.getData(), NULL, mesh_nx*mesh_ny);
|
||||
|
||||
ImageData<double> xs(mesh_nx, mesh_ny);
|
||||
ImageData<double> ys(mesh_nx, mesh_ny);
|
||||
// Initialize AGG objects
|
||||
typedef agg::pixfmt_rgba32 pixfmt;
|
||||
typedef pixfmt::color_type color_type;
|
||||
typedef agg::renderer_base<pixfmt> renderer_base;
|
||||
typedef agg::pixfmt_rgba32_pre pixfmt_pre;
|
||||
typedef agg::renderer_base<pixfmt_pre> renderer_base_pre;
|
||||
|
||||
// Precalculate reprojected mesh
|
||||
for(j=0; j<mesh_ny; j++) {
|
||||
for (i=0; i<mesh_nx; i++) {
|
||||
xs(i,j) = i*mesh_size;
|
||||
ys(i,j) = j*mesh_size;
|
||||
ts.backward(&xs(i,j), &ys(i,j));
|
||||
}
|
||||
}
|
||||
prj_trans.backward(xs.getData(), ys.getData(), NULL, mesh_nx*mesh_ny);
|
||||
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);
|
||||
|
||||
// Initialize AGG objects
|
||||
typedef agg::pixfmt_rgba32 pixfmt;
|
||||
typedef pixfmt::color_type color_type;
|
||||
typedef agg::renderer_base<pixfmt> renderer_base;
|
||||
typedef agg::pixfmt_rgba32_pre pixfmt_pre;
|
||||
typedef agg::renderer_base<pixfmt_pre> renderer_base_pre;
|
||||
pixfmt pixf_tile(buf_tile);
|
||||
|
||||
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);
|
||||
typedef agg::image_accessor_clone<pixfmt> img_accessor_type;
|
||||
img_accessor_type ia(pixf_tile);
|
||||
|
||||
pixfmt pixf_tile(buf_tile);
|
||||
agg::span_allocator<color_type> sa;
|
||||
|
||||
typedef agg::image_accessor_clone<pixfmt> img_accessor_type;
|
||||
img_accessor_type ia(pixf_tile);
|
||||
// Initialize filter
|
||||
agg::image_filter_lut filter;
|
||||
switch(scaling_method)
|
||||
{
|
||||
case SCALING_NEAR: break;
|
||||
case SCALING_BILINEAR8: // TODO - impl this or remove?
|
||||
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;
|
||||
}
|
||||
|
||||
agg::span_allocator<color_type> sa;
|
||||
// Project mesh cells into target interpolating raster inside each one
|
||||
for(j=0; j<mesh_ny-1; j++) {
|
||||
for (i=0; i<mesh_nx-1; i++) {
|
||||
double polygon[8] = {xs(i,j), ys(i,j),
|
||||
xs(i+1,j), ys(i+1,j),
|
||||
xs(i+1,j+1), ys(i+1,j+1),
|
||||
xs(i,j+1), ys(i,j+1)};
|
||||
tt.forward(polygon+0, polygon+1);
|
||||
tt.forward(polygon+2, polygon+3);
|
||||
tt.forward(polygon+4, polygon+5);
|
||||
tt.forward(polygon+6, polygon+7);
|
||||
|
||||
// Initialize filter
|
||||
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;
|
||||
}
|
||||
rasterizer.reset();
|
||||
rasterizer.move_to_d(polygon[0]-1, polygon[1]-1);
|
||||
rasterizer.line_to_d(polygon[2]+1, polygon[3]-1);
|
||||
rasterizer.line_to_d(polygon[4]+1, polygon[5]+1);
|
||||
rasterizer.line_to_d(polygon[6]-1, polygon[7]+1);
|
||||
|
||||
// Project mesh cells into target interpolating raster inside each one
|
||||
for(j=0; j<mesh_ny-1; j++) {
|
||||
for (i=0; i<mesh_nx-1; i++) {
|
||||
double polygon[8] = {xs(i,j), ys(i,j),
|
||||
xs(i+1,j), ys(i+1,j),
|
||||
xs(i+1,j+1), ys(i+1,j+1),
|
||||
xs(i,j+1), ys(i,j+1)};
|
||||
tt.forward(polygon+0, polygon+1);
|
||||
tt.forward(polygon+2, polygon+3);
|
||||
tt.forward(polygon+4, polygon+5);
|
||||
tt.forward(polygon+6, polygon+7);
|
||||
unsigned x0 = i * mesh_size;
|
||||
unsigned y0 = j * mesh_size;
|
||||
unsigned x1 = (i+1) * mesh_size;
|
||||
unsigned y1 = (j+1) * mesh_size;
|
||||
|
||||
rasterizer.reset();
|
||||
rasterizer.move_to_d(polygon[0]-1, polygon[1]-1);
|
||||
rasterizer.line_to_d(polygon[2]+1, polygon[3]-1);
|
||||
rasterizer.line_to_d(polygon[4]+1, polygon[5]+1);
|
||||
rasterizer.line_to_d(polygon[6]-1, polygon[7]+1);
|
||||
agg::trans_affine tr(polygon, x0, y0, x1, y1);
|
||||
if (tr.is_valid())
|
||||
{
|
||||
typedef agg::span_interpolator_linear<agg::trans_affine>
|
||||
interpolator_type;
|
||||
interpolator_type interpolator(tr);
|
||||
|
||||
unsigned x0 = i * mesh_size;
|
||||
unsigned y0 = j * mesh_size;
|
||||
unsigned x1 = (i+1) * mesh_size;
|
||||
unsigned y1 = (j+1) * mesh_size;
|
||||
|
||||
agg::trans_affine tr(polygon, x0, y0, x1, y1);
|
||||
if (tr.is_valid())
|
||||
{
|
||||
typedef agg::span_interpolator_linear<agg::trans_affine>
|
||||
interpolator_type;
|
||||
interpolator_type interpolator(tr);
|
||||
|
||||
if (scaling_method == SCALING_NEAR) {
|
||||
typedef agg::span_image_filter_rgba_nn
|
||||
<img_accessor_type, interpolator_type>
|
||||
span_gen_type;
|
||||
span_gen_type sg(ia, interpolator);
|
||||
agg::render_scanlines_aa(rasterizer, scanline, rb_pre,
|
||||
sa, sg);
|
||||
} else {
|
||||
typedef mapnik::span_image_resample_rgba_affine
|
||||
<img_accessor_type> span_gen_type;
|
||||
span_gen_type sg(ia, interpolator, filter);
|
||||
agg::render_scanlines_aa(rasterizer, scanline, rb_pre,
|
||||
sa, sg);
|
||||
}
|
||||
if (scaling_method == SCALING_NEAR) {
|
||||
typedef agg::span_image_filter_rgba_nn
|
||||
<img_accessor_type, interpolator_type>
|
||||
span_gen_type;
|
||||
span_gen_type sg(ia, interpolator);
|
||||
agg::render_scanlines_aa(rasterizer, scanline, rb_pre,
|
||||
sa, sg);
|
||||
} else {
|
||||
typedef mapnik::span_image_resample_rgba_affine
|
||||
<img_accessor_type> span_gen_type;
|
||||
span_gen_type sg(ia, interpolator, filter);
|
||||
agg::render_scanlines_aa(rasterizer, scanline, rb_pre,
|
||||
sa, sg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue