[postgis-tickets] r16206 - code and tests for ST_Grayscale
Bborie Park
dustymugs at dspiral.net
Mon Jan 1 05:02:27 PST 2018
Author: dustymugs
Date: 2018-01-01 17:02:27 -0800 (Mon, 01 Jan 2018)
New Revision: 16206
Added:
trunk/raster/test/regress/rt_grayscale.sql
trunk/raster/test/regress/rt_grayscale_expected
Modified:
trunk/raster/rt_pg/rtpostgis.sql.in
trunk/raster/test/regress/Makefile.in
Log:
code and tests for ST_Grayscale
Modified: trunk/raster/rt_pg/rtpostgis.sql.in
===================================================================
--- trunk/raster/rt_pg/rtpostgis.sql.in 2018-01-02 01:02:23 UTC (rev 16205)
+++ trunk/raster/rt_pg/rtpostgis.sql.in 2018-01-02 01:02:27 UTC (rev 16206)
@@ -4786,6 +4786,7 @@
-----------------------------------------------------------------------
-- ST_Grayscale
+-- Equation from algorithm section of https://www.mathworks.com/help/matlab/ref/rgb2gray.html
-----------------------------------------------------------------------
-- Availability: 2.5.0
@@ -4799,9 +4800,10 @@
red double precision;
green double precision;
blue double precision;
+
+ gray double precision;
BEGIN
- RAISE NOTICE 'value = %', value;
ndims := array_ndims(value);
-- add a third dimension if 2-dimension
IF ndims = 2 THEN
@@ -4816,31 +4818,125 @@
green := _value[2][1][1];
blue := _value[3][1][1];
- RETURN 0.2989 * red + 0.5870 * green + 0.1140 * blue;
+ gray = round(0.2989 * red + 0.5870 * green + 0.1140 * blue);
+ RETURN gray;
+
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE _PARALLEL;
-- Availability: 2.5.0
-CREATE OR REPLACE FUNCTION st_grayscale(rast raster, redband integer DEFAULT 1, blueband DEFAULT 2, greenband DEFAULT 3)
+CREATE OR REPLACE FUNCTION st_grayscale(
+ rastbandargset rastbandarg[],
+ extenttype text DEFAULT 'INTERSECTION'
+)
RETURNS RASTER
AS $$
DECLARE
+
+ _NBANDS integer DEFAULT 3;
+ _NODATA integer DEFAULT 255;
+ _PIXTYPE text DEFAULT '8BUI';
+
+ _set rastbandarg[];
+
+ nrast integer;
+ idx integer;
+ rast raster;
+ nband integer;
+
+ stats summarystats;
+ nodata double precision;
+ nodataval integer;
+ reclassexpr text;
+
BEGIN
- -- check that each band index is found in raster
+ -- check for three rastbandarg
+ nrast := array_length(rastbandargset, 1);
+ IF nrast < _NBANDS THEN
+ RAISE EXCEPTION '''rastbandargset'' must have three bands for red, green and blue';
+ ELSIF nrast > _NBANDS THEN
+ RAISE WARNING 'Only the first three elements of ''rastbandargset'' will be used';
+ _set := rastbandargset[1:3];
+ ELSE
+ _set := rastbandargset;
+ END IF;
- -- check that each band is 8BUI. if not, reclassify to 8BUI
+ FOR idx IN 1.._NBANDS LOOP
+ rast := _set[idx].rast;
+ nband := _set[idx].nband;
+
+ -- check that each raster has the specified band
+ IF @extschema at .ST_HasNoBand(rast, nband) THEN
+
+ RAISE EXCEPTION 'Band at index ''%'' not found for raster ''%''', nband, idx;
+
+ -- check that each band is 8BUI. if not, reclassify to 8BUI
+ ELSIF @extschema at .ST_BandPixelType(rast, nband) != _PIXTYPE THEN
+
+ stats := @extschema at .ST_SummaryStats(rast, nband);
+ nodata := @extschema at .ST_BandNoDataValue(rast, nband);
+
+ IF nodata IS NOT NULL THEN
+ nodataval := _NODATA;
+ reclassexpr := concat(
+ concat('[', nodata , '-', nodata, ']:', _NODATA, '-', _NODATA, ','),
+ concat('[', stats.min , '-', stats.max , ']:0-', _NODATA - 1)
+ );
+ ELSE
+ nodataval := NULL;
+ reclassexpr := concat('[', stats.min , '-', stats.max , ']:0-', _NODATA);
+ END IF;
+
+ _set[idx] := ROW(
+ @extschema at .ST_Reclass(
+ rast,
+ ROW(nband, reclassexpr, _PIXTYPE, nodataval)::reclassarg
+ ),
+ nband
+ )::rastbandarg;
+
+ END IF;
+
+ END LOOP;
+
-- call map algebra with _st_grayscale4ma
RETURN @extschema at .ST_MapAlgebra(
- rast,
- ARRAY[redband, blueband, greenband],
- '@extschema at ._ST_Grayscale4MA(double precision[][][], integer[][], text[])'::regprocedure,,
- '8BUI'
+ _set,
+ '@extschema at ._ST_Grayscale4MA(double precision[][][], integer[][], text[])'::regprocedure,
+ '8BUI',
+ extenttype
);
+
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE _PARALLEL;
+-- Availability: 2.5.0
+CREATE OR REPLACE FUNCTION st_grayscale(
+ rast raster,
+ redband integer DEFAULT 1,
+ greenband integer DEFAULT 2,
+ blueband integer DEFAULT 3,
+ extenttype text DEFAULT 'INTERSECTION'
+)
+ RETURNS RASTER
+ AS $$
+ DECLARE
+ BEGIN
+
+ RETURN @extschema at .ST_Grayscale(
+ ARRAY[
+ ROW(rast, redband)::rastbandarg,
+ ROW(rast, greenband)::rastbandarg,
+ ROW(rast, blueband)::rastbandarg
+ ]::rastbandarg[],
+ extenttype
+ );
+
+ END;
+ $$ LANGUAGE 'plpgsql' IMMUTABLE _PARALLEL;
+
-----------------------------------------------------------------------
-- Get information about the raster
-----------------------------------------------------------------------
@@ -6078,9 +6174,8 @@
m := ST_Metadata(rast);
agg.refraster := ST_MakeEmptyRaster(1, 1, m.upperleftx, m.upperlefty, m.scalex, m.scaley, m.skewx, m.skewy, m.srid);
agg.aligned := TRUE;
- ELSE IF agg.aligned IS TRUE THEN
- agg.aligned := ST_SameAlignment(agg.refraster, rast);
- END IF;
+ ELSIF agg.aligned IS TRUE THEN
+ agg.aligned := ST_SameAlignment(agg.refraster, rast);
END IF;
END IF;
RETURN agg;
Modified: trunk/raster/test/regress/Makefile.in
===================================================================
--- trunk/raster/test/regress/Makefile.in 2018-01-02 01:02:23 UTC (rev 16205)
+++ trunk/raster/test/regress/Makefile.in 2018-01-02 01:02:27 UTC (rev 16206)
@@ -129,7 +129,8 @@
rt_4ma \
rt_setvalues_geomval \
rt_elevation_functions \
- rt_colormap
+ rt_colormap \
+ rt_grayscale
TEST_SREL = \
rt_gist_relationships \
Added: trunk/raster/test/regress/rt_grayscale.sql
===================================================================
--- trunk/raster/test/regress/rt_grayscale.sql (rev 0)
+++ trunk/raster/test/regress/rt_grayscale.sql 2018-01-02 01:02:27 UTC (rev 16206)
@@ -0,0 +1,166 @@
+SET client_min_messages = NOTICE;
+DROP TABLE IF EXISTS raster_grayscale_out;
+CREATE TABLE raster_grayscale_out (
+ testid integer,
+ rid integer,
+ rast raster
+);
+DROP TABLE IF EXISTS raster_grayscale_in;
+CREATE TABLE raster_grayscale_in (
+ rid integer,
+ rast raster
+);
+
+INSERT INTO raster_grayscale_in
+SELECT
+ 1 AS rid,
+ ST_SetValues(
+ ST_AddBand(
+ ST_MakeEmptyRaster(2, 2, 0, 0, 1, -1, 0, 0, 0),
+ 1, '8BUI', 0, NULL
+ ),
+ 1, 1, 1, ARRAY[
+ [ 0, 128],
+ [ 254, 255]
+ ]::double precision[]
+ ) AS rast
+UNION ALL
+SELECT
+ 2 AS rid,
+ ST_SetValues(
+ ST_AddBand(
+ ST_MakeEmptyRaster(2, 2, 0, 0, 1, -1, 0, 0, 0),
+ 1, '8BSI', 0, NULL
+ ),
+ 1, 1, 1, ARRAY[
+ [ -128, 0],
+ [ 126, 127]
+ ]::double precision[]
+ ) AS rast
+UNION ALL
+SELECT
+ 3 AS rid,
+ ST_SetValues(
+ ST_AddBand(
+ ST_MakeEmptyRaster(2, 2, 0, 0, 1, -1, 0, 0, 0),
+ 1, '16BUI', 0, 0
+ ),
+ 1, 1, 1, ARRAY[
+ [ 0, 32768],
+ [ 65534, 65535]
+ ]::double precision[]
+ ) AS rast
+UNION ALL
+SELECT
+ 4 AS rid,
+ ST_SetValues(
+ ST_AddBand(
+ ST_MakeEmptyRaster(2, 2, 0, 0, 1, -1, 0, 0, 0),
+ 1, '16BSI', 0, -32768
+ ),
+ 1, 1, 1, ARRAY[
+ [ -32768, -32767],
+ [ 32766, 32767]
+ ]::double precision[]
+ ) AS rast
+UNION ALL
+SELECT
+ 5 AS rid,
+ ST_SetValues(
+ ST_AddBand(
+ ST_MakeEmptyRaster(2, 3, 0, 0, 1, -1, 0, 0, 0),
+ 1, '16BSI', 0, NULL
+ ),
+ 1, 1, 1, ARRAY[
+ [ -32768, -32767],
+ [ 0, 0],
+ [ 32766, 32767]
+ ]::double precision[]
+ ) AS rast
+;
+
+INSERT INTO raster_grayscale_out
+SELECT
+ 1,
+ rid,
+ ST_Grayscale(
+ rast,
+ 1,
+ 1,
+ 1
+ )
+FROM raster_grayscale_in
+UNION ALL
+SELECT
+ 2,
+ rid,
+ ST_Grayscale(
+ ARRAY[
+ ROW(rast, 1)::rastbandarg,
+ ROW(rast, 1)::rastbandarg,
+ ROW(rast, 1)::rastbandarg
+ ]::rastbandarg[]
+ )
+FROM raster_grayscale_in
+UNION ALL
+SELECT
+ 3,
+ rid,
+ ST_Grayscale(
+ ARRAY[
+ ROW(rast, 1)::rastbandarg,
+ ROW(rast, 1)::rastbandarg,
+ ROW(rast, 1)::rastbandarg,
+ ROW(rast, 1)::rastbandarg
+ ]::rastbandarg[]
+ )
+FROM raster_grayscale_in
+ORDER BY rid
+;
+
+SELECT
+ testid,
+ rid,
+ (ST_DumpValues(rast)).*
+FROM raster_grayscale_out
+ORDER BY 1, 2, nband;
+
+-- error because of insufficient bands
+BEGIN;
+SELECT
+ ST_Grayscale(
+ ARRAY[
+ ROW(rast, 1)::rastbandarg
+ ]::rastbandarg[]
+ )
+FROM raster_grayscale_in
+ORDER BY rid
+LIMIT 1;
+ROLLBACK;
+
+-- error because of no band at index
+BEGIN;
+SELECT
+ ST_Grayscale(rast)
+FROM raster_grayscale_in
+ORDER BY rid
+LIMIT 1;
+ROLLBACK;
+
+-- error because of no band at index
+BEGIN;
+SELECT
+ ST_Grayscale(
+ ARRAY[
+ ROW(rast, 1)::rastbandarg,
+ ROW(rast, 2)::rastbandarg,
+ ROW(rast, 1)::rastbandarg
+ ]::rastbandarg[]
+ )
+FROM raster_grayscale_in
+ORDER BY rid
+LIMIT 1;
+ROLLBACK;
+
+DROP TABLE IF EXISTS raster_grayscale_in;
+DROP TABLE IF EXISTS raster_grayscale_out;
Added: trunk/raster/test/regress/rt_grayscale_expected
===================================================================
--- trunk/raster/test/regress/rt_grayscale_expected (rev 0)
+++ trunk/raster/test/regress/rt_grayscale_expected 2018-01-02 01:02:27 UTC (rev 16206)
@@ -0,0 +1,31 @@
+NOTICE: table "raster_grayscale_out" does not exist, skipping
+NOTICE: table "raster_grayscale_in" does not exist, skipping
+WARNING: Only the first three elements of 'rastbandargset' will be used
+WARNING: Only the first three elements of 'rastbandargset' will be used
+WARNING: Only the first three elements of 'rastbandargset' will be used
+WARNING: Only the first three elements of 'rastbandargset' will be used
+WARNING: Only the first three elements of 'rastbandargset' will be used
+1|1|1|{{NULL,128},{254,255}}
+1|2|1|{{NULL,128},{254,255}}
+1|3|1|{{NULL,0},{254,254}}
+1|4|1|{{NULL,0},{254,254}}
+1|5|1|{{NULL,NULL},{128,128},{255,255}}
+2|1|1|{{NULL,128},{254,255}}
+2|2|1|{{NULL,128},{254,255}}
+2|3|1|{{NULL,0},{254,254}}
+2|4|1|{{NULL,0},{254,254}}
+2|5|1|{{NULL,NULL},{128,128},{255,255}}
+3|1|1|{{NULL,128},{254,255}}
+3|2|1|{{NULL,128},{254,255}}
+3|3|1|{{NULL,0},{254,254}}
+3|4|1|{{NULL,0},{254,254}}
+3|5|1|{{NULL,NULL},{128,128},{255,255}}
+BEGIN
+ERROR: 'rastbandargset' must have three bands for red, green and blue
+COMMIT
+BEGIN
+ERROR: Band at index '2' not found for raster '2'
+COMMIT
+BEGIN
+ERROR: Band at index '2' not found for raster '2'
+COMMIT
More information about the postgis-tickets
mailing list