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
This commit is contained in:
Bborie Park 2011-12-16 01:11:21 +00:00
parent b87956b7d3
commit 7edd2ae967
10 changed files with 93 additions and 67 deletions

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;
-------------------------------------------------------------------

View file

@ -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);

View file

@ -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;

View file

@ -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';

View file

@ -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.;

View file

@ -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