PostGIS  2.5.1dev-r@@SVN_REVISION@@
rtpg_raster_properties.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>
33 
34 #include "../../postgis_config.h"
35 
36 
37 #include "access/htup_details.h" /* for heap_form_tuple() */
38 
39 
40 #include "rtpostgis.h"
41 
42 /* Get all the properties of a raster */
43 Datum RASTER_getSRID(PG_FUNCTION_ARGS);
44 Datum RASTER_getWidth(PG_FUNCTION_ARGS);
45 Datum RASTER_getHeight(PG_FUNCTION_ARGS);
46 Datum RASTER_getNumBands(PG_FUNCTION_ARGS);
47 Datum RASTER_getFileSize(PG_FUNCTION_ARGS);
48 Datum RASTER_getFileTimestamp(PG_FUNCTION_ARGS);
49 Datum RASTER_getXScale(PG_FUNCTION_ARGS);
50 Datum RASTER_getYScale(PG_FUNCTION_ARGS);
51 Datum RASTER_getXSkew(PG_FUNCTION_ARGS);
52 Datum RASTER_getYSkew(PG_FUNCTION_ARGS);
53 Datum RASTER_getXUpperLeft(PG_FUNCTION_ARGS);
54 Datum RASTER_getYUpperLeft(PG_FUNCTION_ARGS);
55 Datum RASTER_getPixelWidth(PG_FUNCTION_ARGS);
56 Datum RASTER_getPixelHeight(PG_FUNCTION_ARGS);
57 Datum RASTER_getGeotransform(PG_FUNCTION_ARGS);
58 Datum RASTER_isEmpty(PG_FUNCTION_ARGS);
59 Datum RASTER_hasNoBand(PG_FUNCTION_ARGS);
60 
61 /* get raster's meta data */
62 Datum RASTER_metadata(PG_FUNCTION_ARGS);
63 
64 /* convert pixel/line to spatial coordinates */
65 Datum RASTER_rasterToWorldCoord(PG_FUNCTION_ARGS);
66 
67 /* convert spatial coordinates to pixel/line*/
68 Datum RASTER_worldToRasterCoord(PG_FUNCTION_ARGS);
69 
70 /* Set all the properties of a raster */
71 Datum RASTER_setSRID(PG_FUNCTION_ARGS);
72 Datum RASTER_setScale(PG_FUNCTION_ARGS);
73 Datum RASTER_setScaleXY(PG_FUNCTION_ARGS);
74 Datum RASTER_setSkew(PG_FUNCTION_ARGS);
75 Datum RASTER_setSkewXY(PG_FUNCTION_ARGS);
76 Datum RASTER_setUpperLeftXY(PG_FUNCTION_ARGS);
77 Datum RASTER_setRotation(PG_FUNCTION_ARGS);
78 Datum RASTER_setGeotransform(PG_FUNCTION_ARGS);
79 
84 Datum RASTER_getSRID(PG_FUNCTION_ARGS)
85 {
86  rt_pgraster *pgraster;
88  int32_t srid;
89 
90  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
91  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
92 
93  raster = rt_raster_deserialize(pgraster, TRUE);
94  if ( ! raster ) {
95  PG_FREE_IF_COPY(pgraster, 0);
96  elog(ERROR, "RASTER_getSRID: Could not deserialize raster");
97  PG_RETURN_NULL();
98  }
99 
100  srid = rt_raster_get_srid(raster);
101 
102  rt_raster_destroy(raster);
103  PG_FREE_IF_COPY(pgraster, 0);
104 
105  PG_RETURN_INT32(srid);
106 }
107 
112 Datum RASTER_getWidth(PG_FUNCTION_ARGS)
113 {
114  rt_pgraster *pgraster;
116  uint16_t width;
117 
118  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
119  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
120 
121  raster = rt_raster_deserialize(pgraster, TRUE);
122  if ( ! raster ) {
123  PG_FREE_IF_COPY(pgraster, 0);
124  elog(ERROR, "RASTER_getWidth: Could not deserialize raster");
125  PG_RETURN_NULL();
126  }
127 
128  width = rt_raster_get_width(raster);
129 
130  rt_raster_destroy(raster);
131  PG_FREE_IF_COPY(pgraster, 0);
132 
133  PG_RETURN_INT32(width);
134 }
135 
140 Datum RASTER_getHeight(PG_FUNCTION_ARGS)
141 {
142  rt_pgraster *pgraster;
144  uint16_t height;
145 
146  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
147  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
148 
149  raster = rt_raster_deserialize(pgraster, TRUE);
150  if ( ! raster ) {
151  PG_FREE_IF_COPY(pgraster, 0);
152  elog(ERROR, "RASTER_getHeight: Could not deserialize raster");
153  PG_RETURN_NULL();
154  }
155 
156  height = rt_raster_get_height(raster);
157 
158  rt_raster_destroy(raster);
159  PG_FREE_IF_COPY(pgraster, 0);
160 
161  PG_RETURN_INT32(height);
162 }
163 
168 Datum RASTER_getNumBands(PG_FUNCTION_ARGS)
169 {
170  rt_pgraster *pgraster;
172  int32_t num_bands;
173 
174  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
175  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
176 
177  raster = rt_raster_deserialize(pgraster, TRUE);
178  if ( ! raster ) {
179  PG_FREE_IF_COPY(pgraster, 0);
180  elog(ERROR, "RASTER_getNumBands: Could not deserialize raster");
181  PG_RETURN_NULL();
182  }
183 
184  num_bands = rt_raster_get_num_bands(raster);
185 
186  rt_raster_destroy(raster);
187  PG_FREE_IF_COPY(pgraster, 0);
188 
189  PG_RETURN_INT32(num_bands);
190 }
191 
196 Datum RASTER_getXScale(PG_FUNCTION_ARGS)
197 {
198  rt_pgraster *pgraster;
200  double xsize;
201 
202  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
203  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
204 
205  raster = rt_raster_deserialize(pgraster, TRUE);
206  if ( ! raster ) {
207  PG_FREE_IF_COPY(pgraster, 0);
208  elog(ERROR, "RASTER_getXScale: Could not deserialize raster");
209  PG_RETURN_NULL();
210  }
211 
212  xsize = rt_raster_get_x_scale(raster);
213 
214  rt_raster_destroy(raster);
215  PG_FREE_IF_COPY(pgraster, 0);
216 
217  PG_RETURN_FLOAT8(xsize);
218 }
219 
224 Datum RASTER_getYScale(PG_FUNCTION_ARGS)
225 {
226  rt_pgraster *pgraster;
228  double ysize;
229 
230  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
231  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
232 
233  raster = rt_raster_deserialize(pgraster, TRUE);
234  if ( ! raster ) {
235  PG_FREE_IF_COPY(pgraster, 0);
236  elog(ERROR, "RASTER_getYScale: Could not deserialize raster");
237  PG_RETURN_NULL();
238  }
239 
240  ysize = rt_raster_get_y_scale(raster);
241 
242  rt_raster_destroy(raster);
243  PG_FREE_IF_COPY(pgraster, 0);
244 
245  PG_RETURN_FLOAT8(ysize);
246 }
247 
252 Datum RASTER_getXSkew(PG_FUNCTION_ARGS)
253 {
254  rt_pgraster *pgraster;
256  double xskew;
257 
258  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
259  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
260 
261  raster = rt_raster_deserialize(pgraster, TRUE);
262  if ( ! raster ) {
263  PG_FREE_IF_COPY(pgraster, 0);
264  elog(ERROR, "RASTER_getXSkew: Could not deserialize raster");
265  PG_RETURN_NULL();
266  }
267 
268  xskew = rt_raster_get_x_skew(raster);
269 
270  rt_raster_destroy(raster);
271  PG_FREE_IF_COPY(pgraster, 0);
272 
273  PG_RETURN_FLOAT8(xskew);
274 }
275 
280 Datum RASTER_getYSkew(PG_FUNCTION_ARGS)
281 {
282  rt_pgraster *pgraster;
284  double yskew;
285 
286  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
287  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
288 
289  raster = rt_raster_deserialize(pgraster, TRUE);
290  if ( ! raster ) {
291  PG_FREE_IF_COPY(pgraster, 0);
292  elog(ERROR, "RASTER_getYSkew: Could not deserialize raster");
293  PG_RETURN_NULL();
294  }
295 
296  yskew = rt_raster_get_y_skew(raster);
297 
298  rt_raster_destroy(raster);
299  PG_FREE_IF_COPY(pgraster, 0);
300 
301  PG_RETURN_FLOAT8(yskew);
302 }
303 
308 Datum RASTER_getXUpperLeft(PG_FUNCTION_ARGS)
309 {
310  rt_pgraster *pgraster;
312  double xul;
313 
314  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
315  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
316 
317  raster = rt_raster_deserialize(pgraster, TRUE);
318  if ( ! raster ) {
319  PG_FREE_IF_COPY(pgraster, 0);
320  elog(ERROR, "RASTER_getXUpperLeft: Could not deserialize raster");
321  PG_RETURN_NULL();
322  }
323 
324  xul = rt_raster_get_x_offset(raster);
325 
326  rt_raster_destroy(raster);
327  PG_FREE_IF_COPY(pgraster, 0);
328 
329  PG_RETURN_FLOAT8(xul);
330 }
331 
336 Datum RASTER_getYUpperLeft(PG_FUNCTION_ARGS)
337 {
338  rt_pgraster *pgraster;
340  double yul;
341 
342  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
343  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
344 
345  raster = rt_raster_deserialize(pgraster, TRUE);
346  if ( ! raster ) {
347  PG_FREE_IF_COPY(pgraster, 0);
348  elog(ERROR, "RASTER_getYUpperLeft: Could not deserialize raster");
349  PG_RETURN_NULL();
350  }
351 
352  yul = rt_raster_get_y_offset(raster);
353 
354  rt_raster_destroy(raster);
355  PG_FREE_IF_COPY(pgraster, 0);
356 
357  PG_RETURN_FLOAT8(yul);
358 }
359 
368 Datum RASTER_getPixelWidth(PG_FUNCTION_ARGS)
369 {
370  rt_pgraster *pgraster;
372  double xscale;
373  double yskew;
374  double pwidth;
375 
376  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
377  pgraster = (rt_pgraster *)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
378 
379  raster = rt_raster_deserialize(pgraster, TRUE);
380  if (!raster) {
381  PG_FREE_IF_COPY(pgraster, 0);
382  elog(ERROR, "RASTER_getPixelWidth: Could not deserialize raster");
383  PG_RETURN_NULL();
384  }
385 
386  xscale = rt_raster_get_x_scale(raster);
387  yskew = rt_raster_get_y_skew(raster);
388  pwidth = sqrt(xscale*xscale + yskew*yskew);
389 
390  rt_raster_destroy(raster);
391  PG_FREE_IF_COPY(pgraster, 0);
392 
393  PG_RETURN_FLOAT8(pwidth);
394 }
395 
404 Datum RASTER_getPixelHeight(PG_FUNCTION_ARGS)
405 {
406  rt_pgraster *pgraster;
408  double yscale;
409  double xskew;
410  double pheight;
411 
412  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
413  pgraster = (rt_pgraster *)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
414 
415  raster = rt_raster_deserialize(pgraster, TRUE);
416  if (!raster) {
417  PG_FREE_IF_COPY(pgraster, 0);
418  elog(ERROR, "RASTER_getPixelHeight: Could not deserialize raster");
419  PG_RETURN_NULL();
420  }
421 
422  yscale = rt_raster_get_y_scale(raster);
423  xskew = rt_raster_get_x_skew(raster);
424  pheight = sqrt(yscale*yscale + xskew*xskew);
425 
426  rt_raster_destroy(raster);
427  PG_FREE_IF_COPY(pgraster, 0);
428 
429  PG_RETURN_FLOAT8(pheight);
430 }
431 
432 #define VALUES_LENGTH 6
433 
439 Datum RASTER_getGeotransform(PG_FUNCTION_ARGS)
440 {
441  rt_pgraster *pgraster = NULL;
442  rt_raster raster = NULL;
443 
444  double imag;
445  double jmag;
446  double theta_i;
447  double theta_ij;
448  /*
449  double xoffset;
450  double yoffset;
451  */
452 
453  TupleDesc result_tuple; /* for returning a composite */
454  Datum values[VALUES_LENGTH];
455  bool nulls[VALUES_LENGTH];
456  HeapTuple heap_tuple ; /* instance of the tuple to return */
457  Datum result;
458 
459  POSTGIS_RT_DEBUG(3, "RASTER_getGeotransform: Starting");
460 
461  /* get argument */
462  if (PG_ARGISNULL(0))
463  PG_RETURN_NULL();
464  pgraster = (rt_pgraster *)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
465 
466  /* raster */
467  raster = rt_raster_deserialize(pgraster, TRUE);
468  if (!raster) {
469  PG_FREE_IF_COPY(pgraster, 0);
470  elog(ERROR, "RASTER_getGeotransform: Could not deserialize raster");
471  PG_RETURN_NULL();
472  }
473 
474  /* do the calculation */
476  rt_raster_get_x_scale(raster),
477  rt_raster_get_x_skew(raster),
478  rt_raster_get_y_skew(raster),
479  rt_raster_get_y_scale(raster),
480  &imag, &jmag, &theta_i, &theta_ij) ;
481 
482  rt_raster_destroy(raster);
483  PG_FREE_IF_COPY(pgraster, 0);
484 
485  /* setup the return value infrastructure */
486  if (get_call_result_type(fcinfo, NULL, &result_tuple) != TYPEFUNC_COMPOSITE) {
487  ereport(ERROR, (
488  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
489  errmsg("RASTER_getGeotransform(): function returning record called in context that cannot accept type record"
490  )
491  ));
492  PG_RETURN_NULL();
493  }
494 
495  BlessTupleDesc(result_tuple);
496 
497  /* get argument */
498  /* prep the composite return value */
499  /* construct datum array */
500  values[0] = Float8GetDatum(imag);
501  values[1] = Float8GetDatum(jmag);
502  values[2] = Float8GetDatum(theta_i);
503  values[3] = Float8GetDatum(theta_ij);
504  values[4] = Float8GetDatum(rt_raster_get_x_offset(raster));
505  values[5] = Float8GetDatum(rt_raster_get_y_offset(raster));
506 
507  memset(nulls, FALSE, sizeof(bool) * VALUES_LENGTH);
508 
509  /* stick em on the heap */
510  heap_tuple = heap_form_tuple(result_tuple, values, nulls);
511 
512  /* make the tuple into a datum */
513  result = HeapTupleGetDatum(heap_tuple);
514 
515  PG_RETURN_DATUM(result);
516 }
517 
522 Datum RASTER_isEmpty(PG_FUNCTION_ARGS)
523 {
524  rt_pgraster *pgraster = NULL;
525  rt_raster raster = NULL;
526  bool isempty = FALSE;
527 
528  /* Deserialize raster */
529  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
530  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
531 
532  raster = rt_raster_deserialize(pgraster, TRUE);
533  if ( ! raster )
534  {
535  ereport(ERROR,
536  (errcode(ERRCODE_OUT_OF_MEMORY),
537  errmsg("RASTER_isEmpty: Could not deserialize raster")));
538  PG_FREE_IF_COPY(pgraster, 0);
539  PG_RETURN_NULL();
540  }
541 
542  isempty = rt_raster_is_empty(raster);
543 
544  rt_raster_destroy(raster);
545  PG_FREE_IF_COPY(pgraster, 0);
546 
547  PG_RETURN_BOOL(isempty);
548 }
549 
554 Datum RASTER_hasNoBand(PG_FUNCTION_ARGS)
555 {
556  rt_pgraster *pgraster = NULL;
557  rt_raster raster = NULL;
558  int bandindex = 0;
559  bool hasnoband = FALSE;
560 
561  /* Deserialize raster */
562  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
563  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
564 
565  raster = rt_raster_deserialize(pgraster, TRUE);
566  if ( ! raster )
567  {
568  ereport(ERROR,
569  (errcode(ERRCODE_OUT_OF_MEMORY),
570  errmsg("RASTER_hasNoBand: Could not deserialize raster")));
571  PG_FREE_IF_COPY(pgraster, 0);
572  PG_RETURN_NULL();
573  }
574 
575  /* Get band number */
576  bandindex = PG_GETARG_INT32(1);
577  hasnoband = !rt_raster_has_band(raster, bandindex - 1);
578 
579  rt_raster_destroy(raster);
580  PG_FREE_IF_COPY(pgraster, 0);
581 
582  PG_RETURN_BOOL(hasnoband);
583 }
584 
585 #undef VALUES_LENGTH
586 #define VALUES_LENGTH 10
587 
592 Datum RASTER_metadata(PG_FUNCTION_ARGS)
593 {
594  rt_pgraster *pgraster = NULL;
595  rt_raster raster = NULL;
596 
598  double scaleX;
599  double scaleY;
600  double ipX;
601  double ipY;
602  double skewX;
603  double skewY;
604  int32_t srid;
605  uint32_t width;
607 
608  TupleDesc tupdesc;
609  Datum values[VALUES_LENGTH];
610  bool nulls[VALUES_LENGTH];
611  HeapTuple tuple;
612  Datum result;
613 
614  POSTGIS_RT_DEBUG(3, "RASTER_metadata: Starting");
615 
616  /* pgraster is null, return null */
617  if (PG_ARGISNULL(0))
618  PG_RETURN_NULL();
619  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
620 
621  /* raster */
622  raster = rt_raster_deserialize(pgraster, TRUE);
623  if (!raster) {
624  PG_FREE_IF_COPY(pgraster, 0);
625  elog(ERROR, "RASTER_metadata; Could not deserialize raster");
626  PG_RETURN_NULL();
627  }
628 
629  /* upper left x, y */
630  ipX = rt_raster_get_x_offset(raster);
631  ipY = rt_raster_get_y_offset(raster);
632 
633  /* width, height */
634  width = rt_raster_get_width(raster);
635  height = rt_raster_get_height(raster);
636 
637  /* scale x, y */
638  scaleX = rt_raster_get_x_scale(raster);
639  scaleY = rt_raster_get_y_scale(raster);
640 
641  /* skew x, y */
642  skewX = rt_raster_get_x_skew(raster);
643  skewY = rt_raster_get_y_skew(raster);
644 
645  /* srid */
646  srid = rt_raster_get_srid(raster);
647 
648  /* numbands */
649  numBands = rt_raster_get_num_bands(raster);
650 
651  rt_raster_destroy(raster);
652  PG_FREE_IF_COPY(pgraster, 0);
653 
654  /* Build a tuple descriptor for our result type */
655  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
656  ereport(ERROR, (
657  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
658  errmsg(
659  "function returning record called in context "
660  "that cannot accept type record"
661  )
662  ));
663  }
664 
665  BlessTupleDesc(tupdesc);
666 
667  values[0] = Float8GetDatum(ipX);
668  values[1] = Float8GetDatum(ipY);
669  values[2] = UInt32GetDatum(width);
670  values[3] = UInt32GetDatum(height);
671  values[4] = Float8GetDatum(scaleX);
672  values[5] = Float8GetDatum(scaleY);
673  values[6] = Float8GetDatum(skewX);
674  values[7] = Float8GetDatum(skewY);
675  values[8] = Int32GetDatum(srid);
676  values[9] = UInt32GetDatum(numBands);
677 
678  memset(nulls, FALSE, sizeof(bool) * VALUES_LENGTH);
679 
680  /* build a tuple */
681  tuple = heap_form_tuple(tupdesc, values, nulls);
682 
683  /* make the tuple into a datum */
684  result = HeapTupleGetDatum(tuple);
685 
686  PG_RETURN_DATUM(result);
687 }
688 
689 #undef VALUES_LENGTH
690 #define VALUES_LENGTH 2
691 
693 Datum RASTER_rasterToWorldCoord(PG_FUNCTION_ARGS)
694 {
695  rt_pgraster *pgraster = NULL;
696  rt_raster raster = NULL;
697  int i = 0;
698  int cr[2] = {0};
699  bool skewed[2] = {false, false};
700  double cw[2] = {0};
701 
702  TupleDesc tupdesc;
703  Datum values[VALUES_LENGTH];
704  bool nulls[VALUES_LENGTH];
705  HeapTuple tuple;
706  Datum result;
707 
708  POSTGIS_RT_DEBUG(3, "RASTER_rasterToWorldCoord: Starting");
709 
710  /* pgraster is null, return null */
711  if (PG_ARGISNULL(0))
712  PG_RETURN_NULL();
713  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
714 
715  /* raster */
716  raster = rt_raster_deserialize(pgraster, TRUE);
717  if (!raster) {
718  PG_FREE_IF_COPY(pgraster, 0);
719  elog(ERROR, "RASTER_rasterToWorldCoord: Could not deserialize raster");
720  PG_RETURN_NULL();
721  }
722 
723  /* raster skewed? */
724  skewed[0] = FLT_NEQ(rt_raster_get_x_skew(raster), 0) ? true : false;
725  skewed[1] = FLT_NEQ(rt_raster_get_y_skew(raster), 0) ? true : false;
726 
727  /* column and row */
728  for (i = 1; i <= 2; i++) {
729  if (PG_ARGISNULL(i)) {
730  /* if skewed on same axis, parameter is required */
731  if (skewed[i - 1]) {
732  elog(NOTICE, "Pixel row and column required for computing longitude and latitude of a rotated raster");
733  rt_raster_destroy(raster);
734  PG_FREE_IF_COPY(pgraster, 0);
735  PG_RETURN_NULL();
736  }
737 
738  continue;
739  }
740 
741  cr[i - 1] = PG_GETARG_INT32(i);
742  }
743 
744  /* user-provided value is 1-based but needs to be 0-based */
746  raster,
747  (double) cr[0] - 1, (double) cr[1] - 1,
748  &(cw[0]), &(cw[1]),
749  NULL
750  ) != ES_NONE) {
751  rt_raster_destroy(raster);
752  PG_FREE_IF_COPY(pgraster, 0);
753  elog(ERROR, "RASTER_rasterToWorldCoord: Could not compute longitude and latitude from pixel row and column");
754  PG_RETURN_NULL();
755  }
756  rt_raster_destroy(raster);
757  PG_FREE_IF_COPY(pgraster, 0);
758 
759  /* Build a tuple descriptor for our result type */
760  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
761  ereport(ERROR, (
762  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
763  errmsg(
764  "function returning record called in context "
765  "that cannot accept type record"
766  )
767  ));
768  }
769 
770  BlessTupleDesc(tupdesc);
771 
772  values[0] = Float8GetDatum(cw[0]);
773  values[1] = Float8GetDatum(cw[1]);
774 
775  memset(nulls, FALSE, sizeof(bool) * VALUES_LENGTH);
776 
777  /* build a tuple */
778  tuple = heap_form_tuple(tupdesc, values, nulls);
779 
780  /* make the tuple into a datum */
781  result = HeapTupleGetDatum(tuple);
782 
783  PG_RETURN_DATUM(result);
784 }
785 
787 Datum RASTER_worldToRasterCoord(PG_FUNCTION_ARGS)
788 {
789  rt_pgraster *pgraster = NULL;
790  rt_raster raster = NULL;
791  int i = 0;
792  double cw[2] = {0};
793  double _cr[2] = {0};
794  int cr[2] = {0};
795  bool skewed = false;
796 
797  TupleDesc tupdesc;
798  Datum values[VALUES_LENGTH];
799  bool nulls[VALUES_LENGTH];
800  HeapTuple tuple;
801  Datum result;
802 
803  POSTGIS_RT_DEBUG(3, "RASTER_worldToRasterCoord: Starting");
804 
805  /* pgraster is null, return null */
806  if (PG_ARGISNULL(0))
807  PG_RETURN_NULL();
808  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
809 
810  /* raster */
811  raster = rt_raster_deserialize(pgraster, TRUE);
812  if (!raster) {
813  PG_FREE_IF_COPY(pgraster, 0);
814  elog(ERROR, "RASTER_worldToRasterCoord: Could not deserialize raster");
815  PG_RETURN_NULL();
816  }
817 
818  /* raster skewed? */
819  skewed = FLT_NEQ(rt_raster_get_x_skew(raster), 0) ? true : false;
820  if (!skewed)
821  skewed = FLT_NEQ(rt_raster_get_y_skew(raster), 0) ? true : false;
822 
823  /* longitude and latitude */
824  for (i = 1; i <= 2; i++) {
825  if (PG_ARGISNULL(i)) {
826  /* if skewed, parameter is required */
827  if (skewed) {
828  elog(NOTICE, "Latitude and longitude required for computing pixel row and column of a rotated raster");
829  rt_raster_destroy(raster);
830  PG_FREE_IF_COPY(pgraster, 0);
831  PG_RETURN_NULL();
832  }
833 
834  continue;
835  }
836 
837  cw[i - 1] = PG_GETARG_FLOAT8(i);
838  }
839 
840  /* return pixel row and column values are 0-based */
842  raster,
843  cw[0], cw[1],
844  &(_cr[0]), &(_cr[1]),
845  NULL
846  ) != ES_NONE) {
847  rt_raster_destroy(raster);
848  PG_FREE_IF_COPY(pgraster, 0);
849  elog(ERROR, "RASTER_worldToRasterCoord: Could not compute pixel row and column from longitude and latitude");
850  PG_RETURN_NULL();
851  }
852  rt_raster_destroy(raster);
853  PG_FREE_IF_COPY(pgraster, 0);
854 
855  /* force to integer and add one to make 1-based */
856  cr[0] = ((int) _cr[0]) + 1;
857  cr[1] = ((int) _cr[1]) + 1;
858 
859  /* Build a tuple descriptor for our result type */
860  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
861  ereport(ERROR, (
862  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
863  errmsg(
864  "function returning record called in context "
865  "that cannot accept type record"
866  )
867  ));
868  }
869 
870  BlessTupleDesc(tupdesc);
871 
872  values[0] = Int32GetDatum(cr[0]);
873  values[1] = Int32GetDatum(cr[1]);
874 
875  memset(nulls, FALSE, sizeof(bool) * VALUES_LENGTH);
876 
877  /* build a tuple */
878  tuple = heap_form_tuple(tupdesc, values, nulls);
879 
880  /* make the tuple into a datum */
881  result = HeapTupleGetDatum(tuple);
882 
883  PG_RETURN_DATUM(result);
884 }
885 
890 Datum RASTER_setSRID(PG_FUNCTION_ARGS)
891 {
892  rt_pgraster *pgraster = NULL;
893  rt_pgraster *pgrtn = NULL;
895  int32_t newSRID = PG_GETARG_INT32(1);
896 
897  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
898  pgraster = (rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
899 
900  raster = rt_raster_deserialize(pgraster, FALSE);
901  if (!raster) {
902  PG_FREE_IF_COPY(pgraster, 0);
903  elog(ERROR, "RASTER_setSRID: Could not deserialize raster");
904  PG_RETURN_NULL();
905  }
906 
907  rt_raster_set_srid(raster, newSRID);
908 
909  pgrtn = rt_raster_serialize(raster);
910  rt_raster_destroy(raster);
911  PG_FREE_IF_COPY(pgraster, 0);
912  if (!pgrtn) PG_RETURN_NULL();
913 
914  SET_VARSIZE(pgrtn, pgrtn->size);
915 
916  PG_RETURN_POINTER(pgrtn);
917 }
918 
923 Datum RASTER_setScale(PG_FUNCTION_ARGS)
924 {
925  rt_pgraster *pgraster = NULL;
926  rt_pgraster *pgrtn = NULL;
928  double size = PG_GETARG_FLOAT8(1);
929 
930  if (PG_ARGISNULL(0))
931  PG_RETURN_NULL();
932  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
933  raster = rt_raster_deserialize(pgraster, FALSE);
934  if (!raster) {
935  PG_FREE_IF_COPY(pgraster, 0);
936  elog(ERROR, "RASTER_setScale: Could not deserialize raster");
937  PG_RETURN_NULL();
938  }
939 
940  rt_raster_set_scale(raster, size, size);
941 
942  pgrtn = rt_raster_serialize(raster);
943  rt_raster_destroy(raster);
944  PG_FREE_IF_COPY(pgraster, 0);
945  if (!pgrtn)
946  PG_RETURN_NULL();
947 
948  SET_VARSIZE(pgrtn, pgrtn->size);
949  PG_RETURN_POINTER(pgrtn);
950 }
951 
956 Datum RASTER_setScaleXY(PG_FUNCTION_ARGS)
957 {
958  rt_pgraster *pgraster = NULL;
959  rt_pgraster *pgrtn = NULL;
961  double xscale = PG_GETARG_FLOAT8(1);
962  double yscale = PG_GETARG_FLOAT8(2);
963 
964  if (PG_ARGISNULL(0))
965  PG_RETURN_NULL();
966  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
967  raster = rt_raster_deserialize(pgraster, FALSE);
968  if (!raster) {
969  PG_FREE_IF_COPY(pgraster, 0);
970  elog(ERROR, "RASTER_setScaleXY: Could not deserialize raster");
971  PG_RETURN_NULL();
972  }
973 
974  rt_raster_set_scale(raster, xscale, yscale);
975  pgrtn = rt_raster_serialize(raster);
976  rt_raster_destroy(raster);
977  PG_FREE_IF_COPY(pgraster, 0);
978  if (!pgrtn)
979  PG_RETURN_NULL();
980 
981  SET_VARSIZE(pgrtn, pgrtn->size);
982  PG_RETURN_POINTER(pgrtn);
983 }
984 
989 Datum RASTER_setSkew(PG_FUNCTION_ARGS)
990 {
991  rt_pgraster *pgraster = NULL;
992  rt_pgraster *pgrtn = NULL;
994  double skew = PG_GETARG_FLOAT8(1);
995 
996  if (PG_ARGISNULL(0))
997  PG_RETURN_NULL();
998  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
999  raster = rt_raster_deserialize(pgraster, FALSE);
1000  if (!raster) {
1001  PG_FREE_IF_COPY(pgraster, 0);
1002  elog(ERROR, "RASTER_setSkew: Could not deserialize raster");
1003  PG_RETURN_NULL();
1004  }
1005 
1006  rt_raster_set_skews(raster, skew, skew);
1007 
1008  pgrtn = rt_raster_serialize(raster);
1009  rt_raster_destroy(raster);
1010  PG_FREE_IF_COPY(pgraster, 0);
1011  if (!pgrtn)
1012  PG_RETURN_NULL();
1013 
1014  SET_VARSIZE(pgrtn, pgrtn->size);
1015  PG_RETURN_POINTER(pgrtn);
1016 }
1017 
1022 Datum RASTER_setSkewXY(PG_FUNCTION_ARGS)
1023 {
1024  rt_pgraster *pgraster = NULL;
1025  rt_pgraster *pgrtn = NULL;
1026  rt_raster raster;
1027  double xskew = PG_GETARG_FLOAT8(1);
1028  double yskew = PG_GETARG_FLOAT8(2);
1029 
1030  if (PG_ARGISNULL(0))
1031  PG_RETURN_NULL();
1032  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1033  raster = rt_raster_deserialize(pgraster, FALSE);
1034  if (!raster) {
1035  PG_FREE_IF_COPY(pgraster, 0);
1036  elog(ERROR, "RASTER_setSkewXY: Could not deserialize raster");
1037  PG_RETURN_NULL();
1038  }
1039 
1040  rt_raster_set_skews(raster, xskew, yskew);
1041 
1042  pgrtn = rt_raster_serialize(raster);
1043  rt_raster_destroy(raster);
1044  PG_FREE_IF_COPY(pgraster, 0);
1045  if (!pgrtn)
1046  PG_RETURN_NULL();
1047 
1048  SET_VARSIZE(pgrtn, pgrtn->size);
1049  PG_RETURN_POINTER(pgrtn);
1050 }
1051 
1056 Datum RASTER_setUpperLeftXY(PG_FUNCTION_ARGS)
1057 {
1058  rt_pgraster *pgraster = NULL;
1059  rt_pgraster *pgrtn = NULL;
1060  rt_raster raster;
1061  double xoffset = PG_GETARG_FLOAT8(1);
1062  double yoffset = PG_GETARG_FLOAT8(2);
1063 
1064  if (PG_ARGISNULL(0))
1065  PG_RETURN_NULL();
1066  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1067  raster = rt_raster_deserialize(pgraster, FALSE);
1068  if (!raster) {
1069  PG_FREE_IF_COPY(pgraster, 0);
1070  elog(ERROR, "RASTER_setUpperLeftXY: Could not deserialize raster");
1071  PG_RETURN_NULL();
1072  }
1073 
1074  rt_raster_set_offsets(raster, xoffset, yoffset);
1075 
1076  pgrtn = rt_raster_serialize(raster);
1077  rt_raster_destroy(raster);
1078  PG_FREE_IF_COPY(pgraster, 0);
1079  if (!pgrtn)
1080  PG_RETURN_NULL();
1081 
1082  SET_VARSIZE(pgrtn, pgrtn->size);
1083  PG_RETURN_POINTER(pgrtn);
1084 }
1085 
1090 Datum RASTER_setGeotransform(PG_FUNCTION_ARGS)
1091 {
1092  rt_pgraster *pgraster = NULL;
1093  rt_pgraster *pgrtn = NULL;
1094  rt_raster raster;
1095  float8 imag, jmag, theta_i, theta_ij, xoffset, yoffset;
1096 
1097  if (
1098  PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) ||
1099  PG_ARGISNULL(3) || PG_ARGISNULL(4) ||
1100  PG_ARGISNULL(5) || PG_ARGISNULL(6)
1101  ) {
1102  PG_RETURN_NULL();
1103  }
1104 
1105  /* get the inputs */
1106  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1107  imag = PG_GETARG_FLOAT8(1);
1108  jmag = PG_GETARG_FLOAT8(2);
1109  theta_i = PG_GETARG_FLOAT8(3);
1110  theta_ij = PG_GETARG_FLOAT8(4);
1111  xoffset = PG_GETARG_FLOAT8(5);
1112  yoffset = PG_GETARG_FLOAT8(6);
1113 
1114  raster = rt_raster_deserialize(pgraster, TRUE);
1115  if (!raster) {
1116  PG_FREE_IF_COPY(pgraster, 0);
1117  elog(ERROR, "RASTER_setGeotransform: Could not deserialize raster");
1118  PG_RETURN_NULL();
1119  }
1120 
1121  /* store the new geotransform */
1122  rt_raster_set_phys_params(raster, imag,jmag,theta_i,theta_ij);
1123  rt_raster_set_offsets(raster, xoffset, yoffset);
1124 
1125  /* prep the return value */
1126  pgrtn = rt_raster_serialize(raster);
1127  rt_raster_destroy(raster);
1128  PG_FREE_IF_COPY(pgraster, 0);
1129  if (!pgrtn)
1130  PG_RETURN_NULL();
1131 
1132  SET_VARSIZE(pgrtn, pgrtn->size);
1133  PG_RETURN_POINTER(pgrtn);
1134 }
1135 
1148 Datum RASTER_setRotation(PG_FUNCTION_ARGS)
1149 {
1150  rt_pgraster *pgraster = NULL;
1151  rt_pgraster *pgrtn = NULL;
1152  rt_raster raster;
1153  double rotation = PG_GETARG_FLOAT8(1);
1154  double imag, jmag, theta_i, theta_ij;
1155 
1156  if (PG_ARGISNULL(0))
1157  PG_RETURN_NULL();
1158  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1159 
1160  raster = rt_raster_deserialize(pgraster, FALSE);
1161  if (! raster ) {
1162  PG_FREE_IF_COPY(pgraster, 0);
1163  elog(ERROR, "RASTER_setRotation: Could not deserialize raster");
1164  PG_RETURN_NULL();
1165  }
1166 
1167  /* preserve all defining characteristics of the grid except for rotation */
1168  rt_raster_get_phys_params(raster, &imag, &jmag, &theta_i, &theta_ij);
1169  rt_raster_set_phys_params(raster, imag, jmag, rotation, theta_ij);
1170 
1171  pgrtn = rt_raster_serialize(raster);
1172  rt_raster_destroy(raster);
1173  PG_FREE_IF_COPY(pgraster, 0);
1174  if (!pgrtn)
1175  PG_RETURN_NULL();
1176 
1177  SET_VARSIZE(pgrtn, pgrtn->size);
1178  PG_RETURN_POINTER(pgrtn);
1179 }
#define VALUES_LENGTH
Datum RASTER_setUpperLeftXY(PG_FUNCTION_ARGS)
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_serialize.c:521
double rt_raster_get_x_offset(rt_raster raster)
Get raster x offset, in projection units.
Definition: rt_raster.c:213
double rt_raster_get_y_skew(rt_raster raster)
Get skew about the Y axis.
Definition: rt_raster.c:190
uint16_t rt_raster_get_num_bands(rt_raster raster)
Definition: rt_raster.c:372
Datum RASTER_getYScale(PG_FUNCTION_ARGS)
Datum RASTER_setScale(PG_FUNCTION_ARGS)
Datum RASTER_getYUpperLeft(PG_FUNCTION_ARGS)
raster
Be careful!! Zeros function&#39;s input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
Datum RASTER_getSRID(PG_FUNCTION_ARGS)
void rt_raster_set_skews(rt_raster raster, double skewX, double skewY)
Set skews about the X and Y axis.
Definition: rt_raster.c:168
ysize
Definition: window.py:69
Datum RASTER_getYSkew(PG_FUNCTION_ARGS)
Datum RASTER_metadata(PG_FUNCTION_ARGS)
void rt_raster_get_phys_params(rt_raster rast, double *i_mag, double *j_mag, double *theta_i, double *theta_ij)
Calculates and returns the physically significant descriptors embodied in the geotransform attached t...
Definition: rt_raster.c:231
Datum RASTER_isEmpty(PG_FUNCTION_ARGS)
Datum RASTER_setSRID(PG_FUNCTION_ARGS)
Datum RASTER_getHeight(PG_FUNCTION_ARGS)
Datum RASTER_setGeotransform(PG_FUNCTION_ARGS)
Datum RASTER_getXSkew(PG_FUNCTION_ARGS)
Datum RASTER_setRotation(PG_FUNCTION_ARGS)
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
Definition: rt_raster.c:1334
unsigned int uint32_t
Definition: uthash.h:78
Datum RASTER_getWidth(PG_FUNCTION_ARGS)
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.
Definition: rt_raster.c:755
Datum RASTER_getPixelWidth(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(RASTER_getSRID)
Return the SRID associated with the raster.
Datum RASTER_getNumBands(PG_FUNCTION_ARGS)
void rt_raster_set_scale(rt_raster raster, double scaleX, double scaleY)
Set scale in projection units.
Definition: rt_raster.c:137
void rt_raster_set_offsets(rt_raster raster, double x, double y)
Set insertion points in projection units.
Definition: rt_raster.c:199
void rt_raster_set_phys_params(rt_raster rast, double i_mag, double j_mag, double theta_i, double theta_ij)
Calculates the geotransform coefficients and applies them to the supplied raster. ...
Definition: rt_raster.c:297
#define FLT_NEQ(x, y)
Definition: librtcore.h:2233
Datum RASTER_setSkewXY(PG_FUNCTION_ARGS)
xsize
Definition: window.py:68
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
Definition: rt_raster.c:150
Datum RASTER_getXScale(PG_FUNCTION_ARGS)
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
Definition: rt_raster.c:1347
Datum RASTER_setSkew(PG_FUNCTION_ARGS)
Datum RASTER_getXUpperLeft(PG_FUNCTION_ARGS)
Datum RASTER_getFileSize(PG_FUNCTION_ARGS)
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
rt_errorstate rt_raster_geopoint_to_cell(rt_raster raster, double xw, double yw, double *xr, double *yr, double *igt)
Convert an xw, yw map point to a xr, yr raster point.
Definition: rt_raster.c:806
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
Definition: rt_raster.c:159
double rt_raster_get_x_skew(rt_raster raster)
Get skew about the X axis.
Definition: rt_raster.c:181
void rt_raster_calc_phys_params(double xscale, double xskew, double yskew, double yscale, double *i_mag, double *j_mag, double *theta_i, double *theta_ij)
Calculates the physically significant descriptors embodied in an arbitrary geotransform.
Definition: rt_raster.c:250
uint16_t rt_raster_get_width(rt_raster raster)
Definition: rt_raster.c:121
#define FALSE
Definition: dbfopen.c:168
Struct definitions.
Definition: librtcore.h:2250
Datum RASTER_worldToRasterCoord(PG_FUNCTION_ARGS)
Datum RASTER_getPixelHeight(PG_FUNCTION_ARGS)
Datum RASTER_setScaleXY(PG_FUNCTION_ARGS)
uint16_t rt_raster_get_height(rt_raster raster)
Definition: rt_raster.c:129
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rtpostgis.h:61
Datum RASTER_getFileTimestamp(PG_FUNCTION_ARGS)
#define TRUE
Definition: dbfopen.c:169
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_serialize.c:725
Datum RASTER_rasterToWorldCoord(PG_FUNCTION_ARGS)
double rt_raster_get_y_offset(rt_raster raster)
Get raster y offset, in projection units.
Definition: rt_raster.c:222
Datum RASTER_getGeotransform(PG_FUNCTION_ARGS)
Datum RASTER_hasNoBand(PG_FUNCTION_ARGS)