PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
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 */
43Datum RASTER_getSRID(PG_FUNCTION_ARGS);
44Datum RASTER_getWidth(PG_FUNCTION_ARGS);
45Datum RASTER_getHeight(PG_FUNCTION_ARGS);
46Datum RASTER_getNumBands(PG_FUNCTION_ARGS);
47Datum RASTER_getFileSize(PG_FUNCTION_ARGS);
48Datum RASTER_getFileTimestamp(PG_FUNCTION_ARGS);
49Datum RASTER_getXScale(PG_FUNCTION_ARGS);
50Datum RASTER_getYScale(PG_FUNCTION_ARGS);
51Datum RASTER_getXSkew(PG_FUNCTION_ARGS);
52Datum RASTER_getYSkew(PG_FUNCTION_ARGS);
53Datum RASTER_getXUpperLeft(PG_FUNCTION_ARGS);
54Datum RASTER_getYUpperLeft(PG_FUNCTION_ARGS);
55Datum RASTER_getPixelWidth(PG_FUNCTION_ARGS);
56Datum RASTER_getPixelHeight(PG_FUNCTION_ARGS);
57Datum RASTER_getGeotransform(PG_FUNCTION_ARGS);
58Datum RASTER_isEmpty(PG_FUNCTION_ARGS);
59Datum RASTER_hasNoBand(PG_FUNCTION_ARGS);
60
61/* get raster's meta data */
62Datum RASTER_metadata(PG_FUNCTION_ARGS);
63
64/* convert pixel/line to spatial coordinates */
65Datum RASTER_rasterToWorldCoord(PG_FUNCTION_ARGS);
66
67/* convert spatial coordinates to pixel/line*/
68Datum RASTER_worldToRasterCoord(PG_FUNCTION_ARGS);
69
70/* Set all the properties of a raster */
71Datum RASTER_setSRID(PG_FUNCTION_ARGS);
72Datum RASTER_setScale(PG_FUNCTION_ARGS);
73Datum RASTER_setScaleXY(PG_FUNCTION_ARGS);
74Datum RASTER_setSkew(PG_FUNCTION_ARGS);
75Datum RASTER_setSkewXY(PG_FUNCTION_ARGS);
76Datum RASTER_setUpperLeftXY(PG_FUNCTION_ARGS);
77Datum RASTER_setRotation(PG_FUNCTION_ARGS);
78Datum RASTER_setGeotransform(PG_FUNCTION_ARGS);
79
84Datum RASTER_getSRID(PG_FUNCTION_ARGS)
85{
86 rt_pgraster *pgraster;
87 rt_raster raster;
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
112Datum RASTER_getWidth(PG_FUNCTION_ARGS)
113{
114 rt_pgraster *pgraster;
115 rt_raster raster;
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
140Datum RASTER_getHeight(PG_FUNCTION_ARGS)
141{
142 rt_pgraster *pgraster;
143 rt_raster raster;
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
157
158 rt_raster_destroy(raster);
159 PG_FREE_IF_COPY(pgraster, 0);
160
161 PG_RETURN_INT32(height);
162}
163
168Datum RASTER_getNumBands(PG_FUNCTION_ARGS)
169{
170 rt_pgraster *pgraster;
171 rt_raster raster;
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
196Datum RASTER_getXScale(PG_FUNCTION_ARGS)
197{
198 rt_pgraster *pgraster;
199 rt_raster raster;
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
224Datum RASTER_getYScale(PG_FUNCTION_ARGS)
225{
226 rt_pgraster *pgraster;
227 rt_raster raster;
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
252Datum RASTER_getXSkew(PG_FUNCTION_ARGS)
253{
254 rt_pgraster *pgraster;
255 rt_raster raster;
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
280Datum RASTER_getYSkew(PG_FUNCTION_ARGS)
281{
282 rt_pgraster *pgraster;
283 rt_raster raster;
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
308Datum RASTER_getXUpperLeft(PG_FUNCTION_ARGS)
309{
310 rt_pgraster *pgraster;
311 rt_raster raster;
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
336Datum RASTER_getYUpperLeft(PG_FUNCTION_ARGS)
337{
338 rt_pgraster *pgraster;
339 rt_raster raster;
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
368Datum RASTER_getPixelWidth(PG_FUNCTION_ARGS)
369{
370 rt_pgraster *pgraster;
371 rt_raster raster;
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
404Datum RASTER_getPixelHeight(PG_FUNCTION_ARGS)
405{
406 rt_pgraster *pgraster;
407 rt_raster raster;
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
439Datum 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
522Datum 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
554Datum 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
592Datum RASTER_metadata(PG_FUNCTION_ARGS)
593{
594 rt_pgraster *pgraster = NULL;
595 rt_raster raster = NULL;
596
597 uint32_t numBands;
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;
606 uint32_t height;
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);
636
637 /* scale x, y */
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 */
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
693Datum 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.0) ? true : false;
725 skewed[1] = FLT_NEQ(rt_raster_get_y_skew(raster), 0.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
787Datum 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.0) ? true : false;
820 if (!skewed)
821 skewed = FLT_NEQ(rt_raster_get_y_skew(raster), 0.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
890Datum RASTER_setSRID(PG_FUNCTION_ARGS)
891{
892 rt_pgraster *pgraster = NULL;
893 rt_pgraster *pgrtn = NULL;
894 rt_raster raster;
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
923Datum RASTER_setScale(PG_FUNCTION_ARGS)
924{
925 rt_pgraster *pgraster = NULL;
926 rt_pgraster *pgrtn = NULL;
927 rt_raster raster;
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
956Datum RASTER_setScaleXY(PG_FUNCTION_ARGS)
957{
958 rt_pgraster *pgraster = NULL;
959 rt_pgraster *pgrtn = NULL;
960 rt_raster raster;
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
989Datum RASTER_setSkew(PG_FUNCTION_ARGS)
990{
991 rt_pgraster *pgraster = NULL;
992 rt_pgraster *pgrtn = NULL;
993 rt_raster raster;
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
1022Datum 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
1056Datum 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
1090Datum 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
1148Datum 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}
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition cu_print.c:267
#define TRUE
Definition dbfopen.c:73
#define FALSE
Definition dbfopen.c:72
#define FLT_NEQ(x, y)
Definition librtcore.h:2435
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:637
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
Definition rt_raster.c:360
double rt_raster_get_x_skew(rt_raster raster)
Get skew about the X axis.
Definition rt_raster.c:185
double rt_raster_get_x_offset(rt_raster raster)
Get raster x offset, in projection units.
Definition rt_raster.c:217
void rt_raster_set_scale(rt_raster raster, double scaleX, double scaleY)
Set scale in projection units.
Definition rt_raster.c:141
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:686
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition rt_raster.c:86
void rt_raster_set_skews(rt_raster raster, double skewX, double skewY)
Set skews about the X and Y axis.
Definition rt_raster.c:172
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:1253
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
Definition rt_raster.c:154
@ ES_NONE
Definition librtcore.h:182
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:235
uint16_t rt_raster_get_num_bands(rt_raster raster)
Definition rt_raster.c:376
uint16_t rt_raster_get_height(rt_raster raster)
Definition rt_raster.c:133
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
Definition rt_raster.c:367
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:301
uint16_t rt_raster_get_width(rt_raster raster)
Definition rt_raster.c:125
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
Definition rt_raster.c:163
double rt_raster_get_y_skew(rt_raster raster)
Get skew about the Y axis.
Definition rt_raster.c:194
void rt_raster_set_offsets(rt_raster raster, double x, double y)
Set insertion points in projection units.
Definition rt_raster.c:203
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
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:254
double rt_raster_get_y_offset(rt_raster raster)
Get raster y offset, in projection units.
Definition rt_raster.c:226
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
Definition rt_raster.c:1240
Datum RASTER_getGeotransform(PG_FUNCTION_ARGS)
Datum RASTER_getXScale(PG_FUNCTION_ARGS)
Datum RASTER_getFileTimestamp(PG_FUNCTION_ARGS)
Datum RASTER_getPixelWidth(PG_FUNCTION_ARGS)
Datum RASTER_getPixelHeight(PG_FUNCTION_ARGS)
Datum RASTER_getYUpperLeft(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(RASTER_getSRID)
Return the SRID associated with the raster.
Datum RASTER_setSkew(PG_FUNCTION_ARGS)
Datum RASTER_hasNoBand(PG_FUNCTION_ARGS)
Datum RASTER_setScale(PG_FUNCTION_ARGS)
Datum RASTER_getYSkew(PG_FUNCTION_ARGS)
Datum RASTER_metadata(PG_FUNCTION_ARGS)
Datum RASTER_getYScale(PG_FUNCTION_ARGS)
Datum RASTER_getFileSize(PG_FUNCTION_ARGS)
Datum RASTER_getNumBands(PG_FUNCTION_ARGS)
Datum RASTER_rasterToWorldCoord(PG_FUNCTION_ARGS)
Datum RASTER_setUpperLeftXY(PG_FUNCTION_ARGS)
Datum RASTER_setRotation(PG_FUNCTION_ARGS)
Datum RASTER_isEmpty(PG_FUNCTION_ARGS)
Datum RASTER_setGeotransform(PG_FUNCTION_ARGS)
Datum RASTER_getWidth(PG_FUNCTION_ARGS)
Datum RASTER_setSkewXY(PG_FUNCTION_ARGS)
#define VALUES_LENGTH
Datum RASTER_getXSkew(PG_FUNCTION_ARGS)
Datum RASTER_worldToRasterCoord(PG_FUNCTION_ARGS)
Datum RASTER_setScaleXY(PG_FUNCTION_ARGS)
Datum RASTER_getHeight(PG_FUNCTION_ARGS)
Datum RASTER_getSRID(PG_FUNCTION_ARGS)
Datum RASTER_getXUpperLeft(PG_FUNCTION_ARGS)
Datum RASTER_setSRID(PG_FUNCTION_ARGS)
#define POSTGIS_RT_DEBUG(level, msg)
Definition rtpostgis.h:65
Struct definitions.
Definition librtcore.h:2452