read single band as int16 then agg_scale and colorize in gray16 color space, output rgb8 (aka image_data_32)

NOTE: proof-of-concept needed re-factoring/duplicate code removal
This commit is contained in:
artemp 2014-12-03 18:16:42 +01:00
parent 27159b8086
commit de7a268333
6 changed files with 148 additions and 34 deletions

View file

@ -191,7 +191,7 @@ private:
using image_data_32 = image_data<std::uint32_t>;
using image_data_8 = image_data<std::uint8_t> ;
using image_data_16 = image_data<std::uint16_t>;
using image_data_16 = image_data<std::int16_t>;
using image_data_float32 = image_data<float>;
}

View file

@ -40,7 +40,9 @@
#include <mapnik/config.hpp>
#include <mapnik/color.hpp>
#include <mapnik/enumeration.hpp>
#include <mapnik/image_data.hpp>
// boost
#include <boost/optional.hpp>
// boost
#include <memory>
@ -201,6 +203,8 @@ public:
//! \param[in, out] raster A raster stored in float32 single channel format, which gets colorized in place.
void colorize(raster & ras, feature_impl const& f) const;
//
void colorize(image_data_32 & out, image_data_16 const& in, boost::optional<double>const& nodata, feature_impl const& f) const;
//! \brief Perform the translation of input to output
//!

View file

@ -72,7 +72,8 @@ void render_raster_symbolizer(raster_symbolizer const &sym,
if (*is_premultiplied) premultiply_source = false;
else premultiply_source = true;
}
if (premultiply_source)
// only premuiltiply rgba8 images
if (premultiply_source && source->data_.is<image_data_32>())
{
agg::rendering_buffer buffer(source->data_.getBytes(),
source->data_.width(),
@ -141,32 +142,25 @@ void render_raster_symbolizer(raster_symbolizer const &sym,
else if (source->data_.is<image_data_float32>())
{
std::cerr << "#3 source->data float32" << std::endl;
raster target(target_ext, image_data_float32(raster_width, raster_height), source->get_filter_factor());
scale_image_agg<image_data_float32>(util::get<image_data_float32>(target.data_),
util::get<image_data_float32>(source->data_),
scaling_method,
image_ratio_x,
image_ratio_y,
0.0,
0.0,
source->get_filter_factor());
image_data_float32 & data = util::get<image_data_float32>(target.data_);
}
else if (source->data_.is<image_data_16>())
{
std::cerr << "#3 source->data int16" << std::endl;
raster target(target_ext, image_data_16(raster_width, raster_height), source->get_filter_factor());
scale_image_agg<image_data_16>(util::get<image_data_16>(target.data_),
util::get<image_data_16>(source->data_),
scaling_method,
image_ratio_x,
image_ratio_y,
0.0,
0.0,
source->get_filter_factor());
image_data_16 & data = util::get<image_data_16>(target.data_);
image_data_32 dst(raster_width, raster_height);
for (unsigned x = 0; x < dst.width(); ++x)
{
for (unsigned y = 0; y < dst.height(); ++y)
{
//std::cerr << data(x,y) << std::endl;
unsigned val = unsigned(255*data(x,y)+0.5);
dst(x,y) = color(val,val,val, unsigned(opacity*255+0.5)).rgba();
}
}
raster out(target_ext, dst,source->get_filter_factor());
// If there's a colorizer defined, use it to color the raster in-place
raster_colorizer_ptr colorizer = get<raster_colorizer_ptr>(sym, keys::colorizer);
if (colorizer) colorizer->colorize(out,feature);
composite(util::get<image_data_32>(out.data_), comp_op, opacity, start_x, start_y);
if (colorizer) colorizer->colorize(dst, data,source->nodata(),feature);
composite(dst, comp_op, opacity, start_x, start_y);
}
}
}

View file

@ -204,8 +204,8 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
if (band_ > 0) // we are querying a single band
{
mapnik::image_data_float32 image(im_width, im_height);
image.set(std::numeric_limits<float>::max());
mapnik::image_data_16 image(im_width, im_height);
image.set(std::numeric_limits<std::int16_t>::max());
if (band_ > nbands_)
{
std::ostringstream s;
@ -217,8 +217,9 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
raster_nodata = band->GetNoDataValue(&raster_has_nodata);
raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
image.getData(), image.width(), image.height(),
GDT_Float32, 0, 0);
if (raster_io_error == CE_Failure) {
GDT_Int16, 0, 0);
if (raster_io_error == CE_Failure)
{
throw datasource_exception(CPLGetLastErrorMsg());
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);

View file

@ -302,6 +302,101 @@ void scale_image_agg<image_data_float32>(image_data_float32 & target,
agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg);
}
template <>
void scale_image_agg<image_data_16>(image_data_16 & target,
image_data_16 const& source,
scaling_method_e scaling_method,
double image_ratio_x,
double image_ratio_y,
double x_off_f,
double y_off_f,
double filter_factor)
{
using pixfmt_pre = agg::pixfmt_gray16_pre;
using renderer_base_pre = agg::renderer_base<pixfmt_pre>;
// define some stuff we'll use soon
agg::rasterizer_scanline_aa<> ras;
agg::scanline_u8 sl;
agg::span_allocator<agg::gray16> sa;
agg::image_filter_lut filter;
// initialize source AGG buffer
agg::rendering_buffer rbuf_src(const_cast<unsigned char*>(source.getBytes()), source.width(), source.height(), source.width() * 2);
pixfmt_pre pixf_src(rbuf_src);
using img_src_type = agg::image_accessor_clone<pixfmt_pre>;
img_src_type img_src(pixf_src);
// initialize destination AGG buffer (with transparency)
agg::rendering_buffer rbuf_dst(target.getBytes(), target.width(), target.height(), target.width() * 2);
pixfmt_pre pixf_dst(rbuf_dst);
renderer_base_pre rb_dst_pre(pixf_dst);
// create a scaling matrix
agg::trans_affine img_mtx;
img_mtx /= agg::trans_affine_scaling(image_ratio_x, image_ratio_y);
// create a linear interpolator for our scaling matrix
using interpolator_type = agg::span_interpolator_linear<>;
interpolator_type interpolator(img_mtx);
// draw an anticlockwise polygon to render our image into
double scaled_width = target.width();
double scaled_height = target.height();
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:
{
using span_gen_type = agg::span_image_filter_gray_nn<img_src_type, interpolator_type>;
span_gen_type sg(img_src, interpolator);
agg::render_scanlines_aa(ras, sl, rb_dst_pre, 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_factor), true); break;
case SCALING_LANCZOS:
filter.calculate(agg::image_filter_lanczos(filter_factor), true); break;
case SCALING_BLACKMAN:
filter.calculate(agg::image_filter_blackman(filter_factor), true); break;
}
using span_gen_type = agg::span_image_resample_gray_affine<img_src_type>;
span_gen_type sg(img_src, interpolator, filter);
agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg);
}
//template void scale_image_agg<image_data_32>(image_data_32& target,
// const image_data_32& source,
// scaling_method_e scaling_method,

View file

@ -124,14 +124,13 @@ bool raster_colorizer::add_stop(colorizer_stop const& stop)
void raster_colorizer::colorize(raster & ras, feature_impl const& f) const
{
unsigned * imageData = reinterpret_cast<unsigned*>(ras.data_.getBytes());
std::int16_t * imageData = reinterpret_cast<std::int16_t*>(ras.data_.getBytes());
int len = ras.data_.width() * ras.data_.height();
boost::optional<double> const& nodata = ras.nodata();
for (int i=0; i<len; ++i)
{
// the GDAL plugin reads single bands as floats
float value = *reinterpret_cast<float *> (&imageData[i]);
std::int16_t value = imageData[i];
if (nodata && (std::fabs(value - *nodata) < epsilon_))
{
imageData[i] = 0;
@ -143,6 +142,27 @@ void raster_colorizer::colorize(raster & ras, feature_impl const& f) const
}
}
void raster_colorizer::colorize(image_data_32 & out, image_data_16 const& in, boost::optional<double>const& nodata, feature_impl const& f) const
{
// TODO: assuming in/out have the same width/height for now
std::uint32_t * out_data = out.getData();
std::int16_t const* in_data = in.getData();
int len = out.width() * out.height();
for (int i=0; i<len; ++i)
{
// the GDAL plugin reads single bands as floats
std::int16_t value = in_data[i];
if (nodata && (std::fabs(value - *nodata) < epsilon_))
{
out_data[i] = 0;
}
else
{
out_data[i] = get_color(value);
}
}
}
inline unsigned interpolate(unsigned start, unsigned end, float fraction)
{
return static_cast<unsigned>(fraction * ((float)end - (float)start) + start);