From 49afe197c3e342f0bd93d55b0265b0668f1c041c Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 3 Mar 2010 02:11:28 +0000 Subject: [PATCH] apply mapnik-0.7.1.mr.raster-position2.diff from mar_rud to close #475 --- include/mapnik/image_util.hpp | 74 +++++++++++------ plugins/input/gdal/gdal_featureset.cpp | 43 +++++----- plugins/input/raster/raster_featureset.cpp | 30 ++++++- src/agg_renderer.cpp | 92 ++++++++++++---------- src/cairo_renderer.cpp | 42 ++++++---- 5 files changed, 181 insertions(+), 100 deletions(-) diff --git a/include/mapnik/image_util.hpp b/include/mapnik/image_util.hpp index a1b3c69fe..62767d288 100644 --- a/include/mapnik/image_util.hpp +++ b/include/mapnik/image_util.hpp @@ -305,7 +305,7 @@ namespace mapnik { } template - inline void scale_image_bilinear (Image& target,const Image& source) + inline void scale_image_bilinear (Image& target,const Image& source, double x_off_f=0, double y_off_f=0) { int source_width=source.width(); @@ -319,28 +319,43 @@ namespace mapnik { int x=0,y=0,xs=0,ys=0; int tw2 = target_width/2; int th2 = target_height/2; + int offs_x = int(round((source_width-target_width-x_off_f*2*source_width)/2)); + int offs_y = int(round((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=source_height) ys1--; - unsigned yprt = y*source_height%target_height; - unsigned yprt1 = target_height-yprt; + if (ys<0) + ys=ys1=0; + if (source_height/2=target_width || source_height>=target_height){ - target(x,y)=source(xs,ys); - continue; - } - unsigned xprt = x*source_width%target_width; - unsigned xprt1 = target_width-xprt; + xs = (x*source_width+offs_x)/target_width; + if (source_width/2=source_width) xs1--; + if (xs<0) + xs=xs1=0; unsigned a = source(xs,ys); unsigned b = source(xs1,ys); @@ -377,7 +392,7 @@ namespace mapnik { } template - inline void scale_image_bilinear8 (Image& target,const Image& source) + inline void scale_image_bilinear8 (Image& target,const Image& source, double x_off_f=0, double y_off_f=0) { int source_width=source.width(); @@ -391,28 +406,43 @@ namespace mapnik { int x=0,y=0,xs=0,ys=0; int tw2 = target_width/2; int th2 = target_height/2; + int offs_x = int(round((source_width-target_width-x_off_f*2*source_width)/2)); + int offs_y = int(round((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=source_height) ys1--; - unsigned yprt = y*source_height%target_height; - unsigned yprt1 = target_height-yprt; + if (ys<0) + ys=ys1=0; + if (source_height/2=target_width || source_height>=target_height){ - target(x,y)=source(xs,ys); - continue; - } - unsigned xprt = x*source_width%target_width; - unsigned xprt1 = target_width-xprt; + xs = (x*source_width+offs_x)/target_width; + if (source_width/2=source_width) xs1--; + if (xs<0) + xs=xs1=0; unsigned a = source(xs,ys); unsigned b = source(xs1,ys); diff --git a/plugins/input/gdal/gdal_featureset.cpp b/plugins/input/gdal/gdal_featureset.cpp index 2cc3b214a..4eaaee0cc 100644 --- a/plugins/input/gdal/gdal_featureset.cpp +++ b/plugins/input/gdal/gdal_featureset.cpp @@ -104,25 +104,30 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) Envelope intersect = raster_extent.intersect(q.get_bbox()); Envelope box = t.forward(intersect); - // TODO: error check this further... - float x_off_f = (intersect.minx()-raster_extent.minx()) / fabs(dx); - float y_off_f = (raster_extent.maxy()-intersect.maxy()) / fabs(dy); - - if (x_off_f < 0) - { - x_off_f = 0; - } - - if (y_off_f < 0) - { - y_off_f = 0; - } - - int x_off = static_cast(x_off_f); - int y_off = static_cast(y_off_f); - - int width = int(box.width() + 0.5); - int height = int(box.height() + 0.5); + //select minimum raster containing whole box + int x_off = static_cast(floor(box.minx())); + int y_off = static_cast(floor(box.miny())); + int end_x = static_cast(ceil(box.maxx())); + int end_y = static_cast(ceil(box.maxy())); + //clip to available data + if (x_off < 0) + x_off = 0; + if (y_off < 0) + y_off = 0; + if (end_x > raster_width) + end_x = raster_width; + if (end_y > raster_height) + end_y = raster_height; + int width = end_x - x_off; + int height = end_y - y_off; + // don't process almost invisible data + if (box.width() < 0.5) + width = 0; + if (box.height() < 0.5) + height = 0; + //calculate actual envelope of returned raster + Envelope feature_raster_extent(x_off, y_off, x_off+width, y_off+height); + intersect = t.backward(feature_raster_extent); #ifdef MAPNIK_DEBUG std::clog << "GDAL Plugin: Raster extent=" << raster_extent << "\n"; diff --git a/plugins/input/raster/raster_featureset.cpp b/plugins/input/raster/raster_featureset.cpp index 600f10469..633f678af 100644 --- a/plugins/input/raster/raster_featureset.cpp +++ b/plugins/input/raster/raster_featureset.cpp @@ -73,9 +73,33 @@ feature_ptr raster_featureset::next() CoordTransform t(image_width,image_height,extent_,0,0); Envelope intersect=bbox_.intersect(curIter_->envelope()); Envelope ext=t.forward(intersect); - ImageData32 image(int(ext.width()+0.5),int(ext.height()+0.5)); - reader->read(int(ext.minx()+0.5),int(ext.miny()+0.5),image); - feature->set_raster(mapnik::raster_ptr(new raster(intersect,image))); + if ( ext.width()>0.5 && ext.height()>0.5 ) + { + //select minimum raster containing whole ext + int x_off = static_cast(floor(ext.minx())); + int y_off = static_cast(floor(ext.miny())); + int end_x = static_cast(ceil(ext.maxx())); + int end_y = static_cast(ceil(ext.maxy())); + //clip to available data + if (x_off < 0) + x_off = 0; + if (y_off < 0) + y_off = 0; + if (end_x > image_width) + end_x = image_width; + if (end_y > image_height) + end_y = image_height; + int width = end_x - x_off; + int height = end_y - y_off; + //calculate actual envelope of returned raster + Envelope feature_raster_extent(x_off, y_off, x_off+width, y_off+height); + intersect = t.backward(feature_raster_extent); + + ImageData32 image(width,height); + reader->read(x_off,y_off,image); + + feature->set_raster(mapnik::raster_ptr(new raster(intersect,image))); + } } } } diff --git a/src/agg_renderer.cpp b/src/agg_renderer.cpp index 0da983fbb..4fb90d496 100644 --- a/src/agg_renderer.cpp +++ b/src/agg_renderer.cpp @@ -714,50 +714,60 @@ namespace mapnik if (raster) { Envelope ext=t_.forward(raster->ext_); - ImageData32 target(int(ceil(ext.width())),int(ceil(ext.height()))); - int start_x = int(ext.minx()+0.5); - int start_y = int(ext.miny()+0.5); + int start_x = int(round(ext.minx())); + int start_y = int(round(ext.miny())); + int raster_width = int(round(ext.width())); + int raster_height = int(round(ext.height())); + int end_x = start_x + raster_width; + int end_y = start_y + raster_height; + double err_offs_x = (ext.minx()-start_x + ext.maxx()-end_x)/2; + double err_offs_y = (ext.miny()-start_y + ext.maxy()-end_y)/2; + + if (raster_width > 0 && raster_height > 0) + { + ImageData32 target(raster_width,raster_height); - if (sym.get_scaling() == "fast") { - scale_image(target,raster->data_); - } else if (sym.get_scaling() == "bilinear"){ - scale_image_bilinear(target,raster->data_); - } else if (sym.get_scaling() == "bilinear8"){ - scale_image_bilinear8(target,raster->data_); - } else { - scale_image(target,raster->data_); - } + if (sym.get_scaling() == "fast") { + scale_image(target,raster->data_); + } else if (sym.get_scaling() == "bilinear"){ + scale_image_bilinear(target,raster->data_, err_offs_x, err_offs_y); + } else if (sym.get_scaling() == "bilinear8"){ + scale_image_bilinear8(target,raster->data_, err_offs_x, err_offs_y); + } else { + scale_image(target,raster->data_); + } - if (sym.get_mode() == "normal"){ - if (sym.get_opacity() == 1.0) { - pixmap_.set_rectangle(start_x,start_y,target); - } else { - pixmap_.set_rectangle_alpha2(target,start_x,start_y, sym.get_opacity()); - } - } else if (sym.get_mode() == "grain_merge"){ - pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); - } else if (sym.get_mode() == "grain_merge2"){ - pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); - } else if (sym.get_mode() == "multiply"){ - pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); - } else if (sym.get_mode() == "multiply2"){ - pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); - } else if (sym.get_mode() == "divide"){ - pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); - } else if (sym.get_mode() == "divide2"){ - pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); - } else if (sym.get_mode() == "screen"){ - pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); - } else if (sym.get_mode() == "hard_light"){ - pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); - } else { - if (sym.get_opacity() == 1.0){ - pixmap_.set_rectangle(start_x,start_y,target); - } else { - pixmap_.set_rectangle_alpha2(target,start_x,start_y, sym.get_opacity()); - } + if (sym.get_mode() == "normal"){ + if (sym.get_opacity() == 1.0) { + pixmap_.set_rectangle(start_x,start_y,target); + } else { + pixmap_.set_rectangle_alpha2(target,start_x,start_y, sym.get_opacity()); + } + } else if (sym.get_mode() == "grain_merge"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "grain_merge2"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "multiply"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "multiply2"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "divide"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "divide2"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "screen"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "hard_light"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else { + if (sym.get_opacity() == 1.0){ + pixmap_.set_rectangle(start_x,start_y,target); + } else { + pixmap_.set_rectangle_alpha2(target,start_x,start_y, sym.get_opacity()); + } + } + // TODO: other modes? (add,diff,sub,...) } - // TODO: other modes? (add,diff,sub,...) } } diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index 8b901f8fb..533a05655 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -974,22 +974,34 @@ namespace mapnik if (raster) { Envelope ext = t_.forward(raster->ext_); - ImageData32 target(int(ext.width() + 0.5), int(ext.height() + 0.5)); - //TODO -- use cairo matrix transformation for scaling - if (sym.get_scaling() == "fast"){ - scale_image(target, raster->data_); - } else if (sym.get_scaling() == "bilinear"){ - scale_image_bilinear(target,raster->data_); - } else if (sym.get_scaling() == "bilinear8"){ - scale_image_bilinear8(target,raster->data_); - } else { - scale_image(target,raster->data_); + int start_x = int(round(ext.minx())); + int start_y = int(round(ext.miny())); + int raster_width = int(round(ext.width())); + int raster_height = int(round(ext.height())); + int end_x = start_x + raster_width; + int end_y = start_y + raster_height; + double err_offs_x = (ext.minx()-start_x + ext.maxx()-end_x)/2; + double err_offs_y = (ext.miny()-start_y + ext.maxy()-end_y)/2; + + if (raster_width > 0 && raster_height > 0) + { + ImageData32 target(raster_width, raster_height); + //TODO -- use cairo matrix transformation for scaling + if (sym.get_scaling() == "fast"){ + scale_image(target, raster->data_); + } else if (sym.get_scaling() == "bilinear"){ + scale_image_bilinear(target,raster->data_, err_offs_x, err_offs_y); + } else if (sym.get_scaling() == "bilinear8"){ + scale_image_bilinear8(target,raster->data_, err_offs_x, err_offs_y); + } else { + scale_image(target,raster->data_); + } + + cairo_context context(context_); + + //TODO -- support for advanced image merging + context.add_image(start_x, start_y, target, sym.get_opacity()); } - - cairo_context context(context_); - - //TODO -- support for advanced image merging - context.add_image(int(ext.minx()+0.5), int(ext.miny()+0.5), target, sym.get_opacity()); } }