/* get raster's meta data */
Datum RASTER_metadata(PG_FUNCTION_ARGS);
+/* get raster band's meta data */
+Datum RASTER_bandmetadata(PG_FUNCTION_ARGS);
+
/* Replace function taken from
* http://ubuntuforums.org/showthread.php?s=aa6f015109fd7e4c7e30d2fd8b717497&t=141670&page=3
*/
* Get raster's meta data
*/
PG_FUNCTION_INFO_V1(RASTER_metadata);
-Datum RASTER_metadata(PG_FUNCTION_ARGS) {
+Datum RASTER_metadata(PG_FUNCTION_ARGS)
+{
rt_pgraster *pgraster = NULL;
rt_raster raster = NULL;
PG_RETURN_DATUM(result);
}
+/**
+ * Get raster band's meta data
+ */
+PG_FUNCTION_INFO_V1(RASTER_bandmetadata);
+Datum RASTER_bandmetadata(PG_FUNCTION_ARGS)
+{
+ rt_pgraster *pgraster = NULL;
+ rt_raster raster = NULL;
+ rt_band band = NULL;
+
+ TupleDesc tupdesc;
+ AttInMetadata *attinmeta;
+
+ uint32_t numBands;
+ uint32_t bandindex = 1;
+ const char *pixtypename = NULL;
+ bool hasnodatavalue = FALSE;
+ double nodatavalue;
+ const char *bandpath = NULL;
+ bool isoutdb = FALSE;
+
+ int i = 0;
+ char **values = NULL;
+ int values_length = 5;
+ HeapTuple tuple;
+ Datum result;
+
+ POSTGIS_RT_DEBUG(3, "RASTER_bandmetadata: Starting");
+
+ /* pgraster is null, return null */
+ if (PG_ARGISNULL(0)) PG_RETURN_NULL();
+ pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+
+ /* raster */
+ /* TODO: can be optimized to only detoast the header! */
+ raster = rt_raster_deserialize(pgraster);
+ if (!raster) {
+ elog(ERROR, "RASTER_transform: Could not deserialize raster");
+ PG_RETURN_NULL();
+ }
+
+ /* numbands */
+ numBands = rt_raster_get_num_bands(raster);
+ if (numBands < 1) {
+ elog(NOTICE, "Raster provided has no bands");
+ rt_raster_destroy(raster);
+ PG_RETURN_NULL();
+ }
+
+ /* band index */
+ if (!PG_ARGISNULL(1)) {
+ bandindex = PG_GETARG_INT32(1);
+ if (bandindex < 1 || bandindex > numBands) {
+ elog(NOTICE, "Invalid band index (must use 1-based). Returning NULL");
+ rt_raster_destroy(raster);
+ PG_RETURN_NULL();
+ }
+ }
+
+ band = rt_raster_get_band(raster, bandindex - 1);
+ if (NULL == band) {
+ elog(NOTICE, "Could not get raster band at index %d", bandindex);
+ rt_raster_destroy(raster);
+ PG_RETURN_NULL();
+ }
+
+ /* pixeltype */
+ pixtypename = rt_pixtype_name(rt_band_get_pixtype(band));
+
+ /* hasnodatavalue */
+ if (rt_band_get_hasnodata_flag(band)) hasnodatavalue = TRUE;
+
+ /* nodatavalue */
+ nodatavalue = rt_band_get_nodata(band);
+
+ /* path */
+ bandpath = rt_band_get_ext_path(band);
+
+ /* isoutdb */
+ isoutdb = bandpath ? TRUE : FALSE;
+
+ rt_band_destroy(band);
+ rt_raster_destroy(raster);
+ PG_FREE_IF_COPY(pgraster, 0);
+
+ /* Build a tuple descriptor for our result type */
+ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
+ ereport(ERROR, (
+ errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg(
+ "function returning record called in context "
+ "that cannot accept type record"
+ )
+ ));
+ }
+
+ /*
+ * generate attribute metadata needed later to produce tuples from raw
+ * C strings
+ */
+ attinmeta = TupleDescGetAttInMetadata(tupdesc);
+
+ /*
+ * Prepare a values array for building the returned tuple.
+ * This should be an array of C strings which will
+ * be processed later by the type input functions.
+ */
+ values = (char **) palloc(values_length * sizeof(char *));
+
+ values[0] = (char *) palloc(sizeof(char) * (strlen(pixtypename) + 1));
+ values[1] = (char *) palloc(sizeof(char) * (MAX_INT_CHARLEN + 1));
+ values[2] = (char *) palloc(sizeof(char) * (MAX_DBL_CHARLEN + 1));
+ values[3] = (char *) palloc(sizeof(char) * (MAX_INT_CHARLEN + 1));
+ if (bandpath)
+ values[4] = (char *) palloc(sizeof(char) * (strlen(bandpath) + 1));
+ else
+ values[4] = NULL;
+
+ snprintf(
+ values[0],
+ sizeof(char) * (strlen(pixtypename) + 1),
+ "%s",
+ pixtypename
+ );
+ snprintf(
+ values[1],
+ sizeof(char) * (MAX_INT_CHARLEN + 1),
+ "%d",
+ hasnodatavalue
+ );
+ snprintf(
+ values[2],
+ sizeof(char) * (MAX_DBL_CHARLEN + 1),
+ "%f",
+ nodatavalue
+ );
+ snprintf(
+ values[3],
+ sizeof(char) * (MAX_INT_CHARLEN + 1),
+ "%d",
+ isoutdb
+ );
+ if (bandpath) {
+ snprintf(
+ values[4],
+ sizeof(char) * (strlen(bandpath) + 1),
+ "%s",
+ bandpath
+ );
+ }
+
+ /* build a tuple */
+ tuple = BuildTupleFromCStrings(attinmeta, values);
+
+ /* make the tuple into a datum */
+ result = HeapTupleGetDatum(tuple);
+
+ /* clean up */
+ for (i = 0; i < values_length; i++) {
+ if (NULL != values[i]) pfree(values[i]);
+ }
+ pfree(values);
+
+ PG_RETURN_DATUM(result);
+}
+
/* ---------------------------------------------------------------- */
/* Memory allocation / error reporting hooks */
/* ---------------------------------------------------------------- */
AS $$ SELECT st_bandpixeltype($1, 1) $$
LANGUAGE SQL IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION st_bandmetadata(rast raster,
- band int,
- OUT pixeltype text,
- OUT hasnodatavalue boolean,
- OUT nodatavalue float4,
- OUT isoutdb boolean,
- OUT path text)
- AS $$
- SELECT st_bandpixeltype($1, $2),
- st_bandnodatavalue($1, $2) IS NOT NULL,
- st_bandnodatavalue($1, $2),
- st_bandpath($1, $2) IS NOT NULL,
- st_bandpath($1, $2)
- $$
- LANGUAGE SQL IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION st_bandmetadata(rast raster,
- OUT pixeltype text,
- OUT hasnodatavalue boolean,
- OUT nodatavalue float4,
- OUT isoutdb boolean,
- OUT path text)
- AS $$
- SELECT st_bandpixeltype($1, 1),
- st_bandnodatavalue($1, 1) IS NOT NULL,
- st_bandnodatavalue($1, 1),
- st_bandpath($1, 1) IS NOT NULL,
- st_bandpath($1, 1)
- $$
- LANGUAGE SQL IMMUTABLE STRICT;
+CREATE OR REPLACE FUNCTION st_bandmetadata(
+ rast raster,
+ band int DEFAULT 1,
+ OUT pixeltype text,
+ OUT hasnodatavalue boolean,
+ OUT nodatavalue float4,
+ OUT isoutdb boolean,
+ OUT path text
+)
+ AS 'MODULE_PATHNAME','RASTER_bandmetadata'
+ LANGUAGE 'C' IMMUTABLE STRICT;
-----------------------------------------------------------------------
-- Raster Pixel Accessors
--- /dev/null
+SELECT * FROM ST_BandMetaData(
+ ST_SetValue(
+ ST_SetValue(
+ ST_SetValue(
+ ST_AddBand(
+ ST_MakeEmptyRaster(10, 10, 10, 10, 2, 2, 0, 0,-1)
+ , 1, '64BF', 0, 0
+ )
+ , 1, 1, 1, -10
+ )
+ , 1, 5, 4, 0
+ )
+ , 1, 5, 5, 3.14159
+ )
+);
+SELECT * FROM ST_BandMetaData(
+ ST_SetValue(
+ ST_SetValue(
+ ST_SetValue(
+ ST_AddBand(
+ ST_MakeEmptyRaster(10, 10, 10, 10, 2, 2, 0, 0,-1)
+ , 1, '64BF', 0, 0
+ )
+ , 1, 1, 1, -10
+ )
+ , 1, 5, 4, 0
+ )
+ , 1, 5, 5, 3.14159
+ ),
+ 1
+);
+SELECT * FROM ST_BandMetaData(
+ ST_SetValue(
+ ST_SetValue(
+ ST_SetValue(
+ ST_AddBand(
+ ST_MakeEmptyRaster(10, 10, 10, 10, 2, 2, 0, 0,-1)
+ , 1, '64BF', 0, 0
+ )
+ , 1, 1, 1, -10
+ )
+ , 1, 5, 4, 0
+ )
+ , 1, 5, 5, 3.14159
+ ),
+ 2
+);