]> granicus.if.org Git - postgis/commitdiff
Added ST_Resize(raster) to resize a raster using desired width/height.
authorBborie Park <bkpark at ucdavis.edu>
Sat, 1 Dec 2012 01:19:53 +0000 (01:19 +0000)
committerBborie Park <bkpark at ucdavis.edu>
Sat, 1 Dec 2012 01:19:53 +0000 (01:19 +0000)
Ticket #1293.

git-svn-id: http://svn.osgeo.org/postgis/trunk@10774 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
doc/reference_raster.xml
raster/rt_pg/rtpostgis.sql.in.c
raster/test/regress/rt_gdalwarp.sql
raster/test/regress/rt_gdalwarp_expected

diff --git a/NEWS b/NEWS
index f5e061d8b668c18d90cbd5940cb8eade2f4b0c88..1015258d884764d78065f389e3ab1d90719e9103 100644 (file)
--- 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 
index bea84ed8f2fd8b379d0a32b7575532541844c5d1..7936e4484343dc0183493b7a01e09bc1699823b6 100644 (file)
@@ -5762,6 +5762,124 @@ SELECT ST_UpperLeftX(ST_SnapToGrid(ST_AddBand(ST_MakeEmptyRaster(10, 10, 0, 0, 0
                        </refsection>
                </refentry>
                
+               <refentry id="RT_ST_Resize">
+                       <refnamediv>
+                               <refname>ST_Resize</refname>
+                               <refpurpose>Resize a raster to a new width/height</refpurpose>
+                       </refnamediv>
+               
+                       <refsynopsisdiv>
+                               <funcsynopsis>
+                                 <funcprototype>
+                                               <funcdef>raster <function>ST_Resize</function></funcdef>
+                                               <paramdef><type>raster </type> <parameter>rast</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>width</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>height</parameter></paramdef>
+                                               <paramdef choice="opt"><type>text </type> <parameter>algorithm=NearestNeighbor</parameter></paramdef>
+                                               <paramdef choice="opt"><type>double precision </type> <parameter>maxerr=0.125</parameter></paramdef>
+                                 </funcprototype>
+
+                                 <funcprototype>
+                                               <funcdef>raster <function>ST_Resize</function></funcdef>
+                                               <paramdef><type>raster </type> <parameter>rast</parameter></paramdef>
+                                               <paramdef><type>double precision </type> <parameter>percentwidth</parameter></paramdef>
+                                               <paramdef><type>double precision </type> <parameter>percentheight</parameter></paramdef>
+                                               <paramdef choice="opt"><type>text </type> <parameter>algorithm=NearestNeighbor</parameter></paramdef>
+                                               <paramdef choice="opt"><type>double precision </type> <parameter>maxerr=0.125</parameter></paramdef>
+                                 </funcprototype>
+
+                                 <funcprototype>
+                                               <funcdef>raster <function>ST_Resize</function></funcdef>
+                                               <paramdef><type>raster </type> <parameter>rast</parameter></paramdef>
+                                               <paramdef><type>text </type> <parameter>width</parameter></paramdef>
+                                               <paramdef><type>text </type> <parameter>height</parameter></paramdef>
+                                               <paramdef choice="opt"><type>text </type> <parameter>algorithm=NearestNeighbor</parameter></paramdef>
+                                               <paramdef choice="opt"><type>double precision </type> <parameter>maxerr=0.125</parameter></paramdef>
+                                 </funcprototype>
+
+                               </funcsynopsis>
+                       </refsynopsisdiv>
+
+                       <refsection>
+                               <title>Description</title>
+
+                               <para>
+                                       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.
+                               </para>
+
+                               <para>
+                                       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.
+                               </para>
+
+                               <para>
+                                       Variant 1 expects the actual width/height of the output raster.
+                               </para>
+
+                               <para>
+                                       Variant 2 expects decimal values between zero (0) and one (1) indicating the percentage of the input raster's width/height.
+                               </para>
+
+                               <para>
+                                       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.
+                               </para>
+
+                               <para>Availability: 2.1.0  Requires GDAL 1.6.1+</para>
+                       </refsection>
+                       <refsection>
+                               <title>Examples</title>
+                               <programlisting>
+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)
+                               </programlisting>
+                       </refsection>
+
+                       <refsection>
+                               <title>See Also</title>
+                               <para>
+                                       <xref linkend="RT_ST_Resample" />, 
+                                       <xref linkend="RT_ST_Rescale" />, 
+                                       <xref linkend="RT_ST_Reskew" />, 
+                                       <xref linkend="RT_ST_SnapToGrid" />
+                               </para>
+                       </refsection>
+               </refentry>
+
                <refentry id="RT_ST_Transform">
                        <refnamediv>
                                <refname>ST_Transform</refname>
index b3afaf9541a04f82c232b54997935433717bddcb..fea9c72b781460629a5d11f55be8583f830e8af3 100644 (file)
@@ -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
 -----------------------------------------------------------------------
index 76593ee06efb8233809b3ef3e4a53b367e792f26..09477c89badc5ef510cf4f118dde37d73eed50d8 100644 (file)
@@ -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
index 9ce521b093a1fc59191c496efd069c681e10da63..75ba9623a473547b60525e6564bce7d15f0fc0c0 100644 (file)
@@ -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