A raquet tile is built either from pixel bytes already in hand or by decoding a raster file, and carries its QUADBIN georeferencing in the value itself. A PostGIS raster is built likewise from the bytes of the pixels of a band and its georeferencing, or as a grid with no band to which bands are added and whose pixels are then set.
Construct a temporal cell holding one cell over a time value
tcell(cell,timestamptz) → tcellInst tcell(cell,tstzset) → tcellDiscSeq tcell(cell,tstzspan) → tcellSeq tcell(cell,tstzspanset) → tcellSeqSet
SELECT th3index(h3index '871fa4418ffffff', timestamptz '2001-01-01'); -- 871fa4418ffffff@2001-01-01 SELECT th3index(h3index '871fa4418ffffff', tstzspan '[2001-01-01, 2001-01-03]'); -- [871fa4418ffffff@2001-01-01, 871fa4418ffffff@2001-01-03] SELECT tquadbin(quadbin '48a6227affffffff', timestamptz '2001-01-01'); -- 48a6227affffffff@2001-01-01 SELECT tquadbin(quadbin '48a6227affffffff', tstzspan '[2001-01-01, 2001-01-03]'); -- [48a6227affffffff@2001-01-01, 48a6227affffffff@2001-01-03] SELECT ts2cell(s2cell '47c3c', timestamptz '2001-01-01'); -- 47c3c@2001-01-01 SELECT ts2cell(s2cell '47c3c', tstzspan '[2001-01-01, 2001-01-03]'); -- [47c3c@2001-01-01, 47c3c@2001-01-03]
Construct a temporal cell of a given subtype from its components
tcellInst(tcell) → tcellInst tcellSeq(tcell[],interp text='step') → tcellSeq tcellSeqSet(tcell[]) → tcellSeqSet
SELECT th3indexSeq(ARRAY[th3index '871fa4418ffffff@2001-01-01', th3index '871fa44a8ffffff@2001-01-02'], 'step'); -- [871fa4418ffffff@2001-01-01, 871fa44a8ffffff@2001-01-02] SELECT tquadbinSeq(ARRAY[tquadbin '48a6227affffffff@2001-01-01', tquadbin '485623ffffffffff@2001-01-02'], 'step'); -- [48a6227affffffff@2001-01-01, 485623ffffffffff@2001-01-02] SELECT ts2cellSeq(ARRAY[ts2cell '47c3c@2001-01-01', ts2cell '47c4@2001-01-02'], 'step'); -- [47c3c@2001-01-01, 47c4@2001-01-02]
Construct a Raquet raster tile from its pixel bytes, dimensions, QUADBIN cell and pixel type
raquet(bytea,width integer,height integer,quadbin,pixtype text, nodata float) → raquet
Packages a row-major single-band pixels array of width × height pixels of type pixtype (one of uint8, int8, uint16, int16, uint32, int32, uint64, int64, float16, float32, or float64), georeferenced by the quadbin cell, into a single self-describing raquet value. The nodata argument is optional; when omitted (NULL) the tile carries no nodata sentinel. An error is raised when the pixels array is smaller than width × height × the pixel size. Pixels of more than one byte are little-endian, which is the byte order the RaQuet specification gives them whatever the byte order of the server, so that a tile keeps its values when it is read on another machine. A raquet is a GDAL-free, variable-length value with a portable Hex-WKB text and binary representation, distinct from and coexisting with the PostGIS raster type used by rasterValue. A Raquet table states the dimensions, the pixel type and the nodata value of its tiles once, in the metadata row at block = 0, which the query below reads and leaves out of the tiles: 0 is no QUADBIN index, so the cast to quadbin refuses it. The constructor reads the pixel bytes as they stand, so the bands of a Raquet file whose metadata states a gzip compression are decompressed before they reach it.
-- Package the tiles of a Raquet table, whose band_1 column is uncompressed,
-- into raquet values keyed by their QUADBIN cell
CREATE TABLE elevation_tiles AS
SELECT r.block::quadbin AS quadbin, raquet(r.band_1,
(m.meta->'tiling'->>'block_width')::integer,
(m.meta->'tiling'->>'block_height')::integer, r.block::quadbin,
m.meta->'bands'->0->>'type', (m.meta->'bands'->0->>'nodata')::float8) AS tile
FROM elevation_raquet r,
(SELECT metadata::jsonb AS meta FROM elevation_raquet WHERE block = 0 LIMIT 1) m
WHERE r.block <> 0;
-- A 2 x 2 UINT8 tile with no nodata
SELECT raquet('\x01020304'::bytea, 2, 2, quadbin '4817ffffffffffff', 'uint8');
Construct a raster of one band from the bytes of its pixels and its georeferencing
raster(pixels bytea,width integer,height integer,upperleftx float,upperlefty float, scalex float,scaley float,skewx float,skewy float,srid integer,pixeltype text, nodataval float=NULL) → raster
The twin of the raquet constructor for a PostGIS raster, the georeferencing of a raster standing for the QUADBIN cell of a tile. The pixels are those pixels answers: row by row, each in the bytes of its type, little-endian when wider than one byte, and one byte for the types 1BB, 2BUI and 4BUI, which bound a pixel to less than a byte. The pixeltype is named as PostGIS names it, 8BUI, 16BSI, 32BF and so on, or as bandPixelType answers it, the name uint8 standing for 8BUI. A raster band has no 16-bit float and no 64-bit integer, so float16, int64 and uint64 are refused, as are bytes of another number than the pixels take and a byte beyond the bound of a type bounding a pixel to less than a byte. The nodataval is optional; when omitted the band states no nodata value. A raster of one band is the raster built from its own pixels and georeferencing, raster(pixels(r), width(r), height(r), upperLeftX(r), upperLeftY(r), scaleX(r), scaleY(r), skewX(r), skewY(r), SRID(r), bandPixelType(r), bandNoDataValue(r)), every value it holds kept exactly. A band of 1BB, 2BUI or 4BUI holds a byte a pixel, as one of 8BUI does, and bandPixelType names it uint8, so it is rebuilt as 8BUI with the same bytes, the bound its name states being the one thing it loses. Further bands are added with addBand.
SELECT dumpValues(raster('\x0100feff2c010080'::bytea, 2, 2, 0, 2, 1, -1, 0, 0,
3857, '16BSI'), 1);
-- {{1,-2},{300,-32768}}
Construct a raster with no band
makeEmptyRaster(width integer,height integer,upperleftx float,upperlefty float, scalex float,scaley float,skewx float,skewy float,srid integer=0) → raster
The raster PostGIS's ST_MakeEmptyRaster answers: a grid of width × height pixels, each dimension from 0 to 65535, georeferenced by its upper left corner, its scale and its skew in the spatial reference system srid.
SELECT width(r), height(r), numBands(r), scaleX(r) FROM (SELECT makeEmptyRaster(3, 2, 10, 20, 2, -1, 0, 0, 3857) AS r) t; -- 3 | 2 | 0 | 2
Add a band to a raster
addBand(rast raster,index integer,pixeltype text,initialvalue float=0, nodataval float=NULL) → raster addBand(torast raster,fromrast raster,fromband integer=1, torastindex integer=NULL) → raster
The raster PostGIS's ST_AddBand answers. The first form adds a band of type pixeltype, named as raster reads it, each of its pixels holding initialvalue, stating the nodata value nodataval or none when it is omitted. The second form adds a copy of band fromband of fromrast, a raster of the same width and height. The band takes the number index or torastindex, from 1 to one more than the number of bands of the raster, and is added after the last band when the number is NULL, written NULL::integer in the first form so that it is not read as a raster of the second. A number out of that range, a band fromrast lacks and a raster of another size are refused, where PostGIS adds the band elsewhere or answers the raster unchanged.
SELECT numBands(r), bandPixelType(r, 1), bandNoDataValue(r, 2) FROM (SELECT addBand(addBand(makeEmptyRaster(2, 2, 0, 2, 1, -1, 0, 0, 3857), NULL::integer, '8BUI', 1), 1, '32BF', 0, -9999) AS r) t; -- 2 | float32 | NULL SELECT numBands(addBand(r, r)) FROM (SELECT addBand(makeEmptyRaster(2, 2, 0, 2, 1, -1, 0, 0, 3857), NULL::integer, '8BUI', 1) AS r) t; -- 2
Decode a raster file into a Raquet raster tile via GDAL
raquetRead(bytea,quadbin) → raquet raquetRead(text,quadbin) → raquet
Reads the bytes of rasterfile, a raster in any format GDAL supports (GeoTIFF, PNG, …), through GDAL's /vsimem/ virtual filesystem, and packs its first band, row-major, into a single self-describing raquet value georeferenced by the quadbin cell. The band data type must be one of Byte, Int16, Int32, Float32, or Float64; the band nodata value, when set, is carried into the tile. Because the file is supplied as bytes, no server-side file access is required. GDAL performs the decode, so the raster's format driver must be permitted by PostGIS's postgis.gdal_enabled_drivers setting (which disables all drivers by default); enable it with, for example, SET postgis.gdal_enabled_drivers = 'ENABLE_ALL'. This is the ingest counterpart of the raquet constructor, which builds a tile from already-decoded pixel bytes. When quadbin is omitted or NULL, the tile identifier is derived from the raster's georeferencing: the raster must carry an EPSG:3857 (Web-Mercator) spatial reference and an axis-aligned geotransform describing a single QUADBIN tile. A raster with no spatial reference, one that is not in EPSG:3857, or a geotransform that is rotated or not aligned to the tile grid raises an error rather than being coerced. The form taking text reads the raster file at that path on the server instead, where PostGIS allows a raster band stored outside the database to be read, as rasterValue states.
-- Decode a GeoTIFF stored in a bytea column into a raquet tile SELECT raquetRead(file_bytes, quadbin) AS tile FROM elevation_files; -- Derive the QUADBIN cell from an EPSG:3857 GeoTIFF's georeferencing SELECT raquetRead(file_bytes) AS tile FROM elevation_files;