PostGIS  2.3.7dev-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 #if POSTGIS_PGSQL_VERSION > 92
37 #include "access/htup_details.h" /* for heap_form_tuple() */
38 #endif
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 
435 Datum RASTER_getGeotransform(PG_FUNCTION_ARGS)
436 {
437  rt_pgraster *pgraster = NULL;
438  rt_raster raster = NULL;
439 
440  double imag;
441  double jmag;
442  double theta_i;
443  double theta_ij;
444  /*
445  double xoffset;
446  double yoffset;
447  */
448 
449  TupleDesc result_tuple; /* for returning a composite */
450  int values_length = 6;
451  Datum values[values_length];
452  bool nulls[values_length];
453  HeapTuple heap_tuple ; /* instance of the tuple to return */
454  Datum result;
455 
456  POSTGIS_RT_DEBUG(3, "RASTER_getGeotransform: Starting");
457 
458  /* get argument */
459  if (PG_ARGISNULL(0))
460  PG_RETURN_NULL();
461  pgraster = (rt_pgraster *)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
462 
463  /* raster */
464  raster = rt_raster_deserialize(pgraster, TRUE);
465  if (!raster) {
466  PG_FREE_IF_COPY(pgraster, 0);
467  elog(ERROR, "RASTER_getGeotransform: Could not deserialize raster");
468  PG_RETURN_NULL();
469  }
470 
471  /* do the calculation */
473  rt_raster_get_x_scale(raster),
474  rt_raster_get_x_skew(raster),
475  rt_raster_get_y_skew(raster),
476  rt_raster_get_y_scale(raster),
477  &imag, &jmag, &theta_i, &theta_ij) ;
478 
479  rt_raster_destroy(raster);
480  PG_FREE_IF_COPY(pgraster, 0);
481 
482  /* setup the return value infrastructure */
483  if (get_call_result_type(fcinfo, NULL, &result_tuple) != TYPEFUNC_COMPOSITE) {
484  ereport(ERROR, (
485  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
486  errmsg("RASTER_getGeotransform(): function returning record called in context that cannot accept type record"
487  )
488  ));
489  PG_RETURN_NULL();
490  }
491 
492  BlessTupleDesc(result_tuple);
493 
494  /* get argument */
495  /* prep the composite return value */
496  /* construct datum array */
497  values[0] = Float8GetDatum(imag);
498  values[1] = Float8GetDatum(jmag);
499  values[2] = Float8GetDatum(theta_i);
500  values[3] = Float8GetDatum(theta_ij);
501  values[4] = Float8GetDatum(rt_raster_get_x_offset(raster));
502  values[5] = Float8GetDatum(rt_raster_get_y_offset(raster));
503 
504  memset(nulls, FALSE, sizeof(bool) * values_length);
505 
506  /* stick em on the heap */
507  heap_tuple = heap_form_tuple(result_tuple, values, nulls);
508 
509  /* make the tuple into a datum */
510  result = HeapTupleGetDatum(heap_tuple);
511 
512  PG_RETURN_DATUM(result);
513 }
514 
519 Datum RASTER_isEmpty(PG_FUNCTION_ARGS)
520 {
521  rt_pgraster *pgraster = NULL;
522  rt_raster raster = NULL;
523  bool isempty = FALSE;
524 
525  /* Deserialize raster */
526  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
527  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
528 
529  raster = rt_raster_deserialize(pgraster, TRUE);
530  if ( ! raster )
531  {
532  ereport(ERROR,
533  (errcode(ERRCODE_OUT_OF_MEMORY),
534  errmsg("RASTER_isEmpty: Could not deserialize raster")));
535  PG_FREE_IF_COPY(pgraster, 0);
536  PG_RETURN_NULL();
537  }
538 
539  isempty = rt_raster_is_empty(raster);
540 
541  rt_raster_destroy(raster);
542  PG_FREE_IF_COPY(pgraster, 0);
543 
544  PG_RETURN_BOOL(isempty);
545 }
546 
551 Datum RASTER_hasNoBand(PG_FUNCTION_ARGS)
552 {
553  rt_pgraster *pgraster = NULL;
554  rt_raster raster = NULL;
555  int bandindex = 0;
556  bool hasnoband = FALSE;
557 
558  /* Deserialize raster */
559  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
560  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
561 
562  raster = rt_raster_deserialize(pgraster, TRUE);
563  if ( ! raster )
564  {
565  ereport(ERROR,
566  (errcode(ERRCODE_OUT_OF_MEMORY),
567  errmsg("RASTER_hasNoBand: Could not deserialize raster")));
568  PG_FREE_IF_COPY(pgraster, 0);
569  PG_RETURN_NULL();
570  }
571 
572  /* Get band number */
573  bandindex = PG_GETARG_INT32(1);
574  hasnoband = !rt_raster_has_band(raster, bandindex - 1);
575 
576  rt_raster_destroy(raster);
577  PG_FREE_IF_COPY(pgraster, 0);
578 
579  PG_RETURN_BOOL(hasnoband);
580 }
581 
586 Datum RASTER_metadata(PG_FUNCTION_ARGS)
587 {
588  rt_pgraster *pgraster = NULL;
589  rt_raster raster = NULL;
590 
591  uint32_t numBands;
592  double scaleX;
593  double scaleY;
594  double ipX;
595  double ipY;
596  double skewX;
597  double skewY;
598  int32_t srid;
599  uint32_t width;
600  uint32_t height;
601 
602  TupleDesc tupdesc;
603  int values_length = 10;
604  Datum values[values_length];
605  bool nulls[values_length];
606  HeapTuple tuple;
607  Datum result;
608 
609  POSTGIS_RT_DEBUG(3, "RASTER_metadata: Starting");
610 
611  /* pgraster is null, return null */
612  if (PG_ARGISNULL(0))
613  PG_RETURN_NULL();
614  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
615 
616  /* raster */
617  raster = rt_raster_deserialize(pgraster, TRUE);
618  if (!raster) {
619  PG_FREE_IF_COPY(pgraster, 0);
620  elog(ERROR, "RASTER_metadata; Could not deserialize raster");
621  PG_RETURN_NULL();
622  }
623 
624  /* upper left x, y */
625  ipX = rt_raster_get_x_offset(raster);
626  ipY = rt_raster_get_y_offset(raster);
627 
628  /* width, height */
629  width = rt_raster_get_width(raster);
630  height = rt_raster_get_height(raster);
631 
632  /* scale x, y */
633  scaleX = rt_raster_get_x_scale(raster);
634  scaleY = rt_raster_get_y_scale(raster);
635 
636  /* skew x, y */
637  skewX = rt_raster_get_x_skew(raster);
638  skewY = rt_raster_get_y_skew(raster);
639 
640  /* srid */
641  srid = rt_raster_get_srid(raster);
642 
643  /* numbands */
644  numBands = rt_raster_get_num_bands(raster);
645 
646  rt_raster_destroy(raster);
647  PG_FREE_IF_COPY(pgraster, 0);
648 
649  /* Build a tuple descriptor for our result type */
650  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
651  ereport(ERROR, (
652  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
653  errmsg(
654  "function returning record called in context "
655  "that cannot accept type record"
656  )
657  ));
658  }
659 
660  BlessTupleDesc(tupdesc);
661 
662  values[0] = Float8GetDatum(ipX);
663  values[1] = Float8GetDatum(ipY);
664  values[2] = UInt32GetDatum(width);
665  values[3] = UInt32GetDatum(height);
666  values[4] = Float8GetDatum(scaleX);
667  values[5] = Float8GetDatum(scaleY);
668  values[6] = Float8GetDatum(skewX);
669  values[7] = Float8GetDatum(skewY);
670  values[8] = Int32GetDatum(srid);
671  values[9] = UInt32GetDatum(numBands);
672 
673  memset(nulls, FALSE, sizeof(bool) * values_length);
674 
675  /* build a tuple */
676  tuple = heap_form_tuple(tupdesc, values, nulls);
677 
678  /* make the tuple into a datum */
679  result = HeapTupleGetDatum(tuple);
680 
681  PG_RETURN_DATUM(result);
682 }
683 
685 Datum RASTER_rasterToWorldCoord(PG_FUNCTION_ARGS)
686 {
687  rt_pgraster *pgraster = NULL;
688  rt_raster raster = NULL;
689  int i = 0;
690  int cr[2] = {0};
691  bool skewed[2] = {false, false};
692  double cw[2] = {0};
693 
694  TupleDesc tupdesc;
695  int values_length = 2;
696  Datum values[values_length];
697  bool nulls[values_length];
698  HeapTuple tuple;
699  Datum result;
700 
701  POSTGIS_RT_DEBUG(3, "RASTER_rasterToWorldCoord: Starting");
702 
703  /* pgraster is null, return null */
704  if (PG_ARGISNULL(0))
705  PG_RETURN_NULL();
706  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
707 
708  /* raster */
709  raster = rt_raster_deserialize(pgraster, TRUE);
710  if (!raster) {
711  PG_FREE_IF_COPY(pgraster, 0);
712  elog(ERROR, "RASTER_rasterToWorldCoord: Could not deserialize raster");
713  PG_RETURN_NULL();
714  }
715 
716  /* raster skewed? */
717  skewed[0] = FLT_NEQ(rt_raster_get_x_skew(raster), 0) ? true : false;
718  skewed[1] = FLT_NEQ(rt_raster_get_y_skew(raster), 0) ? true : false;
719 
720  /* column and row */
721  for (i = 1; i <= 2; i++) {
722  if (PG_ARGISNULL(i)) {
723  /* if skewed on same axis, parameter is required */
724  if (skewed[i - 1]) {
725  elog(NOTICE, "Pixel row and column required for computing longitude and latitude of a rotated raster");
726  rt_raster_destroy(raster);
727  PG_FREE_IF_COPY(pgraster, 0);
728  PG_RETURN_NULL();
729  }
730 
731  continue;
732  }
733 
734  cr[i - 1] = PG_GETARG_INT32(i);
735  }
736 
737  /* user-provided value is 1-based but needs to be 0-based */
739  raster,
740  (double) cr[0] - 1, (double) cr[1] - 1,
741  &(cw[0]), &(cw[1]),
742  NULL
743  ) != ES_NONE) {
744  rt_raster_destroy(raster);
745  PG_FREE_IF_COPY(pgraster, 0);
746  elog(ERROR, "RASTER_rasterToWorldCoord: Could not compute longitude and latitude from pixel row and column");
747  PG_RETURN_NULL();
748  }
749  rt_raster_destroy(raster);
750  PG_FREE_IF_COPY(pgraster, 0);
751 
752  /* Build a tuple descriptor for our result type */
753  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
754  ereport(ERROR, (
755  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
756  errmsg(
757  "function returning record called in context "
758  "that cannot accept type record"
759  )
760  ));
761  }
762 
763  BlessTupleDesc(tupdesc);
764 
765  values[0] = Float8GetDatum(cw[0]);
766  values[1] = Float8GetDatum(cw[1]);
767 
768  memset(nulls, FALSE, sizeof(bool) * values_length);
769 
770  /* build a tuple */
771  tuple = heap_form_tuple(tupdesc, values, nulls);
772 
773  /* make the tuple into a datum */
774  result = HeapTupleGetDatum(tuple);
775 
776  PG_RETURN_DATUM(result);
777 }
778 
780 Datum RASTER_worldToRasterCoord(PG_FUNCTION_ARGS)
781 {
782  rt_pgraster *pgraster = NULL;
783  rt_raster raster = NULL;
784  int i = 0;
785  double cw[2] = {0};
786  double _cr[2] = {0};
787  int cr[2] = {0};
788  bool skewed = false;
789 
790  TupleDesc tupdesc;
791  int values_length = 2;
792  Datum values[values_length];
793  bool nulls[values_length];
794  HeapTuple tuple;
795  Datum result;
796 
797  POSTGIS_RT_DEBUG(3, "RASTER_worldToRasterCoord: Starting");
798 
799  /* pgraster is null, return null */
800  if (PG_ARGISNULL(0))
801  PG_RETURN_NULL();
802  pgraster = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, sizeof(struct rt_raster_serialized_t));
803 
804  /* raster */
805  raster = rt_raster_deserialize(pgraster, TRUE);
806  if (!raster) {
807  PG_FREE_IF_COPY(pgraster, 0);
808  elog(ERROR, "RASTER_worldToRasterCoord: Could not deserialize raster");
809  PG_RETURN_NULL();
810  }
811 
812  /* raster skewed? */
813  skewed = FLT_NEQ(rt_raster_get_x_skew(raster), 0) ? true : false;
814  if (!skewed)
815  skewed = FLT_NEQ(rt_raster_get_y_skew(raster), 0) ? true : false;
816 
817  /* longitude and latitude */
818  for (i = 1; i <= 2; i++) {
819  if (PG_ARGISNULL(i)) {
820  /* if skewed, parameter is required */
821  if (skewed) {
822  elog(NOTICE, "Latitude and longitude required for computing pixel row and column of a rotated raster");
823  rt_raster_destroy(raster);
824  PG_FREE_IF_COPY(pgraster, 0);
825  PG_RETURN_NULL();
826  }
827 
828  continue;
829  }
830 
831  cw[i - 1] = PG_GETARG_FLOAT8(i);
832  }
833 
834  /* return pixel row and column values are 0-based */
836  raster,
837  cw[0], cw[1],
838  &(_cr[0]), &(_cr[1]),
839  NULL
840  ) != ES_NONE) {
841  rt_raster_destroy(raster);
842  PG_FREE_IF_COPY(pgraster, 0);
843  elog(ERROR, "RASTER_worldToRasterCoord: Could not compute pixel row and column from longitude and latitude");
844  PG_RETURN_NULL();
845  }
846  rt_raster_destroy(raster);
847  PG_FREE_IF_COPY(pgraster, 0);
848 
849  /* force to integer and add one to make 1-based */
850  cr[0] = ((int) _cr[0]) + 1;
851  cr[1] = ((int) _cr[1]) + 1;
852 
853  /* Build a tuple descriptor for our result type */
854  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
855  ereport(ERROR, (
856  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
857  errmsg(
858  "function returning record called in context "
859  "that cannot accept type record"
860  )
861  ));
862  }
863 
864  BlessTupleDesc(tupdesc);
865 
866  values[0] = Int32GetDatum(cr[0]);
867  values[1] = Int32GetDatum(cr[1]);
868 
869  memset(nulls, FALSE, sizeof(bool) * values_length);
870 
871  /* build a tuple */
872  tuple = heap_form_tuple(tupdesc, values, nulls);
873 
874  /* make the tuple into a datum */
875  result = HeapTupleGetDatum(tuple);
876 
877  PG_RETURN_DATUM(result);
878 }
879 
884 Datum RASTER_setSRID(PG_FUNCTION_ARGS)
885 {
886  rt_pgraster *pgraster = NULL;
887  rt_pgraster *pgrtn = NULL;
889  int32_t newSRID = PG_GETARG_INT32(1);
890 
891  if (PG_ARGISNULL(0)) PG_RETURN_NULL();
892  pgraster = (rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
893 
894  raster = rt_raster_deserialize(pgraster, FALSE);
895  if (!raster) {
896  PG_FREE_IF_COPY(pgraster, 0);
897  elog(ERROR, "RASTER_setSRID: Could not deserialize raster");
898  PG_RETURN_NULL();
899  }
900 
901  rt_raster_set_srid(raster, newSRID);
902 
903  pgrtn = rt_raster_serialize(raster);
904  rt_raster_destroy(raster);
905  PG_FREE_IF_COPY(pgraster, 0);
906  if (!pgrtn) PG_RETURN_NULL();
907 
908  SET_VARSIZE(pgrtn, pgrtn->size);
909 
910  PG_RETURN_POINTER(pgrtn);
911 }
912 
917 Datum RASTER_setScale(PG_FUNCTION_ARGS)
918 {
919  rt_pgraster *pgraster = NULL;
920  rt_pgraster *pgrtn = NULL;
922  double size = PG_GETARG_FLOAT8(1);
923 
924  if (PG_ARGISNULL(0))
925  PG_RETURN_NULL();
926  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
927  raster = rt_raster_deserialize(pgraster, FALSE);
928  if (!raster) {
929  PG_FREE_IF_COPY(pgraster, 0);
930  elog(ERROR, "RASTER_setScale: Could not deserialize raster");
931  PG_RETURN_NULL();
932  }
933 
934  rt_raster_set_scale(raster, size, size);
935 
936  pgrtn = rt_raster_serialize(raster);
937  rt_raster_destroy(raster);
938  PG_FREE_IF_COPY(pgraster, 0);
939  if (!pgrtn)
940  PG_RETURN_NULL();
941 
942  SET_VARSIZE(pgrtn, pgrtn->size);
943  PG_RETURN_POINTER(pgrtn);
944 }
945 
950 Datum RASTER_setScaleXY(PG_FUNCTION_ARGS)
951 {
952  rt_pgraster *pgraster = NULL;
953  rt_pgraster *pgrtn = NULL;
955  double xscale = PG_GETARG_FLOAT8(1);
956  double yscale = PG_GETARG_FLOAT8(2);
957 
958  if (PG_ARGISNULL(0))
959  PG_RETURN_NULL();
960  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
961  raster = rt_raster_deserialize(pgraster, FALSE);
962  if (!raster) {
963  PG_FREE_IF_COPY(pgraster, 0);
964  elog(ERROR, "RASTER_setScaleXY: Could not deserialize raster");
965  PG_RETURN_NULL();
966  }
967 
968  rt_raster_set_scale(raster, xscale, yscale);
969  pgrtn = rt_raster_serialize(raster);
970  rt_raster_destroy(raster);
971  PG_FREE_IF_COPY(pgraster, 0);
972  if (!pgrtn)
973  PG_RETURN_NULL();
974 
975  SET_VARSIZE(pgrtn, pgrtn->size);
976  PG_RETURN_POINTER(pgrtn);
977 }
978 
983 Datum RASTER_setSkew(PG_FUNCTION_ARGS)
984 {
985  rt_pgraster *pgraster = NULL;
986  rt_pgraster *pgrtn = NULL;
988  double skew = PG_GETARG_FLOAT8(1);
989 
990  if (PG_ARGISNULL(0))
991  PG_RETURN_NULL();
992  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
993  raster = rt_raster_deserialize(pgraster, FALSE);
994  if (!raster) {
995  PG_FREE_IF_COPY(pgraster, 0);
996  elog(ERROR, "RASTER_setSkew: Could not deserialize raster");
997  PG_RETURN_NULL();
998  }
999 
1000  rt_raster_set_skews(raster, skew, skew);
1001 
1002  pgrtn = rt_raster_serialize(raster);
1003  rt_raster_destroy(raster);
1004  PG_FREE_IF_COPY(pgraster, 0);
1005  if (!pgrtn)
1006  PG_RETURN_NULL();
1007 
1008  SET_VARSIZE(pgrtn, pgrtn->size);
1009  PG_RETURN_POINTER(pgrtn);
1010 }
1011 
1016 Datum RASTER_setSkewXY(PG_FUNCTION_ARGS)
1017 {
1018  rt_pgraster *pgraster = NULL;
1019  rt_pgraster *pgrtn = NULL;
1020  rt_raster raster;
1021  double xskew = PG_GETARG_FLOAT8(1);
1022  double yskew = PG_GETARG_FLOAT8(2);
1023 
1024  if (PG_ARGISNULL(0))
1025  PG_RETURN_NULL();
1026  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1027  raster = rt_raster_deserialize(pgraster, FALSE);
1028  if (!raster) {
1029  PG_FREE_IF_COPY(pgraster, 0);
1030  elog(ERROR, "RASTER_setSkewXY: Could not deserialize raster");
1031  PG_RETURN_NULL();
1032  }
1033 
1034  rt_raster_set_skews(raster, xskew, yskew);
1035 
1036  pgrtn = rt_raster_serialize(raster);
1037  rt_raster_destroy(raster);
1038  PG_FREE_IF_COPY(pgraster, 0);
1039  if (!pgrtn)
1040  PG_RETURN_NULL();
1041 
1042  SET_VARSIZE(pgrtn, pgrtn->size);
1043  PG_RETURN_POINTER(pgrtn);
1044 }
1045 
1050 Datum RASTER_setUpperLeftXY(PG_FUNCTION_ARGS)
1051 {
1052  rt_pgraster *pgraster = NULL;
1053  rt_pgraster *pgrtn = NULL;
1054  rt_raster raster;
1055  double xoffset = PG_GETARG_FLOAT8(1);
1056  double yoffset = PG_GETARG_FLOAT8(2);
1057 
1058  if (PG_ARGISNULL(0))
1059  PG_RETURN_NULL();
1060  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1061  raster = rt_raster_deserialize(pgraster, FALSE);
1062  if (!raster) {
1063  PG_FREE_IF_COPY(pgraster, 0);
1064  elog(ERROR, "RASTER_setUpperLeftXY: Could not deserialize raster");
1065  PG_RETURN_NULL();
1066  }
1067 
1068  rt_raster_set_offsets(raster, xoffset, yoffset);
1069 
1070  pgrtn = rt_raster_serialize(raster);
1071  rt_raster_destroy(raster);
1072  PG_FREE_IF_COPY(pgraster, 0);
1073  if (!pgrtn)
1074  PG_RETURN_NULL();
1075 
1076  SET_VARSIZE(pgrtn, pgrtn->size);
1077  PG_RETURN_POINTER(pgrtn);
1078 }
1079 
1084 Datum RASTER_setGeotransform(PG_FUNCTION_ARGS)
1085 {
1086  rt_pgraster *pgraster = NULL;
1087  rt_pgraster *pgrtn = NULL;
1088  rt_raster raster;
1089  float8 imag, jmag, theta_i, theta_ij, xoffset, yoffset;
1090 
1091  if (
1092  PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) ||
1093  PG_ARGISNULL(3) || PG_ARGISNULL(4) ||
1094  PG_ARGISNULL(5) || PG_ARGISNULL(6)
1095  ) {
1096  PG_RETURN_NULL();
1097  }
1098 
1099  /* get the inputs */
1100  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1101  imag = PG_GETARG_FLOAT8(1);
1102  jmag = PG_GETARG_FLOAT8(2);
1103  theta_i = PG_GETARG_FLOAT8(3);
1104  theta_ij = PG_GETARG_FLOAT8(4);
1105  xoffset = PG_GETARG_FLOAT8(5);
1106  yoffset = PG_GETARG_FLOAT8(6);
1107 
1108  raster = rt_raster_deserialize(pgraster, TRUE);
1109  if (!raster) {
1110  PG_FREE_IF_COPY(pgraster, 0);
1111  elog(ERROR, "RASTER_setGeotransform: Could not deserialize raster");
1112  PG_RETURN_NULL();
1113  }
1114 
1115  /* store the new geotransform */
1116  rt_raster_set_phys_params(raster, imag,jmag,theta_i,theta_ij);
1117  rt_raster_set_offsets(raster, xoffset, yoffset);
1118 
1119  /* prep the return value */
1120  pgrtn = rt_raster_serialize(raster);
1121  rt_raster_destroy(raster);
1122  PG_FREE_IF_COPY(pgraster, 0);
1123  if (!pgrtn)
1124  PG_RETURN_NULL();
1125 
1126  SET_VARSIZE(pgrtn, pgrtn->size);
1127  PG_RETURN_POINTER(pgrtn);
1128 }
1129 
1142 Datum RASTER_setRotation(PG_FUNCTION_ARGS)
1143 {
1144  rt_pgraster *pgraster = NULL;
1145  rt_pgraster *pgrtn = NULL;
1146  rt_raster raster;
1147  double rotation = PG_GETARG_FLOAT8(1);
1148  double imag, jmag, theta_i, theta_ij;
1149 
1150  if (PG_ARGISNULL(0))
1151  PG_RETURN_NULL();
1152  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1153 
1154  raster = rt_raster_deserialize(pgraster, FALSE);
1155  if (! raster ) {
1156  PG_FREE_IF_COPY(pgraster, 0);
1157  elog(ERROR, "RASTER_setRotation: Could not deserialize raster");
1158  PG_RETURN_NULL();
1159  }
1160 
1161  /* preserve all defining characteristics of the grid except for rotation */
1162  rt_raster_get_phys_params(raster, &imag, &jmag, &theta_i, &theta_ij);
1163  rt_raster_set_phys_params(raster, imag, jmag, rotation, theta_ij);
1164 
1165  pgrtn = rt_raster_serialize(raster);
1166  rt_raster_destroy(raster);
1167  PG_FREE_IF_COPY(pgraster, 0);
1168  if (!pgrtn)
1169  PG_RETURN_NULL();
1170 
1171  SET_VARSIZE(pgrtn, pgrtn->size);
1172  PG_RETURN_POINTER(pgrtn);
1173 }
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)
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)
tuple raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
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
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:2196
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's SRID.
Definition: rt_raster.c:363
int32_t rt_raster_get_srid(rt_raster raster)
Get raster'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:2213
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:53
#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)