33 #include <utils/builtins.h>
34 #include "utils/lsyscache.h"
35 #include "utils/array.h"
36 #include "catalog/pg_type.h"
38 #include "../../postgis_config.h"
41 #include "access/htup_details.h"
66 VSILFILE *vsifp = NULL;
78 bytea_data = (bytea *) PG_GETARG_BYTEA_P(0);
80 data_len = VARSIZE(bytea_data) - VARHDRSZ;
88 vsifp = VSIFileFromMemBuffer(
"/vsimem/in.dat",
data, data_len,
FALSE);
90 PG_FREE_IF_COPY(bytea_data, 0);
91 elog(ERROR,
"RASTER_fromGDALRaster: Could not load bytea into memory file for use by GDAL");
100 if (hdsSrc == NULL) {
102 PG_FREE_IF_COPY(bytea_data, 0);
103 elog(ERROR,
"RASTER_fromGDALRaster: Could not open bytea with GDAL. Check that the bytea is of a GDAL supported format");
107 #if POSTGIS_DEBUG_LEVEL > 3
109 GDALDriverH hdrv = GDALGetDatasetDriver(hdsSrc);
112 GDALGetDriverShortName(hdrv),
113 GDALGetRasterXSize(hdsSrc),
114 GDALGetRasterYSize(hdsSrc)
124 PG_FREE_IF_COPY(bytea_data, 0);
127 elog(ERROR,
"RASTER_fromGDALRaster: Could not convert GDAL raster to raster");
140 SET_VARSIZE(pgraster, pgraster->
size);
141 PG_RETURN_POINTER(pgraster);
153 text *formattext = NULL;
155 char **options = NULL;
156 text *optiontext = NULL;
173 uint64_t gdal_size = 0;
174 bytea *result = NULL;
175 uint64_t result_size = 0;
180 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
181 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
185 PG_FREE_IF_COPY(pgraster, 0);
186 elog(ERROR,
"RASTER_asGDALRaster: Could not deserialize raster");
191 if (PG_ARGISNULL(1)) {
192 elog(NOTICE,
"Format must be provided");
194 PG_FREE_IF_COPY(pgraster, 0);
198 formattext = PG_GETARG_TEXT_P(1);
205 if (!PG_ARGISNULL(2)) {
207 array = PG_GETARG_ARRAYTYPE_P(2);
208 etype = ARR_ELEMTYPE(array);
209 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
216 PG_FREE_IF_COPY(pgraster, 0);
217 elog(ERROR,
"RASTER_asGDALRaster: Invalid data type for options");
222 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
226 options = (
char **) palloc(
sizeof(
char *) * (n + 1));
227 if (options == NULL) {
229 PG_FREE_IF_COPY(pgraster, 0);
230 elog(ERROR,
"RASTER_asGDALRaster: Could not allocate memory for options");
235 for (i = 0, j = 0; i < n; i++) {
236 if (nulls[i])
continue;
241 optiontext = (text *) DatumGetPointer(e[i]);
242 if (NULL == optiontext)
break;
251 if (strlen(option)) {
252 options[j] = (
char *) palloc(
sizeof(
char) * (strlen(option) + 1));
253 strcpy(options[j], option);
260 options = repalloc(options, (j + 1) *
sizeof(
char *));
278 srid = PG_GETARG_INT32(3);
284 if (NULL != options) {
285 for (i = j - 1; i >= 0; i--) pfree(options[i]);
289 PG_FREE_IF_COPY(pgraster, 0);
290 elog(ERROR,
"RASTER_asGDALRaster: Could not find srtext for SRID (%d)", srid);
302 if (NULL != options) {
303 for (i = j - 1; i >= 0; i--) pfree(options[i]);
306 if (NULL != srs) pfree(srs);
308 PG_FREE_IF_COPY(pgraster, 0);
311 elog(ERROR,
"RASTER_asGDALRaster: Could not allocate and generate GDAL raster");
314 POSTGIS_RT_DEBUGF(3,
"RASTER_asGDALRaster: GDAL raster generated with %d bytes", (
int) gdal_size);
317 result_size = gdal_size + VARHDRSZ;
318 result = (bytea *) palloc(result_size);
319 if (NULL == result) {
320 elog(ERROR,
"RASTER_asGDALRaster: Insufficient virtual memory for GDAL raster");
323 SET_VARSIZE(result, result_size);
324 memcpy(VARDATA(result), gdal, VARSIZE(result) - VARHDRSZ);
329 POSTGIS_RT_DEBUG(3,
"RASTER_asGDALRaster: Returning pointer to GDAL raster");
330 PG_RETURN_POINTER(result);
333 #define VALUES_LENGTH 6
341 FuncCallContext *funcctx;
351 if (SRF_IS_FIRSTCALL()) {
352 MemoryContext oldcontext;
355 funcctx = SRF_FIRSTCALL_INIT();
358 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
361 if (NULL == drv_set || !drv_count) {
362 elog(NOTICE,
"No GDAL drivers found");
363 MemoryContextSwitchTo(oldcontext);
364 SRF_RETURN_DONE(funcctx);
370 funcctx->user_fctx = drv_set;
373 funcctx->max_calls = drv_count;
376 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
378 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
380 "function returning record called in context "
381 "that cannot accept type record"
386 BlessTupleDesc(tupdesc);
387 funcctx->tuple_desc = tupdesc;
388 MemoryContextSwitchTo(oldcontext);
392 funcctx = SRF_PERCALL_SETUP();
394 call_cntr = funcctx->call_cntr;
395 max_calls = funcctx->max_calls;
396 tupdesc = funcctx->tuple_desc;
397 drv_set2 = funcctx->user_fctx;
400 if (call_cntr < max_calls) {
410 values[0] = Int32GetDatum(drv_set2[call_cntr].idx);
411 values[1] = CStringGetTextDatum(drv_set2[call_cntr].short_name);
412 values[2] = CStringGetTextDatum(drv_set2[call_cntr].long_name);
413 values[3] = BoolGetDatum(drv_set2[call_cntr].can_read);
414 values[4] = BoolGetDatum(drv_set2[call_cntr].can_write);
415 values[5] = CStringGetTextDatum(drv_set2[call_cntr].create_options);
418 POSTGIS_RT_DEBUGF(4,
"Result %d, Short Name %s", call_cntr, drv_set2[call_cntr].short_name);
419 POSTGIS_RT_DEBUGF(4,
"Result %d, Full Name %s", call_cntr, drv_set2[call_cntr].long_name);
420 POSTGIS_RT_DEBUGF(4,
"Result %d, Can Read %s", call_cntr, drv_set2[call_cntr].can_read);
421 POSTGIS_RT_DEBUGF(4,
"Result %d, Can Write %s", call_cntr, drv_set2[call_cntr].can_write);
422 POSTGIS_RT_DEBUGF(5,
"Result %d, Create Options %s", call_cntr, drv_set2[call_cntr].create_options);
425 tuple = heap_form_tuple(tupdesc, values, nulls);
428 result = HeapTupleGetDatum(tuple);
431 pfree(drv_set2[call_cntr].short_name);
432 pfree(drv_set2[call_cntr].long_name);
433 pfree(drv_set2[call_cntr].create_options);
435 SRF_RETURN_NEXT(funcctx, result);
440 SRF_RETURN_DONE(funcctx);
455 text *algtext = NULL;
456 char *algchar = NULL;
457 GDALResampleAlg alg = GRA_NearestNeighbour;
458 double max_err = 0.125;
461 char *src_srs = NULL;
463 char *dst_srs = NULL;
466 double scale[2] = {0};
467 double *scale_x = NULL;
468 double *scale_y = NULL;
470 double gridw[2] = {0};
471 double *grid_xw = NULL;
472 double *grid_yw = NULL;
474 double skew[2] = {0};
475 double *skew_x = NULL;
476 double *skew_y = NULL;
487 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
492 PG_FREE_IF_COPY(pgraster, 0);
493 elog(ERROR,
"RASTER_GDALWarp: Could not deserialize raster");
498 if (!PG_ARGISNULL(1)) {
499 algtext = PG_GETARG_TEXT_P(1);
506 if (!PG_ARGISNULL(2)) {
507 max_err = PG_GETARG_FLOAT8(2);
508 if (max_err < 0.) max_err = 0.;
517 if (!PG_ARGISNULL(3)) {
521 PG_FREE_IF_COPY(pgraster, 0);
522 elog(ERROR,
"RASTER_GDALWarp: %d is an invalid target SRID", dst_srid);
533 PG_FREE_IF_COPY(pgraster, 0);
534 elog(ERROR,
"RASTER_GDALWarp: Input raster has unknown (%d) SRID", src_srid);
538 else if (dst_srid == src_srid) {
543 if (!PG_ARGISNULL(4)) {
544 scale[0] = PG_GETARG_FLOAT8(4);
545 if (
FLT_NEQ(scale[0], 0)) scale_x = &scale[0];
549 if (!PG_ARGISNULL(5)) {
550 scale[1] = PG_GETARG_FLOAT8(5);
551 if (
FLT_NEQ(scale[1], 0)) scale_y = &scale[1];
555 if (!PG_ARGISNULL(6)) {
556 gridw[0] = PG_GETARG_FLOAT8(6);
561 if (!PG_ARGISNULL(7)) {
562 gridw[1] = PG_GETARG_FLOAT8(7);
567 if (!PG_ARGISNULL(8)) {
568 skew[0] = PG_GETARG_FLOAT8(8);
569 if (
FLT_NEQ(skew[0], 0)) skew_x = &skew[0];
573 if (!PG_ARGISNULL(9)) {
574 skew[1] = PG_GETARG_FLOAT8(9);
575 if (
FLT_NEQ(skew[1], 0)) skew_y = &skew[1];
579 if (!PG_ARGISNULL(10)) {
580 dim[0] = PG_GETARG_INT32(10);
581 if (dim[0] < 0) dim[0] = 0;
582 if (dim[0] > 0) dim_x = &dim[0];
586 if (!PG_ARGISNULL(11)) {
587 dim[1] = PG_GETARG_INT32(11);
588 if (dim[1] < 0) dim[1] = 0;
589 if (dim[1] > 0) dim_y = &dim[1];
595 (scale_x == NULL) && (scale_y == NULL) &&
596 (grid_xw == NULL) && (grid_yw == NULL) &&
597 (skew_x == NULL) && (skew_y == NULL) &&
598 (dim_x == NULL) && (dim_y == NULL)
600 elog(NOTICE,
"No resampling parameters provided. Returning original raster");
602 PG_RETURN_POINTER(pgraster);
606 (grid_xw != NULL && grid_yw == NULL) ||
607 (grid_xw == NULL && grid_yw != NULL)
609 elog(NOTICE,
"Values must be provided for both X and Y when specifying the alignment. Returning original raster");
611 PG_RETURN_POINTER(pgraster);
615 (scale_x != NULL && scale_y == NULL) ||
616 (scale_x == NULL && scale_y != NULL)
618 elog(NOTICE,
"Values must be provided for both X and Y when specifying the scale. Returning original raster");
620 PG_RETURN_POINTER(pgraster);
624 (scale_x != NULL || scale_y != NULL) &&
625 (dim_x != NULL || dim_y != NULL)
627 elog(NOTICE,
"Scale X/Y and width/height are mutually exclusive. Only provide one. Returning original raster");
629 PG_RETURN_POINTER(pgraster);
636 if (NULL == src_srs) {
638 PG_FREE_IF_COPY(pgraster, 0);
639 elog(ERROR,
"RASTER_GDALWarp: Input raster has unknown SRID (%d)", src_srid);
645 if (NULL == dst_srs) {
648 PG_FREE_IF_COPY(pgraster, 0);
649 elog(ERROR,
"RASTER_GDALWarp: Target SRID (%d) is unknown", dst_srid);
665 PG_FREE_IF_COPY(pgraster, 0);
671 elog(ERROR,
"RASTER_band: Could not create transformed raster");
681 if (NULL == pgrast) PG_RETURN_NULL();
685 SET_VARSIZE(pgrast, pgrast->
size);
686 PG_RETURN_POINTER(pgrast);
int clamp_srid(int srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
#define SRID_UNKNOWN
Unknown SRID value.
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
int rt_util_gdal_register_all(int force_register_all)
rt_gdaldriver rt_raster_gdal_drivers(uint32_t *drv_count, uint8_t cancc)
Returns a set of available GDAL drivers.
uint8_t * rt_raster_to_gdal(rt_raster raster, const char *srs, char *format, char **options, uint64_t *gdalsize)
Return formatted GDAL raster from raster.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
rt_raster rt_raster_from_gdal_dataset(GDALDatasetH ds)
Return a raster from a GDAL dataset.
GDALDatasetH rt_util_gdal_open(const char *fn, GDALAccess fn_access, int shared)
GDALResampleAlg rt_util_gdal_resample_alg(const char *algname)
Convert cstring name to GDAL Resample Algorithm.
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
rt_raster rt_raster_gdal_warp(rt_raster raster, const char *src_srs, const char *dst_srs, double *scale_x, double *scale_y, int *width, int *height, double *ul_xw, double *ul_yw, double *grid_xw, double *grid_yw, double *skew_x, double *skew_y, GDALResampleAlg resample_alg, double max_err)
Return a warped raster using GDAL Warp API.
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
char * text_to_cstring(const text *textptr)
Datum RASTER_fromGDALRaster(PG_FUNCTION_ARGS)
Datum RASTER_getGDALDrivers(PG_FUNCTION_ARGS)
Datum RASTER_asGDALRaster(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(RASTER_fromGDALRaster)
Datum RASTER_GDALWarp(PG_FUNCTION_ARGS)
char * rtpg_getSR(int srid)
char * rtpg_strtoupper(char *str)
char * rtpg_trim(const char *input)
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)