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:
parent
27159b8086
commit
de7a268333
6 changed files with 148 additions and 34 deletions
|
@ -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>;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
//!
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue