PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
rt_raster.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) 2013 Bborie Park <dustymugs@gmail.com>
7 * Copyright (C) 2011-2013 Regents of the University of California
8 * <bkpark@ucdavis.edu>
9 * Copyright (C) 2010-2011 Jorge Arevalo <jorge.arevalo@deimos-space.com>
10 * Copyright (C) 2010-2011 David Zwarg <dzwarg@azavea.com>
11 * Copyright (C) 2009-2011 Pierre Racine <pierre.racine@sbf.ulaval.ca>
12 * Copyright (C) 2009-2011 Mateusz Loskot <mateusz@loskot.net>
13 * Copyright (C) 2008-2009 Sandro Santilli <strk@kbt.io>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software Foundation,
27 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28 *
29 */
30
31#include "librtcore.h"
32#include "librtcore_internal.h"
33
34#include <math.h>
35
48rt_raster_new(uint32_t width, uint32_t height) {
49 rt_raster ret = NULL;
50
51 ret = (rt_raster) rtalloc(sizeof (struct rt_raster_t));
52 if (!ret) {
53 rterror("rt_raster_new: Out of virtual memory creating an rt_raster");
54 return NULL;
55 }
56
57 RASTER_DEBUGF(3, "Created rt_raster @ %p", ret);
58
59 if (width > 65535 || height > 65535) {
60 rterror("rt_raster_new: Dimensions requested exceed the maximum (65535 x 65535) permitted for a raster");
62 return NULL;
63 }
64
65 ret->width = width;
66 ret->height = height;
67 ret->scaleX = 1;
68 ret->scaleY = -1;
69 ret->ipX = 0.0;
70 ret->ipY = 0.0;
71 ret->skewX = 0.0;
72 ret->skewY = 0.0;
73 ret->srid = SRID_UNKNOWN;
74
75 ret->numBands = 0;
76 ret->bands = NULL;
77
78 return ret;
79}
80
81void
83 if (raster == NULL)
84 return;
85
86 RASTER_DEBUGF(3, "Destroying rt_raster @ %p", raster);
87
88 if (raster->bands)
89 rtdealloc(raster->bands);
90
91 rtdealloc(raster);
92}
93
94static void
96 int numband = 0;
97 int i = 0;
98 rt_band band = NULL;
99
100 if (raster == NULL)
101 return;
102
103 numband = rt_raster_get_num_bands(raster);
104 if (numband < 1)
105 return;
106
107 for (i = 0; i < numband; i++) {
108 band = rt_raster_get_band(raster, i);
109 if (NULL == band)
110 continue;
111
112 if (!rt_band_is_offline(band))
113 continue;
114
115 rtwarn("Changes made to raster geotransform matrix may affect out-db band data. Returned band data may be incorrect");
116 break;
117 }
118}
119
120uint16_t
122
123 assert(NULL != raster);
124
125 return raster->width;
126}
127
128uint16_t
130
131 assert(NULL != raster);
132
133 return raster->height;
134}
135
136void
138 rt_raster raster,
139 double scaleX, double scaleY
140) {
141 assert(NULL != raster);
142
143 raster->scaleX = scaleX;
144 raster->scaleY = scaleY;
145
147}
148
149double
151
152
153 assert(NULL != raster);
154
155 return raster->scaleX;
156}
157
158double
160
161
162 assert(NULL != raster);
163
164 return raster->scaleY;
165}
166
167void
169 rt_raster raster,
170 double skewX, double skewY
171) {
172 assert(NULL != raster);
173
174 raster->skewX = skewX;
175 raster->skewY = skewY;
176
178}
179
180double
182
183
184 assert(NULL != raster);
185
186 return raster->skewX;
187}
188
189double
191
192
193 assert(NULL != raster);
194
195 return raster->skewY;
196}
197
198void
200 rt_raster raster,
201 double x, double y
202) {
203
204 assert(NULL != raster);
205
206 raster->ipX = x;
207 raster->ipY = y;
208
210}
211
212double
214
215
216 assert(NULL != raster);
217
218 return raster->ipX;
219}
220
221double
223
224
225 assert(NULL != raster);
226
227 return raster->ipY;
228}
229
230void
232 double *i_mag, double *j_mag, double *theta_i, double *theta_ij)
233{
234 double o11, o12, o21, o22 ; /* geotransform coefficients */
235
236 if (rast == NULL) return ;
237 if ( (i_mag==NULL) || (j_mag==NULL) || (theta_i==NULL) || (theta_ij==NULL))
238 return ;
239
240 /* retrieve coefficients from raster */
241 o11 = rt_raster_get_x_scale(rast) ;
242 o12 = rt_raster_get_x_skew(rast) ;
243 o21 = rt_raster_get_y_skew(rast) ;
244 o22 = rt_raster_get_y_scale(rast) ;
245
246 rt_raster_calc_phys_params(o11, o12, o21, o22, i_mag, j_mag, theta_i, theta_ij);
247}
248
249void
250rt_raster_calc_phys_params(double xscale, double xskew, double yskew, double yscale,
251 double *i_mag, double *j_mag, double *theta_i, double *theta_ij)
252
253{
254 double theta_test ;
255
256 if ( (i_mag==NULL) || (j_mag==NULL) || (theta_i==NULL) || (theta_ij==NULL))
257 return ;
258
259 /* pixel size in the i direction */
260 *i_mag = sqrt(xscale*xscale + yskew*yskew) ;
261
262 /* pixel size in the j direction */
263 *j_mag = sqrt(xskew*xskew + yscale*yscale) ;
264
265 /* Rotation
266 * ========
267 * Two steps:
268 * 1] calculate the magnitude of the angle between the x axis and
269 * the i basis vector.
270 * 2] Calculate the sign of theta_i based on the angle between the y axis
271 * and the i basis vector.
272 */
273 *theta_i = acos(xscale/(*i_mag)) ; /* magnitude */
274 theta_test = acos(yskew/(*i_mag)) ; /* sign */
275 if (theta_test < M_PI_2){
276 *theta_i = -(*theta_i) ;
277 }
278
279
280 /* Angular separation of basis vectors
281 * ===================================
282 * Two steps:
283 * 1] calculate the magnitude of the angle between the j basis vector and
284 * the i basis vector.
285 * 2] Calculate the sign of theta_ij based on the angle between the
286 * perpendicular of the i basis vector and the j basis vector.
287 */
288 *theta_ij = acos(((xscale*xskew) + (yskew*yscale))/((*i_mag)*(*j_mag))) ;
289 theta_test = acos( ((-yskew*xskew)+(xscale*yscale)) /
290 ((*i_mag)*(*j_mag)));
291 if (theta_test > M_PI_2) {
292 *theta_ij = -(*theta_ij) ;
293 }
294}
295
296void
297rt_raster_set_phys_params(rt_raster rast,double i_mag, double j_mag, double theta_i, double theta_ij)
298{
299 double o11, o12, o21, o22 ; /* calculated geotransform coefficients */
300 int success ;
301
302 if (rast == NULL) return ;
303
304 success = rt_raster_calc_gt_coeff(i_mag, j_mag, theta_i, theta_ij,
305 &o11, &o12, &o21, &o22) ;
306
307 if (success) {
308 rt_raster_set_scale(rast, o11, o22) ;
309 rt_raster_set_skews(rast, o12, o21) ;
310 }
311}
312
313int
314rt_raster_calc_gt_coeff(double i_mag, double j_mag, double theta_i, double theta_ij,
315 double *xscale, double *xskew, double *yskew, double *yscale)
316{
317 double f ; /* reflection flag 1.0 or -1.0 */
318 double k_i ; /* shearing coefficient */
319 double s_i, s_j ; /* scaling coefficients */
320 double cos_theta_i, sin_theta_i ;
321
322 if ( (xscale==NULL) || (xskew==NULL) || (yskew==NULL) || (yscale==NULL)) {
323 return 0;
324 }
325
326 if ( (theta_ij == 0.0) || (theta_ij == M_PI)) {
327 return 0;
328 }
329
330 /* Reflection across the i axis */
331 f=1.0 ;
332 if (theta_ij < 0) {
333 f = -1.0;
334 }
335
336 /* scaling along i axis */
337 s_i = i_mag ;
338
339 /* shearing parallel to i axis */
340 k_i = tan(f*M_PI_2 - theta_ij) ;
341
342 /* scaling along j axis */
343 s_j = j_mag / (sqrt(k_i*k_i + 1)) ;
344
345 /* putting it altogether */
346 cos_theta_i = cos(theta_i) ;
347 sin_theta_i = sin(theta_i) ;
348 *xscale = s_i * cos_theta_i ;
349 *xskew = k_i * s_j * f * cos_theta_i + s_j * f * sin_theta_i ;
350 *yskew = -s_i * sin_theta_i ;
351 *yscale = -k_i * s_j * f * sin_theta_i + s_j * f * cos_theta_i ;
352 return 1;
353}
354
355int32_t
357 assert(NULL != raster);
358
359 return clamp_srid(raster->srid);
360}
361
362void
363rt_raster_set_srid(rt_raster raster, int32_t srid) {
364 assert(NULL != raster);
365
366 raster->srid = clamp_srid(srid);
367
369}
370
371uint16_t
373
374
375 assert(NULL != raster);
376
377 return raster->numBands;
378}
379
382 assert(NULL != raster);
383
384 if (n >= raster->numBands || n < 0)
385 return NULL;
386
387 return raster->bands[n];
388}
389
390/******************************************************************************
391* rt_raster_add_band()
392******************************************************************************/
393
404int
405rt_raster_add_band(rt_raster raster, rt_band band, int index) {
406 rt_band *oldbands = NULL;
407 rt_band oldband = NULL;
408 rt_band tmpband = NULL;
409 uint16_t i = 0;
410
411 assert(NULL != raster);
412 assert(NULL != band);
413
414 RASTER_DEBUGF(3, "Adding band %p to raster %p", band, raster);
415
416 if (band->width != raster->width || band->height != raster->height) {
417 rterror("rt_raster_add_band: Can't add a %dx%d band to a %dx%d raster",
418 band->width, band->height, raster->width, raster->height);
419 return -1;
420 }
421
422 if (index > raster->numBands)
423 index = raster->numBands;
424
425 if (index < 0)
426 index = 0;
427
428 oldbands = raster->bands;
429
430 RASTER_DEBUGF(3, "Oldbands at %p", oldbands);
431
432 raster->bands = (rt_band*) rtrealloc(raster->bands,
433 sizeof (rt_band)*(raster->numBands + 1)
434 );
435
436 RASTER_DEBUG(3, "Checking bands");
437
438 if (NULL == raster->bands) {
439 rterror("rt_raster_add_band: Out of virtual memory "
440 "reallocating band pointers");
441 raster->bands = oldbands;
442 return -1;
443 }
444
445 RASTER_DEBUGF(4, "realloc returned %p", raster->bands);
446
447 for (i = 0; i <= raster->numBands; ++i) {
448 if (i == index) {
449 oldband = raster->bands[i];
450 raster->bands[i] = band;
451 } else if (i > index) {
452 tmpband = raster->bands[i];
453 raster->bands[i] = oldband;
454 oldband = tmpband;
455 }
456 }
457
458 band->raster = raster;
459
460 raster->numBands++;
461
462 RASTER_DEBUGF(4, "Raster now has %d bands", raster->numBands);
463
464 return index;
465}
466
467/******************************************************************************
468* rt_raster_generate_new_band()
469******************************************************************************/
470
484int
486 rt_raster raster, rt_pixtype pixtype,
487 double initialvalue, uint32_t hasnodata, double nodatavalue,
488 int index
489) {
490 rt_band band = NULL;
491 int width = 0;
492 int height = 0;
493 int numval = 0;
494 int datasize = 0;
495 int oldnumbands = 0;
496 int numbands = 0;
497 void * mem = NULL;
498 int32_t checkvalint = 0;
499 uint32_t checkvaluint = 0;
500 double checkvaldouble = 0;
501 float checkvalfloat = 0;
502 int i;
503
504
505 assert(NULL != raster);
506
507 /* Make sure index is in a valid range */
508 oldnumbands = rt_raster_get_num_bands(raster);
509 if (index < 0)
510 index = 0;
511 else if (index > oldnumbands + 1)
512 index = oldnumbands + 1;
513
514 /* Determine size of memory block to allocate and allocate it */
515 width = rt_raster_get_width(raster);
516 height = rt_raster_get_height(raster);
517 numval = width * height;
518 datasize = rt_pixtype_size(pixtype) * numval;
519
520 mem = (int *)rtalloc(datasize);
521 if (!mem) {
522 rterror("rt_raster_generate_new_band: Could not allocate memory for band");
523 return -1;
524 }
525
526 if (FLT_EQ(initialvalue, 0.0))
527 memset(mem, 0, datasize);
528 else {
529 switch (pixtype)
530 {
531 case PT_1BB:
532 {
533 uint8_t *ptr = mem;
534 uint8_t clamped_initval = rt_util_clamp_to_1BB(initialvalue);
535 for (i = 0; i < numval; i++)
536 ptr[i] = clamped_initval;
537 checkvalint = ptr[0];
538 break;
539 }
540 case PT_2BUI:
541 {
542 uint8_t *ptr = mem;
543 uint8_t clamped_initval = rt_util_clamp_to_2BUI(initialvalue);
544 for (i = 0; i < numval; i++)
545 ptr[i] = clamped_initval;
546 checkvalint = ptr[0];
547 break;
548 }
549 case PT_4BUI:
550 {
551 uint8_t *ptr = mem;
552 uint8_t clamped_initval = rt_util_clamp_to_4BUI(initialvalue);
553 for (i = 0; i < numval; i++)
554 ptr[i] = clamped_initval;
555 checkvalint = ptr[0];
556 break;
557 }
558 case PT_8BSI:
559 {
560 int8_t *ptr = mem;
561 int8_t clamped_initval = rt_util_clamp_to_8BSI(initialvalue);
562 for (i = 0; i < numval; i++)
563 ptr[i] = clamped_initval;
564 checkvalint = ptr[0];
565 break;
566 }
567 case PT_8BUI:
568 {
569 uint8_t *ptr = mem;
570 uint8_t clamped_initval = rt_util_clamp_to_8BUI(initialvalue);
571 for (i = 0; i < numval; i++)
572 ptr[i] = clamped_initval;
573 checkvalint = ptr[0];
574 break;
575 }
576 case PT_16BSI:
577 {
578 int16_t *ptr = mem;
579 int16_t clamped_initval = rt_util_clamp_to_16BSI(initialvalue);
580 for (i = 0; i < numval; i++)
581 ptr[i] = clamped_initval;
582 checkvalint = ptr[0];
583 break;
584 }
585 case PT_16BUI:
586 {
587 uint16_t *ptr = mem;
588 uint16_t clamped_initval = rt_util_clamp_to_16BUI(initialvalue);
589 for (i = 0; i < numval; i++)
590 ptr[i] = clamped_initval;
591 checkvalint = ptr[0];
592 break;
593 }
594 case PT_32BSI:
595 {
596 int32_t *ptr = mem;
597 int32_t clamped_initval = rt_util_clamp_to_32BSI(initialvalue);
598 for (i = 0; i < numval; i++)
599 ptr[i] = clamped_initval;
600 checkvalint = ptr[0];
601 break;
602 }
603 case PT_32BUI:
604 {
605 uint32_t *ptr = mem;
606 uint32_t clamped_initval = rt_util_clamp_to_32BUI(initialvalue);
607 for (i = 0; i < numval; i++)
608 ptr[i] = clamped_initval;
609 checkvaluint = ptr[0];
610 break;
611 }
612 case PT_32BF:
613 {
614 float *ptr = mem;
615 float clamped_initval = rt_util_clamp_to_32F(initialvalue);
616 for (i = 0; i < numval; i++)
617 ptr[i] = clamped_initval;
618 checkvalfloat = ptr[0];
619 break;
620 }
621 case PT_64BF:
622 {
623 double *ptr = mem;
624 for (i = 0; i < numval; i++)
625 ptr[i] = initialvalue;
626 checkvaldouble = ptr[0];
627 break;
628 }
629 default:
630 {
631 rterror("rt_raster_generate_new_band: Unknown pixeltype %d", pixtype);
632 rtdealloc(mem);
633 return -1;
634 }
635 }
636 }
637
638 /* Overflow checking */
640 initialvalue,
641 checkvalint, checkvaluint,
642 checkvalfloat, checkvaldouble,
643 pixtype
644 );
645
646 band = rt_band_new_inline(width, height, pixtype, hasnodata, nodatavalue, mem);
647 if (! band) {
648 rterror("rt_raster_generate_new_band: Could not add band to raster. Aborting");
649 rtdealloc(mem);
650 return -1;
651 }
652 rt_band_set_ownsdata_flag(band, 1); /* we DO own this data!!! */
653 index = rt_raster_add_band(raster, band, index);
654 numbands = rt_raster_get_num_bands(raster);
655 if (numbands == oldnumbands || index == -1) {
656 rterror("rt_raster_generate_new_band: Could not add band to raster. Aborting");
657 rt_band_destroy(band);
658 }
659
660 /* set isnodata if hasnodata = TRUE and initial value = nodatavalue */
661 if (hasnodata && FLT_EQ(initialvalue, nodatavalue))
663
664 return index;
665}
666
677 rt_raster raster,
678 double *gt, double *igt
679) {
680 double _gt[6] = {0};
681
682 assert((raster != NULL || gt != NULL));
683 assert(igt != NULL);
684
685 if (gt == NULL)
687 else
688 memcpy(_gt, gt, sizeof(double) * 6);
689
690 if (!GDALInvGeoTransform(_gt, igt)) {
691 rterror("rt_raster_get_inverse_geotransform_matrix: Could not compute inverse geotransform matrix");
692 return ES_ERROR;
693 }
694
695 return ES_NONE;
696}
697
705void
707 double *gt) {
708 assert(NULL != raster);
709 assert(NULL != gt);
710
711 gt[0] = raster->ipX;
712 gt[1] = raster->scaleX;
713 gt[2] = raster->skewX;
714 gt[3] = raster->ipY;
715 gt[4] = raster->skewY;
716 gt[5] = raster->scaleY;
717}
718
726void
728 double *gt) {
729 assert(NULL != raster);
730 assert(NULL != gt);
731
732 raster->ipX = gt[0];
733 raster->scaleX = gt[1];
734 raster->skewX = gt[2];
735 raster->ipY = gt[3];
736 raster->skewY = gt[4];
737 raster->scaleY = gt[5];
738
740}
741
756 rt_raster raster,
757 double xr, double yr,
758 double *xw, double *yw,
759 double *gt
760) {
761 double _gt[6] = {0};
762
763 assert(NULL != raster);
764 assert(NULL != xw && NULL != yw);
765
766 if (NULL != gt)
767 memcpy(_gt, gt, sizeof(double) * 6);
768
769 /* scale of matrix is not set */
770 if (FLT_EQ(_gt[1], 0.0) || FLT_EQ(_gt[5], 0.0))
771 {
773 }
774
775 RASTER_DEBUGF(4, "gt = (%f, %f, %f, %f, %f, %f)",
776 _gt[0],
777 _gt[1],
778 _gt[2],
779 _gt[3],
780 _gt[4],
781 _gt[5]
782 );
783
784 GDALApplyGeoTransform(_gt, xr, yr, xw, yw);
785 RASTER_DEBUGF(4, "GDALApplyGeoTransform (c -> g) for (%f, %f) = (%f, %f)",
786 xr, yr, *xw, *yw);
787
788 return ES_NONE;
789}
790
805 rt_raster raster,
806 double xw, double yw,
807 double *xr, double *yr,
808 double *igt
809) {
810 double _igt[6] = {0};
811 double rnd = 0;
812
813 assert(NULL != raster);
814 assert(NULL != xr && NULL != yr);
815
816 if (igt != NULL)
817 memcpy(_igt, igt, sizeof(double) * 6);
818
819 /* matrix is not set */
820 if (
821 FLT_EQ(_igt[0], 0.) &&
822 FLT_EQ(_igt[1], 0.) &&
823 FLT_EQ(_igt[2], 0.) &&
824 FLT_EQ(_igt[3], 0.) &&
825 FLT_EQ(_igt[4], 0.) &&
826 FLT_EQ(_igt[5], 0.)
827 ) {
828 if (rt_raster_get_inverse_geotransform_matrix(raster, NULL, _igt) != ES_NONE) {
829 rterror("rt_raster_geopoint_to_cell: Could not get inverse geotransform matrix");
830 return ES_ERROR;
831 }
832 }
833
834 GDALApplyGeoTransform(_igt, xw, yw, xr, yr);
835 RASTER_DEBUGF(4, "GDALApplyGeoTransform (g -> c) for (%f, %f) = (%f, %f)",
836 xw, yw, *xr, *yr);
837
838 rnd = ROUND(*xr, 0);
839 if (FLT_EQ(rnd, *xr))
840 *xr = rnd;
841 else
842 *xr = floor(*xr);
843
844 rnd = ROUND(*yr, 0);
845 if (FLT_EQ(rnd, *yr))
846 *yr = rnd;
847 else
848 *yr = floor(*yr);
849
850 RASTER_DEBUGF(4, "Corrected GDALApplyGeoTransform (g -> c) for (%f, %f) = (%f, %f)",
851 xw, yw, *xr, *yr);
852
853 return ES_NONE;
854}
855
856/******************************************************************************
857* rt_raster_get_envelope()
858******************************************************************************/
859
872 rt_raster raster,
873 rt_envelope *env
874) {
875 int i;
876 int rtn;
877 int set = 0;
878 double _r[2] = {0.};
879 double _w[2] = {0.};
880 double _gt[6] = {0.};
881
882 assert(raster != NULL);
883 assert(env != NULL);
884
886
887 for (i = 0; i < 4; i++) {
888 switch (i) {
889 case 0:
890 _r[0] = 0;
891 _r[1] = 0;
892 break;
893 case 1:
894 _r[0] = 0;
895 _r[1] = raster->height;
896 break;
897 case 2:
898 _r[0] = raster->width;
899 _r[1] = raster->height;
900 break;
901 case 3:
902 _r[0] = raster->width;
903 _r[1] = 0;
904 break;
905 }
906
908 raster,
909 _r[0], _r[1],
910 &(_w[0]), &(_w[1]),
911 _gt
912 );
913 if (rtn != ES_NONE) {
914 rterror("rt_raster_get_envelope: Could not compute spatial coordinates for raster pixel");
915 return ES_ERROR;
916 }
917
918 if (!set) {
919 set = 1;
920 env->MinX = _w[0];
921 env->MaxX = _w[0];
922 env->MinY = _w[1];
923 env->MaxY = _w[1];
924 }
925 else {
926 if (_w[0] < env->MinX)
927 env->MinX = _w[0];
928 else if (_w[0] > env->MaxX)
929 env->MaxX = _w[0];
930
931 if (_w[1] < env->MinY)
932 env->MinY = _w[1];
933 else if (_w[1] > env->MaxY)
934 env->MaxY = _w[1];
935 }
936 }
937
938 return ES_NONE;
939}
940
941/******************************************************************************
942* rt_raster_compute_skewed_raster()
943******************************************************************************/
944
945/*
946 * Compute skewed extent that covers unskewed extent.
947 *
948 * @param envelope : unskewed extent of type rt_envelope
949 * @param skew : pointer to 2-element array (x, y) of skew
950 * @param scale : pointer to 2-element array (x, y) of scale
951 * @param tolerance : value between 0 and 1 where the smaller the tolerance
952 * results in an extent approaching the "minimum" skewed extent.
953 * If value <= 0, tolerance = 0.1. If value > 1, tolerance = 1.
954 *
955 * @return skewed raster who's extent covers unskewed extent, NULL on error
956 */
959 rt_envelope extent,
960 double *skew,
961 double *scale,
962 double tolerance
963) {
964 uint32_t run = 0;
965 uint32_t max_run = 1;
966 double dbl_run = 0;
967
968 int rtn;
969 int covers = 0;
970 rt_raster raster;
971 double _gt[6] = {0};
972 double _igt[6] = {0};
973 int _d[2] = {1, -1};
974 int _dlast = 0;
975 int _dlastpos = 0;
976 double _w[2] = {0};
977 double _r[2] = {0};
978 double _xy[2] = {0};
979 int i;
980 int j;
981 int x;
982 int y;
983
984 LWGEOM *geom = NULL;
985 GEOSGeometry *sgeom = NULL;
986 GEOSGeometry *ngeom = NULL;
987
988 if (
989 (tolerance < 0.) ||
990 FLT_EQ(tolerance, 0.)
991 ) {
992 tolerance = 0.1;
993 }
994 else if (tolerance > 1.)
995 tolerance = 1;
996
997 dbl_run = tolerance;
998 while (dbl_run < 10) {
999 dbl_run *= 10.;
1000 max_run *= 10;
1001 }
1002
1003 /* scale must be provided */
1004 if (scale == NULL)
1005 return NULL;
1006 for (i = 0; i < 2; i++) {
1007 if (FLT_EQ(scale[i], 0.0))
1008 {
1009 rterror("rt_raster_compute_skewed_raster: Scale cannot be zero");
1010 return 0;
1011 }
1012
1013 if (i < 1)
1014 _gt[1] = fabs(scale[i] * tolerance);
1015 else
1016 _gt[5] = fabs(scale[i] * tolerance);
1017 }
1018 /* conform scale-y to be negative */
1019 _gt[5] *= -1;
1020
1021 /* skew not provided or skew is zero, return raster of correct dim and spatial attributes */
1022 if ((skew == NULL) || (FLT_EQ(skew[0], 0.0) && FLT_EQ(skew[1], 0.0)))
1023 {
1024 int _dim[2] = {
1025 (int) fmax((fabs(extent.MaxX - extent.MinX) + (fabs(scale[0]) / 2.)) / fabs(scale[0]), 1),
1026 (int) fmax((fabs(extent.MaxY - extent.MinY) + (fabs(scale[1]) / 2.)) / fabs(scale[1]), 1)
1027 };
1028
1029 raster = rt_raster_new(_dim[0], _dim[1]);
1030 if (raster == NULL) {
1031 rterror("rt_raster_compute_skewed_raster: Could not create output raster");
1032 return NULL;
1033 }
1034
1035 rt_raster_set_offsets(raster, extent.MinX, extent.MaxY);
1036 rt_raster_set_scale(raster, fabs(scale[0]), -1 * fabs(scale[1]));
1037 rt_raster_set_skews(raster, skew[0], skew[1]);
1038
1039 return raster;
1040 }
1041
1042 /* direction to shift upper-left corner */
1043 if (skew[0] > 0.)
1044 _d[0] = -1;
1045 if (skew[1] < 0.)
1046 _d[1] = 1;
1047
1048 /* geotransform */
1049 _gt[0] = extent.UpperLeftX;
1050 _gt[2] = skew[0] * tolerance;
1051 _gt[3] = extent.UpperLeftY;
1052 _gt[4] = skew[1] * tolerance;
1053
1054 RASTER_DEBUGF(4, "Initial geotransform: %f, %f, %f, %f, %f, %f",
1055 _gt[0], _gt[1], _gt[2], _gt[3], _gt[4], _gt[5]
1056 );
1057 RASTER_DEBUGF(4, "Delta: %d, %d", _d[0], _d[1]);
1058
1059 /* simple raster */
1060 if ((raster = rt_raster_new(1, 1)) == NULL) {
1061 rterror("rt_raster_compute_skewed_raster: Out of memory allocating extent raster");
1062 return NULL;
1063 }
1065
1066 /* get inverse geotransform matrix */
1067 if (!GDALInvGeoTransform(_gt, _igt)) {
1068 rterror("rt_raster_compute_skewed_raster: Could not compute inverse geotransform matrix");
1069 rt_raster_destroy(raster);
1070 return NULL;
1071 }
1072 RASTER_DEBUGF(4, "Inverse geotransform: %f, %f, %f, %f, %f, %f",
1073 _igt[0], _igt[1], _igt[2], _igt[3], _igt[4], _igt[5]
1074 );
1075
1076 /* shift along axis */
1077 for (i = 0; i < 2; i++) {
1078 covers = 0;
1079 run = 0;
1080
1081 RASTER_DEBUGF(3, "Shifting along %s axis", i < 1 ? "X" : "Y");
1082
1083 do {
1084
1085 /* prevent possible infinite loop */
1086 if (run > max_run) {
1087 rterror("rt_raster_compute_skewed_raster: Could not compute skewed extent due to check preventing infinite loop");
1088 rt_raster_destroy(raster);
1089 return NULL;
1090 }
1091
1092 /*
1093 check the four corners that they are covered along the specific axis
1094 pixel column should be >= 0
1095 */
1096 for (j = 0; j < 4; j++) {
1097 switch (j) {
1098 /* upper-left */
1099 case 0:
1100 _xy[0] = extent.MinX;
1101 _xy[1] = extent.MaxY;
1102 break;
1103 /* lower-left */
1104 case 1:
1105 _xy[0] = extent.MinX;
1106 _xy[1] = extent.MinY;
1107 break;
1108 /* lower-right */
1109 case 2:
1110 _xy[0] = extent.MaxX;
1111 _xy[1] = extent.MinY;
1112 break;
1113 /* upper-right */
1114 case 3:
1115 _xy[0] = extent.MaxX;
1116 _xy[1] = extent.MaxY;
1117 break;
1118 }
1119
1121 raster,
1122 _xy[0], _xy[1],
1123 &(_r[0]), &(_r[1]),
1124 _igt
1125 );
1126 if (rtn != ES_NONE) {
1127 rterror("rt_raster_compute_skewed_raster: Could not compute raster pixel for spatial coordinates");
1128 rt_raster_destroy(raster);
1129 return NULL;
1130 }
1131
1132 RASTER_DEBUGF(4, "Point %d at cell %d x %d", j, (int) _r[0], (int) _r[1]);
1133
1134 /* raster doesn't cover point */
1135 if ((int) _r[i] < 0) {
1136 RASTER_DEBUGF(4, "Point outside of skewed extent: %d", j);
1137 covers = 0;
1138
1139 if (_dlastpos != j) {
1140 _dlast = (int) _r[i];
1141 _dlastpos = j;
1142 }
1143 else if ((int) _r[i] < _dlast) {
1144 RASTER_DEBUG(4, "Point going in wrong direction. Reversing direction");
1145 _d[i] *= -1;
1146 _dlastpos = -1;
1147 run = 0;
1148 }
1149
1150 break;
1151 }
1152
1153 covers++;
1154 }
1155
1156 if (!covers) {
1157 x = 0;
1158 y = 0;
1159 if (i < 1)
1160 x = _d[i] * fabs(_r[i]);
1161 else
1162 y = _d[i] * fabs(_r[i]);
1163
1165 raster,
1166 x, y,
1167 &(_w[0]), &(_w[1]),
1168 _gt
1169 );
1170 if (rtn != ES_NONE) {
1171 rterror("rt_raster_compute_skewed_raster: Could not compute spatial coordinates for raster pixel");
1172 rt_raster_destroy(raster);
1173 return NULL;
1174 }
1175
1176 /* adjust ul */
1177 if (i < 1)
1178 _gt[0] = _w[i];
1179 else
1180 _gt[3] = _w[i];
1182 RASTER_DEBUGF(4, "Shifted geotransform: %f, %f, %f, %f, %f, %f",
1183 _gt[0], _gt[1], _gt[2], _gt[3], _gt[4], _gt[5]
1184 );
1185
1186 /* get inverse geotransform matrix */
1187 if (!GDALInvGeoTransform(_gt, _igt)) {
1188 rterror("rt_raster_compute_skewed_raster: Could not compute inverse geotransform matrix");
1189 rt_raster_destroy(raster);
1190 return NULL;
1191 }
1192 RASTER_DEBUGF(4, "Inverse geotransform: %f, %f, %f, %f, %f, %f",
1193 _igt[0], _igt[1], _igt[2], _igt[3], _igt[4], _igt[5]
1194 );
1195 }
1196
1197 run++;
1198 }
1199 while (!covers);
1200 }
1201
1202 /* covers test */
1204 raster,
1205 extent.MaxX, extent.MinY,
1206 &(_r[0]), &(_r[1]),
1207 _igt
1208 );
1209 if (rtn != ES_NONE) {
1210 rterror("rt_raster_compute_skewed_raster: Could not compute raster pixel for spatial coordinates");
1211 rt_raster_destroy(raster);
1212 return NULL;
1213 }
1214
1215 RASTER_DEBUGF(4, "geopoint %f x %f at cell %d x %d", extent.MaxX, extent.MinY, (int) _r[0], (int) _r[1]);
1216
1217 raster->width = _r[0];
1218 raster->height = _r[1];
1219
1220 /* initialize GEOS */
1221 initGEOS(rtinfo, lwgeom_geos_error);
1222
1223 /* create reference LWPOLY */
1224 {
1225 LWPOLY *npoly = rt_util_envelope_to_lwpoly(extent);
1226 if (npoly == NULL) {
1227 rterror("rt_raster_compute_skewed_raster: Could not build extent's geometry for covers test");
1228 rt_raster_destroy(raster);
1229 return NULL;
1230 }
1231
1232 ngeom = (GEOSGeometry *) LWGEOM2GEOS(lwpoly_as_lwgeom(npoly), 0);
1233 lwpoly_free(npoly);
1234 }
1235
1236 do {
1237 covers = 0;
1238
1239 /* construct sgeom from raster */
1240 if ((rt_raster_get_convex_hull(raster, &geom) != ES_NONE) || geom == NULL) {
1241 rterror("rt_raster_compute_skewed_raster: Could not build skewed extent's geometry for covers test");
1242 GEOSGeom_destroy(ngeom);
1243 rt_raster_destroy(raster);
1244 return NULL;
1245 }
1246
1247 sgeom = (GEOSGeometry *) LWGEOM2GEOS(geom, 0);
1248 lwgeom_free(geom);
1249
1250 covers = GEOSRelatePattern(sgeom, ngeom, "******FF*");
1251 GEOSGeom_destroy(sgeom);
1252
1253 if (covers == 2) {
1254 rterror("rt_raster_compute_skewed_raster: Could not run covers test");
1255 GEOSGeom_destroy(ngeom);
1256 rt_raster_destroy(raster);
1257 return NULL;
1258 }
1259
1260 if (!covers)
1261 {
1262 raster->width++;
1263 raster->height++;
1264 }
1265 }
1266 while (!covers);
1267
1268 RASTER_DEBUGF(4, "Skewed extent does cover normal extent with dimensions %d x %d", raster->width, raster->height);
1269
1270 raster->width = (int) ((((double) raster->width) * fabs(_gt[1]) + fabs(scale[0] / 2.)) / fabs(scale[0]));
1271 raster->height = (int) ((((double) raster->height) * fabs(_gt[5]) + fabs(scale[1] / 2.)) / fabs(scale[1]));
1272 _gt[1] = fabs(scale[0]);
1273 _gt[5] = -1 * fabs(scale[1]);
1274 _gt[2] = skew[0];
1275 _gt[4] = skew[1];
1277
1278 /* minimize width/height */
1279 for (i = 0; i < 2; i++) {
1280 covers = 1;
1281 do {
1282 if (i < 1)
1283 raster->width--;
1284 else
1285 raster->height--;
1286
1287 /* construct sgeom from raster */
1288 if ((rt_raster_get_convex_hull(raster, &geom) != ES_NONE) || geom == NULL) {
1289 rterror("rt_raster_compute_skewed_raster: Could not build skewed extent's geometry for minimizing dimensions");
1290 GEOSGeom_destroy(ngeom);
1291 rt_raster_destroy(raster);
1292 return NULL;
1293 }
1294
1295 sgeom = (GEOSGeometry *) LWGEOM2GEOS(geom, 0);
1296 lwgeom_free(geom);
1297
1298 covers = GEOSRelatePattern(sgeom, ngeom, "******FF*");
1299 GEOSGeom_destroy(sgeom);
1300
1301 if (covers == 2) {
1302 rterror("rt_raster_compute_skewed_raster: Could not run covers test for minimizing dimensions");
1303 GEOSGeom_destroy(ngeom);
1304 rt_raster_destroy(raster);
1305 return NULL;
1306 }
1307 } while (covers);
1308
1309 if (i < 1)
1310 raster->width++;
1311 else
1312 raster->height++;
1313
1314 }
1315
1316 GEOSGeom_destroy(ngeom);
1317
1318 return raster;
1319}
1320
1328int
1330 return (!raster || raster->height == 0 || raster->width == 0);
1331}
1332
1341int
1342rt_raster_has_band(rt_raster raster, int nband) {
1343 return !(NULL == raster || nband >= raster->numBands || nband < 0);
1344}
1345
1346/******************************************************************************
1347* rt_raster_copy_band()
1348******************************************************************************/
1349
1364int
1366 rt_raster torast, rt_raster fromrast,
1367 int fromindex, int toindex
1368) {
1369 rt_band srcband = NULL;
1370 rt_band dstband = NULL;
1371
1372 assert(NULL != torast);
1373 assert(NULL != fromrast);
1374
1375 /* Check raster dimensions */
1376 if (torast->height != fromrast->height || torast->width != fromrast->width) {
1377 rtwarn("rt_raster_copy_band: Attempting to add a band with different width or height");
1378 return -1;
1379 }
1380
1381 /* Check bands limits */
1382 if (fromrast->numBands < 1) {
1383 rtwarn("rt_raster_copy_band: Second raster has no band");
1384 return -1;
1385 }
1386 else if (fromindex < 0) {
1387 rtwarn("rt_raster_copy_band: Band index for second raster < 0. Defaulted to 0");
1388 fromindex = 0;
1389 }
1390 else if (fromindex >= fromrast->numBands) {
1391 rtwarn("rt_raster_copy_band: Band index for second raster > number of bands, truncated from %u to %u", fromindex, fromrast->numBands - 1);
1392 fromindex = fromrast->numBands - 1;
1393 }
1394
1395 if (toindex < 0) {
1396 rtwarn("rt_raster_copy_band: Band index for first raster < 0. Defaulted to 0");
1397 toindex = 0;
1398 }
1399 else if (toindex > torast->numBands) {
1400 rtwarn("rt_raster_copy_band: Band index for first raster > number of bands, truncated from %u to %u", toindex, torast->numBands);
1401 toindex = torast->numBands;
1402 }
1403
1404 /* Get band from source raster */
1405 srcband = rt_raster_get_band(fromrast, fromindex);
1406
1407 /* duplicate band */
1408 dstband = rt_band_duplicate(srcband);
1409
1410 /* Add band to the second raster */
1411 return rt_raster_add_band(torast, dstband, toindex);
1412}
1413
1414/******************************************************************************
1415* rt_raster_from_band()
1416******************************************************************************/
1417
1430rt_raster_from_band(rt_raster raster, uint32_t *bandNums, int count) {
1431 rt_raster rast = NULL;
1432 int i = 0;
1433 int j = 0;
1434 int idx;
1435 int32_t flag;
1436 double gt[6] = {0.};
1437
1438 assert(NULL != raster);
1439 assert(NULL != bandNums);
1440
1441 RASTER_DEBUGF(3, "rt_raster_from_band: source raster has %d bands",
1442 rt_raster_get_num_bands(raster));
1443
1444 /* create new raster */
1445 rast = rt_raster_new(raster->width, raster->height);
1446 if (NULL == rast) {
1447 rterror("rt_raster_from_band: Out of memory allocating new raster");
1448 return NULL;
1449 }
1450
1451 /* copy raster attributes */
1454
1455 /* srid */
1456 rt_raster_set_srid(rast, raster->srid);
1457
1458 /* copy bands */
1459 for (i = 0; i < count; i++) {
1460 idx = bandNums[i];
1461 flag = rt_raster_copy_band(rast, raster, idx, i);
1462
1463 if (flag < 0) {
1464 rterror("rt_raster_from_band: Could not copy band");
1465 for (j = 0; j < i; j++) rt_band_destroy(rast->bands[j]);
1466 rt_raster_destroy(rast);
1467 return NULL;
1468 }
1469
1470 RASTER_DEBUGF(3, "rt_raster_from_band: band created at index %d",
1471 flag);
1472 }
1473
1474 RASTER_DEBUGF(3, "rt_raster_from_band: new raster has %d bands",
1476 return rast;
1477}
1478
1479/******************************************************************************
1480* rt_raster_replace_band()
1481******************************************************************************/
1482
1492rt_band
1493rt_raster_replace_band(rt_raster raster, rt_band band, int index) {
1494 rt_band oldband = NULL;
1495 assert(NULL != raster);
1496 assert(NULL != band);
1497
1498 if (band->width != raster->width || band->height != raster->height) {
1499 rterror("rt_raster_replace_band: Band does not match raster's dimensions: %dx%d band to %dx%d raster",
1500 band->width, band->height, raster->width, raster->height);
1501 return 0;
1502 }
1503
1504 if (index >= raster->numBands || index < 0) {
1505 rterror("rt_raster_replace_band: Band index is not valid");
1506 return 0;
1507 }
1508
1509 oldband = rt_raster_get_band(raster, index);
1510 RASTER_DEBUGF(3, "rt_raster_replace_band: old band at %p", oldband);
1511 RASTER_DEBUGF(3, "rt_raster_replace_band: new band at %p", band);
1512
1513 raster->bands[index] = band;
1514 RASTER_DEBUGF(3, "rt_raster_replace_band: new band at %p", raster->bands[index]);
1515
1516 band->raster = raster;
1517 oldband->raster = NULL;
1518
1519 return oldband;
1520}
1521
1522/******************************************************************************
1523* rt_raster_clone()
1524******************************************************************************/
1525
1535rt_raster_clone(rt_raster raster, uint8_t deep) {
1536 rt_raster rtn = NULL;
1537 double gt[6] = {0};
1538
1539 assert(NULL != raster);
1540
1541 if (deep) {
1542 int numband = rt_raster_get_num_bands(raster);
1543 uint32_t *nband = NULL;
1544 int i = 0;
1545
1546 nband = rtalloc(sizeof(uint32_t) * numband);
1547 if (nband == NULL) {
1548 rterror("rt_raster_clone: Could not allocate memory for deep clone");
1549 return NULL;
1550 }
1551 for (i = 0; i < numband; i++)
1552 nband[i] = i;
1553
1554 rtn = rt_raster_from_band(raster, nband, numband);
1555 rtdealloc(nband);
1556
1557 return rtn;
1558 }
1559
1560 rtn = rt_raster_new(
1561 rt_raster_get_width(raster),
1562 rt_raster_get_height(raster)
1563 );
1564 if (rtn == NULL) {
1565 rterror("rt_raster_clone: Could not create cloned raster");
1566 return NULL;
1567 }
1568
1572
1573 return rtn;
1574}
1575
1576/******************************************************************************
1577* rt_raster_to_gdal()
1578******************************************************************************/
1579
1592uint8_t*
1594 rt_raster raster, const char *srs,
1595 char *format, char **options, uint64_t *gdalsize
1596) {
1597 const char *cc;
1598 const char *vio;
1599
1600 GDALDriverH src_drv = NULL;
1601 int destroy_src_drv = 0;
1602 GDALDatasetH src_ds = NULL;
1603
1604 vsi_l_offset rtn_lenvsi;
1605 uint64_t rtn_len = 0;
1606
1607 GDALDriverH rtn_drv = NULL;
1608 GDALDatasetH rtn_ds = NULL;
1609 uint8_t *rtn = NULL;
1610
1611 assert(NULL != raster);
1612 assert(NULL != gdalsize);
1613
1614 /* any supported format is possible */
1616 RASTER_DEBUG(3, "loaded all supported GDAL formats");
1617
1618 /* output format not specified */
1619 if (format == NULL || !strlen(format))
1620 format = "GTiff";
1621 RASTER_DEBUGF(3, "output format is %s", format);
1622
1623 /* load raster into a GDAL MEM raster */
1624 src_ds = rt_raster_to_gdal_mem(raster, srs, NULL, NULL, 0, &src_drv, &destroy_src_drv);
1625 if (NULL == src_ds) {
1626 rterror("rt_raster_to_gdal: Could not convert raster to GDAL MEM format");
1627 return 0;
1628 }
1629
1630 /* load driver */
1631 rtn_drv = GDALGetDriverByName(format);
1632 if (NULL == rtn_drv) {
1633 rterror("rt_raster_to_gdal: Could not load the output GDAL driver");
1634 GDALClose(src_ds);
1635 if (destroy_src_drv) GDALDestroyDriver(src_drv);
1636 return 0;
1637 }
1638 RASTER_DEBUG(3, "Output driver loaded");
1639
1640 /* CreateCopy support */
1641 cc = GDALGetMetadataItem(rtn_drv, GDAL_DCAP_CREATECOPY, NULL);
1642 /* VirtualIO support */
1643 vio = GDALGetMetadataItem(rtn_drv, GDAL_DCAP_VIRTUALIO, NULL);
1644
1645 if (cc == NULL || vio == NULL) {
1646 rterror("rt_raster_to_gdal: Output GDAL driver does not support CreateCopy and/or VirtualIO");
1647 GDALClose(src_ds);
1648 if (destroy_src_drv) GDALDestroyDriver(src_drv);
1649 return 0;
1650 }
1651
1652 /* convert GDAL MEM raster to output format */
1653 RASTER_DEBUG(3, "Copying GDAL MEM raster to memory file in output format");
1654 rtn_ds = GDALCreateCopy(
1655 rtn_drv,
1656 "/vsimem/out.dat", /* should be fine assuming this is in a process */
1657 src_ds,
1658 FALSE, /* should copy be strictly equivelent? */
1659 options, /* format options */
1660 NULL, /* progress function */
1661 NULL /* progress data */
1662 );
1663
1664 /* close source dataset */
1665 GDALClose(src_ds);
1666 if (destroy_src_drv) GDALDestroyDriver(src_drv);
1667 RASTER_DEBUG(3, "Closed GDAL MEM raster");
1668
1669 if (NULL == rtn_ds) {
1670 rterror("rt_raster_to_gdal: Could not create the output GDAL dataset");
1671 return 0;
1672 }
1673
1674 RASTER_DEBUGF(4, "dataset SRS: %s", GDALGetProjectionRef(rtn_ds));
1675
1676 /* close dataset, this also flushes any pending writes */
1677 GDALClose(rtn_ds);
1678 RASTER_DEBUG(3, "Closed GDAL output raster");
1679
1680 RASTER_DEBUG(3, "Done copying GDAL MEM raster to memory file in output format");
1681
1682 /* from memory file to buffer */
1683 RASTER_DEBUG(3, "Copying GDAL memory file to buffer");
1684 rtn = VSIGetMemFileBuffer("/vsimem/out.dat", &rtn_lenvsi, TRUE);
1685 RASTER_DEBUG(3, "Done copying GDAL memory file to buffer");
1686 if (NULL == rtn) {
1687 rterror("rt_raster_to_gdal: Could not create the output GDAL raster");
1688 return 0;
1689 }
1690
1691 rtn_len = (uint64_t) rtn_lenvsi;
1692 *gdalsize = rtn_len;
1693
1694 return rtn;
1695}
1696
1697/******************************************************************************
1698* rt_raster_gdal_drivers()
1699******************************************************************************/
1700
1711rt_raster_gdal_drivers(uint32_t *drv_count, uint8_t can_write) {
1712 const char *cc;
1713 const char *vio;
1714 const char *txt;
1715 int txt_len;
1716 GDALDriverH *drv = NULL;
1717 rt_gdaldriver rtn = NULL;
1718 int count;
1719 int i;
1720 uint32_t j;
1721
1722 assert(drv_count != NULL);
1723
1725 count = GDALGetDriverCount();
1726 RASTER_DEBUGF(3, "%d drivers found", count);
1727
1728 rtn = (rt_gdaldriver) rtalloc(count * sizeof(struct rt_gdaldriver_t));
1729 if (NULL == rtn) {
1730 rterror("rt_raster_gdal_drivers: Could not allocate memory for gdaldriver structure");
1731 return 0;
1732 }
1733
1734 for (i = 0, j = 0; i < count; i++) {
1735 drv = GDALGetDriver(i);
1736
1737#ifdef GDAL_DCAP_RASTER
1738 /* Starting with GDAL 2.0, vector drivers can also be returned */
1739 /* Only keep raster drivers */
1740 const char *is_raster;
1741 is_raster = GDALGetMetadataItem(drv, GDAL_DCAP_RASTER, NULL);
1742 if (is_raster == NULL || !EQUAL(is_raster, "YES"))
1743 continue;
1744#endif
1745
1746 /* CreateCopy support */
1747 cc = GDALGetMetadataItem(drv, GDAL_DCAP_CREATECOPY, NULL);
1748
1749 /* VirtualIO support */
1750 vio = GDALGetMetadataItem(drv, GDAL_DCAP_VIRTUALIO, NULL);
1751
1752 if (can_write && (cc == NULL || vio == NULL))
1753 continue;
1754
1755 /* we can always read what GDAL can load */
1756 rtn[j].can_read = 1;
1757 /* we require CreateCopy and VirtualIO support to write to GDAL */
1758 rtn[j].can_write = (cc != NULL && vio != NULL);
1759
1760 if (rtn[j].can_write) {
1761 RASTER_DEBUGF(3, "driver %s (%d) supports CreateCopy() and VirtualIO()", txt, i);
1762 }
1763
1764 /* index of driver */
1765 rtn[j].idx = i;
1766
1767 /* short name */
1768 txt = GDALGetDriverShortName(drv);
1769 txt_len = strlen(txt);
1770
1771 txt_len = (txt_len + 1) * sizeof(char);
1772 rtn[j].short_name = (char *) rtalloc(txt_len);
1773 memcpy(rtn[j].short_name, txt, txt_len);
1774
1775 /* long name */
1776 txt = GDALGetDriverLongName(drv);
1777 txt_len = strlen(txt);
1778
1779 txt_len = (txt_len + 1) * sizeof(char);
1780 rtn[j].long_name = (char *) rtalloc(txt_len);
1781 memcpy(rtn[j].long_name, txt, txt_len);
1782
1783 /* creation options */
1784 txt = GDALGetDriverCreationOptionList(drv);
1785 txt_len = strlen(txt);
1786
1787 txt_len = (txt_len + 1) * sizeof(char);
1788 rtn[j].create_options = (char *) rtalloc(txt_len);
1789 memcpy(rtn[j].create_options, txt, txt_len);
1790
1791 j++;
1792 }
1793
1794 /* free unused memory */
1795 rtn = rtrealloc(rtn, j * sizeof(struct rt_gdaldriver_t));
1796 *drv_count = j;
1797
1798 return rtn;
1799}
1800
1801/******************************************************************************
1802* rt_raster_to_gdal_mem()
1803******************************************************************************/
1804
1820GDALDatasetH
1822 rt_raster raster,
1823 const char *srs,
1824 uint32_t *bandNums,
1825 int *excludeNodataValues,
1826 int count,
1827 GDALDriverH *rtn_drv, int *destroy_rtn_drv
1828) {
1829 GDALDriverH drv = NULL;
1830 GDALDatasetH ds = NULL;
1831 double gt[6] = {0.0};
1832 CPLErr cplerr;
1833 GDALDataType gdal_pt = GDT_Unknown;
1834 GDALRasterBandH band;
1835 void *pVoid;
1836 char *pszDataPointer;
1837 char szGDALOption[50];
1838 char *apszOptions[4];
1839 double nodata = 0.0;
1840 int allocBandNums = 0;
1841 int allocNodataValues = 0;
1842
1843 int i;
1844 uint32_t numBands;
1845 uint32_t width = 0;
1846 uint32_t height = 0;
1847 rt_band rtband = NULL;
1848 rt_pixtype pt = PT_END;
1849
1850 assert(NULL != raster);
1851 assert(NULL != rtn_drv);
1852 assert(NULL != destroy_rtn_drv);
1853
1854 *destroy_rtn_drv = 0;
1855
1856 /* store raster in GDAL MEM raster */
1857 if (!rt_util_gdal_driver_registered("MEM")) {
1858 RASTER_DEBUG(4, "Registering MEM driver");
1859 GDALRegister_MEM();
1860 *destroy_rtn_drv = 1;
1861 }
1862 drv = GDALGetDriverByName("MEM");
1863 if (NULL == drv) {
1864 rterror("rt_raster_to_gdal_mem: Could not load the MEM GDAL driver");
1865 return 0;
1866 }
1867 *rtn_drv = drv;
1868
1869 /* unload driver from GDAL driver manager */
1870 if (*destroy_rtn_drv) {
1871 RASTER_DEBUG(4, "Deregistering MEM driver");
1872 GDALDeregisterDriver(drv);
1873 }
1874
1875 width = rt_raster_get_width(raster);
1876 height = rt_raster_get_height(raster);
1877 ds = GDALCreate(
1878 drv, "",
1879 width, height,
1880 0, GDT_Byte, NULL
1881 );
1882 if (NULL == ds) {
1883 rterror("rt_raster_to_gdal_mem: Could not create a GDALDataset to convert into");
1884 return 0;
1885 }
1886
1887 /* add geotransform */
1889 cplerr = GDALSetGeoTransform(ds, gt);
1890 if (cplerr != CE_None) {
1891 rterror("rt_raster_to_gdal_mem: Could not set geotransformation");
1892 GDALClose(ds);
1893 return 0;
1894 }
1895
1896 /* set spatial reference */
1897 if (NULL != srs && strlen(srs)) {
1898 char *_srs = rt_util_gdal_convert_sr(srs, 0);
1899 if (_srs == NULL) {
1900 rterror("rt_raster_to_gdal_mem: Could not convert srs to GDAL accepted format");
1901 GDALClose(ds);
1902 return 0;
1903 }
1904
1905 cplerr = GDALSetProjection(ds, _srs);
1906 CPLFree(_srs);
1907 if (cplerr != CE_None) {
1908 rterror("rt_raster_to_gdal_mem: Could not set projection");
1909 GDALClose(ds);
1910 return 0;
1911 }
1912 RASTER_DEBUGF(3, "Projection set to: %s", GDALGetProjectionRef(ds));
1913 }
1914
1915 /* process bandNums */
1916 numBands = rt_raster_get_num_bands(raster);
1917 if (NULL != bandNums && count > 0) {
1918 for (i = 0; i < count; i++) {
1919 if (bandNums[i] >= numBands) {
1920 rterror("rt_raster_to_gdal_mem: The band index %d is invalid", bandNums[i]);
1921 GDALClose(ds);
1922 return 0;
1923 }
1924 }
1925 }
1926 else {
1927 count = numBands;
1928 bandNums = (uint32_t *) rtalloc(sizeof(uint32_t) * count);
1929 if (NULL == bandNums) {
1930 rterror("rt_raster_to_gdal_mem: Could not allocate memory for band indices");
1931 GDALClose(ds);
1932 return 0;
1933 }
1934 allocBandNums = 1;
1935 for (i = 0; i < count; i++) bandNums[i] = i;
1936 }
1937
1938 /* process exclude_nodata_values */
1939 if (NULL == excludeNodataValues) {
1940 excludeNodataValues = (int *) rtalloc(sizeof(int) * count);
1941 if (NULL == excludeNodataValues) {
1942 rterror("rt_raster_to_gdal_mem: Could not allocate memory for NODATA flags");
1943 GDALClose(ds);
1944 return 0;
1945 }
1946 allocNodataValues = 1;
1947 for (i = 0; i < count; i++) excludeNodataValues[i] = 1;
1948 }
1949
1950 /* add band(s) */
1951 for (i = 0; i < count; i++) {
1952 rtband = rt_raster_get_band(raster, bandNums[i]);
1953 if (NULL == rtband) {
1954 rterror("rt_raster_to_gdal_mem: Could not get requested band index %d", bandNums[i]);
1955 if (allocBandNums) rtdealloc(bandNums);
1956 if (allocNodataValues) rtdealloc(excludeNodataValues);
1957 GDALClose(ds);
1958 return 0;
1959 }
1960
1961 pt = rt_band_get_pixtype(rtband);
1963 if (gdal_pt == GDT_Unknown)
1964 rtwarn("rt_raster_to_gdal_mem: Unknown pixel type for band");
1965
1966 /*
1967 For all pixel types other than PT_8BSI, set pointer to start of data
1968 */
1969 if (pt != PT_8BSI) {
1970 pVoid = rt_band_get_data(rtband);
1971 RASTER_DEBUGF(4, "Band data is at pos %p", pVoid);
1972
1973 pszDataPointer = (char *) rtalloc(20 * sizeof (char));
1974 sprintf(pszDataPointer, "%p", pVoid);
1975 RASTER_DEBUGF(4, "rt_raster_to_gdal_mem: szDatapointer is %p",
1976 pszDataPointer);
1977
1978 if (strncasecmp(pszDataPointer, "0x", 2) == 0)
1979 sprintf(szGDALOption, "DATAPOINTER=%s", pszDataPointer);
1980 else
1981 sprintf(szGDALOption, "DATAPOINTER=0x%s", pszDataPointer);
1982
1983 RASTER_DEBUG(3, "Storing info for GDAL MEM raster band");
1984
1985 apszOptions[0] = szGDALOption;
1986 apszOptions[1] = NULL; /* pixel offset, not needed */
1987 apszOptions[2] = NULL; /* line offset, not needed */
1988 apszOptions[3] = NULL;
1989
1990 /* free */
1991 rtdealloc(pszDataPointer);
1992
1993 /* add band */
1994 if (GDALAddBand(ds, gdal_pt, apszOptions) == CE_Failure) {
1995 rterror("rt_raster_to_gdal_mem: Could not add GDAL raster band");
1996 if (allocBandNums) rtdealloc(bandNums);
1997 GDALClose(ds);
1998 return 0;
1999 }
2000 }
2001 /*
2002 PT_8BSI is special as GDAL has no equivalent pixel type.
2003 Must convert 8BSI to 16BSI so create basic band
2004 */
2005 else {
2006 /* add band */
2007 if (GDALAddBand(ds, gdal_pt, NULL) == CE_Failure) {
2008 rterror("rt_raster_to_gdal_mem: Could not add GDAL raster band");
2009 if (allocBandNums) rtdealloc(bandNums);
2010 if (allocNodataValues) rtdealloc(excludeNodataValues);
2011 GDALClose(ds);
2012 return 0;
2013 }
2014 }
2015
2016 /* check band count */
2017 if (GDALGetRasterCount(ds) != i + 1) {
2018 rterror("rt_raster_to_gdal_mem: Error creating GDAL MEM raster band");
2019 if (allocBandNums) rtdealloc(bandNums);
2020 if (allocNodataValues) rtdealloc(excludeNodataValues);
2021 GDALClose(ds);
2022 return 0;
2023 }
2024
2025 /* get new band */
2026 band = NULL;
2027 band = GDALGetRasterBand(ds, i + 1);
2028 if (NULL == band) {
2029 rterror("rt_raster_to_gdal_mem: Could not get GDAL band for additional processing");
2030 if (allocBandNums) rtdealloc(bandNums);
2031 if (allocNodataValues) rtdealloc(excludeNodataValues);
2032 GDALClose(ds);
2033 return 0;
2034 }
2035
2036 /* PT_8BSI requires manual setting of pixels */
2037 if (pt == PT_8BSI) {
2038 uint32_t nXBlocks, nYBlocks;
2039 int nXBlockSize, nYBlockSize;
2040 uint32_t iXBlock, iYBlock;
2041 int nXValid, nYValid;
2042 int iX, iY;
2043 int iXMax, iYMax;
2044
2045 int x, y, z;
2046 uint32_t valueslen = 0;
2047 int16_t *values = NULL;
2048 double value = 0.;
2049
2050 /* this makes use of GDAL's "natural" blocks */
2051 GDALGetBlockSize(band, &nXBlockSize, &nYBlockSize);
2052 nXBlocks = (width + nXBlockSize - 1) / nXBlockSize;
2053 nYBlocks = (height + nYBlockSize - 1) / nYBlockSize;
2054 RASTER_DEBUGF(4, "(nXBlockSize, nYBlockSize) = (%d, %d)", nXBlockSize, nYBlockSize);
2055 RASTER_DEBUGF(4, "(nXBlocks, nYBlocks) = (%d, %d)", nXBlocks, nYBlocks);
2056
2057 /* length is for the desired pixel type */
2058 valueslen = rt_pixtype_size(PT_16BSI) * nXBlockSize * nYBlockSize;
2059 values = rtalloc(valueslen);
2060 if (NULL == values) {
2061 rterror("rt_raster_to_gdal_mem: Could not allocate memory for GDAL band pixel values");
2062 if (allocBandNums) rtdealloc(bandNums);
2063 if (allocNodataValues) rtdealloc(excludeNodataValues);
2064 GDALClose(ds);
2065 return 0;
2066 }
2067
2068 for (iYBlock = 0; iYBlock < nYBlocks; iYBlock++) {
2069 for (iXBlock = 0; iXBlock < nXBlocks; iXBlock++) {
2070 memset(values, 0, valueslen);
2071
2072 x = iXBlock * nXBlockSize;
2073 y = iYBlock * nYBlockSize;
2074 RASTER_DEBUGF(4, "(iXBlock, iYBlock) = (%d, %d)", iXBlock, iYBlock);
2075 RASTER_DEBUGF(4, "(x, y) = (%d, %d)", x, y);
2076
2077 /* valid block width */
2078 if ((iXBlock + 1) * nXBlockSize > width)
2079 nXValid = width - (iXBlock * nXBlockSize);
2080 else
2081 nXValid = nXBlockSize;
2082
2083 /* valid block height */
2084 if ((iYBlock + 1) * nYBlockSize > height)
2085 nYValid = height - (iYBlock * nYBlockSize);
2086 else
2087 nYValid = nYBlockSize;
2088
2089 RASTER_DEBUGF(4, "(nXValid, nYValid) = (%d, %d)", nXValid, nYValid);
2090
2091 /* convert 8BSI values to 16BSI */
2092 z = 0;
2093 iYMax = y + nYValid;
2094 iXMax = x + nXValid;
2095 for (iY = y; iY < iYMax; iY++) {
2096 for (iX = x; iX < iXMax; iX++) {
2097 if (rt_band_get_pixel(rtband, iX, iY, &value, NULL) != ES_NONE) {
2098 rterror("rt_raster_to_gdal_mem: Could not get pixel value to convert from 8BSI to 16BSI");
2099 rtdealloc(values);
2100 if (allocBandNums) rtdealloc(bandNums);
2101 if (allocNodataValues) rtdealloc(excludeNodataValues);
2102 GDALClose(ds);
2103 return 0;
2104 }
2105
2106 values[z++] = rt_util_clamp_to_16BSI(value);
2107 }
2108 }
2109
2110 /* burn values */
2111 if (GDALRasterIO(
2112 band, GF_Write,
2113 x, y,
2114 nXValid, nYValid,
2115 values, nXValid, nYValid,
2116 gdal_pt,
2117 0, 0
2118 ) != CE_None) {
2119 rterror("rt_raster_to_gdal_mem: Could not write converted 8BSI to 16BSI values to GDAL band");
2120 rtdealloc(values);
2121 if (allocBandNums) rtdealloc(bandNums);
2122 if (allocNodataValues) rtdealloc(excludeNodataValues);
2123 GDALClose(ds);
2124 return 0;
2125 }
2126 }
2127 }
2128
2129 rtdealloc(values);
2130 }
2131
2132 /* Add nodata value for band */
2133 if (rt_band_get_hasnodata_flag(rtband) != FALSE && excludeNodataValues[i]) {
2134 rt_band_get_nodata(rtband, &nodata);
2135 if (GDALSetRasterNoDataValue(band, nodata) != CE_None)
2136 rtwarn("rt_raster_to_gdal_mem: Could not set nodata value for band");
2137 RASTER_DEBUGF(3, "nodata value set to %f", GDALGetRasterNoDataValue(band, NULL));
2138 }
2139
2140#if POSTGIS_DEBUG_LEVEL > 3
2141 {
2142 GDALRasterBandH _grb = NULL;
2143 double _min;
2144 double _max;
2145 double _mean;
2146 double _stddev;
2147
2148 _grb = GDALGetRasterBand(ds, i + 1);
2149 GDALComputeRasterStatistics(_grb, FALSE, &_min, &_max, &_mean, &_stddev, NULL, NULL);
2150 RASTER_DEBUGF(4, "GDAL Band %d stats: %f, %f, %f, %f", i + 1, _min, _max, _mean, _stddev);
2151 }
2152#endif
2153
2154 }
2155
2156 /* necessary??? */
2157 GDALFlushCache(ds);
2158
2159 if (allocBandNums) rtdealloc(bandNums);
2160 if (allocNodataValues) rtdealloc(excludeNodataValues);
2161
2162 return ds;
2163}
2164
2165/******************************************************************************
2166* rt_raster_from_gdal_dataset()
2167******************************************************************************/
2168
2178 rt_raster rast = NULL;
2179 double gt[6] = {0};
2180 CPLErr cplerr;
2181 uint32_t width = 0;
2182 uint32_t height = 0;
2183 uint32_t numBands = 0;
2184 uint32_t i = 0;
2185 char *authname = NULL;
2186 char *authcode = NULL;
2187
2188 GDALRasterBandH gdband = NULL;
2189 GDALDataType gdpixtype = GDT_Unknown;
2190 rt_band band;
2191 int32_t idx;
2192 rt_pixtype pt = PT_END;
2193 uint32_t ptlen = 0;
2194 int hasnodata = 0;
2195 double nodataval;
2196
2197 int x;
2198 int y;
2199
2200 uint32_t nXBlocks, nYBlocks;
2201 int nXBlockSize, nYBlockSize;
2202 uint32_t iXBlock, iYBlock;
2203 uint32_t nXValid, nYValid;
2204 uint32_t iY;
2205
2206 uint8_t *values = NULL;
2207 uint32_t valueslen = 0;
2208 uint8_t *ptr = NULL;
2209
2210 assert(NULL != ds);
2211
2212 /* raster size */
2213 width = GDALGetRasterXSize(ds);
2214 height = GDALGetRasterYSize(ds);
2215 RASTER_DEBUGF(3, "Raster dimensions (width x height): %d x %d", width, height);
2216
2217 /* create new raster */
2218 RASTER_DEBUG(3, "Creating new raster");
2219 rast = rt_raster_new(width, height);
2220 if (NULL == rast) {
2221 rterror("rt_raster_from_gdal_dataset: Out of memory allocating new raster");
2222 return NULL;
2223 }
2224 RASTER_DEBUGF(3, "Created raster dimensions (width x height): %d x %d", rast->width, rast->height);
2225
2226 /* get raster attributes */
2227 cplerr = GDALGetGeoTransform(ds, gt);
2228 if (GDALGetGeoTransform(ds, gt) != CE_None) {
2229 RASTER_DEBUG(4, "Using default geotransform matrix (0, 1, 0, 0, 0, -1)");
2230 gt[0] = 0;
2231 gt[1] = 1;
2232 gt[2] = 0;
2233 gt[3] = 0;
2234 gt[4] = 0;
2235 gt[5] = -1;
2236 }
2237
2238 /* apply raster attributes */
2240
2241 RASTER_DEBUGF(3, "Raster geotransform (%f, %f, %f, %f, %f, %f)",
2242 gt[0], gt[1], gt[2], gt[3], gt[4], gt[5]);
2243
2244 /* srid */
2245 if (rt_util_gdal_sr_auth_info(ds, &authname, &authcode) == ES_NONE) {
2246 if (
2247 authname != NULL &&
2248 strcmp(authname, "EPSG") == 0 &&
2249 authcode != NULL
2250 ) {
2251 rt_raster_set_srid(rast, atoi(authcode));
2252 RASTER_DEBUGF(3, "New raster's SRID = %d", rast->srid);
2253 }
2254
2255 if (authname != NULL)
2256 rtdealloc(authname);
2257 if (authcode != NULL)
2258 rtdealloc(authcode);
2259 }
2260
2261 numBands = GDALGetRasterCount(ds);
2262
2263#if POSTGIS_DEBUG_LEVEL > 3
2264 for (i = 1; i <= numBands; i++) {
2265 GDALRasterBandH _grb = NULL;
2266 double _min;
2267 double _max;
2268 double _mean;
2269 double _stddev;
2270
2271 _grb = GDALGetRasterBand(ds, i);
2272 GDALComputeRasterStatistics(_grb, FALSE, &_min, &_max, &_mean, &_stddev, NULL, NULL);
2273 RASTER_DEBUGF(4, "GDAL Band %d stats: %f, %f, %f, %f", i, _min, _max, _mean, _stddev);
2274 }
2275#endif
2276
2277 /* copy bands */
2278 for (i = 1; i <= numBands; i++) {
2279 RASTER_DEBUGF(3, "Processing band %d of %d", i, numBands);
2280 gdband = NULL;
2281 gdband = GDALGetRasterBand(ds, i);
2282 if (NULL == gdband) {
2283 rterror("rt_raster_from_gdal_dataset: Could not get GDAL band");
2284 rt_raster_destroy(rast);
2285 return NULL;
2286 }
2287 RASTER_DEBUGF(4, "gdband @ %p", gdband);
2288
2289 /* pixtype */
2290 gdpixtype = GDALGetRasterDataType(gdband);
2291 RASTER_DEBUGF(4, "gdpixtype, size = %s, %d", GDALGetDataTypeName(gdpixtype), GDALGetDataTypeSize(gdpixtype) / 8);
2292 pt = rt_util_gdal_datatype_to_pixtype(gdpixtype);
2293 if (pt == PT_END) {
2294 rterror("rt_raster_from_gdal_dataset: Unknown pixel type for GDAL band");
2295 rt_raster_destroy(rast);
2296 return NULL;
2297 }
2298 ptlen = rt_pixtype_size(pt);
2299
2300 /* size: width and height */
2301 width = GDALGetRasterBandXSize(gdband);
2302 height = GDALGetRasterBandYSize(gdband);
2303 RASTER_DEBUGF(3, "GDAL band dimensions (width x height): %d x %d", width, height);
2304
2305 /* nodata */
2306 nodataval = GDALGetRasterNoDataValue(gdband, &hasnodata);
2307 RASTER_DEBUGF(3, "(hasnodata, nodataval) = (%d, %f)", hasnodata, nodataval);
2308
2309 /* create band object */
2311 rast, pt,
2312 (hasnodata ? nodataval : 0),
2313 hasnodata, nodataval, rt_raster_get_num_bands(rast)
2314 );
2315 if (idx < 0) {
2316 rterror("rt_raster_from_gdal_dataset: Could not allocate memory for raster band");
2317 rt_raster_destroy(rast);
2318 return NULL;
2319 }
2320 band = rt_raster_get_band(rast, idx);
2321 RASTER_DEBUGF(3, "Created band of dimension (width x height): %d x %d", band->width, band->height);
2322
2323 /* this makes use of GDAL's "natural" blocks */
2324 GDALGetBlockSize(gdband, &nXBlockSize, &nYBlockSize);
2325 nXBlocks = (width + nXBlockSize - 1) / nXBlockSize;
2326 nYBlocks = (height + nYBlockSize - 1) / nYBlockSize;
2327 RASTER_DEBUGF(4, "(nXBlockSize, nYBlockSize) = (%d, %d)", nXBlockSize, nYBlockSize);
2328 RASTER_DEBUGF(4, "(nXBlocks, nYBlocks) = (%d, %d)", nXBlocks, nYBlocks);
2329
2330 /* allocate memory for values */
2331 valueslen = ptlen * nXBlockSize * nYBlockSize;
2332 values = rtalloc(valueslen);
2333 if (values == NULL) {
2334 rterror("rt_raster_from_gdal_dataset: Could not allocate memory for GDAL band pixel values");
2335 rt_raster_destroy(rast);
2336 return NULL;
2337 }
2338 RASTER_DEBUGF(3, "values @ %p of length = %d", values, valueslen);
2339
2340 for (iYBlock = 0; iYBlock < nYBlocks; iYBlock++) {
2341 for (iXBlock = 0; iXBlock < nXBlocks; iXBlock++) {
2342 x = iXBlock * nXBlockSize;
2343 y = iYBlock * nYBlockSize;
2344 RASTER_DEBUGF(4, "(iXBlock, iYBlock) = (%d, %d)", iXBlock, iYBlock);
2345 RASTER_DEBUGF(4, "(x, y) = (%d, %d)", x, y);
2346
2347 memset(values, 0, valueslen);
2348
2349 /* valid block width */
2350 if ((iXBlock + 1) * nXBlockSize > width)
2351 nXValid = width - (iXBlock * nXBlockSize);
2352 else
2353 nXValid = nXBlockSize;
2354
2355 /* valid block height */
2356 if ((iYBlock + 1) * nYBlockSize > height)
2357 nYValid = height - (iYBlock * nYBlockSize);
2358 else
2359 nYValid = nYBlockSize;
2360
2361 RASTER_DEBUGF(4, "(nXValid, nYValid) = (%d, %d)", nXValid, nYValid);
2362
2363 cplerr = GDALRasterIO(
2364 gdband, GF_Read,
2365 x, y,
2366 nXValid, nYValid,
2367 values, nXValid, nYValid,
2368 gdpixtype,
2369 0, 0
2370 );
2371 if (cplerr != CE_None) {
2372 rterror("rt_raster_from_gdal_dataset: Could not get data from GDAL raster");
2373 rtdealloc(values);
2374 rt_raster_destroy(rast);
2375 return NULL;
2376 }
2377
2378 /* if block width is same as raster width, shortcut */
2379 if (nXBlocks == 1 && nYBlockSize > 1 && nXValid == width) {
2380 x = 0;
2381 y = nYBlockSize * iYBlock;
2382
2383 RASTER_DEBUGF(4, "Setting set of pixel lines at (%d, %d) for %d pixels", x, y, nXValid * nYValid);
2384 rt_band_set_pixel_line(band, x, y, values, nXValid * nYValid);
2385 }
2386 else {
2387 ptr = values;
2388 x = nXBlockSize * iXBlock;
2389 for (iY = 0; iY < nYValid; iY++) {
2390 y = iY + (nYBlockSize * iYBlock);
2391
2392 RASTER_DEBUGF(4, "Setting pixel line at (%d, %d) for %d pixels", x, y, nXValid);
2393 rt_band_set_pixel_line(band, x, y, ptr, nXValid);
2394 ptr += (nXValid * ptlen);
2395 }
2396 }
2397 }
2398 }
2399
2400 /* free memory */
2401 rtdealloc(values);
2402 }
2403
2404 return rast;
2405}
2406
2407/******************************************************************************
2408* rt_raster_gdal_rasterize()
2409******************************************************************************/
2410
2413 uint8_t noband;
2414
2415 uint32_t numbands;
2416
2417 OGRSpatialReferenceH src_sr;
2418
2420 double *init;
2421 double *nodata;
2422 uint8_t *hasnodata;
2423 double *value;
2425};
2426
2427static _rti_rasterize_arg
2429 _rti_rasterize_arg arg = NULL;
2430
2431 arg = rtalloc(sizeof(struct _rti_rasterize_arg_t));
2432 if (arg == NULL) {
2433 rterror("_rti_rasterize_arg_init: Could not allocate memory for _rti_rasterize_arg");
2434 return NULL;
2435 }
2436
2437 arg->noband = 0;
2438
2439 arg->numbands = 0;
2440
2441 arg->src_sr = NULL;
2442
2443 arg->pixtype = NULL;
2444 arg->init = NULL;
2445 arg->nodata = NULL;
2446 arg->hasnodata = NULL;
2447 arg->value = NULL;
2448 arg->bandlist = NULL;
2449
2450 return arg;
2451}
2452
2453static void
2455 if (arg->noband) {
2456 if (arg->pixtype != NULL)
2457 rtdealloc(arg->pixtype);
2458 if (arg->init != NULL)
2459 rtdealloc(arg->init);
2460 if (arg->nodata != NULL)
2461 rtdealloc(arg->nodata);
2462 if (arg->hasnodata != NULL)
2463 rtdealloc(arg->hasnodata);
2464 if (arg->value != NULL)
2465 rtdealloc(arg->value);
2466 }
2467
2468 if (arg->bandlist != NULL)
2469 rtdealloc(arg->bandlist);
2470
2471 if (arg->src_sr != NULL)
2472 OSRDestroySpatialReference(arg->src_sr);
2473
2474 rtdealloc(arg);
2475}
2476
2505 const unsigned char *wkb, uint32_t wkb_len,
2506 const char *srs,
2507 uint32_t num_bands, rt_pixtype *pixtype,
2508 double *init, double *value,
2509 double *nodata, uint8_t *hasnodata,
2510 int *width, int *height,
2511 double *scale_x, double *scale_y,
2512 double *ul_xw, double *ul_yw,
2513 double *grid_xw, double *grid_yw,
2514 double *skew_x, double *skew_y,
2515 char **options
2516) {
2517 rt_raster rast = NULL;
2518 uint32_t i = 0;
2519 int err = 0;
2520
2521 _rti_rasterize_arg arg = NULL;
2522
2523 int _dim[2] = {0};
2524 double _scale[2] = {0};
2525 double _skew[2] = {0};
2526
2527 OGRErr ogrerr;
2528 OGRGeometryH src_geom;
2529 OGREnvelope src_env;
2530 rt_envelope extent;
2531 OGRwkbGeometryType wkbtype = wkbUnknown;
2532
2533 int ul_user = 0;
2534
2535 CPLErr cplerr;
2536 double _gt[6] = {0};
2537 GDALDriverH _drv = NULL;
2538 int unload_drv = 0;
2539 GDALDatasetH _ds = NULL;
2540 GDALRasterBandH _band = NULL;
2541
2542 uint16_t _width = 0;
2543 uint16_t _height = 0;
2544
2545 RASTER_DEBUG(3, "starting");
2546
2547 assert(NULL != wkb);
2548 assert(0 != wkb_len);
2549
2550 /* internal variables */
2552 if (arg == NULL) {
2553 rterror("rt_raster_gdal_rasterize: Could not initialize internal variables");
2554 return NULL;
2555 }
2556
2557 /* no bands, raster is a mask */
2558 if (num_bands < 1) {
2559 arg->noband = 1;
2560 arg->numbands = 1;
2561
2562 arg->pixtype = (rt_pixtype *) rtalloc(sizeof(rt_pixtype));
2563 arg->pixtype[0] = PT_8BUI;
2564
2565 arg->init = (double *) rtalloc(sizeof(double));
2566 arg->init[0] = 0;
2567
2568 arg->nodata = (double *) rtalloc(sizeof(double));
2569 arg->nodata[0] = 0;
2570
2571 arg->hasnodata = (uint8_t *) rtalloc(sizeof(uint8_t));
2572 arg->hasnodata[0] = 1;
2573
2574 arg->value = (double *) rtalloc(sizeof(double));
2575 arg->value[0] = 1;
2576 }
2577 else {
2578 arg->noband = 0;
2579 arg->numbands = num_bands;
2580
2581 arg->pixtype = pixtype;
2582 arg->init = init;
2583 arg->nodata = nodata;
2584 arg->hasnodata = hasnodata;
2585 arg->value = value;
2586 }
2587
2588 /* OGR spatial reference */
2589 if (NULL != srs && strlen(srs)) {
2590 arg->src_sr = OSRNewSpatialReference(NULL);
2591 if (OSRSetFromUserInput(arg->src_sr, srs) != OGRERR_NONE) {
2592 rterror("rt_raster_gdal_rasterize: Could not create OSR spatial reference using the provided srs: %s", srs);
2594 return NULL;
2595 }
2596 }
2597
2598 /* convert WKB to OGR Geometry */
2599 ogrerr = OGR_G_CreateFromWkb((unsigned char *) wkb, arg->src_sr, &src_geom, wkb_len);
2600 if (ogrerr != OGRERR_NONE) {
2601 rterror("rt_raster_gdal_rasterize: Could not create OGR Geometry from WKB");
2602
2604 /* OGRCleanupAll(); */
2605
2606 return NULL;
2607 }
2608
2609 /* OGR Geometry is empty */
2610 if (OGR_G_IsEmpty(src_geom)) {
2611 rtinfo("Geometry provided is empty. Returning empty raster");
2612
2613 OGR_G_DestroyGeometry(src_geom);
2615 /* OGRCleanupAll(); */
2616
2617 return rt_raster_new(0, 0);
2618 }
2619
2620 /* get envelope */
2621 OGR_G_GetEnvelope(src_geom, &src_env);
2622 rt_util_from_ogr_envelope(src_env, &extent);
2623
2624 RASTER_DEBUGF(3, "Suggested raster envelope: %f, %f, %f, %f",
2625 extent.MinX, extent.MinY, extent.MaxX, extent.MaxY);
2626
2627 /* user-defined scale */
2628 if (
2629 (NULL != scale_x) &&
2630 (NULL != scale_y) &&
2631 (FLT_NEQ(*scale_x, 0.0)) &&
2632 (FLT_NEQ(*scale_y, 0.0))
2633 ) {
2634 /* for now, force scale to be in left-right, top-down orientation */
2635 _scale[0] = fabs(*scale_x);
2636 _scale[1] = fabs(*scale_y);
2637 }
2638 /* user-defined width/height */
2639 else if ((NULL != width) && (NULL != height) && (*width != 0) && (*height != 0))
2640 {
2641 _dim[0] = abs(*width);
2642 _dim[1] = abs(*height);
2643
2644 if (FLT_NEQ(extent.MaxX, extent.MinX))
2645 _scale[0] = fabs((extent.MaxX - extent.MinX) / _dim[0]);
2646 else
2647 _scale[0] = 1.;
2648
2649 if (FLT_NEQ(extent.MaxY, extent.MinY))
2650 _scale[1] = fabs((extent.MaxY - extent.MinY) / _dim[1]);
2651 else
2652 _scale[1] = 1.;
2653 }
2654 else {
2655 rterror("rt_raster_gdal_rasterize: Values must be provided for width and height or X and Y of scale");
2656
2657 OGR_G_DestroyGeometry(src_geom);
2659 /* OGRCleanupAll(); */
2660
2661 return NULL;
2662 }
2663 RASTER_DEBUGF(3, "scale (x, y) = %f, %f", _scale[0], -1 * _scale[1]);
2664 RASTER_DEBUGF(3, "dim (x, y) = %d, %d", _dim[0], _dim[1]);
2665
2666 /* user-defined skew */
2667 if (NULL != skew_x) {
2668 _skew[0] = *skew_x;
2669
2670 /*
2671 negative scale-x affects skew
2672 for now, force skew to be in left-right, top-down orientation
2673 */
2674 if (
2675 NULL != scale_x &&
2676 *scale_x < 0.
2677 ) {
2678 _skew[0] *= -1;
2679 }
2680 }
2681 if (NULL != skew_y) {
2682 _skew[1] = *skew_y;
2683
2684 /*
2685 positive scale-y affects skew
2686 for now, force skew to be in left-right, top-down orientation
2687 */
2688 if (
2689 NULL != scale_y &&
2690 *scale_y > 0.
2691 ) {
2692 _skew[1] *= -1;
2693 }
2694 }
2695
2696 /*
2697 if geometry is a point, a linestring or set of either and bounds not set,
2698 increase extent by a pixel to avoid missing points on border
2699
2700 a whole pixel is used instead of half-pixel due to backward
2701 compatibility with GDAL 1.6, 1.7 and 1.8. 1.9+ works fine with half-pixel.
2702 */
2703 wkbtype = wkbFlatten(OGR_G_GetGeometryType(src_geom));
2704 if ((
2705 (wkbtype == wkbPoint) ||
2706 (wkbtype == wkbMultiPoint) ||
2707 (wkbtype == wkbLineString) ||
2708 (wkbtype == wkbMultiLineString)
2709 ) &&
2710 _dim[0] == 0 &&
2711 _dim[1] == 0
2712 ) {
2713
2714#if POSTGIS_GDAL_VERSION > 18
2715
2716 RASTER_DEBUG(3, "Adjusting extent for GDAL > 1.8 by half the scale on X-axis");
2717 extent.MinX -= (_scale[0] / 2.);
2718 extent.MaxX += (_scale[0] / 2.);
2719
2720 RASTER_DEBUG(3, "Adjusting extent for GDAL > 1.8 by half the scale on Y-axis");
2721 extent.MinY -= (_scale[1] / 2.);
2722 extent.MaxY += (_scale[1] / 2.);
2723
2724#else
2725
2726 RASTER_DEBUG(3, "Adjusting extent for GDAL <= 1.8 by the scale on X-axis");
2727 extent.MinX -= _scale[0];
2728 extent.MaxX += _scale[0];
2729
2730 RASTER_DEBUG(3, "Adjusting extent for GDAL <= 1.8 by the scale on Y-axis");
2731 extent.MinY -= _scale[1];
2732 extent.MaxY += _scale[1];
2733
2734#endif
2735
2736
2737 RASTER_DEBUGF(3, "Adjusted extent: %f, %f, %f, %f",
2738 extent.MinX, extent.MinY, extent.MaxX, extent.MaxY);
2739
2740 extent.UpperLeftX = extent.MinX;
2741 extent.UpperLeftY = extent.MaxY;
2742 }
2743
2744 /* reprocess extent if skewed */
2745 if (FLT_NEQ(_skew[0], 0.0) || FLT_NEQ(_skew[1], 0.0))
2746 {
2747 rt_raster skewedrast;
2748
2749 RASTER_DEBUG(3, "Computing skewed extent's envelope");
2750
2752 extent,
2753 _skew,
2754 _scale,
2755 0.01
2756 );
2757 if (skewedrast == NULL) {
2758 rterror("rt_raster_gdal_rasterize: Could not compute skewed raster");
2759
2760 OGR_G_DestroyGeometry(src_geom);
2762 /* OGRCleanupAll(); */
2763
2764 return NULL;
2765 }
2766
2767 _dim[0] = skewedrast->width;
2768 _dim[1] = skewedrast->height;
2769
2770 extent.UpperLeftX = skewedrast->ipX;
2771 extent.UpperLeftY = skewedrast->ipY;
2772
2773 rt_raster_destroy(skewedrast);
2774 }
2775
2776 /* raster dimensions */
2777 if (!_dim[0])
2778 _dim[0] = (int) fmax((fabs(extent.MaxX - extent.MinX) + (_scale[0] / 2.)) / _scale[0], 1);
2779 if (!_dim[1])
2780 _dim[1] = (int) fmax((fabs(extent.MaxY - extent.MinY) + (_scale[1] / 2.)) / _scale[1], 1);
2781
2782 /* temporary raster */
2783 rast = rt_raster_new(_dim[0], _dim[1]);
2784 if (rast == NULL) {
2785 rterror("rt_raster_gdal_rasterize: Out of memory allocating temporary raster");
2786
2787 OGR_G_DestroyGeometry(src_geom);
2789 /* OGRCleanupAll(); */
2790
2791 return NULL;
2792 }
2793
2794 /* set raster's spatial attributes */
2795 rt_raster_set_offsets(rast, extent.UpperLeftX, extent.UpperLeftY);
2796 rt_raster_set_scale(rast, _scale[0], -1 * _scale[1]);
2797 rt_raster_set_skews(rast, _skew[0], _skew[1]);
2798
2800 RASTER_DEBUGF(3, "Temp raster's geotransform: %f, %f, %f, %f, %f, %f",
2801 _gt[0], _gt[1], _gt[2], _gt[3], _gt[4], _gt[5]);
2802 RASTER_DEBUGF(3, "Temp raster's dimensions (width x height): %d x %d",
2803 _dim[0], _dim[1]);
2804
2805 /* user-specified upper-left corner */
2806 if (
2807 NULL != ul_xw &&
2808 NULL != ul_yw
2809 ) {
2810 ul_user = 1;
2811
2812 RASTER_DEBUGF(4, "Using user-specified upper-left corner: %f, %f", *ul_xw, *ul_yw);
2813
2814 /* set upper-left corner */
2815 rt_raster_set_offsets(rast, *ul_xw, *ul_yw);
2816 extent.UpperLeftX = *ul_xw;
2817 extent.UpperLeftY = *ul_yw;
2818 }
2819 else if (
2820 ((NULL != ul_xw) && (NULL == ul_yw)) ||
2821 ((NULL == ul_xw) && (NULL != ul_yw))
2822 ) {
2823 rterror("rt_raster_gdal_rasterize: Both X and Y upper-left corner values must be provided");
2824
2825 rt_raster_destroy(rast);
2826 OGR_G_DestroyGeometry(src_geom);
2828 /* OGRCleanupAll(); */
2829
2830 return NULL;
2831 }
2832
2833 /* alignment only considered if upper-left corner not provided */
2834 if (
2835 !ul_user && (
2836 (NULL != grid_xw) || (NULL != grid_yw)
2837 )
2838 ) {
2839
2840 if (
2841 ((NULL != grid_xw) && (NULL == grid_yw)) ||
2842 ((NULL == grid_xw) && (NULL != grid_yw))
2843 ) {
2844 rterror("rt_raster_gdal_rasterize: Both X and Y alignment values must be provided");
2845
2846 rt_raster_destroy(rast);
2847 OGR_G_DestroyGeometry(src_geom);
2849 /* OGRCleanupAll(); */
2850
2851 return NULL;
2852 }
2853
2854 RASTER_DEBUGF(4, "Aligning extent to user-specified grid: %f, %f", *grid_xw, *grid_yw);
2855
2856 do {
2857 double _r[2] = {0};
2858 double _w[2] = {0};
2859
2860 /* raster is already aligned */
2861 if (FLT_EQ(*grid_xw, extent.UpperLeftX) && FLT_EQ(*grid_yw, extent.UpperLeftY)) {
2862 RASTER_DEBUG(3, "Skipping raster alignment as it is already aligned to grid");
2863 break;
2864 }
2865
2866 extent.UpperLeftX = rast->ipX;
2867 extent.UpperLeftY = rast->ipY;
2868 rt_raster_set_offsets(rast, *grid_xw, *grid_yw);
2869
2870 /* process upper-left corner */
2872 rast,
2873 extent.UpperLeftX, extent.UpperLeftY,
2874 &(_r[0]), &(_r[1]),
2875 NULL
2876 ) != ES_NONE) {
2877 rterror("rt_raster_gdal_rasterize: Could not compute raster pixel for spatial coordinates");
2878
2879 rt_raster_destroy(rast);
2880 OGR_G_DestroyGeometry(src_geom);
2882 /* OGRCleanupAll(); */
2883
2884 return NULL;
2885 }
2886
2888 rast,
2889 _r[0], _r[1],
2890 &(_w[0]), &(_w[1]),
2891 NULL
2892 ) != ES_NONE) {
2893 rterror("rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
2894
2895 rt_raster_destroy(rast);
2896 OGR_G_DestroyGeometry(src_geom);
2898 /* OGRCleanupAll(); */
2899
2900 return NULL;
2901 }
2902
2903 /* shift occurred */
2904 if (FLT_NEQ(_w[0], extent.UpperLeftX)) {
2905 if (NULL == width)
2906 rast->width++;
2907 else if (NULL == scale_x) {
2908 double _c[2] = {0};
2909
2910 rt_raster_set_offsets(rast, extent.UpperLeftX, extent.UpperLeftY);
2911
2912 /* get upper-right corner */
2914 rast,
2915 rast->width, 0,
2916 &(_c[0]), &(_c[1]),
2917 NULL
2918 ) != ES_NONE) {
2919 rterror("rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
2920
2921 rt_raster_destroy(rast);
2922 OGR_G_DestroyGeometry(src_geom);
2924 /* OGRCleanupAll(); */
2925
2926 return NULL;
2927 }
2928
2929 rast->scaleX = fabs((_c[0] - _w[0]) / ((double) rast->width));
2930 }
2931 }
2932 if (FLT_NEQ(_w[1], extent.UpperLeftY)) {
2933 if (NULL == height)
2934 rast->height++;
2935 else if (NULL == scale_y) {
2936 double _c[2] = {0};
2937
2938 rt_raster_set_offsets(rast, extent.UpperLeftX, extent.UpperLeftY);
2939
2940 /* get upper-right corner */
2942 rast,
2943 0, rast->height,
2944 &(_c[0]), &(_c[1]),
2945 NULL
2946 ) != ES_NONE) {
2947 rterror("rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
2948
2949 rt_raster_destroy(rast);
2950 OGR_G_DestroyGeometry(src_geom);
2952 /* OGRCleanupAll(); */
2953
2954 return NULL;
2955 }
2956
2957 rast->scaleY = -1 * fabs((_c[1] - _w[1]) / ((double) rast->height));
2958 }
2959 }
2960
2961 rt_raster_set_offsets(rast, _w[0], _w[1]);
2962 }
2963 while (0);
2964 }
2965
2966 /*
2967 after this point, rt_envelope extent is no longer used
2968 */
2969
2970 /* get key attributes from rast */
2971 _dim[0] = rast->width;
2972 _dim[1] = rast->height;
2974
2975 /* scale-x is negative or scale-y is positive */
2976 if ((
2977 (NULL != scale_x) && (*scale_x < 0.)
2978 ) || (
2979 (NULL != scale_y) && (*scale_y > 0)
2980 )) {
2981 double _w[2] = {0};
2982
2983 /* negative scale-x */
2984 if (
2985 (NULL != scale_x) &&
2986 (*scale_x < 0.)
2987 ) {
2988 RASTER_DEBUG(3, "Processing negative scale-x");
2989
2991 rast,
2992 _dim[0], 0,
2993 &(_w[0]), &(_w[1]),
2994 NULL
2995 ) != ES_NONE) {
2996 rterror("rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
2997
2998 rt_raster_destroy(rast);
2999 OGR_G_DestroyGeometry(src_geom);
3001 /* OGRCleanupAll(); */
3002
3003 return NULL;
3004 }
3005
3006 _gt[0] = _w[0];
3007 _gt[1] = *scale_x;
3008
3009 /* check for skew */
3010 if (NULL != skew_x && FLT_NEQ(*skew_x, 0.0))
3011 _gt[2] = *skew_x;
3012 }
3013 /* positive scale-y */
3014 if (
3015 (NULL != scale_y) &&
3016 (*scale_y > 0)
3017 ) {
3018 RASTER_DEBUG(3, "Processing positive scale-y");
3019
3021 rast,
3022 0, _dim[1],
3023 &(_w[0]), &(_w[1]),
3024 NULL
3025 ) != ES_NONE) {
3026 rterror("rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
3027
3028 rt_raster_destroy(rast);
3029 OGR_G_DestroyGeometry(src_geom);
3031 /* OGRCleanupAll(); */
3032
3033 return NULL;
3034 }
3035
3036 _gt[3] = _w[1];
3037 _gt[5] = *scale_y;
3038
3039 /* check for skew */
3040 if (NULL != skew_y && FLT_NEQ(*skew_y, 0.0))
3041 _gt[4] = *skew_y;
3042 }
3043 }
3044
3045 rt_raster_destroy(rast);
3046 rast = NULL;
3047
3048 RASTER_DEBUGF(3, "Applied geotransform: %f, %f, %f, %f, %f, %f",
3049 _gt[0], _gt[1], _gt[2], _gt[3], _gt[4], _gt[5]);
3050 RASTER_DEBUGF(3, "Raster dimensions (width x height): %d x %d",
3051 _dim[0], _dim[1]);
3052
3053 /* load GDAL mem */
3054 if (!rt_util_gdal_driver_registered("MEM")) {
3055 RASTER_DEBUG(4, "Registering MEM driver");
3056 GDALRegister_MEM();
3057 unload_drv = 1;
3058 }
3059 _drv = GDALGetDriverByName("MEM");
3060 if (NULL == _drv) {
3061 rterror("rt_raster_gdal_rasterize: Could not load the MEM GDAL driver");
3062
3063 OGR_G_DestroyGeometry(src_geom);
3065 /* OGRCleanupAll(); */
3066
3067 return NULL;
3068 }
3069
3070 /* unload driver from GDAL driver manager */
3071 if (unload_drv) {
3072 RASTER_DEBUG(4, "Deregistering MEM driver");
3073 GDALDeregisterDriver(_drv);
3074 }
3075
3076 _ds = GDALCreate(_drv, "", _dim[0], _dim[1], 0, GDT_Byte, NULL);
3077 if (NULL == _ds) {
3078 rterror("rt_raster_gdal_rasterize: Could not create a GDALDataset to rasterize the geometry into");
3079
3080 OGR_G_DestroyGeometry(src_geom);
3082 /* OGRCleanupAll(); */
3083 if (unload_drv) GDALDestroyDriver(_drv);
3084
3085 return NULL;
3086 }
3087
3088 /* set geotransform */
3089 cplerr = GDALSetGeoTransform(_ds, _gt);
3090 if (cplerr != CE_None) {
3091 rterror("rt_raster_gdal_rasterize: Could not set geotransform on GDALDataset");
3092
3093 OGR_G_DestroyGeometry(src_geom);
3095 /* OGRCleanupAll(); */
3096
3097 GDALClose(_ds);
3098 if (unload_drv) GDALDestroyDriver(_drv);
3099
3100 return NULL;
3101 }
3102
3103 /* set SRS */
3104 if (NULL != arg->src_sr) {
3105 char *_srs = NULL;
3106 OSRExportToWkt(arg->src_sr, &_srs);
3107
3108 cplerr = GDALSetProjection(_ds, _srs);
3109 CPLFree(_srs);
3110 if (cplerr != CE_None) {
3111 rterror("rt_raster_gdal_rasterize: Could not set projection on GDALDataset");
3112
3113 OGR_G_DestroyGeometry(src_geom);
3115 /* OGRCleanupAll(); */
3116
3117 GDALClose(_ds);
3118 if (unload_drv) GDALDestroyDriver(_drv);
3119
3120 return NULL;
3121 }
3122 }
3123
3124 /* set bands */
3125 for (i = 0; i < arg->numbands; i++) {
3126 err = 0;
3127
3128 do {
3129 /* add band */
3130 cplerr = GDALAddBand(_ds, rt_util_pixtype_to_gdal_datatype(arg->pixtype[i]), NULL);
3131 if (cplerr != CE_None) {
3132 rterror("rt_raster_gdal_rasterize: Could not add band to GDALDataset");
3133 err = 1;
3134 break;
3135 }
3136
3137 _band = GDALGetRasterBand(_ds, i + 1);
3138 if (NULL == _band) {
3139 rterror("rt_raster_gdal_rasterize: Could not get band %d from GDALDataset", i + 1);
3140 err = 1;
3141 break;
3142 }
3143
3144 /* nodata value */
3145 if (arg->hasnodata[i]) {
3146 RASTER_DEBUGF(4, "Setting NODATA value of band %d to %f", i, arg->nodata[i]);
3147 cplerr = GDALSetRasterNoDataValue(_band, arg->nodata[i]);
3148 if (cplerr != CE_None) {
3149 rterror("rt_raster_gdal_rasterize: Could not set nodata value");
3150 err = 1;
3151 break;
3152 }
3153 RASTER_DEBUGF(4, "NODATA value set to %f", GDALGetRasterNoDataValue(_band, NULL));
3154 }
3155
3156 /* initial value */
3157 cplerr = GDALFillRaster(_band, arg->init[i], 0);
3158 if (cplerr != CE_None) {
3159 rterror("rt_raster_gdal_rasterize: Could not set initial value");
3160 err = 1;
3161 break;
3162 }
3163 }
3164 while (0);
3165
3166 if (err) {
3167
3168 OGR_G_DestroyGeometry(src_geom);
3170
3171 /* OGRCleanupAll(); */
3172
3173 GDALClose(_ds);
3174 if (unload_drv) GDALDestroyDriver(_drv);
3175
3176 return NULL;
3177 }
3178 }
3179
3180 arg->bandlist = (int *) rtalloc(sizeof(int) * arg->numbands);
3181 for (i = 0; i < arg->numbands; i++) arg->bandlist[i] = i + 1;
3182
3183 /* burn geometry */
3184 cplerr = GDALRasterizeGeometries(
3185 _ds,
3186 arg->numbands, arg->bandlist,
3187 1, &src_geom,
3188 NULL, NULL,
3189 arg->value,
3190 options,
3191 NULL, NULL
3192 );
3193 if (cplerr != CE_None) {
3194 rterror("rt_raster_gdal_rasterize: Could not rasterize geometry");
3195
3196 OGR_G_DestroyGeometry(src_geom);
3198 /* OGRCleanupAll(); */
3199
3200 GDALClose(_ds);
3201 if (unload_drv) GDALDestroyDriver(_drv);
3202
3203 return NULL;
3204 }
3205
3206 /* convert gdal dataset to raster */
3207 GDALFlushCache(_ds);
3208 RASTER_DEBUG(3, "Converting GDAL dataset to raster");
3209 rast = rt_raster_from_gdal_dataset(_ds);
3210
3211 OGR_G_DestroyGeometry(src_geom);
3212 /* OGRCleanupAll(); */
3213
3214 GDALClose(_ds);
3215 if (unload_drv) GDALDestroyDriver(_drv);
3216
3217 if (NULL == rast) {
3218 rterror("rt_raster_gdal_rasterize: Could not rasterize geometry");
3219 return NULL;
3220 }
3221
3222 /* width, height */
3223 _width = rt_raster_get_width(rast);
3224 _height = rt_raster_get_height(rast);
3225
3226 /* check each band for pixtype */
3227 for (i = 0; i < arg->numbands; i++) {
3228 uint8_t *data = NULL;
3229 rt_band band = NULL;
3230 rt_band oldband = NULL;
3231
3232 double val = 0;
3233 int nodata = 0;
3234 int hasnodata = 0;
3235 double nodataval = 0;
3236 int x = 0;
3237 int y = 0;
3238
3239 oldband = rt_raster_get_band(rast, i);
3240 if (oldband == NULL) {
3241 rterror("rt_raster_gdal_rasterize: Could not get band %d of output raster", i);
3243 rt_raster_destroy(rast);
3244 return NULL;
3245 }
3246
3247 /* band is of user-specified type */
3248 if (rt_band_get_pixtype(oldband) == arg->pixtype[i])
3249 continue;
3250
3251 /* hasnodata, nodataval */
3252 hasnodata = rt_band_get_hasnodata_flag(oldband);
3253 if (hasnodata)
3254 rt_band_get_nodata(oldband, &nodataval);
3255
3256 /* allocate data */
3257 data = rtalloc(rt_pixtype_size(arg->pixtype[i]) * _width * _height);
3258 if (data == NULL) {
3259 rterror("rt_raster_gdal_rasterize: Could not allocate memory for band data");
3261 rt_raster_destroy(rast);
3262 return NULL;
3263 }
3264 memset(data, 0, rt_pixtype_size(arg->pixtype[i]) * _width * _height);
3265
3266 /* create new band of correct type */
3267 band = rt_band_new_inline(
3268 _width, _height,
3269 arg->pixtype[i],
3270 hasnodata, nodataval,
3271 data
3272 );
3273 if (band == NULL) {
3274 rterror("rt_raster_gdal_rasterize: Could not create band");
3275 rtdealloc(data);
3277 rt_raster_destroy(rast);
3278 return NULL;
3279 }
3280
3281 /* give ownership of data to band */
3283
3284 /* copy pixel by pixel */
3285 for (x = 0; x < _width; x++) {
3286 for (y = 0; y < _height; y++) {
3287 err = rt_band_get_pixel(oldband, x, y, &val, &nodata);
3288 if (err != ES_NONE) {
3289 rterror("rt_raster_gdal_rasterize: Could not get pixel value");
3291 rt_raster_destroy(rast);
3292 rt_band_destroy(band);
3293 return NULL;
3294 }
3295
3296 if (nodata)
3297 val = nodataval;
3298
3299 err = rt_band_set_pixel(band, x, y, val, NULL);
3300 if (err != ES_NONE) {
3301 rterror("rt_raster_gdal_rasterize: Could not set pixel value");
3303 rt_raster_destroy(rast);
3304 rt_band_destroy(band);
3305 return NULL;
3306 }
3307 }
3308 }
3309
3310 /* replace band */
3311 oldband = rt_raster_replace_band(rast, band, i);
3312 if (oldband == NULL) {
3313 rterror("rt_raster_gdal_rasterize: Could not replace band %d of output raster", i);
3315 rt_raster_destroy(rast);
3316 rt_band_destroy(band);
3317 return NULL;
3318 }
3319
3320 /* free oldband */
3321 rt_band_destroy(oldband);
3322 }
3323
3325
3326 RASTER_DEBUG(3, "done");
3327
3328 return rast;
3329}
3330
3331/******************************************************************************
3332* rt_raster_from_two_rasters()
3333******************************************************************************/
3334
3335/*
3336 * Return raster of computed extent specified extenttype applied
3337 * on two input rasters. The raster returned should be freed by
3338 * the caller
3339 *
3340 * @param rast1 : the first raster
3341 * @param rast2 : the second raster
3342 * @param extenttype : type of extent for the output raster
3343 * @param *rtnraster : raster of computed extent
3344 * @param *offset : 4-element array indicating the X,Y offsets
3345 * for each raster. 0,1 for rast1 X,Y. 2,3 for rast2 X,Y.
3346 *
3347 * @return ES_NONE if success, ES_ERROR if error
3348 */
3351 rt_raster rast1, rt_raster rast2,
3352 rt_extenttype extenttype,
3353 rt_raster *rtnraster, double *offset
3354) {
3355 int i;
3356
3357 rt_raster _rast[2] = {rast1, rast2};
3358 double _offset[2][4] = {{0.}};
3359 uint16_t _dim[2][2] = {{0}};
3360
3361 rt_raster raster = NULL;
3362 int aligned = 0;
3363 int dim[2] = {0};
3364 double gt[6] = {0.};
3365
3366 assert(NULL != rast1);
3367 assert(NULL != rast2);
3368 assert(NULL != rtnraster);
3369
3370 /* set rtnraster to NULL */
3371 *rtnraster = NULL;
3372
3373 /* rasters must be aligned */
3374 if (rt_raster_same_alignment(rast1, rast2, &aligned, NULL) != ES_NONE) {
3375 rterror("rt_raster_from_two_rasters: Could not test for alignment on the two rasters");
3376 return ES_ERROR;
3377 }
3378 if (!aligned) {
3379 rterror("rt_raster_from_two_rasters: The two rasters provided do not have the same alignment");
3380 return ES_ERROR;
3381 }
3382
3383 /* dimensions */
3384 _dim[0][0] = rast1->width;
3385 _dim[0][1] = rast1->height;
3386 _dim[1][0] = rast2->width;
3387 _dim[1][1] = rast2->height;
3388
3389 /* get raster offsets */
3391 _rast[1],
3392 _rast[0]->ipX, _rast[0]->ipY,
3393 &(_offset[1][0]), &(_offset[1][1]),
3394 NULL
3395 ) != ES_NONE) {
3396 rterror("rt_raster_from_two_rasters: Could not compute offsets of the second raster relative to the first raster");
3397 return ES_ERROR;
3398 }
3399 _offset[1][0] = -1 * _offset[1][0];
3400 _offset[1][1] = -1 * _offset[1][1];
3401 _offset[1][2] = _offset[1][0] + _dim[1][0] - 1;
3402 _offset[1][3] = _offset[1][1] + _dim[1][1] - 1;
3403
3404 i = -1;
3405 switch (extenttype) {
3406 case ET_FIRST:
3407 i = 0;
3408 _offset[0][0] = 0.;
3409 _offset[0][1] = 0.;
3410 /* FALLTHROUGH */
3411 case ET_LAST:
3412 case ET_SECOND:
3413 if (i < 0) {
3414 i = 1;
3415 _offset[0][0] = -1 * _offset[1][0];
3416 _offset[0][1] = -1 * _offset[1][1];
3417 _offset[1][0] = 0.;
3418 _offset[1][1] = 0.;
3419 }
3420
3421 dim[0] = _dim[i][0];
3422 dim[1] = _dim[i][1];
3423 raster = rt_raster_new(
3424 dim[0],
3425 dim[1]
3426 );
3427 if (raster == NULL) {
3428 rterror("rt_raster_from_two_rasters: Could not create output raster");
3429 return ES_ERROR;
3430 }
3431 rt_raster_set_srid(raster, _rast[i]->srid);
3434 break;
3435 case ET_UNION: {
3436 double off[4] = {0};
3437
3439 RASTER_DEBUGF(4, "gt = (%f, %f, %f, %f, %f, %f)",
3440 gt[0],
3441 gt[1],
3442 gt[2],
3443 gt[3],
3444 gt[4],
3445 gt[5]
3446 );
3447
3448 /* new raster upper left offset */
3449 off[0] = 0;
3450 if (_offset[1][0] < 0)
3451 off[0] = _offset[1][0];
3452 off[1] = 0;
3453 if (_offset[1][1] < 0)
3454 off[1] = _offset[1][1];
3455
3456 /* new raster lower right offset */
3457 off[2] = _dim[0][0] - 1;
3458 if ((int) _offset[1][2] >= _dim[0][0])
3459 off[2] = _offset[1][2];
3460 off[3] = _dim[0][1] - 1;
3461 if ((int) _offset[1][3] >= _dim[0][1])
3462 off[3] = _offset[1][3];
3463
3464 /* upper left corner */
3466 _rast[0],
3467 off[0], off[1],
3468 &(gt[0]), &(gt[3]),
3469 NULL
3470 ) != ES_NONE) {
3471 rterror("rt_raster_from_two_rasters: Could not get spatial coordinates of upper-left pixel of output raster");
3472 return ES_ERROR;
3473 }
3474
3475 dim[0] = off[2] - off[0] + 1;
3476 dim[1] = off[3] - off[1] + 1;
3477 RASTER_DEBUGF(4, "off = (%f, %f, %f, %f)",
3478 off[0],
3479 off[1],
3480 off[2],
3481 off[3]
3482 );
3483 RASTER_DEBUGF(4, "dim = (%d, %d)", dim[0], dim[1]);
3484
3485 raster = rt_raster_new(
3486 dim[0],
3487 dim[1]
3488 );
3489 if (raster == NULL) {
3490 rterror("rt_raster_from_two_rasters: Could not create output raster");
3491 return ES_ERROR;
3492 }
3493 rt_raster_set_srid(raster, _rast[0]->srid);
3495 RASTER_DEBUGF(4, "gt = (%f, %f, %f, %f, %f, %f)",
3496 gt[0],
3497 gt[1],
3498 gt[2],
3499 gt[3],
3500 gt[4],
3501 gt[5]
3502 );
3503
3504 /* get offsets */
3506 _rast[0],
3507 gt[0], gt[3],
3508 &(_offset[0][0]), &(_offset[0][1]),
3509 NULL
3510 ) != ES_NONE) {
3511 rterror("rt_raster_from_two_rasters: Could not get offsets of the FIRST raster relative to the output raster");
3512 rt_raster_destroy(raster);
3513 return ES_ERROR;
3514 }
3515 _offset[0][0] *= -1;
3516 _offset[0][1] *= -1;
3517
3519 _rast[1],
3520 gt[0], gt[3],
3521 &(_offset[1][0]), &(_offset[1][1]),
3522 NULL
3523 ) != ES_NONE) {
3524 rterror("rt_raster_from_two_rasters: Could not get offsets of the SECOND raster relative to the output raster");
3525 rt_raster_destroy(raster);
3526 return ES_ERROR;
3527 }
3528 _offset[1][0] *= -1;
3529 _offset[1][1] *= -1;
3530 break;
3531 }
3532 case ET_INTERSECTION: {
3533 double off[4] = {0};
3534
3535 /* no intersection */
3536 if (
3537 (_offset[1][2] < 0 || _offset[1][0] > (_dim[0][0] - 1)) ||
3538 (_offset[1][3] < 0 || _offset[1][1] > (_dim[0][1] - 1))
3539 ) {
3540 RASTER_DEBUG(3, "The two rasters provided have no intersection. Returning no band raster");
3541
3542 raster = rt_raster_new(0, 0);
3543 if (raster == NULL) {
3544 rterror("rt_raster_from_two_rasters: Could not create output raster");
3545 return ES_ERROR;
3546 }
3547 rt_raster_set_srid(raster, _rast[0]->srid);
3548 rt_raster_set_scale(raster, 0, 0);
3549
3550 /* set offsets if provided */
3551 if (NULL != offset) {
3552 for (i = 0; i < 4; i++)
3553 offset[i] = _offset[i / 2][i % 2];
3554 }
3555
3556 *rtnraster = raster;
3557 return ES_NONE;
3558 }
3559
3560 if (_offset[1][0] > 0)
3561 off[0] = _offset[1][0];
3562 if (_offset[1][1] > 0)
3563 off[1] = _offset[1][1];
3564
3565 off[2] = _dim[0][0] - 1;
3566 if (_offset[1][2] < _dim[0][0])
3567 off[2] = _offset[1][2];
3568 off[3] = _dim[0][1] - 1;
3569 if (_offset[1][3] < _dim[0][1])
3570 off[3] = _offset[1][3];
3571
3572 dim[0] = off[2] - off[0] + 1;
3573 dim[1] = off[3] - off[1] + 1;
3574 raster = rt_raster_new(
3575 dim[0],
3576 dim[1]
3577 );
3578 if (raster == NULL) {
3579 rterror("rt_raster_from_two_rasters: Could not create output raster");
3580 return ES_ERROR;
3581 }
3582 rt_raster_set_srid(raster, _rast[0]->srid);
3583
3584 /* get upper-left corner */
3587 _rast[0],
3588 off[0], off[1],
3589 &(gt[0]), &(gt[3]),
3590 gt
3591 ) != ES_NONE) {
3592 rterror("rt_raster_from_two_rasters: Could not get spatial coordinates of upper-left pixel of output raster");
3593 rt_raster_destroy(raster);
3594 return ES_ERROR;
3595 }
3596
3598
3599 /* get offsets */
3601 _rast[0],
3602 gt[0], gt[3],
3603 &(_offset[0][0]), &(_offset[0][1]),
3604 NULL
3605 ) != ES_NONE) {
3606 rterror("rt_raster_from_two_rasters: Could not get pixel coordinates to compute the offsets of the FIRST raster relative to the output raster");
3607 rt_raster_destroy(raster);
3608 return ES_ERROR;
3609 }
3610 _offset[0][0] *= -1;
3611 _offset[0][1] *= -1;
3612
3614 _rast[1],
3615 gt[0], gt[3],
3616 &(_offset[1][0]), &(_offset[1][1]),
3617 NULL
3618 ) != ES_NONE) {
3619 rterror("rt_raster_from_two_rasters: Could not get pixel coordinates to compute the offsets of the SECOND raster relative to the output raster");
3620 rt_raster_destroy(raster);
3621 return ES_ERROR;
3622 }
3623 _offset[1][0] *= -1;
3624 _offset[1][1] *= -1;
3625 break;
3626 }
3627 case ET_CUSTOM:
3628 rterror("rt_raster_from_two_rasters: Extent type ET_CUSTOM is not supported by this function");
3629 break;
3630 }
3631
3632 /* set offsets if provided */
3633 if (NULL != offset) {
3634 for (i = 0; i < 4; i++)
3635 offset[i] = _offset[i / 2][i % 2];
3636 }
3637
3638 *rtnraster = raster;
3639 return ES_NONE;
3640}
return(const char *)
Definition dbfopen.c:1554
#define TRUE
Definition dbfopen.c:169
#define FALSE
Definition dbfopen.c:168
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
void lwgeom_geos_error(const char *fmt,...)
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1138
void lwpoly_free(LWPOLY *poly)
Definition lwpoly.c:175
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:229
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition lwgeom.c:311
int32_t clamp_srid(int32_t srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition lwutil.c:333
rt_band rt_band_new_inline(uint16_t width, uint16_t height, rt_pixtype pixtype, uint32_t hasnodata, double nodataval, uint8_t *data)
Create an in-db rt_band with no data.
Definition rt_band.c:63
void rt_band_set_ownsdata_flag(rt_band band, int flag)
Definition rt_band.c:667
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
Definition rt_context.c:199
void * rtalloc(size_t size)
Wrappers used for managing memory.
Definition rt_context.c:171
rt_pixtype rt_util_gdal_datatype_to_pixtype(GDALDataType gdt)
Convert GDALDataType to rt_pixtype.
Definition rt_util.c:155
rt_band rt_band_duplicate(rt_band band)
Create a new band duplicated from source band.
Definition rt_band.c:287
rt_errorstate rt_band_set_isnodata_flag(rt_band band, int flag)
Set isnodata flag value.
Definition rt_band.c:695
#define FLT_NEQ(x, y)
Definition librtcore.h:2234
#define RASTER_DEBUG(level, msg)
Definition librtcore.h:295
LWPOLY * rt_util_envelope_to_lwpoly(rt_envelope ext)
Definition rt_util.c:439
int rt_util_gdal_register_all(int force_register_all)
Definition rt_util.c:338
#define RASTER_DEBUGF(level, msg,...)
Definition librtcore.h:299
int8_t rt_util_clamp_to_8BSI(double value)
Definition rt_util.c:49
uint8_t rt_util_clamp_to_1BB(double value)
Definition rt_util.c:34
void rtinfo(const char *fmt,...)
Definition rt_context.c:211
int32_t rt_util_clamp_to_32BSI(double value)
Definition rt_util.c:69
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition rt_band.c:674
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
Definition rt_band.c:400
#define ROUND(x, y)
Definition librtcore.h:2242
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition rt_band.c:1221
rt_pixtype
Definition librtcore.h:185
@ PT_32BUI
Definition librtcore.h:194
@ PT_2BUI
Definition librtcore.h:187
@ PT_32BSI
Definition librtcore.h:193
@ PT_END
Definition librtcore.h:197
@ PT_4BUI
Definition librtcore.h:188
@ PT_32BF
Definition librtcore.h:195
@ PT_1BB
Definition librtcore.h:186
@ PT_16BUI
Definition librtcore.h:192
@ PT_8BSI
Definition librtcore.h:189
@ PT_16BSI
Definition librtcore.h:191
@ PT_64BF
Definition librtcore.h:196
@ PT_8BUI
Definition librtcore.h:190
char * rt_util_gdal_convert_sr(const char *srs, int proj4)
Definition rt_util.c:214
int rt_util_dbl_trunc_warning(double initialvalue, int32_t checkvalint, uint32_t checkvaluint, float checkvalfloat, double checkvaldouble, rt_pixtype pixtype)
Definition rt_util.c:629
GDALDataType rt_util_pixtype_to_gdal_datatype(rt_pixtype pt)
Convert rt_pixtype to GDALDataType.
Definition rt_util.c:120
#define FLT_EQ(x, y)
Definition librtcore.h:2235
uint8_t rt_util_clamp_to_2BUI(double value)
Definition rt_util.c:39
void rtwarn(const char *fmt,...)
Definition rt_context.c:224
uint8_t rt_util_clamp_to_8BUI(double value)
Definition rt_util.c:54
rt_errorstate rt_band_set_pixel(rt_band band, int x, int y, double val, int *converted)
Set single pixel's value.
Definition rt_band.c:974
rt_errorstate
Enum definitions.
Definition librtcore.h:179
@ ES_NONE
Definition librtcore.h:180
@ ES_ERROR
Definition librtcore.h:181
rt_errorstate rt_band_set_pixel_line(rt_band band, int x, int y, void *vals, uint32_t len)
Set values of multiple pixels.
Definition rt_band.c:853
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition rt_band.c:340
int16_t rt_util_clamp_to_16BSI(double value)
Definition rt_util.c:59
void * rtrealloc(void *mem, size_t size)
Definition rt_context.c:179
struct rt_gdaldriver_t * rt_gdaldriver
Definition librtcore.h:154
rt_errorstate rt_raster_get_convex_hull(rt_raster raster, LWGEOM **hull)
Get raster's convex hull.
int rt_util_gdal_driver_registered(const char *drv)
Definition rt_util.c:357
rt_extenttype
Definition librtcore.h:200
@ ET_CUSTOM
Definition librtcore.h:206
@ ET_LAST
Definition librtcore.h:205
@ ET_INTERSECTION
Definition librtcore.h:201
@ ET_UNION
Definition librtcore.h:202
@ ET_SECOND
Definition librtcore.h:204
@ ET_FIRST
Definition librtcore.h:203
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition rt_band.c:1730
uint8_t rt_util_clamp_to_4BUI(double value)
Definition rt_util.c:44
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
Definition rt_band.c:631
void rtdealloc(void *mem)
Definition rt_context.c:186
rt_errorstate rt_util_gdal_sr_auth_info(GDALDatasetH hds, char **authname, char **authcode)
Get auth name and code.
Definition rt_util.c:272
uint16_t rt_util_clamp_to_16BUI(double value)
Definition rt_util.c:64
uint32_t rt_util_clamp_to_32BUI(double value)
Definition rt_util.c:74
int rt_band_is_offline(rt_band band)
Return non-zero if the given band data is on the filesystem.
Definition rt_band.c:329
struct rt_raster_t * rt_raster
Types definitions.
Definition librtcore.h:145
float rt_util_clamp_to_32F(double value)
Definition rt_util.c:79
rt_errorstate rt_raster_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
void rt_util_from_ogr_envelope(OGREnvelope env, rt_envelope *ext)
Definition rt_util.c:410
int rt_pixtype_size(rt_pixtype pixtype)
Return size in bytes of a value in the given pixtype.
Definition rt_pixel.c:39
This library is the generic raster handling section of PostGIS.
Datum covers(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
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
Definition rt_raster.c:356
double rt_raster_get_x_skew(rt_raster raster)
Get skew about the X axis.
Definition rt_raster.c:181
double rt_raster_get_x_offset(rt_raster raster)
Get raster x offset, in projection units.
Definition rt_raster.c:213
int rt_raster_calc_gt_coeff(double i_mag, double j_mag, double theta_i, double theta_ij, double *xscale, double *xskew, double *yskew, double *yscale)
Calculates the coefficients of a geotransform given the physically significant parameters describing ...
Definition rt_raster.c:314
int rt_raster_generate_new_band(rt_raster raster, rt_pixtype pixtype, double initialvalue, uint32_t hasnodata, double nodatavalue, int index)
Generate a new inline band and add it to a raster.
Definition rt_raster.c:485
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster's geotransform using 6-element array.
Definition rt_raster.c:727
void rt_raster_set_scale(rt_raster raster, double scaleX, double scaleY)
Set scale in projection units.
Definition rt_raster.c:137
int rt_raster_add_band(rt_raster raster, rt_band band, int index)
Add band data to a raster.
Definition rt_raster.c:405
rt_errorstate rt_raster_get_inverse_geotransform_matrix(rt_raster raster, double *gt, double *igt)
Get 6-element array of raster inverse geotransform matrix.
Definition rt_raster.c:676
uint8_t * rt_raster_to_gdal(rt_raster raster, const char *srs, char *format, char **options, uint64_t *gdalsize)
Return formatted GDAL raster from raster.
Definition rt_raster.c:1593
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:804
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition rt_raster.c:82
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
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
Definition rt_raster.c:48
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:1342
rt_raster rt_raster_compute_skewed_raster(rt_envelope extent, double *skew, double *scale, double tolerance)
Definition rt_raster.c:958
rt_gdaldriver rt_raster_gdal_drivers(uint32_t *drv_count, uint8_t can_write)
Returns a set of available GDAL drivers.
Definition rt_raster.c:1711
rt_raster rt_raster_from_gdal_dataset(GDALDatasetH ds)
Return a raster from a GDAL dataset.
Definition rt_raster.c:2177
static void _rti_rasterize_arg_destroy(_rti_rasterize_arg arg)
Definition rt_raster.c:2454
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
Definition rt_raster.c:150
rt_band rt_raster_replace_band(rt_raster raster, rt_band band, int index)
Replace band at provided index with new band.
Definition rt_raster.c:1493
rt_raster rt_raster_gdal_rasterize(const unsigned char *wkb, uint32_t wkb_len, const char *srs, uint32_t num_bands, rt_pixtype *pixtype, double *init, double *value, double *nodata, uint8_t *hasnodata, int *width, int *height, double *scale_x, double *scale_y, double *ul_xw, double *ul_yw, double *grid_xw, double *grid_yw, double *skew_x, double *skew_y, char **options)
Return a raster of the provided geometry.
Definition rt_raster.c:2504
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
uint16_t rt_raster_get_num_bands(rt_raster raster)
Definition rt_raster.c:372
rt_raster rt_raster_clone(rt_raster raster, uint8_t deep)
Clone an existing raster.
Definition rt_raster.c:1535
uint16_t rt_raster_get_height(rt_raster raster)
Definition rt_raster.c:129
rt_band rt_raster_get_band(rt_raster raster, int n)
Return Nth band, or NULL if unavailable.
Definition rt_raster.c:381
static void _rt_raster_geotransform_warn_offline_band(rt_raster raster)
Definition rt_raster.c:95
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
Definition rt_raster.c:363
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
rt_raster rt_raster_from_band(rt_raster raster, uint32_t *bandNums, int count)
Construct a new rt_raster from an existing rt_raster and an array of band numbers.
Definition rt_raster.c:1430
uint16_t rt_raster_get_width(rt_raster raster)
Definition rt_raster.c:121
GDALDatasetH rt_raster_to_gdal_mem(rt_raster raster, const char *srs, uint32_t *bandNums, int *excludeNodataValues, int count, GDALDriverH *rtn_drv, int *destroy_rtn_drv)
Return GDAL dataset using GDAL MEM driver from raster.
Definition rt_raster.c:1821
struct _rti_rasterize_arg_t * _rti_rasterize_arg
Definition rt_raster.c:2411
rt_errorstate rt_raster_from_two_rasters(rt_raster rast1, rt_raster rast2, rt_extenttype extenttype, rt_raster *rtnraster, double *offset)
Definition rt_raster.c:3350
int rt_raster_copy_band(rt_raster torast, rt_raster fromrast, int fromindex, int toindex)
Copy one band from one raster to another.
Definition rt_raster.c:1365
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
Definition rt_raster.c:159
rt_errorstate rt_raster_get_envelope(rt_raster raster, rt_envelope *env)
Get raster's envelope.
Definition rt_raster.c:871
static _rti_rasterize_arg _rti_rasterize_arg_init()
Definition rt_raster.c:2428
double rt_raster_get_y_skew(rt_raster raster)
Get skew about the Y axis.
Definition rt_raster.c:190
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
Definition rt_raster.c:706
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_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
double rt_raster_get_y_offset(rt_raster raster)
Get raster y offset, in projection units.
Definition rt_raster.c:222
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
Definition rt_raster.c:1329
rt_pixtype * pixtype
Definition rt_raster.c:2419
OGRSpatialReferenceH src_sr
Definition rt_raster.c:2417
rt_raster raster
Definition librtcore.h:2325
double MinX
Definition librtcore.h:165
double UpperLeftY
Definition librtcore.h:171
double UpperLeftX
Definition librtcore.h:170
double MaxX
Definition librtcore.h:166
double MinY
Definition librtcore.h:167
double MaxY
Definition librtcore.h:168
uint8_t can_write
Definition librtcore.h:2478
char * create_options
Definition librtcore.h:2476
double scaleX
Definition librtcore.h:2294
rt_band * bands
Definition librtcore.h:2304
uint16_t width
Definition librtcore.h:2302
double skewY
Definition librtcore.h:2299
uint16_t numBands
Definition librtcore.h:2291
int32_t srid
Definition librtcore.h:2301
uint16_t height
Definition librtcore.h:2303
double scaleY
Definition librtcore.h:2295
double skewX
Definition librtcore.h:2298