From: Bborie Park Date: Mon, 19 Nov 2012 23:18:59 +0000 (+0000) Subject: Fixed issue where ST_AsRaster() may not return raster with specified X-Git-Tag: 2.1.0beta2~380 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cf1fad5072d362949352cf6597da38ecd4f9ba32;p=postgis Fixed issue where ST_AsRaster() may not return raster with specified pixel types. Ticket #2100 git-svn-id: http://svn.osgeo.org/postgis/trunk@10710 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/NEWS b/NEWS index c88aab06b..5f5a4cdca 100644 --- a/NEWS +++ b/NEWS @@ -103,6 +103,7 @@ PostGIS 2.1.0 - #2057, Fixed linking issue for raster2psql to libpq - #2077, Fixed incorrect values returning from ST_Hillshade() - #2019, ST_FlipCoordinates does not update bbox + - #2100, ST_AsRaster may not return raster with specified pixel type PostGIS 2.0.1 diff --git a/raster/rt_core/rt_api.c b/raster/rt_core/rt_api.c index 8becd3fcd..8302ba0a7 100644 --- a/raster/rt_core/rt_api.c +++ b/raster/rt_core/rt_api.c @@ -10173,19 +10173,19 @@ _rti_rasterize_arg_init() { static void _rti_rasterize_arg_destroy(_rti_rasterize_arg arg) { - if (!arg->noband || !arg->numbands) - return; + if (arg->noband) { + if (arg->pixtype != NULL) + rtdealloc(arg->pixtype); + if (arg->init != NULL) + rtdealloc(arg->init); + if (arg->nodata != NULL) + rtdealloc(arg->nodata); + if (arg->hasnodata != NULL) + rtdealloc(arg->hasnodata); + if (arg->value != NULL) + rtdealloc(arg->value); + } - if (arg->pixtype != NULL) - rtdealloc(arg->pixtype); - if (arg->init != NULL) - rtdealloc(arg->init); - if (arg->nodata != NULL) - rtdealloc(arg->nodata); - if (arg->hasnodata != NULL) - rtdealloc(arg->hasnodata); - if (arg->value != NULL) - rtdealloc(arg->value); if (arg->bandlist != NULL) rtdealloc(arg->bandlist); @@ -10231,9 +10231,9 @@ rt_raster_gdal_rasterize(const unsigned char *wkb, double *skew_x, double *skew_y, char **options ) { - rt_raster rast; + rt_raster rast = NULL; int i = 0; - int banderr = 0; + int err = 0; _rti_rasterize_arg arg = NULL; @@ -10256,6 +10256,9 @@ rt_raster_gdal_rasterize(const unsigned char *wkb, GDALDatasetH _ds = NULL; GDALRasterBandH _band = NULL; + uint16_t _width = 0; + uint16_t _height = 0; + RASTER_DEBUG(3, "starting"); assert(NULL != wkb); @@ -10964,21 +10967,21 @@ rt_raster_gdal_rasterize(const unsigned char *wkb, /* set bands */ for (i = 0; i < arg->numbands; i++) { - banderr = 0; + err = 0; do { /* add band */ cplerr = GDALAddBand(_ds, rt_util_pixtype_to_gdal_datatype(arg->pixtype[i]), NULL); if (cplerr != CE_None) { rterror("rt_raster_gdal_rasterize: Unable to add band to GDALDataset"); - banderr = 1; + err = 1; break; } _band = GDALGetRasterBand(_ds, i + 1); if (NULL == _band) { rterror("rt_raster_gdal_rasterize: Unable to get band %d from GDALDataset", i + 1); - banderr = 1; + err = 1; break; } @@ -10988,7 +10991,7 @@ rt_raster_gdal_rasterize(const unsigned char *wkb, cplerr = GDALSetRasterNoDataValue(_band, arg->nodata[i]); if (cplerr != CE_None) { rterror("rt_raster_gdal_rasterize: Unable to set nodata value"); - banderr = 1; + err = 1; break; } RASTER_DEBUGF(4, "NODATA value set to %f", GDALGetRasterNoDataValue(_band, NULL)); @@ -10998,13 +11001,13 @@ rt_raster_gdal_rasterize(const unsigned char *wkb, cplerr = GDALFillRaster(_band, arg->init[i], 0); if (cplerr != CE_None) { rterror("rt_raster_gdal_rasterize: Unable to set initial value"); - banderr = 1; + err = 1; break; } } while (0); - if (banderr) { + if (err) { _rti_rasterize_arg_destroy(arg); OGR_G_DestroyGeometry(src_geom); @@ -11020,6 +11023,7 @@ rt_raster_gdal_rasterize(const unsigned char *wkb, arg->bandlist = (int *) rtalloc(sizeof(int) * arg->numbands); for (i = 0; i < arg->numbands; i++) arg->bandlist[i] = i + 1; + /* burn geometry */ cplerr = GDALRasterizeGeometries( _ds, @@ -11030,10 +11034,11 @@ rt_raster_gdal_rasterize(const unsigned char *wkb, options, NULL, NULL ); - _rti_rasterize_arg_destroy(arg); if (cplerr != CE_None) { rterror("rt_raster_gdal_rasterize: Unable to rasterize geometry"); + _rti_rasterize_arg_destroy(arg); + OGR_G_DestroyGeometry(src_geom); OSRDestroySpatialReference(src_sr); /* OGRCleanupAll(); */ @@ -11059,6 +11064,110 @@ rt_raster_gdal_rasterize(const unsigned char *wkb, return NULL; } + /* width, height */ + _width = rt_raster_get_width(rast); + _height = rt_raster_get_height(rast); + + /* check each band for pixtype */ + for (i = 0; i < arg->numbands; i++) { + uint8_t *data = NULL; + rt_band band = NULL; + rt_band oldband = NULL; + + double val = 0; + int nodata = 0; + int hasnodata = 0; + double nodataval = 0; + int x = 0; + int y = 0; + + oldband = rt_raster_get_band(rast, i); + if (oldband == NULL) { + rterror("rt_raster_gdal_rasterize: Unable to get band %d of output raster", i); + _rti_rasterize_arg_destroy(arg); + rt_raster_destroy(rast); + return NULL; + } + + /* band is of user-specified type */ + if (rt_band_get_pixtype(oldband) == arg->pixtype[i]) + continue; + + /* hasnodata, nodataval */ + hasnodata = rt_band_get_hasnodata_flag(oldband); + if (hasnodata) + rt_band_get_nodata(oldband, &nodataval); + + /* allocate data */ + data = rtalloc(rt_pixtype_size(arg->pixtype[i]) * _width * _height); + if (data == NULL) { + rterror("rt_raster_gdal_rasterize: Could not allocate memory for band data"); + _rti_rasterize_arg_destroy(arg); + rt_raster_destroy(rast); + return NULL; + } + memset(data, 0, rt_pixtype_size(arg->pixtype[i]) * _width * _height); + + /* create new band of correct type */ + band = rt_band_new_inline( + _width, _height, + arg->pixtype[i], + hasnodata, nodataval, + data + ); + if (band == NULL) { + rterror("rt_raster_gdal_rasterize: Unable to create band"); + rtdealloc(data); + _rti_rasterize_arg_destroy(arg); + rt_raster_destroy(rast); + return NULL; + } + + /* give ownership of data to band */ + rt_band_set_ownsdata_flag(band, 1); + + /* copy pixel by pixel */ + for (x = 0; x < _width; x++) { + for (y = 0; y < _height; y++) { + err = rt_band_get_pixel(oldband, x, y, &val, &nodata); + if (err != 0) { + rterror("rt_raster_gdal_rasterize: Unable to get pixel value"); + _rti_rasterize_arg_destroy(arg); + rt_raster_destroy(rast); + rt_band_destroy(band); + return NULL; + } + + if (nodata) + val = nodataval; + + err = rt_band_set_pixel(band, x, y, val); + if (err < 0) { + rterror("rt_raster_gdal_rasterize: Unable to set pixel value"); + _rti_rasterize_arg_destroy(arg); + rt_raster_destroy(rast); + rt_band_destroy(band); + return NULL; + } + } + } + + /* replace band */ + oldband = rt_raster_replace_band(rast, band, i); + if (oldband == NULL) { + rterror("rt_raster_gdal_rasterize: Unable to replace band %d of output raster", i); + _rti_rasterize_arg_destroy(arg); + rt_raster_destroy(rast); + rt_band_destroy(band); + return NULL; + } + + /* free oldband */ + rt_band_destroy(oldband); + } + + _rti_rasterize_arg_destroy(arg); + RASTER_DEBUG(3, "done"); return rast; diff --git a/raster/test/regress/rt_asraster_expected b/raster/test/regress/rt_asraster_expected index f9b6b4556..dafd25e06 100644 --- a/raster/test/regress/rt_asraster_expected +++ b/raster/test/regress/rt_asraster_expected @@ -17,7 +17,7 @@ NOTICE: The two rasters provided have different scales on the X axis 1.0|||||||||||||||| 1.1|993310|100|100|1|1406.537|-869.114|0.000|0.000|-175453.086|114987.661|8BUI|0.000|t|1.000|1.000| 1.10|993310|141|87|1|1000.000|-1000.000|0.000|0.000|-175453.086|114987.661|32BF|0.000|t|1.000|1.000| -1.11|993310|100|100|1|1406.537|-869.114|0.000|0.000|-175453.086|114987.661|16BSI|0.000|t|1.000|1.000| +1.11|993310|100|100|1|1406.537|-869.114|0.000|0.000|-175453.086|114987.661|8BSI|0.000|t|1.000|1.000| 1.12|993310|100|100|1|1406.537|-869.114|0.000|0.000|-175453.086|114987.661|16BUI|0.000|t|1.000|1.000| 1.13|993310|100|100|1|1406.537|-869.114|0.000|0.000|-175453.086|114987.661|32BF|0.000|t|255.000|255.000| 1.14|993310|100|100|1|1406.537|-869.114|0.000|0.000|-175453.086|114987.661|32BF|1.000|t|255.000|255.000| @@ -27,13 +27,13 @@ NOTICE: The two rasters provided have different scales on the X axis 1.18|993310|10|10|2|14065.366|-8691.142|0.000|0.000|-175453.086|114987.661|8BUI|0.000|t|255.000|255.000| 1.19|993310|141|87|3|1000.000|-1000.000|0.000|0.000|-175453.086|114987.661|32BF||t|0.000|255.000| 1.2|993310|1407|869|1|100.000|-100.000|0.000|0.000|-175453.086|114987.661|8BUI|0.000|t|1.000|1.000| -1.20|993310|141|87|2|1000.000|-1000.000|0.000|0.000|-175453.086|114987.661|8BUI|1.000|f||| +1.20|993310|141|87|2|1000.000|-1000.000|0.000|0.000|-175453.086|114987.661|1BB|1.000|f||| 1.3|993310|500|500|1|281.307|-173.823|0.000|0.000|-175453.086|114987.661|8BUI|0.000|t|1.000|1.000| 1.4|993310|141|87|1|1000.000|-1000.000|0.000|0.000|-175453.086|114987.661|8BUI|0.000|t|1.000|1.000| -1.5|993310|141|87|1|1000.000|-1000.000|0.000|0.000|-175453.086|114987.661|16BSI|0.000|t|1.000|1.000| +1.5|993310|141|87|1|1000.000|-1000.000|0.000|0.000|-175453.086|114987.661|8BSI|0.000|t|1.000|1.000| 1.6|993310|141|87|1|1000.000|-1000.000|0.000|0.000|-175453.086|114987.661|16BUI|0.000|t|1.000|1.000| 1.7|993310|1407|869|1|100.000|-100.000|0.000|0.000|-175453.086|114987.661|32BF|0.000|t|1.000|1.000| -1.8|993310|141|87|1|1000.000|-1000.000|0.000|0.000|-175453.086|114987.661|16BSI|0.000|t|1.000|1.000| +1.8|993310|141|87|1|1000.000|-1000.000|0.000|0.000|-175453.086|114987.661|8BSI|0.000|t|1.000|1.000| 1.9|993310|141|87|1|1000.000|-1000.000|0.000|0.000|-175453.086|114987.661|16BUI|0.000|t|1.000|1.000| 2.0|||||||||||||||| 2.1||||||||||||||||