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