- #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
</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>
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
-----------------------------------------------------------------------
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
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