From 5a770d6a96bb8736ae9f4218a0825d2238118ab0 Mon Sep 17 00:00:00 2001 From: Stephen Davis Date: Fri, 31 Oct 2014 16:32:56 +1300 Subject: [PATCH] throw datasource_exception on GDAL RasterIO failures --- plugins/input/gdal/gdal_featureset.cpp | 84 ++++++++++++++++++-------- tests/data/raster/missing_raster.vrt | 45 ++++++++++++++ tests/python_tests/datasource_test.py | 27 +++++++++ 3 files changed, 132 insertions(+), 24 deletions(-) create mode 100644 tests/data/raster/missing_raster.vrt diff --git a/plugins/input/gdal/gdal_featureset.cpp b/plugins/input/gdal/gdal_featureset.cpp index 63f39de76..f70ef37ff 100644 --- a/plugins/input/gdal/gdal_featureset.cpp +++ b/plugins/input/gdal/gdal_featureset.cpp @@ -104,6 +104,7 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) GDALRasterBand * blue = 0; GDALRasterBand * alpha = 0; GDALRasterBand * grey = 0; + CPLErr raster_io_error = CE_None; /* #ifdef MAPNIK_LOG @@ -215,9 +216,12 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) float* imageData = (float*)image.getBytes(); GDALRasterBand * band = dataset_.GetRasterBand(band_); raster_nodata = band->GetNoDataValue(&raster_has_nodata); - band->RasterIO(GF_Read, x_off, y_off, width, height, - imageData, image.width(), image.height(), - GDT_Float32, 0, 0); + raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height, + imageData, image.width(), image.height(), + GDT_Float32, 0, 0); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } } else // working with all bands { @@ -307,9 +311,12 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) // TODO - we assume here the nodata value for the red band applies to all bands // more details about this at http://trac.osgeo.org/gdal/ticket/2734 float* imageData = (float*)image.getBytes(); - red->RasterIO(GF_Read, x_off, y_off, width, height, - imageData, image.width(), image.height(), - GDT_Float32, 0, 0); + raster_io_error = red->RasterIO(GF_Read, x_off, y_off, width, height, + imageData, image.width(), image.height(), + GDT_Float32, 0, 0); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } int len = image.width() * image.height(); for (int i = 0; i < len; ++i) { @@ -323,12 +330,21 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) } } } - red->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); - green->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 1, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); - blue->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 2, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + raster_io_error = red->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } + raster_io_error = green->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 1, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } + raster_io_error = blue->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 2, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } } else if (grey) { @@ -342,9 +358,12 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: applying nodata value for layer=" << apply_nodata; // first read the data in and create an alpha channel from the nodata values float* imageData = (float*)image.getBytes(); - grey->RasterIO(GF_Read, x_off, y_off, width, height, - imageData, image.width(), image.height(), - GDT_Float32, 0, 0); + raster_io_error = grey->RasterIO(GF_Read, x_off, y_off, width, height, + imageData, image.width(), image.height(), + GDT_Float32, 0, 0); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } int len = image.width() * image.height(); for (int i = 0; i < len; ++i) { @@ -358,12 +377,21 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) } } } - grey->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); - grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 1, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); - grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 2, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + raster_io_error = grey->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } + raster_io_error = grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 1, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } + raster_io_error = grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 2, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } if (color_table) { @@ -394,8 +422,11 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: processing alpha band..."; if (!raster_has_nodata) { - alpha->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 3, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + raster_io_error = alpha->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 3, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } } else { @@ -426,6 +457,8 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) feature_ptr gdal_featureset::get_feature_at_point(mapnik::coord2d const& pt) { + CPLErr raster_io_error = CE_None; + if (band_ > 0) { unsigned raster_xsize = dataset_.GetRasterXSize(); @@ -453,7 +486,10 @@ feature_ptr gdal_featureset::get_feature_at_point(mapnik::coord2d const& pt) int raster_has_nodata; double nodata = band->GetNoDataValue(&raster_has_nodata); double value; - band->RasterIO(GF_Read, x, y, 1, 1, &value, 1, 1, GDT_Float64, 0, 0); + raster_io_error = band->RasterIO(GF_Read, x, y, 1, 1, &value, 1, 1, GDT_Float64, 0, 0); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } if (! raster_has_nodata || value != nodata) { // construct feature diff --git a/tests/data/raster/missing_raster.vrt b/tests/data/raster/missing_raster.vrt new file mode 100644 index 000000000..98d0bea30 --- /dev/null +++ b/tests/data/raster/missing_raster.vrt @@ -0,0 +1,45 @@ + + PROJCS["WGS 84 / UTM zone 30N",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-3],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32630"]] + -1.4637000000000000e+04, 5.0000000000000000e+02, 0.0000000000000000e+00, 4.8596780000000000e+06, 0.0000000000000000e+00, -5.0000000000000000e+02 + + -9.99000000000000E+02 + 0 + Palette + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + this_file_should_not_exist.tif + 1 + + + + -999 + + + diff --git a/tests/python_tests/datasource_test.py b/tests/python_tests/datasource_test.py index c86b829bc..e6a05e5a5 100644 --- a/tests/python_tests/datasource_test.py +++ b/tests/python_tests/datasource_test.py @@ -13,6 +13,33 @@ def test_that_datasources_exist(): if len(mapnik.DatasourceCache.plugin_names()) == 0: print '***NOTICE*** - no datasource plugins have been loaded' +# adapted from raster_symboliser_test#test_dataraster_query_point +def test_vrt_referring_to_missing_files(): + srs = '+init=epsg:32630' + if 'gdal' in mapnik.DatasourceCache.plugin_names(): + lyr = mapnik.Layer('dataraster') + lyr.datasource = mapnik.Gdal( + file = '../data/raster/missing_raster.vrt', + band = 1, + ) + lyr.srs = srs + _map = mapnik.Map(256, 256, srs) + _map.layers.append(lyr) + + # center of extent of raster + x, y = 556113.0,4381428.0 # center of extent of raster + + _map.zoom_all() + + # Should RuntimeError here + try: + _map.query_point(0, x, y).features + except RuntimeError, e: + eq_("this_file_should_not_exist.tif' does not exist in the file system" in str(e), True) + else: + assert False + + def test_field_listing(): if 'shape' in mapnik.DatasourceCache.plugin_names(): ds = mapnik.Shapefile(file='../data/shp/poly.shp')