From: Bborie Park Date: Sat, 1 Dec 2012 01:19:53 +0000 (+0000) Subject: Added ST_Resize(raster) to resize a raster using desired width/height. X-Git-Tag: 2.1.0beta2~336 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=249b501069b73b142ca0be4884d98d0065338d34;p=postgis Added ST_Resize(raster) to resize a raster using desired width/height. Ticket #1293. git-svn-id: http://svn.osgeo.org/postgis/trunk@10774 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/NEWS b/NEWS index f5e061d8b..1015258d8 100644 --- a/NEWS +++ b/NEWS @@ -56,6 +56,7 @@ PostGIS 2.1.0 - #739, UpdateRasterSRID() - #1895, new r-tree node splitting algorithm (Alex Korotkov) - #1709, ST_NotSameAlignmentReason(raster, raster) + - #1293, ST_Resize(raster) to resize rasters based upon width/height * Enhancements * - #823, tiger geocoder: Make loader_generate_script download portion diff --git a/doc/reference_raster.xml b/doc/reference_raster.xml index bea84ed8f..7936e4484 100644 --- a/doc/reference_raster.xml +++ b/doc/reference_raster.xml @@ -5762,6 +5762,124 @@ SELECT ST_UpperLeftX(ST_SnapToGrid(ST_AddBand(ST_MakeEmptyRaster(10, 10, 0, 0, 0 + + + ST_Resize + Resize a raster to a new width/height + + + + + + raster ST_Resize + raster rast + integer width + integer height + text algorithm=NearestNeighbor + double precision maxerr=0.125 + + + + raster ST_Resize + raster rast + double precision percentwidth + double precision percentheight + text algorithm=NearestNeighbor + double precision maxerr=0.125 + + + + raster ST_Resize + raster rast + text width + text height + text algorithm=NearestNeighbor + double precision maxerr=0.125 + + + + + + + Description + + + Resize a raster to a new width/height. The new width/height can be specified in exact number of pixels or a percentage of the raster's width/height. + + + + New pixel values are computed using the NearestNeighbor (english or american spelling), Bilinear, Cubic, CubicSpline or Lanczos resampling algorithm. The default is NearestNeighbor which is the fastest but results in the worst interpolation. + + + + Variant 1 expects the actual width/height of the output raster. + + + + Variant 2 expects decimal values between zero (0) and one (1) indicating the percentage of the input raster's width/height. + + + + Variant 3 takes either the actual width/height of the output raster or a textual percentage ("20%") indicating the percentage of the input raster's width/height. + + + Availability: 2.1.0 Requires GDAL 1.6.1+ + + + Examples + +WITH foo AS( +SELECT + 1 AS rid, + ST_Resize( + ST_AddBand( + ST_MakeEmptyRaster(1000, 1000, 0, 0, 1, -1, 0, 0, 0) + , 1, '8BUI', 255, 0 + ) + , '50%', '500') AS rast +UNION ALL +SELECT + 2 AS rid, + ST_Resize( + ST_AddBand( + ST_MakeEmptyRaster(1000, 1000, 0, 0, 1, -1, 0, 0, 0) + , 1, '8BUI', 255, 0 + ) + , 500, 100) AS rast +UNION ALL +SELECT + 3 AS rid, + ST_Resize( + ST_AddBand( + ST_MakeEmptyRaster(1000, 1000, 0, 0, 1, -1, 0, 0, 0) + , 1, '8BUI', 255, 0 + ) + , 0.25, 0.9) AS rast +), bar AS ( + SELECT rid, ST_Metadata(rast) AS meta, rast FROM foo +) +SELECT rid, (meta).* FROM bar + + rid | upperleftx | upperlefty | width | height | scalex | scaley | skewx | skewy | srid | numbands +-----+------------+------------+-------+--------+--------+--------+-------+-------+------+---------- + 1 | 0 | 0 | 500 | 500 | 1 | -1 | 0 | 0 | 0 | 1 + 2 | 0 | 0 | 500 | 100 | 1 | -1 | 0 | 0 | 0 | 1 + 3 | 0 | 0 | 250 | 900 | 1 | -1 | 0 | 0 | 0 | 1 +(3 rows) + + + + + See Also + + , + , + , + + + + + ST_Transform diff --git a/raster/rt_pg/rtpostgis.sql.in.c b/raster/rt_pg/rtpostgis.sql.in.c index b3afaf954..fea9c72b7 100644 --- a/raster/rt_pg/rtpostgis.sql.in.c +++ b/raster/rt_pg/rtpostgis.sql.in.c @@ -2167,6 +2167,140 @@ CREATE OR REPLACE FUNCTION st_snaptogrid( AS $$ SELECT _st_gdalwarp($1, $5, $6, NULL, $4, $4, $2, $3) $$ LANGUAGE 'sql' STABLE STRICT; +----------------------------------------------------------------------- +-- ST_Resize +----------------------------------------------------------------------- +CREATE OR REPLACE FUNCTION st_resize( + rast raster, + width text, height text, + algorithm text DEFAULT 'NearestNeighbour', maxerr double precision DEFAULT 0.125 +) + RETURNS raster + AS $$ + DECLARE + i integer; + + wh text[2]; + + whi integer[2]; + whd double precision[2]; + + _width integer; + _height integer; + BEGIN + wh[1] := trim(both from $2); + wh[2] := trim(both from $3); + + -- see if width and height are percentages + FOR i IN 1..2 LOOP + IF position('%' in wh[i]) > 0 THEN + BEGIN + wh[i] := (regexp_matches(wh[i], E'^(\\d*.?\\d*)%{1}$'))[1]; + IF length(wh[i]) < 1 THEN + RAISE invalid_parameter_value; + END IF; + + whd[i] := wh[i]::double precision * 0.01; + EXCEPTION WHEN OTHERS THEN + RAISE EXCEPTION 'Invalid percentage value provided for width/height'; + RETURN NULL; + END; + ELSE + BEGIN + whi[i] := abs(wh[i]::integer); + EXCEPTION WHEN OTHERS THEN + RAISE EXCEPTION 'Non-integer value provided for width/height'; + RETURN NULL; + END; + END IF; + END LOOP; + + IF whd[1] IS NOT NULL OR whd[2] IS NOT NULL THEN + SELECT foo.width, foo.height INTO _width, _height FROM ST_Metadata($1) AS foo; + + IF whd[1] IS NOT NULL THEN + whi[1] := round(_width::double precision * whd[1])::integer; + END IF; + + IF whd[2] IS NOT NULL THEN + whi[2] := round(_height::double precision * whd[2])::integer; + END IF; + + END IF; + + -- should NEVER be here + IF whi[1] IS NULL OR whi[2] IS NULL THEN + RAISE EXCEPTION 'Unable to determine appropriate width or height'; + RETURN NULL; + END IF; + + FOR i IN 1..2 LOOP + IF whi[i] < 1 THEN + whi[i] = 1; + END IF; + END LOOP; + + RETURN _st_gdalwarp( + $1, + $4, $5, + NULL, + NULL, NULL, + NULL, NULL, + NULL, NULL, + whi[1], whi[2] + ); + END; + $$ LANGUAGE 'plpgsql' STABLE STRICT; + +CREATE OR REPLACE FUNCTION st_resize( + rast raster, + width integer, height integer, + algorithm text DEFAULT 'NearestNeighbour', maxerr double precision DEFAULT 0.125 +) + RETURNS raster + AS $$ SELECT _st_gdalwarp($1, $4, $5, NULL, NULL, NULL, NULL, NULL, NULL, NULL, abs($2), abs($3)) $$ + LANGUAGE 'sql' STABLE STRICT; + +CREATE OR REPLACE FUNCTION st_resize( + rast raster, + percentwidth double precision, percentheight double precision, + algorithm text DEFAULT 'NearestNeighbour', maxerr double precision DEFAULT 0.125 +) + RETURNS raster + AS $$ + DECLARE + _width integer; + _height integer; + BEGIN + -- range check + IF $2 <= 0. OR $2 > 1. OR $3 <= 0. OR $3 > 1. THEN + RAISE EXCEPTION 'Percentages must be a value greater than zero and less than or equal to one, e.g. 0.5 for 50%'; + END IF; + + SELECT width, height INTO _width, _height FROM ST_Metadata($1); + + _width := round(_width::double precision * $2)::integer; + _height:= round(_height::double precision * $3)::integer; + + IF _width < 1 THEN + _width := 1; + END IF; + IF _height < 1 THEN + _height := 1; + END IF; + + RETURN _st_gdalwarp( + $1, + $4, $5, + NULL, + NULL, NULL, + NULL, NULL, + NULL, NULL, + _width, _height + ); + END; + $$ LANGUAGE 'plpgsql' STABLE STRICT; + ----------------------------------------------------------------------- -- One Raster ST_MapAlgebra ----------------------------------------------------------------------- diff --git a/raster/test/regress/rt_gdalwarp.sql b/raster/test/regress/rt_gdalwarp.sql index 76593ee06..09477c89b 100644 --- a/raster/test/regress/rt_gdalwarp.sql +++ b/raster/test/regress/rt_gdalwarp.sql @@ -805,3 +805,36 @@ DELETE FROM "spatial_ref_sys" WHERE srid = 993310; DELETE FROM "spatial_ref_sys" WHERE srid = 994269; DELETE FROM "spatial_ref_sys" WHERE srid = 984269; DELETE FROM "spatial_ref_sys" WHERE srid = 974269; + +-- ST_Resize() +WITH foo AS( +SELECT + 1 AS rid, + ST_Resize( + ST_AddBand( + ST_MakeEmptyRaster(1000, 1000, 0, 0, 1, -1, 0, 0, 0) + , 1, '8BUI', 255, 0 + ) + , '50%', '500') AS rast +UNION ALL +SELECT + 2 AS rid, + ST_Resize( + ST_AddBand( + ST_MakeEmptyRaster(1000, 1000, 0, 0, 1, -1, 0, 0, 0) + , 1, '8BUI', 255, 0 + ) + , 500, 100) AS rast +UNION ALL +SELECT + 3 AS rid, + ST_Resize( + ST_AddBand( + ST_MakeEmptyRaster(1000, 1000, 0, 0, 1, -1, 0, 0, 0) + , 1, '8BUI', 255, 0 + ) + , 0.25, 0.9) AS rast +), bar AS ( + SELECT rid, ST_Metadata(rast) AS meta, rast FROM foo +) +SELECT rid, (meta).* FROM bar diff --git a/raster/test/regress/rt_gdalwarp_expected b/raster/test/regress/rt_gdalwarp_expected index 9ce521b09..75ba9623a 100644 --- a/raster/test/regress/rt_gdalwarp_expected +++ b/raster/test/regress/rt_gdalwarp_expected @@ -130,3 +130,6 @@ NOTICE: The rasters are aligned NOTICE: The rasters are aligned NOTICE: The rasters are aligned t|f|t +1|0|0|500|500|1|-1|0|0|0|1 +2|0|0|500|100|1|-1|0|0|0|1 +3|0|0|250|900|1|-1|0|0|0|1