From: Bborie Park Date: Fri, 16 Dec 2011 01:11:21 +0000 (+0000) Subject: Addition of C-based ST_MinPossibleValue to replace the existing ST_MinPossibleVal... X-Git-Tag: 2.0.0alpha1~437 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7edd2ae9675281ad0c698a8329dd3fd475e5d372;p=postgis Addition of C-based ST_MinPossibleValue to replace the existing ST_MinPossibleVal which uses hard-coded values. Updated dependent functions and scripts/plpgsql to use new function. Deleted scripts/plpgsql/st_minpossibleval.sql to stop people from using it. Associated ticket is #1298. git-svn-id: http://svn.osgeo.org/postgis/trunk@8436 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/raster/rt_pg/rt_pg.c b/raster/rt_pg/rt_pg.c index e2e5e3683..8a60e873f 100644 --- a/raster/rt_pg/rt_pg.c +++ b/raster/rt_pg/rt_pg.c @@ -142,6 +142,7 @@ static char *rtpg_getSRTextSPI(int srid); Datum RASTER_lib_version(PG_FUNCTION_ARGS); Datum RASTER_lib_build_date(PG_FUNCTION_ARGS); Datum RASTER_gdal_version(PG_FUNCTION_ARGS); +Datum RASTER_minPossibleValue(PG_FUNCTION_ARGS); /* Input/output and format conversions */ Datum RASTER_in(PG_FUNCTION_ARGS); @@ -569,6 +570,49 @@ Datum RASTER_gdal_version(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } +PG_FUNCTION_INFO_V1(RASTER_minPossibleValue); +Datum RASTER_minPossibleValue(PG_FUNCTION_ARGS) +{ + text *pixeltypetext = NULL; + char *pixeltypechar = NULL; + rt_pixtype pixtype = PT_END; + double pixsize = 0; + + if (PG_ARGISNULL(0)) + PG_RETURN_NULL(); + + pixeltypetext = PG_GETARG_TEXT_P(0); + pixeltypechar = text_to_cstring(pixeltypetext); + + pixtype = rt_pixtype_index_from_name(pixeltypechar); + if (pixtype == PT_END) { + elog(ERROR, "RASTER_minPossibleValue: Invalid pixel type: %s", pixeltypechar); + PG_RETURN_NULL(); + } + + pixsize = rt_pixtype_get_min_value(pixtype); + + /* + correct pixsize of unsigned pixel types + example: for PT_8BUI, the value is CHAR_MIN but if char is signed, + the value returned is -127 instead of 0. + */ + switch (pixtype) { + case PT_1BB: + case PT_2BUI: + case PT_4BUI: + case PT_8BUI: + case PT_16BUI: + case PT_32BUI: + pixsize = 0; + break; + default: + break; + } + + PG_RETURN_FLOAT8(pixsize); +} + /** * Input is a string with hex chars in it. * Convert to binary and put in the result diff --git a/raster/rt_pg/rtpostgis.sql.in.c b/raster/rt_pg/rtpostgis.sql.in.c index 21ffbfe6b..c1921cd20 100644 --- a/raster/rt_pg/rtpostgis.sql.in.c +++ b/raster/rt_pg/rtpostgis.sql.in.c @@ -2768,34 +2768,16 @@ CREATE OR REPLACE FUNCTION st_raster2worldcoordy(rast raster, yr int) LANGUAGE 'plpgsql' IMMUTABLE STRICT; ----------------------------------------------------------------------- --- ST_MinPossibleVal(pixeltype text) +-- ST_MinPossibleValue(pixeltype text) -- Return the smallest value for a given pixeltyp. -- Should be called like this: --- SELECT ST_MinPossibleVal(ST_BandPixelType(rast, band)) +-- SELECT ST_MinPossibleValue(ST_BandPixelType(rast, band)) ----------------------------------------------------------------------- -CREATE OR REPLACE FUNCTION ST_MinPossibleVal(pixeltype text) - RETURNS float8 AS - $$ - DECLARE - newval int := 0; - BEGIN - newval := CASE - WHEN pixeltype = '1BB' THEN 0 - WHEN pixeltype = '2BUI' THEN 0 - WHEN pixeltype = '4BUI' THEN 0 - WHEN pixeltype = '8BUI' THEN 0 - WHEN pixeltype = '8BSI' THEN -128 - WHEN pixeltype = '16BUI' THEN 0 - WHEN pixeltype = '16BSI' THEN -32768 - WHEN pixeltype = '32BUI' THEN 0 - WHEN pixeltype = '32BSI' THEN -2147483648 - WHEN pixeltype = '32BF' THEN -2147483648 -- Could not find a function returning the smallest real yet - WHEN pixeltype = '64BF' THEN -2147483648 -- Could not find a function returning the smallest float8 yet - END; - RETURN newval; - END; - $$ - LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION st_minpossiblevalue(pixeltype text) + RETURNS double precision + AS 'MODULE_PATHNAME', 'RASTER_minPossibleValue' + LANGUAGE 'C' IMMUTABLE STRICT; ----------------------------------------------------------------------- -- Raster Outputs @@ -3526,7 +3508,7 @@ CREATE OR REPLACE FUNCTION ST_Clip(rast raster, band int, geom geometry, nodata bandend := band; END IF; newpixtype := ST_BandPixelType(rast, bandstart); - newnodata := coalesce(nodata, ST_BandNodataValue(rast, bandstart), ST_MinPossibleVal(newpixtype)); + newnodata := coalesce(nodata, ST_BandNodataValue(rast, bandstart), ST_MinPossibleValue(newpixtype)); newextent := CASE WHEN trimraster THEN 'INTERSECTION' ELSE 'FIRST' END; --RAISE NOTICE 'newextent=%', newextent; @@ -3543,7 +3525,7 @@ CREATE OR REPLACE FUNCTION ST_Clip(rast raster, band int, geom geometry, nodata --RAISE NOTICE 'bandi=%', bandi; -- for each band we must determine the nodata value newpixtype := ST_BandPixelType(rast, bandi); - newnodata := coalesce(nodata, ST_BandNodataValue(sourceraster, bandi), ST_MinPossibleVal(newpixtype)); + newnodata := coalesce(nodata, ST_BandNodataValue(sourceraster, bandi), ST_MinPossibleValue(newpixtype)); sourceraster := ST_SetBandNodataValue(sourceraster, bandi, newnodata); newrast := ST_AddBand(newrast, ST_MapAlgebraExpr(sourceraster, bandi, geomrast, 1, 'rast1', newpixtype, newextent)); END LOOP; diff --git a/raster/rt_pg/rtpostgis_drop.sql.in.c b/raster/rt_pg/rtpostgis_drop.sql.in.c index aec8add36..6413854e5 100644 --- a/raster/rt_pg/rtpostgis_drop.sql.in.c +++ b/raster/rt_pg/rtpostgis_drop.sql.in.c @@ -330,3 +330,6 @@ DROP FUNCTION IF EXISTS st_intersects(raster, raster); -- functions have changed dramatically DROP FUNCTION IF EXISTS st_intersection(rast raster, band integer, geom geometry); DROP FUNCTION IF EXISTS st_intersection(rast raster, geom geometry); + +-- function was renamed +DROP FUNCTION IF EXISTS st_minpossibleval(text); diff --git a/raster/scripts/plpgsql/st_clip.sql b/raster/scripts/plpgsql/st_clip.sql index 056ef5639..1c68c810e 100644 --- a/raster/scripts/plpgsql/st_clip.sql +++ b/raster/scripts/plpgsql/st_clip.sql @@ -79,7 +79,7 @@ CREATE OR REPLACE FUNCTION ST_Clip(rast raster, band int, geom geometry, nodata bandend := band; END IF; newpixtype := ST_BandPixelType(rast, bandstart); - newnodata := coalesce(nodata, ST_BandNodataValue(rast, bandstart), ST_MinPossibleVal(newpixtype)); + newnodata := coalesce(nodata, ST_BandNodataValue(rast, bandstart), ST_MinPossibleValue(newpixtype)); newextent := CASE WHEN trimraster THEN 'INTERSECTION' ELSE 'FIRST' END; --RAISE NOTICE 'newextent=%', newextent; @@ -96,7 +96,7 @@ CREATE OR REPLACE FUNCTION ST_Clip(rast raster, band int, geom geometry, nodata --RAISE NOTICE 'bandi=%', bandi; -- for each band we must determine the nodata value newpixtype := ST_BandPixelType(rast, bandi); - newnodata := coalesce(nodata, ST_BandNodataValue(sourceraster, bandi), ST_MinPossibleVal(newpixtype)); + newnodata := coalesce(nodata, ST_BandNodataValue(sourceraster, bandi), ST_MinPossibleValue(newpixtype)); sourceraster := ST_SetBandNodataValue(sourceraster, bandi, newnodata); newrast := ST_AddBand(newrast, ST_MapAlgebraExpr(sourceraster, bandi, geomrast, 1, 'rast1', newpixtype, newextent)); END LOOP; diff --git a/raster/scripts/plpgsql/st_mapalgebra.sql b/raster/scripts/plpgsql/st_mapalgebra.sql index 358ce4173..9369e2129 100644 --- a/raster/scripts/plpgsql/st_mapalgebra.sql +++ b/raster/scripts/plpgsql/st_mapalgebra.sql @@ -82,12 +82,12 @@ CREATE OR REPLACE FUNCTION ST_MapAlgebra(rast raster, band integer, expression t -- Check for notada value newnodatavalue := ST_BandNodataValue(rast, band); - IF newnodatavalue IS NULL OR newnodatavalue < ST_MinPossibleVal(newpixeltype) OR newnodatavalue > (-ST_MinPossibleVal(newpixeltype) - 1) THEN + IF newnodatavalue IS NULL OR newnodatavalue < ST_MinPossibleValue(newpixeltype) OR newnodatavalue > (-ST_MinPossibleValue(newpixeltype) - 1) THEN RAISE NOTICE 'ST_MapAlgebra: Source raster do not have a nodata value or is out of range for the new raster pixeltype, nodata value for new raster set to the min value possible'; - newnodatavalue := ST_MinPossibleVal(newpixeltype); + newnodatavalue := ST_MinPossibleValue(newpixeltype); END IF; -- We set the initial value of the future band to nodata value. - -- If nodatavalue is null then the raster will be initialise to ST_MinPossibleVal + -- If nodatavalue is null then the raster will be initialise to ST_MinPossibleValue -- but all the values should be recomputed anyway. newinitialvalue := newnodatavalue; @@ -758,7 +758,7 @@ CREATE OR REPLACE FUNCTION ST_MapAlgebra(rast1 raster, newnodatavalue := rast2nodataval; ELSE RAISE NOTICE 'ST_MapAlgebra: Both source rasters do not have a nodata value, nodata value for new raster set to the minimum value possible'; - newnodatavalue := ST_MinPossibleVal(newrast); + newnodatavalue := ST_MinPossibleValue(newrast); END IF; ------------------------------------------------------------------- diff --git a/raster/scripts/plpgsql/st_mapalgebra_optimized.sql b/raster/scripts/plpgsql/st_mapalgebra_optimized.sql index 9b72a188a..a1f4bef48 100644 --- a/raster/scripts/plpgsql/st_mapalgebra_optimized.sql +++ b/raster/scripts/plpgsql/st_mapalgebra_optimized.sql @@ -510,7 +510,7 @@ RAISE NOTICE 'ST_MapAlgebra2 000'; newnodatavalue := rast1nodataval; ELSE RAISE NOTICE 'ST_MapAlgebra: Both source rasters do not have a nodata value, nodata value for new raster set to the minimum value possible'; - newnodatavalue := ST_MinPossibleVal(newrast); + newnodatavalue := ST_MinPossibleValue(newrast); END IF; upnodatanodataexpr := upper(nodatanodataexpr); diff --git a/raster/scripts/plpgsql/st_mapalgebrafctngb.sql b/raster/scripts/plpgsql/st_mapalgebrafctngb.sql index 8d053b186..0e0599ee7 100644 --- a/raster/scripts/plpgsql/st_mapalgebrafctngb.sql +++ b/raster/scripts/plpgsql/st_mapalgebrafctngb.sql @@ -8,7 +8,7 @@ -- -- Helper method to get the smallest value in a raster, based on the pixeltype. -- -CREATE OR REPLACE FUNCTION ST_MinPossibleVal(pixeltype text) +CREATE OR REPLACE FUNCTION ST_MinPossibleValue(pixeltype text) RETURNS float8 AS $$ DECLARE @@ -114,13 +114,13 @@ CREATE OR REPLACE FUNCTION ST_MapAlgebraFctNgb(rast raster, band integer, pixelt -- Check for notada value newnodatavalue := ST_BandNodataValue(rast, band); - IF newnodatavalue IS NULL OR newnodatavalue < ST_MinPossibleVal(newpixeltype) OR newnodatavalue > (-ST_MinPossibleVal(newpixeltype) - 1) THEN + IF newnodatavalue IS NULL OR newnodatavalue < ST_MinPossibleValue(newpixeltype) OR newnodatavalue > (-ST_MinPossibleValue(newpixeltype) - 1) THEN RAISE NOTICE 'ST_MapAlgebraFctNgb: Source raster does not have a nodata value or is out of range for the new raster pixeltype, nodata value for new raster set to the min value possible'; - newnodatavalue := ST_MinPossibleVal(newpixeltype); + newnodatavalue := ST_MinPossibleValue(newpixeltype); END IF; -- We set the initial value of the future band to nodata value. - -- If nodatavalue is null then the raster will be initialise to ST_MinPossibleVal + -- If nodatavalue is null then the raster will be initialise to ST_MinPossibleValue -- but all the values should be recomputed anyway. newinitialvalue := newnodatavalue; diff --git a/raster/scripts/plpgsql/st_minpossibleval.sql b/raster/scripts/plpgsql/st_minpossibleval.sql deleted file mode 100644 index 5af03a507..000000000 --- a/raster/scripts/plpgsql/st_minpossibleval.sql +++ /dev/null @@ -1,29 +0,0 @@ ------------------------------------------------------------------------ --- ST_MinPossibleVal --- Return the smallest value for a given pixeltyp. --- Should be called like this: --- SELECT ST_MinPossibleVal(ST_BandPixelType(rast, band)) ------------------------------------------------------------------------ -CREATE OR REPLACE FUNCTION ST_MinPossibleVal(pixeltype text) - RETURNS float8 AS - $$ - DECLARE - newval int := 0; - BEGIN - newval := CASE - WHEN pixeltype = '1BB' THEN 0 - WHEN pixeltype = '2BUI' THEN 0 - WHEN pixeltype = '4BUI' THEN 0 - WHEN pixeltype = '8BUI' THEN 0 - WHEN pixeltype = '8BSI' THEN -128 - WHEN pixeltype = '16BUI' THEN 0 - WHEN pixeltype = '16BSI' THEN -32768 - WHEN pixeltype = '32BUI' THEN 0 - WHEN pixeltype = '32BSI' THEN -2147483648 - WHEN pixeltype = '32BF' THEN -2147483648 -- Could not find a function returning the smallest real yet - WHEN pixeltype = '64BF' THEN -2147483648 -- Could not find a function returning the smallest float8 yet - END; - RETURN newval; - END; - $$ - LANGUAGE 'plpgsql'; diff --git a/raster/test/regress/rt_utility.sql b/raster/test/regress/rt_utility.sql index 646f9fe94..d8edb8283 100644 --- a/raster/test/regress/rt_utility.sql +++ b/raster/test/regress/rt_utility.sql @@ -238,3 +238,18 @@ SELECT 'test 10.3', id, name FROM rt_utility_test WHERE st_raster2worldcoordy(rast, 1)::numeric != ipy::numeric; +----------------------------------------------------------------------- +-- Test 11 - st_minpossiblevalue(pixtype text) +----------------------------------------------------------------------- + +SELECT 'test 11.1', st_minpossiblevalue('1BB') = 0.; +SELECT 'test 11.2', st_minpossiblevalue('2BUI') = 0.; +SELECT 'test 11.3', st_minpossiblevalue('4BUI') = 0.; +SELECT 'test 11.4', st_minpossiblevalue('8BUI') = 0.; +SELECT 'test 11.5', st_minpossiblevalue('8BSI') < 0.; +SELECT 'test 11.6', st_minpossiblevalue('16BUI') = 0.; +SELECT 'test 11.7', st_minpossiblevalue('16BSI') < 0.; +SELECT 'test 11.8', st_minpossiblevalue('32BUI') = 0.; +SELECT 'test 11.9', st_minpossiblevalue('32BSI') < 0.; +SELECT 'test 11.10', st_minpossiblevalue('32BF') < 0.; +SELECT 'test 11.11', st_minpossiblevalue('64BF') < 0.; diff --git a/raster/test/regress/rt_utility_expected b/raster/test/regress/rt_utility_expected index 7c9f61ff0..b9d96bd4e 100644 --- a/raster/test/regress/rt_utility_expected +++ b/raster/test/regress/rt_utility_expected @@ -2,3 +2,14 @@ ERROR: Attempting to compute raster coordinate on a raster with rotation provid ERROR: Attempting to compute raster coordinate on a raster with rotation providing y only. A x must also be provided ERROR: Attempting to compute raster coordinates on a raster with rotation providing X only. A Y coordinate must also be provided ERROR: Attempting to compute raster coordinates on a raster with rotation providing Y only. An X coordinate must also be provided +test 11.1|t +test 11.2|t +test 11.3|t +test 11.4|t +test 11.5|t +test 11.6|t +test 11.7|t +test 11.8|t +test 11.9|t +test 11.10|t +test 11.11|t