Merge branch 'fix-gray-scaling-2' of https://github.com/mapycz/mapnik into mapycz-fix-gray-scaling-2
This commit is contained in:
commit
6d599dff0a
9 changed files with 243 additions and 45 deletions
|
@ -23,6 +23,7 @@ Released:
|
||||||
- `mapnik.Image` - fixed copy semantics implementation for internal buffer
|
- `mapnik.Image` - fixed copy semantics implementation for internal buffer
|
||||||
- JSON parsing: unified error_handler across all grammars
|
- JSON parsing: unified error_handler across all grammars
|
||||||
- Improved unit test coverage
|
- Improved unit test coverage
|
||||||
|
- Raster scaling: fixed nodata handling, acurracy when working with small floats and clipping floats by \[0; 255\] (https://github.com/mapnik/mapnik/pull/3147)
|
||||||
|
|
||||||
## 3.0.8
|
## 3.0.8
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,8 @@ MAPNIK_DECL void scale_image_agg(T & target, T const& source,
|
||||||
double image_ratio_y,
|
double image_ratio_y,
|
||||||
double x_off_f,
|
double x_off_f,
|
||||||
double y_off_f,
|
double y_off_f,
|
||||||
double filter_factor);
|
double filter_factor,
|
||||||
|
boost::optional<double> const & nodata_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MAPNIK_IMAGE_SCALING_HPP
|
#endif // MAPNIK_IMAGE_SCALING_HPP
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
#ifndef MAPNIK_IMAGE_SCALING_TRAITS_HPP
|
#ifndef MAPNIK_IMAGE_SCALING_TRAITS_HPP
|
||||||
#define MAPNIK_IMAGE_SCALING_TRAITS_HPP
|
#define MAPNIK_IMAGE_SCALING_TRAITS_HPP
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/span_image_filter.h>
|
||||||
|
|
||||||
// agg
|
// agg
|
||||||
#include "agg_image_accessors.h"
|
#include "agg_image_accessors.h"
|
||||||
#include "agg_pixfmt_rgba.h"
|
#include "agg_pixfmt_rgba.h"
|
||||||
|
@ -45,7 +48,7 @@ struct agg_scaling_traits<image_rgba8>
|
||||||
using interpolator_type = agg::span_interpolator_linear<>;
|
using interpolator_type = agg::span_interpolator_linear<>;
|
||||||
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
|
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
|
||||||
using span_image_filter = agg::span_image_filter_rgba_nn<img_src_type,interpolator_type>;
|
using span_image_filter = agg::span_image_filter_rgba_nn<img_src_type,interpolator_type>;
|
||||||
using span_image_resample_affine = agg::span_image_resample_rgba_affine<img_src_type>;
|
using span_image_resample_affine = span_image_resample_rgba_affine<img_src_type>;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -57,7 +60,7 @@ struct agg_scaling_traits<image_gray8>
|
||||||
using interpolator_type = agg::span_interpolator_linear<>;
|
using interpolator_type = agg::span_interpolator_linear<>;
|
||||||
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
|
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_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>;
|
using span_image_resample_affine = span_image_resample_gray_affine<img_src_type>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -68,7 +71,7 @@ struct agg_scaling_traits<image_gray8s>
|
||||||
using interpolator_type = agg::span_interpolator_linear<>;
|
using interpolator_type = agg::span_interpolator_linear<>;
|
||||||
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
|
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_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>;
|
using span_image_resample_affine = span_image_resample_gray_affine<img_src_type>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -79,7 +82,7 @@ struct agg_scaling_traits<image_gray16>
|
||||||
using interpolator_type = agg::span_interpolator_linear<>;
|
using interpolator_type = agg::span_interpolator_linear<>;
|
||||||
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
|
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_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>;
|
using span_image_resample_affine = span_image_resample_gray_affine<img_src_type>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -90,7 +93,7 @@ struct agg_scaling_traits<image_gray16s>
|
||||||
using interpolator_type = agg::span_interpolator_linear<>;
|
using interpolator_type = agg::span_interpolator_linear<>;
|
||||||
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
|
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_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>;
|
using span_image_resample_affine = span_image_resample_gray_affine<img_src_type>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -101,7 +104,7 @@ struct agg_scaling_traits<image_gray32>
|
||||||
using interpolator_type = agg::span_interpolator_linear<>;
|
using interpolator_type = agg::span_interpolator_linear<>;
|
||||||
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
|
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_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>;
|
using span_image_resample_affine = span_image_resample_gray_affine<img_src_type>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -112,7 +115,7 @@ struct agg_scaling_traits<image_gray32s>
|
||||||
using interpolator_type = agg::span_interpolator_linear<>;
|
using interpolator_type = agg::span_interpolator_linear<>;
|
||||||
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
|
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_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>;
|
using span_image_resample_affine = span_image_resample_gray_affine<img_src_type>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -123,7 +126,7 @@ struct agg_scaling_traits<image_gray32f>
|
||||||
using interpolator_type = agg::span_interpolator_linear<>;
|
using interpolator_type = agg::span_interpolator_linear<>;
|
||||||
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
|
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_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>;
|
using span_image_resample_affine = span_image_resample_gray_affine<img_src_type>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -134,7 +137,7 @@ struct agg_scaling_traits<image_gray64>
|
||||||
using interpolator_type = agg::span_interpolator_linear<>;
|
using interpolator_type = agg::span_interpolator_linear<>;
|
||||||
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
|
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_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>;
|
using span_image_resample_affine = span_image_resample_gray_affine<img_src_type>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -145,7 +148,7 @@ struct agg_scaling_traits<image_gray64s>
|
||||||
using interpolator_type = agg::span_interpolator_linear<>;
|
using interpolator_type = agg::span_interpolator_linear<>;
|
||||||
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
|
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_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>;
|
using span_image_resample_affine = span_image_resample_gray_affine<img_src_type>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -156,7 +159,7 @@ struct agg_scaling_traits<image_gray64f>
|
||||||
using interpolator_type = agg::span_interpolator_linear<>;
|
using interpolator_type = agg::span_interpolator_linear<>;
|
||||||
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
|
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_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>;
|
using span_image_resample_affine = span_image_resample_gray_affine<img_src_type>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Filter>
|
template <typename Filter>
|
||||||
|
|
|
@ -77,7 +77,7 @@ struct image_dispatcher
|
||||||
if (need_scaling_)
|
if (need_scaling_)
|
||||||
{
|
{
|
||||||
image_rgba8 data_out(width_, height_, true, true);
|
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_);
|
scale_image_agg(data_out, data_in, method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_, nodata_);
|
||||||
composite_(data_out, comp_op_, opacity_, start_x_, start_y_);
|
composite_(data_out, comp_op_, opacity_, start_x_, start_y_);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -95,7 +95,7 @@ struct image_dispatcher
|
||||||
if (need_scaling_)
|
if (need_scaling_)
|
||||||
{
|
{
|
||||||
image_type data_out(width_, height_);
|
image_type data_out(width_, height_);
|
||||||
scale_image_agg(data_out, data_in, method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_);
|
scale_image_agg(data_out, data_in, method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_, nodata_);
|
||||||
if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_);
|
if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -157,7 +157,7 @@ struct image_warp_dispatcher
|
||||||
void operator() (image_rgba8 const& data_in) const
|
void operator() (image_rgba8 const& data_in) const
|
||||||
{
|
{
|
||||||
image_rgba8 data_out(width_, height_, true, true);
|
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_);
|
warp_image(data_out, data_in, prj_trans_, target_ext_, source_ext_, offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_, nodata_);
|
||||||
composite_(data_out, comp_op_, opacity_, start_x_, start_y_);
|
composite_(data_out, comp_op_, opacity_, start_x_, start_y_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ struct image_warp_dispatcher
|
||||||
using image_type = T;
|
using image_type = T;
|
||||||
image_type data_out(width_, height_);
|
image_type data_out(width_, height_);
|
||||||
if (nodata_) data_out.set(*nodata_);
|
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_);
|
warp_image(data_out, data_in, prj_trans_, target_ext_, source_ext_, offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_, nodata_);
|
||||||
image_rgba8 dst(width_, height_);
|
image_rgba8 dst(width_, height_);
|
||||||
raster_colorizer_ptr colorizer = get<raster_colorizer_ptr>(sym_, keys::colorizer);
|
raster_colorizer_ptr colorizer = get<raster_colorizer_ptr>(sym_, keys::colorizer);
|
||||||
if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_);
|
if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_);
|
||||||
|
|
178
include/mapnik/span_image_filter.h
Normal file
178
include/mapnik/span_image_filter.h
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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_SPAN_IMAGE_FILTER_INCLUDED
|
||||||
|
#define MAPNIK_SPAN_IMAGE_FILTER_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_span_image_filter_gray.h"
|
||||||
|
#include "agg_span_image_filter_rgba.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace mapnik
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class Source>
|
||||||
|
class span_image_resample_gray_affine : public agg::span_image_resample_affine<Source>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using source_type = Source;
|
||||||
|
using color_type = typename source_type::color_type;
|
||||||
|
using base_type = agg::span_image_resample_affine<source_type>;
|
||||||
|
using interpolator_type = typename base_type::interpolator_type;
|
||||||
|
using value_type = typename color_type::value_type;
|
||||||
|
using long_type = typename color_type::long_type;
|
||||||
|
|
||||||
|
enum base_scale_e
|
||||||
|
{
|
||||||
|
downscale_shift = agg::image_filter_shift,
|
||||||
|
base_mask = color_type::base_mask
|
||||||
|
};
|
||||||
|
|
||||||
|
span_image_resample_gray_affine(source_type & src,
|
||||||
|
interpolator_type & inter,
|
||||||
|
agg::image_filter_lut const & filter,
|
||||||
|
boost::optional<value_type> const & nodata_value) :
|
||||||
|
base_type(src, inter, filter),
|
||||||
|
nodata_value_(nodata_value)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void generate(color_type* span, int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||||
|
y + base_type::filter_dy_dbl(), len);
|
||||||
|
|
||||||
|
long_type fg;
|
||||||
|
|
||||||
|
int diameter = base_type::filter().diameter();
|
||||||
|
int filter_scale = diameter << agg::image_subpixel_shift;
|
||||||
|
int radius_x = (diameter * base_type::m_rx) >> 1;
|
||||||
|
int radius_y = (diameter * base_type::m_ry) >> 1;
|
||||||
|
int len_x_lr =
|
||||||
|
(diameter * base_type::m_rx + agg::image_subpixel_mask) >>
|
||||||
|
agg::image_subpixel_shift;
|
||||||
|
|
||||||
|
const agg::int16* weight_array = base_type::filter().weight_array();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::interpolator().coordinates(&x, &y);
|
||||||
|
|
||||||
|
int src_x = x >> agg::image_subpixel_shift;
|
||||||
|
int src_y = y >> agg::image_subpixel_shift;
|
||||||
|
const value_type* pix = reinterpret_cast<const value_type*>(base_type::source().span(src_x, src_y, 0));
|
||||||
|
if (nodata_value_ && *nodata_value_ == *pix)
|
||||||
|
{
|
||||||
|
span->v = *nodata_value_;
|
||||||
|
span->a = base_mask;
|
||||||
|
++span;
|
||||||
|
++base_type::interpolator();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
x += base_type::filter_dx_int() - radius_x;
|
||||||
|
y += base_type::filter_dy_int() - radius_y;
|
||||||
|
|
||||||
|
fg = 0;
|
||||||
|
|
||||||
|
int y_lr = y >> agg::image_subpixel_shift;
|
||||||
|
int y_hr = ((agg::image_subpixel_mask - (y & agg::image_subpixel_mask)) *
|
||||||
|
base_type::m_ry_inv) >>
|
||||||
|
agg::image_subpixel_shift;
|
||||||
|
int total_weight = 0;
|
||||||
|
int x_lr = x >> agg::image_subpixel_shift;
|
||||||
|
int x_hr = ((agg::image_subpixel_mask - (x & agg::image_subpixel_mask)) *
|
||||||
|
base_type::m_rx_inv) >>
|
||||||
|
agg::image_subpixel_shift;
|
||||||
|
|
||||||
|
int x_hr2 = x_hr;
|
||||||
|
const value_type* fg_ptr = reinterpret_cast<const value_type*>(base_type::source().span(x_lr, y_lr, len_x_lr));
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
int weight_y = weight_array[y_hr];
|
||||||
|
x_hr = x_hr2;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
int weight = (weight_y * weight_array[x_hr] +
|
||||||
|
agg::image_filter_scale) >>
|
||||||
|
downscale_shift;
|
||||||
|
if (!nodata_value_ || *nodata_value_ != *fg_ptr)
|
||||||
|
{
|
||||||
|
fg += *fg_ptr * weight;
|
||||||
|
total_weight += weight;
|
||||||
|
}
|
||||||
|
x_hr += base_type::m_rx_inv;
|
||||||
|
if (x_hr >= filter_scale) break;
|
||||||
|
fg_ptr = reinterpret_cast<const value_type*>(base_type::source().next_x());
|
||||||
|
}
|
||||||
|
y_hr += base_type::m_ry_inv;
|
||||||
|
if (y_hr >= filter_scale) break;
|
||||||
|
fg_ptr = reinterpret_cast<const value_type*>(base_type::source().next_y());
|
||||||
|
}
|
||||||
|
|
||||||
|
fg /= total_weight;
|
||||||
|
if (fg < std::numeric_limits<value_type>::min())
|
||||||
|
{
|
||||||
|
span->v = std::numeric_limits<value_type>::min();
|
||||||
|
}
|
||||||
|
else if (fg > std::numeric_limits<value_type>::max())
|
||||||
|
{
|
||||||
|
span->v = std::numeric_limits<value_type>::max();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
span->v = static_cast<value_type>(fg);
|
||||||
|
}
|
||||||
|
span->a = base_mask;
|
||||||
|
|
||||||
|
++span;
|
||||||
|
++base_type::interpolator();
|
||||||
|
} while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::optional<value_type> nodata_value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Source>
|
||||||
|
class span_image_resample_rgba_affine : public agg::span_image_resample_rgba_affine<Source>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using source_type = Source;
|
||||||
|
using color_type = typename source_type::color_type;
|
||||||
|
using order_type = typename source_type::order_type;
|
||||||
|
using base_type = agg::span_image_resample_rgba_affine<source_type>;
|
||||||
|
using interpolator_type = typename base_type::interpolator_type;
|
||||||
|
using value_type = typename color_type::value_type;
|
||||||
|
using long_type = typename color_type::long_type;
|
||||||
|
|
||||||
|
span_image_resample_rgba_affine(source_type & src,
|
||||||
|
interpolator_type & inter,
|
||||||
|
agg::image_filter_lut const & filter,
|
||||||
|
boost::optional<value_type> const & nodata_value) :
|
||||||
|
agg::span_image_resample_rgba_affine<Source>(src, inter, filter)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -44,7 +44,8 @@ MAPNIK_DECL void reproject_and_scale_raster(raster & target,
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MAPNIK_DECL void warp_image (T & target, T const& source, proj_transform const& prj_trans,
|
MAPNIK_DECL void warp_image (T & target, T const& source, proj_transform const& prj_trans,
|
||||||
box2d<double> const& target_ext, box2d<double> const& source_ext,
|
box2d<double> const& target_ext, box2d<double> const& source_ext,
|
||||||
double offset_x, double offset_y, unsigned mesh_size, scaling_method_e scaling_method, double filter_factor);
|
double offset_x, double offset_y, unsigned mesh_size, scaling_method_e scaling_method, double filter_factor,
|
||||||
|
boost::optional<double> const & nodata_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MAPNIK_WARP_HPP
|
#endif // MAPNIK_WARP_HPP
|
||||||
|
|
|
@ -197,12 +197,13 @@ struct grid_render_marker_visitor
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
image_rgba8 target(data.width(), data.height());
|
image_rgba8 target(data.width(), data.height());
|
||||||
|
boost::optional<double> nodata;
|
||||||
mapnik::scale_image_agg(target,
|
mapnik::scale_image_agg(target,
|
||||||
data,
|
data,
|
||||||
SCALING_NEAR,
|
SCALING_NEAR,
|
||||||
1,
|
1,
|
||||||
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?
|
0.0, 0.0, 1.0, nodata); // 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,
|
pixmap_.set_rectangle(feature_.id(), target,
|
||||||
boost::math::iround(pos_.x - cx),
|
boost::math::iround(pos_.x - cx),
|
||||||
boost::math::iround(pos_.y - cy));
|
boost::math::iround(pos_.y - cy));
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
#include <mapnik/image.hpp>
|
#include <mapnik/image.hpp>
|
||||||
#include <mapnik/image_scaling.hpp>
|
#include <mapnik/image_scaling.hpp>
|
||||||
#include <mapnik/image_scaling_traits.hpp>
|
#include <mapnik/image_scaling_traits.hpp>
|
||||||
// does not handle alpha correctly
|
|
||||||
//#include <mapnik/span_image_filter.hpp>
|
|
||||||
|
|
||||||
// boost
|
// boost
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
|
@ -100,7 +98,7 @@ boost::optional<std::string> scaling_method_to_string(scaling_method_e scaling_m
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void scale_image_agg(T & target, T const& source, scaling_method_e scaling_method,
|
void scale_image_agg(T & target, T const& source, scaling_method_e scaling_method,
|
||||||
double image_ratio_x, double image_ratio_y, double x_off_f, double y_off_f,
|
double image_ratio_x, double image_ratio_y, double x_off_f, double y_off_f,
|
||||||
double filter_factor)
|
double filter_factor, boost::optional<double> const & nodata_value)
|
||||||
{
|
{
|
||||||
// "the image filters should work namely in the premultiplied color space"
|
// "the image filters should work namely in the premultiplied color space"
|
||||||
// http://old.nabble.com/Re:--AGG--Basic-image-transformations-p1110665.html
|
// http://old.nabble.com/Re:--AGG--Basic-image-transformations-p1110665.html
|
||||||
|
@ -158,42 +156,46 @@ void scale_image_agg(T & target, T const& source, scaling_method_e scaling_metho
|
||||||
using span_gen_type = typename detail::agg_scaling_traits<image_type>::span_image_resample_affine;
|
using span_gen_type = typename detail::agg_scaling_traits<image_type>::span_image_resample_affine;
|
||||||
agg::image_filter_lut filter;
|
agg::image_filter_lut filter;
|
||||||
detail::set_scaling_method(filter, scaling_method, filter_factor);
|
detail::set_scaling_method(filter, scaling_method, filter_factor);
|
||||||
span_gen_type sg(img_src, interpolator, filter);
|
boost::optional<typename span_gen_type::value_type> nodata;
|
||||||
|
if (nodata_value)
|
||||||
|
{
|
||||||
|
nodata = nodata_value;
|
||||||
|
}
|
||||||
|
span_gen_type sg(img_src, interpolator, filter, nodata);
|
||||||
agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg);
|
agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template MAPNIK_DECL void scale_image_agg(image_rgba8 &, image_rgba8 const&, scaling_method_e,
|
template MAPNIK_DECL void scale_image_agg(image_rgba8 &, image_rgba8 const&, scaling_method_e,
|
||||||
double, double , double, double , double);
|
double, double , double, double , double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void scale_image_agg(image_gray8 &, image_gray8 const&, scaling_method_e,
|
template MAPNIK_DECL void scale_image_agg(image_gray8 &, image_gray8 const&, scaling_method_e,
|
||||||
double, double , double, double , double);
|
double, double , double, double , double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void scale_image_agg(image_gray8s &, image_gray8s const&, scaling_method_e,
|
template MAPNIK_DECL void scale_image_agg(image_gray8s &, image_gray8s const&, scaling_method_e,
|
||||||
double, double , double, double , double);
|
double, double , double, double , double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void scale_image_agg(image_gray16 &, image_gray16 const&, scaling_method_e,
|
template MAPNIK_DECL void scale_image_agg(image_gray16 &, image_gray16 const&, scaling_method_e,
|
||||||
double, double , double, double , double);
|
double, double , double, double , double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void scale_image_agg(image_gray16s &, image_gray16s const&, scaling_method_e,
|
template MAPNIK_DECL void scale_image_agg(image_gray16s &, image_gray16s const&, scaling_method_e,
|
||||||
double, double , double, double , double);
|
double, double , double, double , double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void scale_image_agg(image_gray32 &, image_gray32 const&, scaling_method_e,
|
template MAPNIK_DECL void scale_image_agg(image_gray32 &, image_gray32 const&, scaling_method_e,
|
||||||
double, double , double, double , double);
|
double, double , double, double , double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void scale_image_agg(image_gray32s &, image_gray32s const&, scaling_method_e,
|
template MAPNIK_DECL void scale_image_agg(image_gray32s &, image_gray32s const&, scaling_method_e,
|
||||||
double, double , double, double , double);
|
double, double , double, double , double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void scale_image_agg(image_gray32f &, image_gray32f const&, scaling_method_e,
|
template MAPNIK_DECL void scale_image_agg(image_gray32f &, image_gray32f const&, scaling_method_e,
|
||||||
double, double , double, double , double);
|
double, double , double, double , double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void scale_image_agg(image_gray64 &, image_gray64 const&, scaling_method_e,
|
template MAPNIK_DECL void scale_image_agg(image_gray64 &, image_gray64 const&, scaling_method_e,
|
||||||
double, double , double, double , double);
|
double, double , double, double , double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void scale_image_agg(image_gray64s &, image_gray64s const&, scaling_method_e,
|
template MAPNIK_DECL void scale_image_agg(image_gray64s &, image_gray64s const&, scaling_method_e,
|
||||||
double, double , double, double , double);
|
double, double , double, double , double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void scale_image_agg(image_gray64f &, image_gray64f const&, scaling_method_e,
|
template MAPNIK_DECL void scale_image_agg(image_gray64f &, image_gray64f const&, scaling_method_e,
|
||||||
double, double , double, double , double);
|
double, double , double, double , double, boost::optional<double> const &);
|
||||||
}
|
}
|
||||||
|
|
33
src/warp.cpp
33
src/warp.cpp
|
@ -51,7 +51,8 @@ namespace mapnik {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MAPNIK_DECL void warp_image (T & target, T const& source, proj_transform const& prj_trans,
|
MAPNIK_DECL void warp_image (T & target, T const& source, proj_transform const& prj_trans,
|
||||||
box2d<double> const& target_ext, box2d<double> const& source_ext,
|
box2d<double> const& target_ext, box2d<double> const& source_ext,
|
||||||
double offset_x, double offset_y, unsigned mesh_size, scaling_method_e scaling_method, double filter_factor)
|
double offset_x, double offset_y, unsigned mesh_size, scaling_method_e scaling_method, double filter_factor,
|
||||||
|
boost::optional<double> const & nodata_value)
|
||||||
{
|
{
|
||||||
using image_type = T;
|
using image_type = T;
|
||||||
using pixel_type = typename image_type::pixel_type;
|
using pixel_type = typename image_type::pixel_type;
|
||||||
|
@ -147,7 +148,12 @@ MAPNIK_DECL void warp_image (T & target, T const& source, proj_transform const&
|
||||||
using span_gen_type = typename detail::agg_scaling_traits<image_type>::span_image_resample_affine;
|
using span_gen_type = typename detail::agg_scaling_traits<image_type>::span_image_resample_affine;
|
||||||
agg::image_filter_lut filter;
|
agg::image_filter_lut filter;
|
||||||
detail::set_scaling_method(filter, scaling_method, filter_factor);
|
detail::set_scaling_method(filter, scaling_method, filter_factor);
|
||||||
span_gen_type sg(ia, interpolator, filter);
|
boost::optional<typename span_gen_type::value_type> nodata;
|
||||||
|
if (nodata_value)
|
||||||
|
{
|
||||||
|
nodata = nodata_value;
|
||||||
|
}
|
||||||
|
span_gen_type sg(ia, interpolator, filter, nodata);
|
||||||
agg::render_scanlines_bin(rasterizer, scanline, rb, sa, sg);
|
agg::render_scanlines_bin(rasterizer, scanline, rb, sa, sg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,7 +168,8 @@ struct warp_image_visitor
|
||||||
{
|
{
|
||||||
warp_image_visitor (raster & target_raster, proj_transform const& prj_trans, box2d<double> const& source_ext,
|
warp_image_visitor (raster & target_raster, proj_transform const& prj_trans, box2d<double> const& source_ext,
|
||||||
double offset_x, double offset_y, unsigned mesh_size,
|
double offset_x, double offset_y, unsigned mesh_size,
|
||||||
scaling_method_e scaling_method, double filter_factor)
|
scaling_method_e scaling_method, double filter_factor,
|
||||||
|
boost::optional<double> const & nodata_value)
|
||||||
: target_raster_(target_raster),
|
: target_raster_(target_raster),
|
||||||
prj_trans_(prj_trans),
|
prj_trans_(prj_trans),
|
||||||
source_ext_(source_ext),
|
source_ext_(source_ext),
|
||||||
|
@ -170,7 +177,9 @@ struct warp_image_visitor
|
||||||
offset_y_(offset_y),
|
offset_y_(offset_y),
|
||||||
mesh_size_(mesh_size),
|
mesh_size_(mesh_size),
|
||||||
scaling_method_(scaling_method),
|
scaling_method_(scaling_method),
|
||||||
filter_factor_(filter_factor) {}
|
filter_factor_(filter_factor),
|
||||||
|
nodata_value_(nodata_value)
|
||||||
|
{}
|
||||||
|
|
||||||
void operator() (image_null const&) {}
|
void operator() (image_null const&) {}
|
||||||
|
|
||||||
|
@ -183,7 +192,7 @@ struct warp_image_visitor
|
||||||
{
|
{
|
||||||
image_type & target = util::get<image_type>(target_raster_.data_);
|
image_type & target = util::get<image_type>(target_raster_.data_);
|
||||||
warp_image (target, source, prj_trans_, target_raster_.ext_, source_ext_,
|
warp_image (target, source, prj_trans_, target_raster_.ext_, source_ext_,
|
||||||
offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_);
|
offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_, nodata_value_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,6 +204,7 @@ struct warp_image_visitor
|
||||||
unsigned mesh_size_;
|
unsigned mesh_size_;
|
||||||
scaling_method_e scaling_method_;
|
scaling_method_e scaling_method_;
|
||||||
double filter_factor_;
|
double filter_factor_;
|
||||||
|
boost::optional<double> const & nodata_value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -203,24 +213,25 @@ void reproject_and_scale_raster(raster & target, raster const& source,
|
||||||
proj_transform const& prj_trans,
|
proj_transform const& prj_trans,
|
||||||
double offset_x, double offset_y,
|
double offset_x, double offset_y,
|
||||||
unsigned mesh_size,
|
unsigned mesh_size,
|
||||||
scaling_method_e scaling_method)
|
scaling_method_e scaling_method,
|
||||||
|
boost::optional<double> const & nodata_value)
|
||||||
{
|
{
|
||||||
detail::warp_image_visitor warper(target, prj_trans, source.ext_, offset_x, offset_y, mesh_size,
|
detail::warp_image_visitor warper(target, prj_trans, source.ext_, offset_x, offset_y, mesh_size,
|
||||||
scaling_method, source.get_filter_factor());
|
scaling_method, source.get_filter_factor(), nodata_value);
|
||||||
util::apply_visitor(warper, source.data_);
|
util::apply_visitor(warper, source.data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template MAPNIK_DECL void warp_image (image_rgba8&, image_rgba8 const&, proj_transform const&,
|
template MAPNIK_DECL void warp_image (image_rgba8&, image_rgba8 const&, proj_transform const&,
|
||||||
box2d<double> const&, box2d<double> const&, double, double, unsigned, scaling_method_e, double);
|
box2d<double> const&, box2d<double> const&, double, double, unsigned, scaling_method_e, double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void warp_image (image_gray8&, image_gray8 const&, proj_transform const&,
|
template MAPNIK_DECL void warp_image (image_gray8&, image_gray8 const&, proj_transform const&,
|
||||||
box2d<double> const&, box2d<double> const&, double, double, unsigned, scaling_method_e, double);
|
box2d<double> const&, box2d<double> const&, double, double, unsigned, scaling_method_e, double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void warp_image (image_gray16&, image_gray16 const&, proj_transform const&,
|
template MAPNIK_DECL void warp_image (image_gray16&, image_gray16 const&, proj_transform const&,
|
||||||
box2d<double> const&, box2d<double> const&, double, double, unsigned, scaling_method_e, double);
|
box2d<double> const&, box2d<double> const&, double, double, unsigned, scaling_method_e, double, boost::optional<double> const &);
|
||||||
|
|
||||||
template MAPNIK_DECL void warp_image (image_gray32f&, image_gray32f const&, proj_transform const&,
|
template MAPNIK_DECL void warp_image (image_gray32f&, image_gray32f const&, proj_transform const&,
|
||||||
box2d<double> const&, box2d<double> const&, double, double, unsigned, scaling_method_e, double);
|
box2d<double> const&, box2d<double> const&, double, double, unsigned, scaling_method_e, double, boost::optional<double> const &);
|
||||||
|
|
||||||
|
|
||||||
}// namespace mapnik
|
}// namespace mapnik
|
||||||
|
|
Loading…
Reference in a new issue