PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
rtpg_gdal.c
Go to the documentation of this file.
1/*
2 *
3 * WKTRaster - Raster Types for PostGIS
4 * http://trac.osgeo.org/postgis/wiki/WKTRaster
5 *
6 * Copyright (C) 2011-2013 Regents of the University of California
7 * <bkpark@ucdavis.edu>
8 * Copyright (C) 2010-2011 Jorge Arevalo <jorge.arevalo@deimos-space.com>
9 * Copyright (C) 2010-2011 David Zwarg <dzwarg@azavea.com>
10 * Copyright (C) 2009-2011 Pierre Racine <pierre.racine@sbf.ulaval.ca>
11 * Copyright (C) 2009-2011 Mateusz Loskot <mateusz@loskot.net>
12 * Copyright (C) 2008-2009 Sandro Santilli <strk@kbt.io>
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software Foundation,
26 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 *
28 */
29
30#include <postgres.h>
31#include <fmgr.h>
32#include <funcapi.h> /* for SRF */
33#include <utils/builtins.h> /* for text_to_cstring() */
34#include "utils/lsyscache.h" /* for get_typlenbyvalalign */
35#include "utils/array.h" /* for ArrayType */
36#include "catalog/pg_type.h" /* for INT2OID, INT4OID, FLOAT4OID, FLOAT8OID and TEXTOID */
37
38#include "../../postgis_config.h"
39
40
41#include "access/htup_details.h" /* for heap_form_tuple() */
42
43
44#include "rtpostgis.h"
45#include "rtpg_internal.h"
46
47/* convert GDAL raster to raster */
48Datum RASTER_fromGDALRaster(PG_FUNCTION_ARGS);
49
50/* convert raster to GDAL raster */
51Datum RASTER_asGDALRaster(PG_FUNCTION_ARGS);
52Datum RASTER_getGDALDrivers(PG_FUNCTION_ARGS);
53
54/* warp a raster using GDAL Warp API */
55Datum RASTER_GDALWarp(PG_FUNCTION_ARGS);
56
57/* ---------------------------------------------------------------- */
58/* Returns raster from GDAL raster */
59/* ---------------------------------------------------------------- */
61Datum RASTER_fromGDALRaster(PG_FUNCTION_ARGS)
62{
63 bytea *bytea_data;
64 uint8_t *data;
65 int data_len = 0;
66 VSILFILE *vsifp = NULL;
67 GDALDatasetH hdsSrc;
68 int32_t srid = -1; /* -1 for NULL */
69
70 rt_pgraster *pgraster = NULL;
71 rt_raster raster;
72
73 /* NULL if NULL */
74 if (PG_ARGISNULL(0))
75 PG_RETURN_NULL();
76
77 /* get data */
78 bytea_data = (bytea *) PG_GETARG_BYTEA_P(0);
79 data = (uint8_t *) VARDATA(bytea_data);
80 data_len = VARSIZE_ANY_EXHDR(bytea_data);
81
82 /* process srid */
83 /* NULL srid means try to determine SRID from bytea */
84 if (!PG_ARGISNULL(1))
85 srid = clamp_srid(PG_GETARG_INT32(1));
86
87 /* create memory "file" */
88 vsifp = VSIFileFromMemBuffer("/vsimem/in.dat", data, data_len, FALSE);
89 if (vsifp == NULL) {
90 PG_FREE_IF_COPY(bytea_data, 0);
91 elog(ERROR, "RASTER_fromGDALRaster: Could not load bytea into memory file for use by GDAL");
92 PG_RETURN_NULL();
93 }
94
95 /* register all GDAL drivers */
97
98 /* open GDAL raster */
99 hdsSrc = rt_util_gdal_open("/vsimem/in.dat", GA_ReadOnly, 1);
100 if (hdsSrc == NULL) {
101 VSIFCloseL(vsifp);
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");
104 PG_RETURN_NULL();
105 }
106
107#if POSTGIS_DEBUG_LEVEL > 3
108 {
109 GDALDriverH hdrv = GDALGetDatasetDriver(hdsSrc);
110
111 POSTGIS_RT_DEBUGF(4, "Input GDAL Raster info: %s, (%d x %d)",
112 GDALGetDriverShortName(hdrv),
113 GDALGetRasterXSize(hdsSrc),
114 GDALGetRasterYSize(hdsSrc)
115 );
116 }
117#endif
118
119 /* convert GDAL raster to raster */
120 raster = rt_raster_from_gdal_dataset(hdsSrc);
121
122 GDALClose(hdsSrc);
123 VSIFCloseL(vsifp);
124 PG_FREE_IF_COPY(bytea_data, 0);
125
126 if (raster == NULL) {
127 elog(ERROR, "RASTER_fromGDALRaster: Could not convert GDAL raster to raster");
128 PG_RETURN_NULL();
129 }
130
131 /* apply SRID if set */
132 if (srid != -1)
133 rt_raster_set_srid(raster, srid);
134
135 pgraster = rt_raster_serialize(raster);
136 rt_raster_destroy(raster);
137 if (!pgraster)
138 PG_RETURN_NULL();
139
140 SET_VARSIZE(pgraster, pgraster->size);
141 PG_RETURN_POINTER(pgraster);
142}
143
148Datum RASTER_asGDALRaster(PG_FUNCTION_ARGS)
149{
150 rt_pgraster *pgraster = NULL;
151 rt_raster raster;
152
153 text *formattext = NULL;
154 char *format = NULL;
155 char **options = NULL;
156 text *optiontext = NULL;
157 char *option = NULL;
158 int32_t srid = SRID_UNKNOWN;
159 char *srs = NULL;
160
161 ArrayType *array;
162 Oid etype;
163 Datum *e;
164 bool *nulls;
165 int16 typlen;
166 bool typbyval;
167 char typalign;
168 int n = 0;
169 int i = 0;
170 int j = 0;
171
172 uint8_t *gdal = NULL;
173 uint64_t gdal_size = 0;
174 bytea *result = NULL;
175 uint64_t result_size = 0;
176
177 POSTGIS_RT_DEBUG(3, "RASTER_asGDALRaster: Starting");
178
179 /* pgraster is null, return null */
180 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
181 pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
182
183 raster = rt_raster_deserialize(pgraster, FALSE);
184 if (!raster) {
185 PG_FREE_IF_COPY(pgraster, 0);
186 elog(ERROR, "RASTER_asGDALRaster: Could not deserialize raster");
187 PG_RETURN_NULL();
188 }
189
190 /* format is required */
191 if (PG_ARGISNULL(1)) {
192 elog(NOTICE, "Format must be provided");
193 rt_raster_destroy(raster);
194 PG_FREE_IF_COPY(pgraster, 0);
195 PG_RETURN_NULL();
196 }
197 else {
198 formattext = PG_GETARG_TEXT_P(1);
199 format = text_to_cstring(formattext);
200 }
201
202 POSTGIS_RT_DEBUGF(3, "RASTER_asGDALRaster: Arg 1 (format) is %s", format);
203
204 /* process options */
205 if (!PG_ARGISNULL(2)) {
206 POSTGIS_RT_DEBUG(3, "RASTER_asGDALRaster: Processing Arg 2 (options)");
207 array = PG_GETARG_ARRAYTYPE_P(2);
208 etype = ARR_ELEMTYPE(array);
209 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
210
211 switch (etype) {
212 case TEXTOID:
213 break;
214 default:
215 rt_raster_destroy(raster);
216 PG_FREE_IF_COPY(pgraster, 0);
217 elog(ERROR, "RASTER_asGDALRaster: Invalid data type for options");
218 PG_RETURN_NULL();
219 break;
220 }
221
222 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
223 &nulls, &n);
224
225 if (n) {
226 options = (char **) palloc(sizeof(char *) * (n + 1));
227 if (options == NULL) {
228 rt_raster_destroy(raster);
229 PG_FREE_IF_COPY(pgraster, 0);
230 elog(ERROR, "RASTER_asGDALRaster: Could not allocate memory for options");
231 PG_RETURN_NULL();
232 }
233
234 /* clean each option */
235 for (i = 0, j = 0; i < n; i++) {
236 if (nulls[i]) continue;
237
238 option = NULL;
239 switch (etype) {
240 case TEXTOID:
241 optiontext = (text *) DatumGetPointer(e[i]);
242 if (NULL == optiontext) break;
243 option = text_to_cstring(optiontext);
244
245 /* trim string */
246 option = rtpg_trim(option);
247 POSTGIS_RT_DEBUGF(3, "RASTER_asGDALRaster: option is '%s'", option);
248 break;
249 }
250
251 if (strlen(option)) {
252 options[j] = (char *) palloc(sizeof(char) * (strlen(option) + 1));
253 strcpy(options[j], option);
254 j++;
255 }
256 }
257
258 if (j > 0) {
259 /* trim allocation */
260 options = repalloc(options, (j + 1) * sizeof(char *));
261
262 /* add NULL to end */
263 options[j] = NULL;
264
265 }
266 else {
267 pfree(options);
268 options = NULL;
269 }
270 }
271 }
272
273 /* process srid */
274 /* NULL srid means use raster's srid */
275 if (PG_ARGISNULL(3))
276 srid = rt_raster_get_srid(raster);
277 else
278 srid = PG_GETARG_INT32(3);
279
280 /* get srs from srid */
281 if (clamp_srid(srid) != SRID_UNKNOWN) {
282 srs = rtpg_getSR(srid);
283 if (NULL == srs) {
284 if (NULL != options) {
285 for (i = j - 1; i >= 0; i--) pfree(options[i]);
286 pfree(options);
287 }
288 rt_raster_destroy(raster);
289 PG_FREE_IF_COPY(pgraster, 0);
290 elog(ERROR, "RASTER_asGDALRaster: Could not find srtext for SRID (%d)", srid);
291 PG_RETURN_NULL();
292 }
293 POSTGIS_RT_DEBUGF(3, "RASTER_asGDALRaster: Arg 3 (srs) is %s", srs);
294 }
295 else
296 srs = NULL;
297
298 POSTGIS_RT_DEBUG(3, "RASTER_asGDALRaster: Generating GDAL raster");
299 gdal = rt_raster_to_gdal(raster, srs, format, options, &gdal_size);
300
301 /* free memory */
302 if (NULL != options) {
303 for (i = j - 1; i >= 0; i--) pfree(options[i]);
304 pfree(options);
305 }
306 if (NULL != srs) pfree(srs);
307 rt_raster_destroy(raster);
308 PG_FREE_IF_COPY(pgraster, 0);
309
310 if (!gdal) {
311 elog(ERROR, "RASTER_asGDALRaster: Could not allocate and generate GDAL raster");
312 PG_RETURN_NULL();
313 }
314 POSTGIS_RT_DEBUGF(3, "RASTER_asGDALRaster: GDAL raster generated with %d bytes", (int) gdal_size);
315
316 /* result is a varlena */
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");
321 PG_RETURN_NULL();
322 }
323 SET_VARSIZE(result, result_size);
324 memcpy(VARDATA(result), gdal, VARSIZE_ANY_EXHDR(result));
325
326 /* free gdal mem buffer */
327 CPLFree(gdal);
328
329 POSTGIS_RT_DEBUG(3, "RASTER_asGDALRaster: Returning pointer to GDAL raster");
330 PG_RETURN_POINTER(result);
331}
332
333#define VALUES_LENGTH 6
334
339Datum RASTER_getGDALDrivers(PG_FUNCTION_ARGS)
340{
341 FuncCallContext *funcctx;
342 TupleDesc tupdesc;
343
344 uint32_t drv_count;
345 rt_gdaldriver drv_set;
346 rt_gdaldriver drv_set2;
347 int call_cntr;
348 int max_calls;
349
350 /* first call of function */
351 if (SRF_IS_FIRSTCALL()) {
352 MemoryContext oldcontext;
353
354 /* create a function context for cross-call persistence */
355 funcctx = SRF_FIRSTCALL_INIT();
356
357 /* switch to memory context appropriate for multiple function calls */
358 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
359
360 drv_set = rt_raster_gdal_drivers(&drv_count, 0);
361 if (NULL == drv_set || !drv_count) {
362 elog(NOTICE, "No GDAL drivers found");
363 MemoryContextSwitchTo(oldcontext);
364 SRF_RETURN_DONE(funcctx);
365 }
366
367 POSTGIS_RT_DEBUGF(3, "%d drivers returned", (int) drv_count);
368
369 /* Store needed information */
370 funcctx->user_fctx = drv_set;
371
372 /* total number of tuples to be returned */
373 funcctx->max_calls = drv_count;
374
375 /* Build a tuple descriptor for our result type */
376 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
377 ereport(ERROR, (
378 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
379 errmsg(
380 "function returning record called in context "
381 "that cannot accept type record"
382 )
383 ));
384 }
385
386 BlessTupleDesc(tupdesc);
387 funcctx->tuple_desc = tupdesc;
388 MemoryContextSwitchTo(oldcontext);
389 }
390
391 /* stuff done on every call of the function */
392 funcctx = SRF_PERCALL_SETUP();
393
394 call_cntr = funcctx->call_cntr;
395 max_calls = funcctx->max_calls;
396 tupdesc = funcctx->tuple_desc;
397 drv_set2 = funcctx->user_fctx;
398
399 /* do when there is more left to send */
400 if (call_cntr < max_calls) {
401 Datum values[VALUES_LENGTH];
402 bool nulls[VALUES_LENGTH];
403 HeapTuple tuple;
404 Datum result;
405
406 POSTGIS_RT_DEBUGF(3, "Result %d", call_cntr);
407
408 memset(nulls, FALSE, sizeof(bool) * VALUES_LENGTH);
409
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);
416
417 POSTGIS_RT_DEBUGF(4, "Result %d, Index %d", call_cntr, drv_set2[call_cntr].idx);
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 %u", call_cntr, drv_set2[call_cntr].can_read);
421 POSTGIS_RT_DEBUGF(4, "Result %d, Can Write %u", 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);
423
424 /* build a tuple */
425 tuple = heap_form_tuple(tupdesc, values, nulls);
426
427 /* make the tuple into a datum */
428 result = HeapTupleGetDatum(tuple);
429
430 /* clean up */
431 pfree(drv_set2[call_cntr].short_name);
432 pfree(drv_set2[call_cntr].long_name);
433 pfree(drv_set2[call_cntr].create_options);
434
435 SRF_RETURN_NEXT(funcctx, result);
436 }
437 /* do when there is no more left */
438 else {
439 pfree(drv_set2);
440 SRF_RETURN_DONE(funcctx);
441 }
442}
443
448Datum RASTER_GDALWarp(PG_FUNCTION_ARGS)
449{
450 rt_pgraster *pgraster = NULL;
451 rt_pgraster *pgrast = NULL;
452 rt_raster raster = NULL;
453 rt_raster rast = NULL;
454
455 text *algtext = NULL;
456 char *algchar = NULL;
457 GDALResampleAlg alg = GRA_NearestNeighbour;
458 double max_err = 0.125;
459
460 int src_srid = SRID_UNKNOWN;
461 char *src_srs = NULL;
462 int dst_srid = SRID_UNKNOWN;
463 char *dst_srs = NULL;
464 int no_srid = 0;
465
466 double scale[2] = {0};
467 double *scale_x = NULL;
468 double *scale_y = NULL;
469
470 double gridw[2] = {0};
471 double *grid_xw = NULL;
472 double *grid_yw = NULL;
473
474 double skew[2] = {0};
475 double *skew_x = NULL;
476 double *skew_y = NULL;
477
478 int dim[2] = {0};
479 int *dim_x = NULL;
480 int *dim_y = NULL;
481
482 POSTGIS_RT_DEBUG(3, "RASTER_GDALWarp: Starting");
483
484 /* pgraster is null, return null */
485 if (PG_ARGISNULL(0))
486 PG_RETURN_NULL();
487 pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
488
489 /* raster */
490 raster = rt_raster_deserialize(pgraster, FALSE);
491 if (!raster) {
492 PG_FREE_IF_COPY(pgraster, 0);
493 elog(ERROR, "RASTER_GDALWarp: Could not deserialize raster");
494 PG_RETURN_NULL();
495 }
496
497 /* resampling algorithm */
498 if (!PG_ARGISNULL(1)) {
499 algtext = PG_GETARG_TEXT_P(1);
500 algchar = rtpg_trim(rtpg_strtoupper(text_to_cstring(algtext)));
501 alg = rt_util_gdal_resample_alg(algchar);
502 }
503 POSTGIS_RT_DEBUGF(4, "Resampling algorithm: %d", alg);
504
505 /* max error */
506 if (!PG_ARGISNULL(2)) {
507 max_err = PG_GETARG_FLOAT8(2);
508 if (max_err < 0.) max_err = 0.;
509 }
510 POSTGIS_RT_DEBUGF(4, "max_err: %f", max_err);
511
512 /* source SRID */
513 src_srid = clamp_srid(rt_raster_get_srid(raster));
514 POSTGIS_RT_DEBUGF(4, "source SRID: %d", src_srid);
515
516 /* target SRID */
517 if (!PG_ARGISNULL(3)) {
518 dst_srid = clamp_srid(PG_GETARG_INT32(3));
519 if (dst_srid == SRID_UNKNOWN) {
520 rt_raster_destroy(raster);
521 PG_FREE_IF_COPY(pgraster, 0);
522 elog(ERROR, "RASTER_GDALWarp: %d is an invalid target SRID", dst_srid);
523 PG_RETURN_NULL();
524 }
525 }
526 else
527 dst_srid = src_srid;
528 POSTGIS_RT_DEBUGF(4, "destination SRID: %d", dst_srid);
529
530 /* target SRID != src SRID, error */
531 if (src_srid == SRID_UNKNOWN && dst_srid != src_srid) {
532 rt_raster_destroy(raster);
533 PG_FREE_IF_COPY(pgraster, 0);
534 elog(ERROR, "RASTER_GDALWarp: Input raster has unknown (%d) SRID", src_srid);
535 PG_RETURN_NULL();
536 }
537 /* target SRID == src SRID, no reprojection */
538 else if (dst_srid == src_srid) {
539 no_srid = 1;
540 }
541
542 /* scale x */
543 if (!PG_ARGISNULL(4)) {
544 scale[0] = PG_GETARG_FLOAT8(4);
545 if (FLT_NEQ(scale[0], 0.0))
546 scale_x = &scale[0];
547 }
548
549 /* scale y */
550 if (!PG_ARGISNULL(5)) {
551 scale[1] = PG_GETARG_FLOAT8(5);
552 if (FLT_NEQ(scale[1], 0.0))
553 scale_y = &scale[1];
554 }
555
556 /* grid alignment x */
557 if (!PG_ARGISNULL(6)) {
558 gridw[0] = PG_GETARG_FLOAT8(6);
559 grid_xw = &gridw[0];
560 }
561
562 /* grid alignment y */
563 if (!PG_ARGISNULL(7)) {
564 gridw[1] = PG_GETARG_FLOAT8(7);
565 grid_yw = &gridw[1];
566 }
567
568 /* skew x */
569 if (!PG_ARGISNULL(8)) {
570 skew[0] = PG_GETARG_FLOAT8(8);
571 if (FLT_NEQ(skew[0], 0.0))
572 skew_x = &skew[0];
573 }
574
575 /* skew y */
576 if (!PG_ARGISNULL(9)) {
577 skew[1] = PG_GETARG_FLOAT8(9);
578 if (FLT_NEQ(skew[1], 0.0))
579 skew_y = &skew[1];
580 }
581
582 /* width */
583 if (!PG_ARGISNULL(10)) {
584 dim[0] = PG_GETARG_INT32(10);
585 if (dim[0] < 0) dim[0] = 0;
586 if (dim[0] > 0) dim_x = &dim[0];
587 }
588
589 /* height */
590 if (!PG_ARGISNULL(11)) {
591 dim[1] = PG_GETARG_INT32(11);
592 if (dim[1] < 0) dim[1] = 0;
593 if (dim[1] > 0) dim_y = &dim[1];
594 }
595
596 /* check that at least something is to be done */
597 if (
598 (dst_srid == SRID_UNKNOWN) &&
599 (scale_x == NULL) && (scale_y == NULL) &&
600 (grid_xw == NULL) && (grid_yw == NULL) &&
601 (skew_x == NULL) && (skew_y == NULL) &&
602 (dim_x == NULL) && (dim_y == NULL)
603 ) {
604 elog(NOTICE, "No resampling parameters provided. Returning original raster");
605 rt_raster_destroy(raster);
606 PG_RETURN_POINTER(pgraster);
607 }
608 /* both values of alignment must be provided if any one is provided */
609 else if (
610 (grid_xw != NULL && grid_yw == NULL) ||
611 (grid_xw == NULL && grid_yw != NULL)
612 ) {
613 elog(NOTICE, "Values must be provided for both X and Y when specifying the alignment. Returning original raster");
614 rt_raster_destroy(raster);
615 PG_RETURN_POINTER(pgraster);
616 }
617 /* both values of scale must be provided if any one is provided */
618 else if (
619 (scale_x != NULL && scale_y == NULL) ||
620 (scale_x == NULL && scale_y != NULL)
621 ) {
622 elog(NOTICE, "Values must be provided for both X and Y when specifying the scale. Returning original raster");
623 rt_raster_destroy(raster);
624 PG_RETURN_POINTER(pgraster);
625 }
626 /* scale and width/height provided */
627 else if (
628 (scale_x != NULL || scale_y != NULL) &&
629 (dim_x != NULL || dim_y != NULL)
630 ) {
631 elog(NOTICE, "Scale X/Y and width/height are mutually exclusive. Only provide one. Returning original raster");
632 rt_raster_destroy(raster);
633 PG_RETURN_POINTER(pgraster);
634 }
635
636 /* get srses from srids */
637 if (!no_srid) {
638 /* source srs */
639 src_srs = rtpg_getSR(src_srid);
640 if (NULL == src_srs) {
641 rt_raster_destroy(raster);
642 PG_FREE_IF_COPY(pgraster, 0);
643 elog(ERROR, "RASTER_GDALWarp: Input raster has unknown SRID (%d)", src_srid);
644 PG_RETURN_NULL();
645 }
646 POSTGIS_RT_DEBUGF(4, "src srs: %s", src_srs);
647
648 dst_srs = rtpg_getSR(dst_srid);
649 if (NULL == dst_srs) {
650 pfree(src_srs);
651 rt_raster_destroy(raster);
652 PG_FREE_IF_COPY(pgraster, 0);
653 elog(ERROR, "RASTER_GDALWarp: Target SRID (%d) is unknown", dst_srid);
654 PG_RETURN_NULL();
655 }
656 POSTGIS_RT_DEBUGF(4, "dst srs: %s", dst_srs);
657 }
658
659 rast = rt_raster_gdal_warp(
660 raster,
661 src_srs, dst_srs,
662 scale_x, scale_y,
663 dim_x, dim_y,
664 NULL, NULL,
665 grid_xw, grid_yw,
666 skew_x, skew_y,
667 alg, max_err);
668 rt_raster_destroy(raster);
669 PG_FREE_IF_COPY(pgraster, 0);
670 if (!no_srid) {
671 pfree(src_srs);
672 pfree(dst_srs);
673 }
674 if (!rast) {
675 elog(ERROR, "RASTER_band: Could not create transformed raster");
676 PG_RETURN_NULL();
677 }
678
679 /* add target SRID */
680 rt_raster_set_srid(rast, dst_srid);
681
682 pgrast = rt_raster_serialize(rast);
683 rt_raster_destroy(rast);
684
685 if (NULL == pgrast) PG_RETURN_NULL();
686
687 POSTGIS_RT_DEBUG(3, "RASTER_GDALWarp: done");
688
689 SET_VARSIZE(pgrast, pgrast->size);
690 PG_RETURN_POINTER(pgrast);
691}
692
#define FALSE
Definition dbfopen.c:168
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:229
int32_t clamp_srid(int32_t srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition lwutil.c:333
#define FLT_NEQ(x, y)
Definition librtcore.h:2234
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
Definition rt_raster.c:356
int rt_util_gdal_register_all(int force_register_all)
Definition rt_util.c:338
rt_gdaldriver rt_raster_gdal_drivers(uint32_t *drv_count, uint8_t cancc)
Returns a set of available GDAL drivers.
Definition rt_raster.c:1711
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.
Definition rt_raster.c:1593
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition rt_raster.c:82
rt_raster rt_raster_from_gdal_dataset(GDALDatasetH ds)
Return a raster from a GDAL dataset.
Definition rt_raster.c:2177
GDALDatasetH rt_util_gdal_open(const char *fn, GDALAccess fn_access, int shared)
Definition rt_util.c:383
GDALResampleAlg rt_util_gdal_resample_alg(const char *algname)
Convert cstring name to GDAL Resample Algorithm.
Definition rt_util.c:93
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
Definition rt_raster.c:363
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
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.
Definition rt_warp.c:178
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
char * text_to_cstring(const text *textptr)
Datum RASTER_fromGDALRaster(PG_FUNCTION_ARGS)
Definition rtpg_gdal.c:61
Datum RASTER_getGDALDrivers(PG_FUNCTION_ARGS)
Definition rtpg_gdal.c:339
Datum RASTER_asGDALRaster(PG_FUNCTION_ARGS)
Definition rtpg_gdal.c:148
PG_FUNCTION_INFO_V1(RASTER_fromGDALRaster)
#define VALUES_LENGTH
Definition rtpg_gdal.c:333
Datum RASTER_GDALWarp(PG_FUNCTION_ARGS)
Definition rtpg_gdal.c:448
char * rtpg_getSR(int32_t srid)
char * rtpg_trim(const char *input)
char * rtpg_strtoupper(char *str)
#define POSTGIS_RT_DEBUG(level, msg)
Definition rtpostgis.h:61
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition rtpostgis.h:65
Struct definitions.
Definition librtcore.h:2251