PostGIS  2.5.0beta1dev-r@@SVN_REVISION@@
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 */
48 Datum RASTER_fromGDALRaster(PG_FUNCTION_ARGS);
49 
50 /* convert raster to GDAL raster */
51 Datum RASTER_asGDALRaster(PG_FUNCTION_ARGS);
52 Datum RASTER_getGDALDrivers(PG_FUNCTION_ARGS);
53 
54 /* warp a raster using GDAL Warp API */
55 Datum RASTER_GDALWarp(PG_FUNCTION_ARGS);
56 
57 /* ---------------------------------------------------------------- */
58 /* Returns raster from GDAL raster */
59 /* ---------------------------------------------------------------- */
61 Datum 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  int srid = -1; /* -1 for NULL */
69 
70  rt_pgraster *pgraster = NULL;
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(bytea_data) - VARHDRSZ;
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 
148 Datum RASTER_asGDALRaster(PG_FUNCTION_ARGS)
149 {
150  rt_pgraster *pgraster = NULL;
152 
153  text *formattext = NULL;
154  char *format = NULL;
155  char **options = NULL;
156  text *optiontext = NULL;
157  char *option = NULL;
158  int 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  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(result) - VARHDRSZ);
325 
326  /* for test output
327  FILE *fh = NULL;
328  fh = fopen("/tmp/out.dat", "w");
329  fwrite(gdal, sizeof(uint8_t), gdal_size, fh);
330  fclose(fh);
331  */
332 
333  /* free gdal mem buffer */
334  if (gdal) CPLFree(gdal);
335 
336  POSTGIS_RT_DEBUG(3, "RASTER_asGDALRaster: Returning pointer to GDAL raster");
337  PG_RETURN_POINTER(result);
338 }
339 
344 Datum RASTER_getGDALDrivers(PG_FUNCTION_ARGS)
345 {
346  FuncCallContext *funcctx;
347  TupleDesc tupdesc;
348 
349  uint32_t drv_count;
350  rt_gdaldriver drv_set;
351  rt_gdaldriver drv_set2;
352  int call_cntr;
353  int max_calls;
354 
355  /* first call of function */
356  if (SRF_IS_FIRSTCALL()) {
357  MemoryContext oldcontext;
358 
359  /* create a function context for cross-call persistence */
360  funcctx = SRF_FIRSTCALL_INIT();
361 
362  /* switch to memory context appropriate for multiple function calls */
363  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
364 
365  drv_set = rt_raster_gdal_drivers(&drv_count, 0);
366  if (NULL == drv_set || !drv_count) {
367  elog(NOTICE, "No GDAL drivers found");
368  MemoryContextSwitchTo(oldcontext);
369  SRF_RETURN_DONE(funcctx);
370  }
371 
372  POSTGIS_RT_DEBUGF(3, "%d drivers returned", (int) drv_count);
373 
374  /* Store needed information */
375  funcctx->user_fctx = drv_set;
376 
377  /* total number of tuples to be returned */
378  funcctx->max_calls = drv_count;
379 
380  /* Build a tuple descriptor for our result type */
381  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
382  ereport(ERROR, (
383  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
384  errmsg(
385  "function returning record called in context "
386  "that cannot accept type record"
387  )
388  ));
389  }
390 
391  BlessTupleDesc(tupdesc);
392  funcctx->tuple_desc = tupdesc;
393  MemoryContextSwitchTo(oldcontext);
394  }
395 
396  /* stuff done on every call of the function */
397  funcctx = SRF_PERCALL_SETUP();
398 
399  call_cntr = funcctx->call_cntr;
400  max_calls = funcctx->max_calls;
401  tupdesc = funcctx->tuple_desc;
402  drv_set2 = funcctx->user_fctx;
403 
404  /* do when there is more left to send */
405  if (call_cntr < max_calls) {
406  int values_length = 6;
407  Datum values[values_length];
408  bool nulls[values_length];
409  HeapTuple tuple;
410  Datum result;
411 
412  POSTGIS_RT_DEBUGF(3, "Result %d", call_cntr);
413 
414  memset(nulls, FALSE, sizeof(bool) * values_length);
415 
416  values[0] = Int32GetDatum(drv_set2[call_cntr].idx);
417  values[1] = CStringGetTextDatum(drv_set2[call_cntr].short_name);
418  values[2] = CStringGetTextDatum(drv_set2[call_cntr].long_name);
419  values[3] = BoolGetDatum(drv_set2[call_cntr].can_read);
420  values[4] = BoolGetDatum(drv_set2[call_cntr].can_write);
421  values[5] = CStringGetTextDatum(drv_set2[call_cntr].create_options);
422 
423  POSTGIS_RT_DEBUGF(4, "Result %d, Index %d", call_cntr, drv_set2[call_cntr].idx);
424  POSTGIS_RT_DEBUGF(4, "Result %d, Short Name %s", call_cntr, drv_set2[call_cntr].short_name);
425  POSTGIS_RT_DEBUGF(4, "Result %d, Full Name %s", call_cntr, drv_set2[call_cntr].long_name);
426  POSTGIS_RT_DEBUGF(4, "Result %d, Can Read %s", call_cntr, drv_set2[call_cntr].can_read);
427  POSTGIS_RT_DEBUGF(4, "Result %d, Can Write %s", call_cntr, drv_set2[call_cntr].can_write);
428  POSTGIS_RT_DEBUGF(5, "Result %d, Create Options %s", call_cntr, drv_set2[call_cntr].create_options);
429 
430  /* build a tuple */
431  tuple = heap_form_tuple(tupdesc, values, nulls);
432 
433  /* make the tuple into a datum */
434  result = HeapTupleGetDatum(tuple);
435 
436  /* clean up */
437  pfree(drv_set2[call_cntr].short_name);
438  pfree(drv_set2[call_cntr].long_name);
439  pfree(drv_set2[call_cntr].create_options);
440 
441  SRF_RETURN_NEXT(funcctx, result);
442  }
443  /* do when there is no more left */
444  else {
445  pfree(drv_set2);
446  SRF_RETURN_DONE(funcctx);
447  }
448 }
449 
454 Datum RASTER_GDALWarp(PG_FUNCTION_ARGS)
455 {
456  rt_pgraster *pgraster = NULL;
457  rt_pgraster *pgrast = NULL;
458  rt_raster raster = NULL;
459  rt_raster rast = NULL;
460 
461  text *algtext = NULL;
462  char *algchar = NULL;
463  GDALResampleAlg alg = GRA_NearestNeighbour;
464  double max_err = 0.125;
465 
466  int src_srid = SRID_UNKNOWN;
467  char *src_srs = NULL;
468  int dst_srid = SRID_UNKNOWN;
469  char *dst_srs = NULL;
470  int no_srid = 0;
471 
472  double scale[2] = {0};
473  double *scale_x = NULL;
474  double *scale_y = NULL;
475 
476  double gridw[2] = {0};
477  double *grid_xw = NULL;
478  double *grid_yw = NULL;
479 
480  double skew[2] = {0};
481  double *skew_x = NULL;
482  double *skew_y = NULL;
483 
484  int dim[2] = {0};
485  int *dim_x = NULL;
486  int *dim_y = NULL;
487 
488  POSTGIS_RT_DEBUG(3, "RASTER_GDALWarp: Starting");
489 
490  /* pgraster is null, return null */
491  if (PG_ARGISNULL(0))
492  PG_RETURN_NULL();
493  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
494 
495  /* raster */
496  raster = rt_raster_deserialize(pgraster, FALSE);
497  if (!raster) {
498  PG_FREE_IF_COPY(pgraster, 0);
499  elog(ERROR, "RASTER_GDALWarp: Could not deserialize raster");
500  PG_RETURN_NULL();
501  }
502 
503  /* resampling algorithm */
504  if (!PG_ARGISNULL(1)) {
505  algtext = PG_GETARG_TEXT_P(1);
506  algchar = rtpg_trim(rtpg_strtoupper(text_to_cstring(algtext)));
507  alg = rt_util_gdal_resample_alg(algchar);
508  }
509  POSTGIS_RT_DEBUGF(4, "Resampling algorithm: %d", alg);
510 
511  /* max error */
512  if (!PG_ARGISNULL(2)) {
513  max_err = PG_GETARG_FLOAT8(2);
514  if (max_err < 0.) max_err = 0.;
515  }
516  POSTGIS_RT_DEBUGF(4, "max_err: %f", max_err);
517 
518  /* source SRID */
519  src_srid = clamp_srid(rt_raster_get_srid(raster));
520  POSTGIS_RT_DEBUGF(4, "source SRID: %d", src_srid);
521 
522  /* target SRID */
523  if (!PG_ARGISNULL(3)) {
524  dst_srid = clamp_srid(PG_GETARG_INT32(3));
525  if (dst_srid == SRID_UNKNOWN) {
526  rt_raster_destroy(raster);
527  PG_FREE_IF_COPY(pgraster, 0);
528  elog(ERROR, "RASTER_GDALWarp: %d is an invalid target SRID", dst_srid);
529  PG_RETURN_NULL();
530  }
531  }
532  else
533  dst_srid = src_srid;
534  POSTGIS_RT_DEBUGF(4, "destination SRID: %d", dst_srid);
535 
536  /* target SRID != src SRID, error */
537  if (src_srid == SRID_UNKNOWN && dst_srid != src_srid) {
538  rt_raster_destroy(raster);
539  PG_FREE_IF_COPY(pgraster, 0);
540  elog(ERROR, "RASTER_GDALWarp: Input raster has unknown (%d) SRID", src_srid);
541  PG_RETURN_NULL();
542  }
543  /* target SRID == src SRID, no reprojection */
544  else if (dst_srid == src_srid) {
545  no_srid = 1;
546  }
547 
548  /* scale x */
549  if (!PG_ARGISNULL(4)) {
550  scale[0] = PG_GETARG_FLOAT8(4);
551  if (FLT_NEQ(scale[0], 0)) scale_x = &scale[0];
552  }
553 
554  /* scale y */
555  if (!PG_ARGISNULL(5)) {
556  scale[1] = PG_GETARG_FLOAT8(5);
557  if (FLT_NEQ(scale[1], 0)) scale_y = &scale[1];
558  }
559 
560  /* grid alignment x */
561  if (!PG_ARGISNULL(6)) {
562  gridw[0] = PG_GETARG_FLOAT8(6);
563  grid_xw = &gridw[0];
564  }
565 
566  /* grid alignment y */
567  if (!PG_ARGISNULL(7)) {
568  gridw[1] = PG_GETARG_FLOAT8(7);
569  grid_yw = &gridw[1];
570  }
571 
572  /* skew x */
573  if (!PG_ARGISNULL(8)) {
574  skew[0] = PG_GETARG_FLOAT8(8);
575  if (FLT_NEQ(skew[0], 0)) skew_x = &skew[0];
576  }
577 
578  /* skew y */
579  if (!PG_ARGISNULL(9)) {
580  skew[1] = PG_GETARG_FLOAT8(9);
581  if (FLT_NEQ(skew[1], 0)) skew_y = &skew[1];
582  }
583 
584  /* width */
585  if (!PG_ARGISNULL(10)) {
586  dim[0] = PG_GETARG_INT32(10);
587  if (dim[0] < 0) dim[0] = 0;
588  if (dim[0] > 0) dim_x = &dim[0];
589  }
590 
591  /* height */
592  if (!PG_ARGISNULL(11)) {
593  dim[1] = PG_GETARG_INT32(11);
594  if (dim[1] < 0) dim[1] = 0;
595  if (dim[1] > 0) dim_y = &dim[1];
596  }
597 
598  /* check that at least something is to be done */
599  if (
600  (dst_srid == SRID_UNKNOWN) &&
601  (scale_x == NULL) && (scale_y == NULL) &&
602  (grid_xw == NULL) && (grid_yw == NULL) &&
603  (skew_x == NULL) && (skew_y == NULL) &&
604  (dim_x == NULL) && (dim_y == NULL)
605  ) {
606  elog(NOTICE, "No resampling parameters provided. Returning original raster");
607  rt_raster_destroy(raster);
608  PG_RETURN_POINTER(pgraster);
609  }
610  /* both values of alignment must be provided if any one is provided */
611  else if (
612  (grid_xw != NULL && grid_yw == NULL) ||
613  (grid_xw == NULL && grid_yw != NULL)
614  ) {
615  elog(NOTICE, "Values must be provided for both X and Y when specifying the alignment. Returning original raster");
616  rt_raster_destroy(raster);
617  PG_RETURN_POINTER(pgraster);
618  }
619  /* both values of scale must be provided if any one is provided */
620  else if (
621  (scale_x != NULL && scale_y == NULL) ||
622  (scale_x == NULL && scale_y != NULL)
623  ) {
624  elog(NOTICE, "Values must be provided for both X and Y when specifying the scale. Returning original raster");
625  rt_raster_destroy(raster);
626  PG_RETURN_POINTER(pgraster);
627  }
628  /* scale and width/height provided */
629  else if (
630  (scale_x != NULL || scale_y != NULL) &&
631  (dim_x != NULL || dim_y != NULL)
632  ) {
633  elog(NOTICE, "Scale X/Y and width/height are mutually exclusive. Only provide one. Returning original raster");
634  rt_raster_destroy(raster);
635  PG_RETURN_POINTER(pgraster);
636  }
637 
638  /* get srses from srids */
639  if (!no_srid) {
640  /* source srs */
641  src_srs = rtpg_getSR(src_srid);
642  if (NULL == src_srs) {
643  rt_raster_destroy(raster);
644  PG_FREE_IF_COPY(pgraster, 0);
645  elog(ERROR, "RASTER_GDALWarp: Input raster has unknown SRID (%d)", src_srid);
646  PG_RETURN_NULL();
647  }
648  POSTGIS_RT_DEBUGF(4, "src srs: %s", src_srs);
649 
650  dst_srs = rtpg_getSR(dst_srid);
651  if (NULL == dst_srs) {
652  if (!no_srid) pfree(src_srs);
653  rt_raster_destroy(raster);
654  PG_FREE_IF_COPY(pgraster, 0);
655  elog(ERROR, "RASTER_GDALWarp: Target SRID (%d) is unknown", dst_srid);
656  PG_RETURN_NULL();
657  }
658  POSTGIS_RT_DEBUGF(4, "dst srs: %s", dst_srs);
659  }
660 
661  rast = rt_raster_gdal_warp(
662  raster,
663  src_srs, dst_srs,
664  scale_x, scale_y,
665  dim_x, dim_y,
666  NULL, NULL,
667  grid_xw, grid_yw,
668  skew_x, skew_y,
669  alg, max_err);
670  rt_raster_destroy(raster);
671  PG_FREE_IF_COPY(pgraster, 0);
672  if (!no_srid) {
673  pfree(src_srs);
674  pfree(dst_srs);
675  }
676  if (!rast) {
677  elog(ERROR, "RASTER_band: Could not create transformed raster");
678  PG_RETURN_NULL();
679  }
680 
681  /* add target SRID */
682  rt_raster_set_srid(rast, dst_srid);
683 
684  pgrast = rt_raster_serialize(rast);
685  rt_raster_destroy(rast);
686 
687  if (NULL == pgrast) PG_RETURN_NULL();
688 
689  POSTGIS_RT_DEBUG(3, "RASTER_GDALWarp: done");
690 
691  SET_VARSIZE(pgrast, pgrast->size);
692  PG_RETURN_POINTER(pgrast);
693 }
694 
char * text_to_cstring(const text *textptr)
int clamp_srid(int srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition: lwutil.c:347
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_serialize.c:521
int rt_util_gdal_register_all(int force_register_all)
Definition: rt_util.c:336
raster
Be careful!! Zeros function&#39;s input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
data
Definition: ovdump.py:103
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
Datum RASTER_GDALWarp(PG_FUNCTION_ARGS)
Definition: rtpg_gdal.c:454
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition: rtpostgis.h:65
unsigned int uint32_t
Definition: uthash.h:78
Datum RASTER_asGDALRaster(PG_FUNCTION_ARGS)
Definition: rtpg_gdal.c:148
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:187
#define FLT_NEQ(x, y)
Definition: librtcore.h:2233
char * rtpg_trim(const char *input)
Datum RASTER_getGDALDrivers(PG_FUNCTION_ARGS)
Definition: rtpg_gdal.c:344
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster&#39;s SRID.
Definition: rt_raster.c:363
int32_t rt_raster_get_srid(rt_raster raster)
Get raster&#39;s SRID.
Definition: rt_raster.c:356
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:82
PG_FUNCTION_INFO_V1(RASTER_fromGDALRaster)
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:1602
#define FALSE
Definition: dbfopen.c:168
Struct definitions.
Definition: librtcore.h:2250
rt_gdaldriver rt_raster_gdal_drivers(uint32_t *drv_count, uint8_t cancc)
Returns a set of available GDAL drivers.
Definition: rt_raster.c:1720
Datum RASTER_fromGDALRaster(PG_FUNCTION_ARGS)
Definition: rtpg_gdal.c:61
char * rtpg_getSR(int srid)
rt_raster rt_raster_from_gdal_dataset(GDALDatasetH ds)
Return a raster from a GDAL dataset.
Definition: rt_raster.c:2186
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rtpostgis.h:61
GDALResampleAlg rt_util_gdal_resample_alg(const char *algname)
Convert cstring name to GDAL Resample Algorithm.
Definition: rt_util.c:91
unsigned char uint8_t
Definition: uthash.h:79
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_serialize.c:717
GDALDatasetH rt_util_gdal_open(const char *fn, GDALAccess fn_access, int shared)
Definition: rt_util.c:381
char * rtpg_strtoupper(char *str)