950 FuncCallContext *funcctx;
983 struct tile_arg_t *arg1 = NULL;
984 struct tile_arg_t *arg2 = NULL;
986 if (SRF_IS_FIRSTCALL()) {
987 MemoryContext oldcontext;
1003 funcctx = SRF_FIRSTCALL_INIT();
1006 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1009 if (PG_ARGISNULL(0)) {
1010 MemoryContextSwitchTo(oldcontext);
1011 SRF_RETURN_DONE(funcctx);
1015 arg1 = palloc(
sizeof(
struct tile_arg_t));
1017 MemoryContextSwitchTo(oldcontext);
1018 elog(ERROR,
"RASTER_tile: Could not allocate memory for arguments");
1019 SRF_RETURN_DONE(funcctx);
1022 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
1024 if (!arg1->raster.raster) {
1026 errcode(ERRCODE_OUT_OF_MEMORY),
1027 errmsg(
"Could not deserialize raster")
1030 PG_FREE_IF_COPY(pgraster, 0);
1031 MemoryContextSwitchTo(oldcontext);
1032 SRF_RETURN_DONE(funcctx);
1049 if (PG_ARGISNULL(1)) {
1050 elog(NOTICE,
"Width cannot be NULL. Returning NULL");
1053 PG_FREE_IF_COPY(pgraster, 0);
1054 MemoryContextSwitchTo(oldcontext);
1055 SRF_RETURN_DONE(funcctx);
1057 arg1->tile.width = PG_GETARG_INT32(1);
1058 if (arg1->tile.width < 1) {
1059 elog(NOTICE,
"Width must be greater than zero. Returning NULL");
1062 PG_FREE_IF_COPY(pgraster, 0);
1063 MemoryContextSwitchTo(oldcontext);
1064 SRF_RETURN_DONE(funcctx);
1068 if (PG_ARGISNULL(2)) {
1069 elog(NOTICE,
"Height cannot be NULL. Returning NULL");
1072 PG_FREE_IF_COPY(pgraster, 0);
1073 MemoryContextSwitchTo(oldcontext);
1074 SRF_RETURN_DONE(funcctx);
1076 arg1->tile.height = PG_GETARG_INT32(2);
1077 if (arg1->tile.height < 1) {
1078 elog(NOTICE,
"Height must be greater than zero. Returning NULL");
1081 PG_FREE_IF_COPY(pgraster, 0);
1082 MemoryContextSwitchTo(oldcontext);
1083 SRF_RETURN_DONE(funcctx);
1087 if (numbands && !PG_ARGISNULL(3)) {
1088 array = PG_GETARG_ARRAYTYPE_P(3);
1089 etype = ARR_ELEMTYPE(array);
1090 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1099 PG_FREE_IF_COPY(pgraster, 0);
1100 MemoryContextSwitchTo(oldcontext);
1101 elog(ERROR,
"RASTER_tile: Invalid data type for band indexes");
1102 SRF_RETURN_DONE(funcctx);
1106 deconstruct_array(array, etype, typlen, typbyval, typalign, &e, &nulls, &(arg1->numbands));
1108 arg1->nbands = palloc(
sizeof(
int) * arg1->numbands);
1109 if (arg1->nbands == NULL) {
1112 PG_FREE_IF_COPY(pgraster, 0);
1113 MemoryContextSwitchTo(oldcontext);
1114 elog(ERROR,
"RASTER_tile: Could not allocate memory for band indexes");
1115 SRF_RETURN_DONE(funcctx);
1118 for (i = 0, j = 0; i < arg1->numbands; i++) {
1119 if (nulls[i])
continue;
1123 arg1->nbands[j] = DatumGetInt16(e[i]) - 1;
1126 arg1->nbands[j] = DatumGetInt32(e[i]) - 1;
1133 if (j < arg1->numbands) {
1134 arg1->nbands = repalloc(arg1->nbands,
sizeof(
int) * j);
1135 if (arg1->nbands == NULL) {
1138 PG_FREE_IF_COPY(pgraster, 0);
1139 MemoryContextSwitchTo(oldcontext);
1140 elog(ERROR,
"RASTER_tile: Could not reallocate memory for band indexes");
1141 SRF_RETURN_DONE(funcctx);
1148 for (i = 0; i < arg1->numbands; i++) {
1150 elog(NOTICE,
"Band at index %d not found in raster", arg1->nbands[i] + 1);
1152 pfree(arg1->nbands);
1154 PG_FREE_IF_COPY(pgraster, 0);
1155 MemoryContextSwitchTo(oldcontext);
1156 SRF_RETURN_DONE(funcctx);
1161 arg1->numbands = numbands;
1164 arg1->nbands = palloc(
sizeof(
int) * arg1->numbands);
1166 if (arg1->nbands == NULL) {
1169 PG_FREE_IF_COPY(pgraster, 0);
1170 MemoryContextSwitchTo(oldcontext);
1171 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for pixel values");
1172 SRF_RETURN_DONE(funcctx);
1175 for (i = 0; i < arg1->numbands; i++) {
1176 arg1->nbands[i] = i;
1183 if (!PG_ARGISNULL(4)) {
1184 arg1->pad.pad = PG_GETARG_BOOL(4) ? 1 : 0;
1186 if (arg1->pad.pad && !PG_ARGISNULL(5)) {
1187 arg1->pad.hasnodata = 1;
1188 arg1->pad.nodataval = PG_GETARG_FLOAT8(5);
1191 arg1->pad.hasnodata = 0;
1192 arg1->pad.nodataval = 0;
1197 arg1->pad.hasnodata = 0;
1198 arg1->pad.nodataval = 0;
1208 arg1->tile.nx = ceil(arg1->raster.width / (
double) arg1->tile.width);
1209 arg1->tile.ny = ceil(arg1->raster.height / (
double) arg1->tile.height);
1210 POSTGIS_RT_DEBUGF(4,
"# of tiles (x, y) = (%d, %d)", arg1->tile.nx, arg1->tile.ny);
1213 funcctx->user_fctx = arg1;
1216 funcctx->max_calls = (arg1->tile.nx * arg1->tile.ny);
1218 MemoryContextSwitchTo(oldcontext);
1222 funcctx = SRF_PERCALL_SETUP();
1224 call_cntr = funcctx->call_cntr;
1225 max_calls = funcctx->max_calls;
1226 arg2 = funcctx->user_fctx;
1229 if (call_cntr < max_calls) {
1236 double nodataval = 0;
1262 ty = call_cntr / arg2->tile.nx;
1263 tx = call_cntr % arg2->tile.nx;
1267 if (!arg2->pad.pad) {
1268 if (ty + 1 == arg2->tile.ny)
1270 if (tx + 1 == arg2->tile.nx)
1275 rx = tx * arg2->tile.width;
1276 ry = ty * arg2->tile.height;
1281 width = arg2->tile.width;
1282 height = arg2->tile.height;
1288 width = arg2->raster.width - rx;
1291 height = arg2->raster.height - ry;
1303 if (arg2->numbands) pfree(arg2->nbands);
1305 elog(ERROR,
"RASTER_tile: Could not compute the coordinates of the upper-left corner of the output tile");
1306 SRF_RETURN_DONE(funcctx);
1312 len = arg2->tile.width;
1313 if (rx + arg2->tile.width >= arg2->raster.width)
1314 len = arg2->raster.width - rx;
1318 for (i = 0; i < arg2->numbands; i++) {
1322 if (_band == NULL) {
1323 int nband = arg2->nbands[i] + 1;
1326 pfree(arg2->nbands);
1328 elog(ERROR,
"RASTER_tile: Could not get band %d from source raster",
nband);
1329 SRF_RETURN_DONE(funcctx);
1336 else if (arg2->pad.pad && arg2->pad.hasnodata) {
1338 nodataval = arg2->pad.nodataval;
1348 pfree(arg2->nbands);
1350 elog(ERROR,
"RASTER_tile: Could not add new band to output tile");
1351 SRF_RETURN_DONE(funcctx);
1357 pfree(arg2->nbands);
1359 elog(ERROR,
"RASTER_tile: Could not get newly added band from output tile");
1360 SRF_RETURN_DONE(funcctx);
1370 for (j = 0; j < arg2->tile.height; j++) {
1373 if (k >= arg2->raster.height) {
1382 pfree(arg2->nbands);
1384 elog(ERROR,
"RASTER_tile: Could not get pixel line from source raster");
1385 SRF_RETURN_DONE(funcctx);
1391 pfree(arg2->nbands);
1393 elog(ERROR,
"RASTER_tile: Could not set pixel line of output tile");
1394 SRF_RETURN_DONE(funcctx);
1406 hasnodata, nodataval,
1413 pfree(arg2->nbands);
1415 elog(ERROR,
"RASTER_tile: Could not create new offline band for output tile");
1416 SRF_RETURN_DONE(funcctx);
1423 pfree(arg2->nbands);
1425 elog(ERROR,
"RASTER_tile: Could not add new offline band to output tile");
1426 SRF_RETURN_DONE(funcctx);
1435 if (arg2->numbands) pfree(arg2->nbands);
1437 SRF_RETURN_DONE(funcctx);
1440 SET_VARSIZE(pgtile, pgtile->
size);
1441 SRF_RETURN_NEXT(funcctx, PointerGetDatum(pgtile));
1446 if (arg2->numbands) pfree(arg2->nbands);
1448 SRF_RETURN_DONE(funcctx);
rt_errorstate rt_band_set_isnodata_flag(rt_band band, int flag)
Set isnodata flag value.
rt_errorstate rt_raster_cell_to_geopoint(rt_raster raster, double xr, double yr, double *xw, double *yw, double *gt)
Convert an xr, yr raster point to an xw, yw point on map.
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
int rt_raster_generate_new_band(rt_raster raster, rt_pixtype pixtype, double initialvalue, uint32_t hasnodata, double nodatavalue, int index)
Generate a new inline band and add it to a raster.
const char * rt_band_get_ext_path(rt_band band)
Return band's external path (only valid when rt_band_is_offline returns non-zero).
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster's geotransform using 6-element array.
int rt_raster_add_band(rt_raster raster, rt_band band, int index)
Add band data to a raster.
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
double rt_band_get_min_value(rt_band band)
Returns the minimal possible value for the band according to the pixel type.
rt_errorstate rt_band_set_pixel_line(rt_band band, int x, int y, void *vals, uint32_t len)
Set values of multiple pixels.
void rt_band_destroy(rt_band band)
Destroy a raster band.
uint16_t rt_raster_get_num_bands(rt_raster raster)
uint16_t rt_raster_get_height(rt_raster raster)
rt_band rt_band_new_offline(uint16_t width, uint16_t height, rt_pixtype pixtype, uint32_t hasnodata, double nodataval, uint8_t bandNum, const char *path)
Create an out-db rt_band.
rt_errorstate rt_band_get_ext_band_num(rt_band band, uint8_t *bandnum)
Return bands' external band number (only valid when rt_band_is_offline returns non-zero).
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
uint16_t rt_raster_get_width(rt_raster raster)
int rt_band_is_offline(rt_band band)
Return non-zero if the given band data is on the filesystem.
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
void rt_raster_set_offsets(rt_raster raster, double x, double y)
Set insertion points in projection units.
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
rt_errorstate rt_band_get_pixel_line(rt_band band, int x, int y, uint16_t len, void **vals, uint16_t *nvals)
Get values of multiple pixels.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)