Commit 52189516 authored by Bborie Park's avatar Bborie Park

code and tests for ST_Grayscale

git-svn-id: http://svn.osgeo.org/postgis/trunk@16206 b70326c6-7e19-0410-871a-916f4a2858ee
parent 99aab843
......@@ -4786,6 +4786,7 @@ CREATE OR REPLACE FUNCTION st_tri(
-----------------------------------------------------------------------
-- ST_Grayscale
-- Equation from algorithm section of https://www.mathworks.com/help/matlab/ref/rgb2gray.html
-----------------------------------------------------------------------
-- Availability: 2.5.0
......@@ -4799,9 +4800,10 @@ CREATE OR REPLACE FUNCTION _st_grayscale4ma(value double precision[][][], pos in
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,28 +4818,122 @@ CREATE OR REPLACE FUNCTION _st_grayscale4ma(value double precision[][][], pos in
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;
FOR idx IN 1.._NBANDS LOOP
rast := _set[idx].rast;
nband := _set[idx].nband;
-- check that each raster has the specified band
IF @extschema@.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@.ST_BandPixelType(rast, nband) != _PIXTYPE THEN
stats := @extschema@.ST_SummaryStats(rast, nband);
nodata := @extschema@.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@.ST_Reclass(
rast,
ROW(nband, reclassexpr, _PIXTYPE, nodataval)::reclassarg
),
nband
)::rastbandarg;
END IF;
-- check that each band is 8BUI. if not, reclassify to 8BUI
END LOOP;
-- call map algebra with _st_grayscale4ma
RETURN @extschema@.ST_MapAlgebra(
rast,
ARRAY[redband, blueband, greenband],
'@extschema@._ST_Grayscale4MA(double precision[][][], integer[][], text[])'::regprocedure,,
'8BUI'
_set,
'@extschema@._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@.ST_Grayscale(
ARRAY[
ROW(rast, redband)::rastbandarg,
ROW(rast, greenband)::rastbandarg,
ROW(rast, blueband)::rastbandarg
]::rastbandarg[],
extenttype
);
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE _PARALLEL;
......@@ -6078,9 +6174,8 @@ CREATE OR REPLACE FUNCTION _st_samealignment_transfn(agg agg_samealignment, rast
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;
......
......@@ -129,7 +129,8 @@ TEST_MAPALGEBRA = \
rt_4ma \
rt_setvalues_geomval \
rt_elevation_functions \
rt_colormap
rt_colormap \
rt_grayscale
TEST_SREL = \
rt_gist_relationships \
......
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;
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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment