PostGIS  3.1.6dev-r@@SVN_REVISION@@
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 
48 rt_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");
61  rt_raster_destroy(ret);
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 
81 void
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 
92 }
93 
94 static 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++) {
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 
120 uint16_t
122 
123  assert(NULL != raster);
124 
125  return raster->width;
126 }
127 
128 uint16_t
130 
131  assert(NULL != raster);
132 
133  return raster->height;
134 }
135 
136 void
139  double scaleX, double scaleY
140 ) {
141  assert(NULL != raster);
142 
143  raster->scaleX = scaleX;
144  raster->scaleY = scaleY;
145 
147 }
148 
149 double
151 
152 
153  assert(NULL != raster);
154 
155  return raster->scaleX;
156 }
157 
158 double
160 
161 
162  assert(NULL != raster);
163 
164  return raster->scaleY;
165 }
166 
167 void
170  double skewX, double skewY
171 ) {
172  assert(NULL != raster);
173 
174  raster->skewX = skewX;
175  raster->skewY = skewY;
176 
178 }
179 
180 double
182 
183 
184  assert(NULL != raster);
185 
186  return raster->skewX;
187 }
188 
189 double
191 
192 
193  assert(NULL != raster);
194 
195  return raster->skewY;
196 }
197 
198 void
201  double x, double y
202 ) {
203 
204  assert(NULL != raster);
205 
206  raster->ipX = x;
207  raster->ipY = y;
208 
210 }
211 
212 double
214 
215 
216  assert(NULL != raster);
217 
218  return raster->ipX;
219 }
220 
221 double
223 
224 
225  assert(NULL != raster);
226 
227  return raster->ipY;
228 }
229 
230 void
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 
249 void
250 rt_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 
296 void
297 rt_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 
313 int
314 rt_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 
355 int32_t
357  assert(NULL != raster);
358 
359  return clamp_srid(raster->srid);
360 }
361 
362 void
364  assert(NULL != raster);
365 
366  raster->srid = clamp_srid(srid);
367 
369 }
370 
371 uint16_t
373 
374 
375  assert(NULL != raster);
376 
377  return raster->numBands;
378 }
379 
380 rt_band
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 
404 int
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 
484 int
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");
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 
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 
705 void
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 
726 void
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 
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 
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  ) {
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 
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  */
957 rt_raster
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;
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");
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");
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");
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");
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");
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");
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");
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);
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);
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);
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);
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 
1328 int
1330  return (!raster || raster->height == 0 || raster->width == 0);
1331 }
1332 
1341 int
1343  return !(NULL == raster || nband >= raster->numBands || nband < 0);
1344 }
1345 
1346 /******************************************************************************
1347 * rt_raster_copy_band()
1348 ******************************************************************************/
1349 
1364 int
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 
1429 rt_raster
1430 rt_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",
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]);
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 
1492 rt_band
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 
1534 rt_raster
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(
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 
1592 uint8_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 
1711 rt_raster_gdal_drivers(uint32_t *drv_count, uint8_t can_write)
1712 {
1713  assert(drv_count != NULL);
1714  uint32_t output_driver = 0;
1716  uint32_t count = (uint32_t)GDALGetDriverCount();
1717 
1718  rt_gdaldriver rtn = (rt_gdaldriver)rtalloc(count * sizeof(struct rt_gdaldriver_t));
1719  if (!rtn)
1720  {
1721  rterror("rt_raster_gdal_drivers: Could not allocate memory for gdaldriver structure");
1722  *drv_count = output_driver;
1723  return NULL;
1724  }
1725 
1726  for (uint32_t i = 0; i < count; i++)
1727  {
1728  GDALDriverH *drv = GDALGetDriver(i);
1729 
1730 #ifdef GDAL_DCAP_RASTER
1731  /* Starting with GDAL 2.0, vector drivers can also be returned */
1732  /* Only keep raster drivers */
1733  const char *is_raster;
1734  is_raster = GDALGetMetadataItem(drv, GDAL_DCAP_RASTER, NULL);
1735  if (!is_raster || !EQUAL(is_raster, "YES"))
1736  continue;
1737 #endif
1738 
1739  /* CreateCopy support */
1740  const char *cc = GDALGetMetadataItem(drv, GDAL_DCAP_CREATECOPY, NULL);
1741  if (can_write && !cc)
1742  continue;
1743 
1744  /* VirtualIO support */
1745  const char *vio = GDALGetMetadataItem(drv, GDAL_DCAP_VIRTUALIO, NULL);
1746  if (can_write && !vio)
1747  continue;
1748 
1749  /* we can always read what GDAL can load */
1750  rtn[output_driver].can_read = 1;
1751  /* we require CreateCopy and VirtualIO support to write to GDAL */
1752  rtn[output_driver].can_write = (cc != NULL && vio != NULL);
1753 
1754  /* index of driver */
1755  rtn[output_driver].idx = i;
1756 
1757  /* short name */
1758  const char *txt = GDALGetDriverShortName(drv);
1759  size_t txt_len = strlen(txt);
1760  txt_len = (txt_len + 1) * sizeof(char);
1761  rtn[output_driver].short_name = (char *)rtalloc(txt_len);
1762  memcpy(rtn[output_driver].short_name, txt, txt_len);
1763 
1764  /* long name */
1765  txt = GDALGetDriverLongName(drv);
1766  txt_len = strlen(txt);
1767  txt_len = (txt_len + 1) * sizeof(char);
1768  rtn[output_driver].long_name = (char *)rtalloc(txt_len);
1769  memcpy(rtn[output_driver].long_name, txt, txt_len);
1770 
1771  /* creation options */
1772  txt = GDALGetDriverCreationOptionList(drv);
1773  txt_len = strlen(txt);
1774  txt_len = (txt_len + 1) * sizeof(char);
1775  rtn[output_driver].create_options = (char *)rtalloc(txt_len);
1776  memcpy(rtn[output_driver].create_options, txt, txt_len);
1777 
1778  output_driver++;
1779  }
1780 
1781  /* free unused memory */
1782  rtn = rtrealloc(rtn, output_driver * sizeof(struct rt_gdaldriver_t));
1783  *drv_count = output_driver;
1784 
1785  return rtn;
1786 }
1787 
1788 /******************************************************************************
1789 * rt_raster_to_gdal_mem()
1790 ******************************************************************************/
1791 
1807 GDALDatasetH
1809  rt_raster raster,
1810  const char *srs,
1811  uint32_t *bandNums,
1812  int *excludeNodataValues,
1813  int count,
1814  GDALDriverH *rtn_drv, int *destroy_rtn_drv
1815 ) {
1816  GDALDriverH drv = NULL;
1817  GDALDatasetH ds = NULL;
1818  double gt[6] = {0.0};
1819  CPLErr cplerr;
1820  GDALDataType gdal_pt = GDT_Unknown;
1821  GDALRasterBandH band;
1822  void *pVoid;
1823  char *pszDataPointer;
1824  char szGDALOption[50];
1825  char *apszOptions[4];
1826  double nodata = 0.0;
1827  int allocBandNums = 0;
1828  int allocNodataValues = 0;
1829 
1830  int i;
1831  uint32_t numBands;
1832  uint32_t width = 0;
1833  uint32_t height = 0;
1834  rt_band rtband = NULL;
1835  rt_pixtype pt = PT_END;
1836 
1837  assert(NULL != raster);
1838  assert(NULL != rtn_drv);
1839  assert(NULL != destroy_rtn_drv);
1840 
1841  *destroy_rtn_drv = 0;
1842 
1843  /* store raster in GDAL MEM raster */
1844  if (!rt_util_gdal_driver_registered("MEM")) {
1845  RASTER_DEBUG(4, "Registering MEM driver");
1846  GDALRegister_MEM();
1847  *destroy_rtn_drv = 1;
1848  }
1849  drv = GDALGetDriverByName("MEM");
1850  if (NULL == drv) {
1851  rterror("rt_raster_to_gdal_mem: Could not load the MEM GDAL driver");
1852  return 0;
1853  }
1854  *rtn_drv = drv;
1855 
1856  /* unload driver from GDAL driver manager */
1857  if (*destroy_rtn_drv) {
1858  RASTER_DEBUG(4, "Deregistering MEM driver");
1859  GDALDeregisterDriver(drv);
1860  }
1861 
1862  width = rt_raster_get_width(raster);
1863  height = rt_raster_get_height(raster);
1864  ds = GDALCreate(
1865  drv, "",
1866  width, height,
1867  0, GDT_Byte, NULL
1868  );
1869  if (NULL == ds) {
1870  rterror("rt_raster_to_gdal_mem: Could not create a GDALDataset to convert into");
1871  return 0;
1872  }
1873 
1874  /* add geotransform */
1876  cplerr = GDALSetGeoTransform(ds, gt);
1877  if (cplerr != CE_None) {
1878  rterror("rt_raster_to_gdal_mem: Could not set geotransformation");
1879  GDALClose(ds);
1880  return 0;
1881  }
1882 
1883  /* set spatial reference */
1884  if (NULL != srs && strlen(srs)) {
1885  char *_srs = rt_util_gdal_convert_sr(srs, 0);
1886  if (_srs == NULL) {
1887  rterror("rt_raster_to_gdal_mem: Could not convert srs to GDAL accepted format");
1888  GDALClose(ds);
1889  return 0;
1890  }
1891 
1892  cplerr = GDALSetProjection(ds, _srs);
1893  CPLFree(_srs);
1894  if (cplerr != CE_None) {
1895  rterror("rt_raster_to_gdal_mem: Could not set projection");
1896  GDALClose(ds);
1897  return 0;
1898  }
1899  RASTER_DEBUGF(3, "Projection set to: %s", GDALGetProjectionRef(ds));
1900  }
1901 
1902  /* process bandNums */
1903  numBands = rt_raster_get_num_bands(raster);
1904  if (NULL != bandNums && count > 0) {
1905  for (i = 0; i < count; i++) {
1906  if (bandNums[i] >= numBands) {
1907  rterror("rt_raster_to_gdal_mem: The band index %d is invalid", bandNums[i]);
1908  GDALClose(ds);
1909  return 0;
1910  }
1911  }
1912  }
1913  else {
1914  count = numBands;
1915  bandNums = (uint32_t *) rtalloc(sizeof(uint32_t) * count);
1916  if (NULL == bandNums) {
1917  rterror("rt_raster_to_gdal_mem: Could not allocate memory for band indices");
1918  GDALClose(ds);
1919  return 0;
1920  }
1921  allocBandNums = 1;
1922  for (i = 0; i < count; i++) bandNums[i] = i;
1923  }
1924 
1925  /* process exclude_nodata_values */
1926  if (NULL == excludeNodataValues) {
1927  excludeNodataValues = (int *) rtalloc(sizeof(int) * count);
1928  if (NULL == excludeNodataValues) {
1929  rterror("rt_raster_to_gdal_mem: Could not allocate memory for NODATA flags");
1930  GDALClose(ds);
1931  return 0;
1932  }
1933  allocNodataValues = 1;
1934  for (i = 0; i < count; i++) excludeNodataValues[i] = 1;
1935  }
1936 
1937  /* add band(s) */
1938  for (i = 0; i < count; i++) {
1939  rtband = rt_raster_get_band(raster, bandNums[i]);
1940  if (NULL == rtband) {
1941  rterror("rt_raster_to_gdal_mem: Could not get requested band index %d", bandNums[i]);
1942  if (allocBandNums) rtdealloc(bandNums);
1943  if (allocNodataValues) rtdealloc(excludeNodataValues);
1944  GDALClose(ds);
1945  return 0;
1946  }
1947 
1948  pt = rt_band_get_pixtype(rtband);
1949  gdal_pt = rt_util_pixtype_to_gdal_datatype(pt);
1950  if (gdal_pt == GDT_Unknown)
1951  rtwarn("rt_raster_to_gdal_mem: Unknown pixel type for band");
1952 
1953  /*
1954  For all pixel types other than PT_8BSI, set pointer to start of data
1955  */
1956  if (pt != PT_8BSI) {
1957  pVoid = rt_band_get_data(rtband);
1958  RASTER_DEBUGF(4, "Band data is at pos %p", pVoid);
1959 
1960  pszDataPointer = (char *) rtalloc(20 * sizeof (char));
1961  sprintf(pszDataPointer, "%p", pVoid);
1962  RASTER_DEBUGF(4, "rt_raster_to_gdal_mem: szDatapointer is %p",
1963  pszDataPointer);
1964 
1965  if (strncasecmp(pszDataPointer, "0x", 2) == 0)
1966  sprintf(szGDALOption, "DATAPOINTER=%s", pszDataPointer);
1967  else
1968  sprintf(szGDALOption, "DATAPOINTER=0x%s", pszDataPointer);
1969 
1970  RASTER_DEBUG(3, "Storing info for GDAL MEM raster band");
1971 
1972  apszOptions[0] = szGDALOption;
1973  apszOptions[1] = NULL; /* pixel offset, not needed */
1974  apszOptions[2] = NULL; /* line offset, not needed */
1975  apszOptions[3] = NULL;
1976 
1977  /* free */
1978  rtdealloc(pszDataPointer);
1979 
1980  /* add band */
1981  if (GDALAddBand(ds, gdal_pt, apszOptions) == CE_Failure) {
1982  rterror("rt_raster_to_gdal_mem: Could not add GDAL raster band");
1983  if (allocBandNums) rtdealloc(bandNums);
1984  GDALClose(ds);
1985  return 0;
1986  }
1987  }
1988  /*
1989  PT_8BSI is special as GDAL has no equivalent pixel type.
1990  Must convert 8BSI to 16BSI so create basic band
1991  */
1992  else {
1993  /* add band */
1994  if (GDALAddBand(ds, gdal_pt, NULL) == CE_Failure) {
1995  rterror("rt_raster_to_gdal_mem: Could not add GDAL raster band");
1996  if (allocBandNums) rtdealloc(bandNums);
1997  if (allocNodataValues) rtdealloc(excludeNodataValues);
1998  GDALClose(ds);
1999  return 0;
2000  }
2001  }
2002 
2003  /* check band count */
2004  if (GDALGetRasterCount(ds) != i + 1) {
2005  rterror("rt_raster_to_gdal_mem: Error creating GDAL MEM raster band");
2006  if (allocBandNums) rtdealloc(bandNums);
2007  if (allocNodataValues) rtdealloc(excludeNodataValues);
2008  GDALClose(ds);
2009  return 0;
2010  }
2011 
2012  /* get new band */
2013  band = NULL;
2014  band = GDALGetRasterBand(ds, i + 1);
2015  if (NULL == band) {
2016  rterror("rt_raster_to_gdal_mem: Could not get GDAL band for additional processing");
2017  if (allocBandNums) rtdealloc(bandNums);
2018  if (allocNodataValues) rtdealloc(excludeNodataValues);
2019  GDALClose(ds);
2020  return 0;
2021  }
2022 
2023  /* PT_8BSI requires manual setting of pixels */
2024  if (pt == PT_8BSI) {
2025  uint32_t nXBlocks, nYBlocks;
2026  int nXBlockSize, nYBlockSize;
2027  uint32_t iXBlock, iYBlock;
2028  int nXValid, nYValid;
2029  int iX, iY;
2030  int iXMax, iYMax;
2031 
2032  int x, y, z;
2033  uint32_t valueslen = 0;
2034  int16_t *values = NULL;
2035  double value = 0.;
2036 
2037  /* this makes use of GDAL's "natural" blocks */
2038  GDALGetBlockSize(band, &nXBlockSize, &nYBlockSize);
2039  nXBlocks = (width + nXBlockSize - 1) / nXBlockSize;
2040  nYBlocks = (height + nYBlockSize - 1) / nYBlockSize;
2041  RASTER_DEBUGF(4, "(nXBlockSize, nYBlockSize) = (%d, %d)", nXBlockSize, nYBlockSize);
2042  RASTER_DEBUGF(4, "(nXBlocks, nYBlocks) = (%d, %d)", nXBlocks, nYBlocks);
2043 
2044  /* length is for the desired pixel type */
2045  valueslen = rt_pixtype_size(PT_16BSI) * nXBlockSize * nYBlockSize;
2046  values = rtalloc(valueslen);
2047  if (NULL == values) {
2048  rterror("rt_raster_to_gdal_mem: Could not allocate memory for GDAL band pixel values");
2049  if (allocBandNums) rtdealloc(bandNums);
2050  if (allocNodataValues) rtdealloc(excludeNodataValues);
2051  GDALClose(ds);
2052  return 0;
2053  }
2054 
2055  for (iYBlock = 0; iYBlock < nYBlocks; iYBlock++) {
2056  for (iXBlock = 0; iXBlock < nXBlocks; iXBlock++) {
2057  memset(values, 0, valueslen);
2058 
2059  x = iXBlock * nXBlockSize;
2060  y = iYBlock * nYBlockSize;
2061  RASTER_DEBUGF(4, "(iXBlock, iYBlock) = (%d, %d)", iXBlock, iYBlock);
2062  RASTER_DEBUGF(4, "(x, y) = (%d, %d)", x, y);
2063 
2064  /* valid block width */
2065  if ((iXBlock + 1) * nXBlockSize > width)
2066  nXValid = width - (iXBlock * nXBlockSize);
2067  else
2068  nXValid = nXBlockSize;
2069 
2070  /* valid block height */
2071  if ((iYBlock + 1) * nYBlockSize > height)
2072  nYValid = height - (iYBlock * nYBlockSize);
2073  else
2074  nYValid = nYBlockSize;
2075 
2076  RASTER_DEBUGF(4, "(nXValid, nYValid) = (%d, %d)", nXValid, nYValid);
2077 
2078  /* convert 8BSI values to 16BSI */
2079  z = 0;
2080  iYMax = y + nYValid;
2081  iXMax = x + nXValid;
2082  for (iY = y; iY < iYMax; iY++) {
2083  for (iX = x; iX < iXMax; iX++) {
2084  if (rt_band_get_pixel(rtband, iX, iY, &value, NULL) != ES_NONE) {
2085  rterror("rt_raster_to_gdal_mem: Could not get pixel value to convert from 8BSI to 16BSI");
2086  rtdealloc(values);
2087  if (allocBandNums) rtdealloc(bandNums);
2088  if (allocNodataValues) rtdealloc(excludeNodataValues);
2089  GDALClose(ds);
2090  return 0;
2091  }
2092 
2093  values[z++] = rt_util_clamp_to_16BSI(value);
2094  }
2095  }
2096 
2097  /* burn values */
2098  if (GDALRasterIO(
2099  band, GF_Write,
2100  x, y,
2101  nXValid, nYValid,
2102  values, nXValid, nYValid,
2103  gdal_pt,
2104  0, 0
2105  ) != CE_None) {
2106  rterror("rt_raster_to_gdal_mem: Could not write converted 8BSI to 16BSI values to GDAL band");
2107  rtdealloc(values);
2108  if (allocBandNums) rtdealloc(bandNums);
2109  if (allocNodataValues) rtdealloc(excludeNodataValues);
2110  GDALClose(ds);
2111  return 0;
2112  }
2113  }
2114  }
2115 
2116  rtdealloc(values);
2117  }
2118 
2119  /* Add nodata value for band */
2120  if (rt_band_get_hasnodata_flag(rtband) != FALSE && excludeNodataValues[i]) {
2121  rt_band_get_nodata(rtband, &nodata);
2122  if (GDALSetRasterNoDataValue(band, nodata) != CE_None)
2123  rtwarn("rt_raster_to_gdal_mem: Could not set nodata value for band");
2124  RASTER_DEBUGF(3, "nodata value set to %f", GDALGetRasterNoDataValue(band, NULL));
2125  }
2126 
2127 #if POSTGIS_DEBUG_LEVEL > 3
2128  {
2129  GDALRasterBandH _grb = NULL;
2130  double _min;
2131  double _max;
2132  double _mean;
2133  double _stddev;
2134 
2135  _grb = GDALGetRasterBand(ds, i + 1);
2136  GDALComputeRasterStatistics(_grb, FALSE, &_min, &_max, &_mean, &_stddev, NULL, NULL);
2137  RASTER_DEBUGF(4, "GDAL Band %d stats: %f, %f, %f, %f", i + 1, _min, _max, _mean, _stddev);
2138  }
2139 #endif
2140 
2141  }
2142 
2143  /* necessary??? */
2144  GDALFlushCache(ds);
2145 
2146  if (allocBandNums) rtdealloc(bandNums);
2147  if (allocNodataValues) rtdealloc(excludeNodataValues);
2148 
2149  return ds;
2150 }
2151 
2152 /******************************************************************************
2153 * rt_raster_from_gdal_dataset()
2154 ******************************************************************************/
2155 
2163 rt_raster
2165  rt_raster rast = NULL;
2166  double gt[6] = {0};
2167  CPLErr cplerr;
2168  uint32_t width = 0;
2169  uint32_t height = 0;
2170  uint32_t numBands = 0;
2171  uint32_t i = 0;
2172  char *authname = NULL;
2173  char *authcode = NULL;
2174 
2175  GDALRasterBandH gdband = NULL;
2176  GDALDataType gdpixtype = GDT_Unknown;
2177  rt_band band;
2178  int32_t idx;
2179  rt_pixtype pt = PT_END;
2180  uint32_t ptlen = 0;
2181  int hasnodata = 0;
2182  double nodataval;
2183 
2184  int x;
2185  int y;
2186 
2187  uint32_t nXBlocks, nYBlocks;
2188  int nXBlockSize, nYBlockSize;
2189  uint32_t iXBlock, iYBlock;
2190  uint32_t nXValid, nYValid;
2191  uint32_t iY;
2192 
2193  uint8_t *values = NULL;
2194  uint32_t valueslen = 0;
2195  uint8_t *ptr = NULL;
2196 
2197  assert(NULL != ds);
2198 
2199  /* raster size */
2200  width = GDALGetRasterXSize(ds);
2201  height = GDALGetRasterYSize(ds);
2202  RASTER_DEBUGF(3, "Raster dimensions (width x height): %d x %d", width, height);
2203 
2204  /* create new raster */
2205  RASTER_DEBUG(3, "Creating new raster");
2206  rast = rt_raster_new(width, height);
2207  if (NULL == rast) {
2208  rterror("rt_raster_from_gdal_dataset: Out of memory allocating new raster");
2209  return NULL;
2210  }
2211  RASTER_DEBUGF(3, "Created raster dimensions (width x height): %d x %d", rast->width, rast->height);
2212 
2213  /* get raster attributes */
2214  cplerr = GDALGetGeoTransform(ds, gt);
2215  if (GDALGetGeoTransform(ds, gt) != CE_None) {
2216  RASTER_DEBUG(4, "Using default geotransform matrix (0, 1, 0, 0, 0, -1)");
2217  gt[0] = 0;
2218  gt[1] = 1;
2219  gt[2] = 0;
2220  gt[3] = 0;
2221  gt[4] = 0;
2222  gt[5] = -1;
2223  }
2224 
2225  /* apply raster attributes */
2227 
2228  RASTER_DEBUGF(3, "Raster geotransform (%f, %f, %f, %f, %f, %f)",
2229  gt[0], gt[1], gt[2], gt[3], gt[4], gt[5]);
2230 
2231  /* srid */
2232  if (rt_util_gdal_sr_auth_info(ds, &authname, &authcode) == ES_NONE) {
2233  if (
2234  authname != NULL &&
2235  strcmp(authname, "EPSG") == 0 &&
2236  authcode != NULL
2237  ) {
2238  rt_raster_set_srid(rast, atoi(authcode));
2239  RASTER_DEBUGF(3, "New raster's SRID = %d", rast->srid);
2240  }
2241 
2242  if (authname != NULL)
2243  rtdealloc(authname);
2244  if (authcode != NULL)
2245  rtdealloc(authcode);
2246  }
2247 
2248  numBands = GDALGetRasterCount(ds);
2249 
2250 #if POSTGIS_DEBUG_LEVEL > 3
2251  for (i = 1; i <= numBands; i++) {
2252  GDALRasterBandH _grb = NULL;
2253  double _min;
2254  double _max;
2255  double _mean;
2256  double _stddev;
2257 
2258  _grb = GDALGetRasterBand(ds, i);
2259  GDALComputeRasterStatistics(_grb, FALSE, &_min, &_max, &_mean, &_stddev, NULL, NULL);
2260  RASTER_DEBUGF(4, "GDAL Band %d stats: %f, %f, %f, %f", i, _min, _max, _mean, _stddev);
2261  }
2262 #endif
2263 
2264  /* copy bands */
2265  for (i = 1; i <= numBands; i++) {
2266  RASTER_DEBUGF(3, "Processing band %d of %d", i, numBands);
2267  gdband = NULL;
2268  gdband = GDALGetRasterBand(ds, i);
2269  if (NULL == gdband) {
2270  rterror("rt_raster_from_gdal_dataset: Could not get GDAL band");
2272  return NULL;
2273  }
2274  RASTER_DEBUGF(4, "gdband @ %p", gdband);
2275 
2276  /* pixtype */
2277  gdpixtype = GDALGetRasterDataType(gdband);
2278  RASTER_DEBUGF(4, "gdpixtype, size = %s, %d", GDALGetDataTypeName(gdpixtype), GDALGetDataTypeSize(gdpixtype) / 8);
2279  pt = rt_util_gdal_datatype_to_pixtype(gdpixtype);
2280  if (pt == PT_END) {
2281  rterror("rt_raster_from_gdal_dataset: Unknown pixel type for GDAL band");
2283  return NULL;
2284  }
2285  ptlen = rt_pixtype_size(pt);
2286 
2287  /* size: width and height */
2288  width = GDALGetRasterBandXSize(gdband);
2289  height = GDALGetRasterBandYSize(gdband);
2290  RASTER_DEBUGF(3, "GDAL band dimensions (width x height): %d x %d", width, height);
2291 
2292  /* nodata */
2293  nodataval = GDALGetRasterNoDataValue(gdband, &hasnodata);
2294  RASTER_DEBUGF(3, "(hasnodata, nodataval) = (%d, %f)", hasnodata, nodataval);
2295 
2296  /* create band object */
2298  rast, pt,
2299  (hasnodata ? nodataval : 0),
2300  hasnodata, nodataval, rt_raster_get_num_bands(rast)
2301  );
2302  if (idx < 0) {
2303  rterror("rt_raster_from_gdal_dataset: Could not allocate memory for raster band");
2305  return NULL;
2306  }
2307  band = rt_raster_get_band(rast, idx);
2308  RASTER_DEBUGF(3, "Created band of dimension (width x height): %d x %d", band->width, band->height);
2309 
2310  /* this makes use of GDAL's "natural" blocks */
2311  GDALGetBlockSize(gdband, &nXBlockSize, &nYBlockSize);
2312  nXBlocks = (width + nXBlockSize - 1) / nXBlockSize;
2313  nYBlocks = (height + nYBlockSize - 1) / nYBlockSize;
2314  RASTER_DEBUGF(4, "(nXBlockSize, nYBlockSize) = (%d, %d)", nXBlockSize, nYBlockSize);
2315  RASTER_DEBUGF(4, "(nXBlocks, nYBlocks) = (%d, %d)", nXBlocks, nYBlocks);
2316 
2317  /* allocate memory for values */
2318  valueslen = ptlen * nXBlockSize * nYBlockSize;
2319  values = rtalloc(valueslen);
2320  if (values == NULL) {
2321  rterror("rt_raster_from_gdal_dataset: Could not allocate memory for GDAL band pixel values");
2323  return NULL;
2324  }
2325  RASTER_DEBUGF(3, "values @ %p of length = %d", values, valueslen);
2326 
2327  for (iYBlock = 0; iYBlock < nYBlocks; iYBlock++) {
2328  for (iXBlock = 0; iXBlock < nXBlocks; iXBlock++) {
2329  x = iXBlock * nXBlockSize;
2330  y = iYBlock * nYBlockSize;
2331  RASTER_DEBUGF(4, "(iXBlock, iYBlock) = (%d, %d)", iXBlock, iYBlock);
2332  RASTER_DEBUGF(4, "(x, y) = (%d, %d)", x, y);
2333 
2334  memset(values, 0, valueslen);
2335 
2336  /* valid block width */
2337  if ((iXBlock + 1) * nXBlockSize > width)
2338  nXValid = width - (iXBlock * nXBlockSize);
2339  else
2340  nXValid = nXBlockSize;
2341 
2342  /* valid block height */
2343  if ((iYBlock + 1) * nYBlockSize > height)
2344  nYValid = height - (iYBlock * nYBlockSize);
2345  else
2346  nYValid = nYBlockSize;
2347 
2348  RASTER_DEBUGF(4, "(nXValid, nYValid) = (%d, %d)", nXValid, nYValid);
2349 
2350  cplerr = GDALRasterIO(
2351  gdband, GF_Read,
2352  x, y,
2353  nXValid, nYValid,
2354  values, nXValid, nYValid,
2355  gdpixtype,
2356  0, 0
2357  );
2358  if (cplerr != CE_None) {
2359  rterror("rt_raster_from_gdal_dataset: Could not get data from GDAL raster");
2360  rtdealloc(values);
2362  return NULL;
2363  }
2364 
2365  /* if block width is same as raster width, shortcut */
2366  if (nXBlocks == 1 && nYBlockSize > 1 && nXValid == width) {
2367  x = 0;
2368  y = nYBlockSize * iYBlock;
2369 
2370  RASTER_DEBUGF(4, "Setting set of pixel lines at (%d, %d) for %d pixels", x, y, nXValid * nYValid);
2371  rt_band_set_pixel_line(band, x, y, values, nXValid * nYValid);
2372  }
2373  else {
2374  ptr = values;
2375  x = nXBlockSize * iXBlock;
2376  for (iY = 0; iY < nYValid; iY++) {
2377  y = iY + (nYBlockSize * iYBlock);
2378 
2379  RASTER_DEBUGF(4, "Setting pixel line at (%d, %d) for %d pixels", x, y, nXValid);
2380  rt_band_set_pixel_line(band, x, y, ptr, nXValid);
2381  ptr += (nXValid * ptlen);
2382  }
2383  }
2384  }
2385  }
2386 
2387  /* free memory */
2388  rtdealloc(values);
2389  }
2390 
2391  return rast;
2392 }
2393 
2394 /******************************************************************************
2395 * rt_raster_gdal_rasterize()
2396 ******************************************************************************/
2397 
2400  uint8_t noband;
2401 
2402  uint32_t numbands;
2403 
2404  OGRSpatialReferenceH src_sr;
2405 
2407  double *init;
2408  double *nodata;
2409  uint8_t *hasnodata;
2410  double *value;
2411  int *bandlist;
2412 };
2413 
2414 static _rti_rasterize_arg
2416  _rti_rasterize_arg arg = NULL;
2417 
2418  arg = rtalloc(sizeof(struct _rti_rasterize_arg_t));
2419  if (arg == NULL) {
2420  rterror("_rti_rasterize_arg_init: Could not allocate memory for _rti_rasterize_arg");
2421  return NULL;
2422  }
2423 
2424  arg->noband = 0;
2425 
2426  arg->numbands = 0;
2427 
2428  arg->src_sr = NULL;
2429 
2430  arg->pixtype = NULL;
2431  arg->init = NULL;
2432  arg->nodata = NULL;
2433  arg->hasnodata = NULL;
2434  arg->value = NULL;
2435  arg->bandlist = NULL;
2436 
2437  return arg;
2438 }
2439 
2440 static void
2442  if (arg->noband) {
2443  if (arg->pixtype != NULL)
2444  rtdealloc(arg->pixtype);
2445  if (arg->init != NULL)
2446  rtdealloc(arg->init);
2447  if (arg->nodata != NULL)
2448  rtdealloc(arg->nodata);
2449  if (arg->hasnodata != NULL)
2450  rtdealloc(arg->hasnodata);
2451  if (arg->value != NULL)
2452  rtdealloc(arg->value);
2453  }
2454 
2455  if (arg->bandlist != NULL)
2456  rtdealloc(arg->bandlist);
2457 
2458  if (arg->src_sr != NULL)
2459  OSRDestroySpatialReference(arg->src_sr);
2460 
2461  rtdealloc(arg);
2462 }
2463 
2490 rt_raster
2492  const unsigned char *wkb, uint32_t wkb_len,
2493  const char *srs,
2494  uint32_t num_bands, rt_pixtype *pixtype,
2495  double *init, double *value,
2496  double *nodata, uint8_t *hasnodata,
2497  int *width, int *height,
2498  double *scale_x, double *scale_y,
2499  double *ul_xw, double *ul_yw,
2500  double *grid_xw, double *grid_yw,
2501  double *skew_x, double *skew_y,
2502  char **options
2503 ) {
2504  rt_raster rast = NULL;
2505  uint32_t i = 0;
2506  int err = 0;
2507 
2508  _rti_rasterize_arg arg = NULL;
2509 
2510  int _dim[2] = {0};
2511  double _scale[2] = {0};
2512  double _skew[2] = {0};
2513 
2514  OGRErr ogrerr;
2515  OGRGeometryH src_geom;
2516  OGREnvelope src_env;
2517  rt_envelope extent;
2518  OGRwkbGeometryType wkbtype = wkbUnknown;
2519 
2520  int ul_user = 0;
2521 
2522  CPLErr cplerr;
2523  double _gt[6] = {0};
2524  GDALDriverH _drv = NULL;
2525  int unload_drv = 0;
2526  GDALDatasetH _ds = NULL;
2527  GDALRasterBandH _band = NULL;
2528 
2529  uint16_t _width = 0;
2530  uint16_t _height = 0;
2531 
2532  RASTER_DEBUG(3, "starting");
2533 
2534  assert(NULL != wkb);
2535  assert(0 != wkb_len);
2536 
2537  /* internal variables */
2538  arg = _rti_rasterize_arg_init();
2539  if (arg == NULL) {
2540  rterror("rt_raster_gdal_rasterize: Could not initialize internal variables");
2541  return NULL;
2542  }
2543 
2544  /* no bands, raster is a mask */
2545  if (num_bands < 1) {
2546  arg->noband = 1;
2547  arg->numbands = 1;
2548 
2549  arg->pixtype = (rt_pixtype *) rtalloc(sizeof(rt_pixtype));
2550  arg->pixtype[0] = PT_8BUI;
2551 
2552  arg->init = (double *) rtalloc(sizeof(double));
2553  arg->init[0] = 0;
2554 
2555  arg->nodata = (double *) rtalloc(sizeof(double));
2556  arg->nodata[0] = 0;
2557 
2558  arg->hasnodata = (uint8_t *) rtalloc(sizeof(uint8_t));
2559  arg->hasnodata[0] = 1;
2560 
2561  arg->value = (double *) rtalloc(sizeof(double));
2562  arg->value[0] = 1;
2563  }
2564  else {
2565  arg->noband = 0;
2566  arg->numbands = num_bands;
2567 
2568  arg->pixtype = pixtype;
2569  arg->init = init;
2570  arg->nodata = nodata;
2571  arg->hasnodata = hasnodata;
2572  arg->value = value;
2573  }
2574 
2575  /* OGR spatial reference */
2576  if (NULL != srs && strlen(srs)) {
2577  arg->src_sr = OSRNewSpatialReference(NULL);
2578  if (OSRSetFromUserInput(arg->src_sr, srs) != OGRERR_NONE) {
2579  rterror("rt_raster_gdal_rasterize: Could not create OSR spatial reference using the provided srs: %s", srs);
2581  return NULL;
2582  }
2583  }
2584 
2585  /* convert WKB to OGR Geometry */
2586  ogrerr = OGR_G_CreateFromWkb((unsigned char *) wkb, arg->src_sr, &src_geom, wkb_len);
2587  if (ogrerr != OGRERR_NONE) {
2588  rterror("rt_raster_gdal_rasterize: Could not create OGR Geometry from WKB");
2589 
2591  /* OGRCleanupAll(); */
2592 
2593  return NULL;
2594  }
2595 
2596  /* OGR Geometry is empty */
2597  if (OGR_G_IsEmpty(src_geom)) {
2598  rtinfo("Geometry provided is empty. Returning empty raster");
2599 
2600  OGR_G_DestroyGeometry(src_geom);
2602  /* OGRCleanupAll(); */
2603 
2604  return rt_raster_new(0, 0);
2605  }
2606 
2607  /* get envelope */
2608  OGR_G_GetEnvelope(src_geom, &src_env);
2609  rt_util_from_ogr_envelope(src_env, &extent);
2610 
2611  RASTER_DEBUGF(3, "Suggested raster envelope: %f, %f, %f, %f",
2612  extent.MinX, extent.MinY, extent.MaxX, extent.MaxY);
2613 
2614  /* user-defined scale */
2615  if (
2616  (NULL != scale_x) &&
2617  (NULL != scale_y) &&
2618  (FLT_NEQ(*scale_x, 0.0)) &&
2619  (FLT_NEQ(*scale_y, 0.0))
2620  ) {
2621  /* for now, force scale to be in left-right, top-down orientation */
2622  _scale[0] = fabs(*scale_x);
2623  _scale[1] = fabs(*scale_y);
2624  }
2625  /* user-defined width/height */
2626  else if ((NULL != width) && (NULL != height) && (*width != 0) && (*height != 0))
2627  {
2628  _dim[0] = abs(*width);
2629  _dim[1] = abs(*height);
2630 
2631  if (FLT_NEQ(extent.MaxX, extent.MinX))
2632  _scale[0] = fabs((extent.MaxX - extent.MinX) / _dim[0]);
2633  else
2634  _scale[0] = 1.;
2635 
2636  if (FLT_NEQ(extent.MaxY, extent.MinY))
2637  _scale[1] = fabs((extent.MaxY - extent.MinY) / _dim[1]);
2638  else
2639  _scale[1] = 1.;
2640  }
2641  else {
2642  rterror("rt_raster_gdal_rasterize: Values must be provided for width and height or X and Y of scale");
2643 
2644  OGR_G_DestroyGeometry(src_geom);
2646  /* OGRCleanupAll(); */
2647 
2648  return NULL;
2649  }
2650  RASTER_DEBUGF(3, "scale (x, y) = %f, %f", _scale[0], -1 * _scale[1]);
2651  RASTER_DEBUGF(3, "dim (x, y) = %d, %d", _dim[0], _dim[1]);
2652 
2653  /* user-defined skew */
2654  if (NULL != skew_x) {
2655  _skew[0] = *skew_x;
2656 
2657  /*
2658  negative scale-x affects skew
2659  for now, force skew to be in left-right, top-down orientation
2660  */
2661  if (
2662  NULL != scale_x &&
2663  *scale_x < 0.
2664  ) {
2665  _skew[0] *= -1;
2666  }
2667  }
2668  if (NULL != skew_y) {
2669  _skew[1] = *skew_y;
2670 
2671  /*
2672  positive scale-y affects skew
2673  for now, force skew to be in left-right, top-down orientation
2674  */
2675  if (
2676  NULL != scale_y &&
2677  *scale_y > 0.
2678  ) {
2679  _skew[1] *= -1;
2680  }
2681  }
2682 
2683  /*
2684  if geometry is a point, a linestring or set of either and bounds not set,
2685  increase extent by a pixel to avoid missing points on border
2686 
2687  a whole pixel is used instead of half-pixel due to backward
2688  compatibility with GDAL 1.6, 1.7 and 1.8. 1.9+ works fine with half-pixel.
2689  */
2690  wkbtype = wkbFlatten(OGR_G_GetGeometryType(src_geom));
2691  if ((
2692  (wkbtype == wkbPoint) ||
2693  (wkbtype == wkbMultiPoint) ||
2694  (wkbtype == wkbLineString) ||
2695  (wkbtype == wkbMultiLineString)
2696  ) &&
2697  _dim[0] == 0 &&
2698  _dim[1] == 0
2699  ) {
2700 
2701 #if POSTGIS_GDAL_VERSION > 18
2702 
2703  RASTER_DEBUG(3, "Adjusting extent for GDAL > 1.8 by half the scale on X-axis");
2704  extent.MinX -= (_scale[0] / 2.);
2705  extent.MaxX += (_scale[0] / 2.);
2706 
2707  RASTER_DEBUG(3, "Adjusting extent for GDAL > 1.8 by half the scale on Y-axis");
2708  extent.MinY -= (_scale[1] / 2.);
2709  extent.MaxY += (_scale[1] / 2.);
2710 
2711 #else
2712 
2713  RASTER_DEBUG(3, "Adjusting extent for GDAL <= 1.8 by the scale on X-axis");
2714  extent.MinX -= _scale[0];
2715  extent.MaxX += _scale[0];
2716 
2717  RASTER_DEBUG(3, "Adjusting extent for GDAL <= 1.8 by the scale on Y-axis");
2718  extent.MinY -= _scale[1];
2719  extent.MaxY += _scale[1];
2720 
2721 #endif
2722 
2723 
2724  RASTER_DEBUGF(3, "Adjusted extent: %f, %f, %f, %f",
2725  extent.MinX, extent.MinY, extent.MaxX, extent.MaxY);
2726 
2727  extent.UpperLeftX = extent.MinX;
2728  extent.UpperLeftY = extent.MaxY;
2729  }
2730 
2731  /* reprocess extent if skewed */
2732  if (FLT_NEQ(_skew[0], 0.0) || FLT_NEQ(_skew[1], 0.0))
2733  {
2734  rt_raster skewedrast;
2735 
2736  RASTER_DEBUG(3, "Computing skewed extent's envelope");
2737 
2738  skewedrast = rt_raster_compute_skewed_raster(
2739  extent,
2740  _skew,
2741  _scale,
2742  0.01
2743  );
2744  if (skewedrast == NULL) {
2745  rterror("rt_raster_gdal_rasterize: Could not compute skewed raster");
2746 
2747  OGR_G_DestroyGeometry(src_geom);
2749  /* OGRCleanupAll(); */
2750 
2751  return NULL;
2752  }
2753 
2754  _dim[0] = skewedrast->width;
2755  _dim[1] = skewedrast->height;
2756 
2757  extent.UpperLeftX = skewedrast->ipX;
2758  extent.UpperLeftY = skewedrast->ipY;
2759 
2760  rt_raster_destroy(skewedrast);
2761  }
2762 
2763  /* raster dimensions */
2764  if (!_dim[0])
2765  _dim[0] = (int) fmax((fabs(extent.MaxX - extent.MinX) + (_scale[0] / 2.)) / _scale[0], 1);
2766  if (!_dim[1])
2767  _dim[1] = (int) fmax((fabs(extent.MaxY - extent.MinY) + (_scale[1] / 2.)) / _scale[1], 1);
2768 
2769  /* temporary raster */
2770  rast = rt_raster_new(_dim[0], _dim[1]);
2771  if (rast == NULL) {
2772  rterror("rt_raster_gdal_rasterize: Out of memory allocating temporary raster");
2773 
2774  OGR_G_DestroyGeometry(src_geom);
2776  /* OGRCleanupAll(); */
2777 
2778  return NULL;
2779  }
2780 
2781  /* set raster's spatial attributes */
2783  rt_raster_set_scale(rast, _scale[0], -1 * _scale[1]);
2784  rt_raster_set_skews(rast, _skew[0], _skew[1]);
2785 
2787  RASTER_DEBUGF(3, "Temp raster's geotransform: %f, %f, %f, %f, %f, %f",
2788  _gt[0], _gt[1], _gt[2], _gt[3], _gt[4], _gt[5]);
2789  RASTER_DEBUGF(3, "Temp raster's dimensions (width x height): %d x %d",
2790  _dim[0], _dim[1]);
2791 
2792  /* user-specified upper-left corner */
2793  if (
2794  NULL != ul_xw &&
2795  NULL != ul_yw
2796  ) {
2797  ul_user = 1;
2798 
2799  RASTER_DEBUGF(4, "Using user-specified upper-left corner: %f, %f", *ul_xw, *ul_yw);
2800 
2801  /* set upper-left corner */
2802  rt_raster_set_offsets(rast, *ul_xw, *ul_yw);
2803  extent.UpperLeftX = *ul_xw;
2804  extent.UpperLeftY = *ul_yw;
2805  }
2806  else if (
2807  ((NULL != ul_xw) && (NULL == ul_yw)) ||
2808  ((NULL == ul_xw) && (NULL != ul_yw))
2809  ) {
2810  rterror("rt_raster_gdal_rasterize: Both X and Y upper-left corner values must be provided");
2811 
2813  OGR_G_DestroyGeometry(src_geom);
2815  /* OGRCleanupAll(); */
2816 
2817  return NULL;
2818  }
2819 
2820  /* alignment only considered if upper-left corner not provided */
2821  if (
2822  !ul_user && (
2823  (NULL != grid_xw) || (NULL != grid_yw)
2824  )
2825  ) {
2826 
2827  if (
2828  ((NULL != grid_xw) && (NULL == grid_yw)) ||
2829  ((NULL == grid_xw) && (NULL != grid_yw))
2830  ) {
2831  rterror("rt_raster_gdal_rasterize: Both X and Y alignment values must be provided");
2832 
2834  OGR_G_DestroyGeometry(src_geom);
2836  /* OGRCleanupAll(); */
2837 
2838  return NULL;
2839  }
2840 
2841  RASTER_DEBUGF(4, "Aligning extent to user-specified grid: %f, %f", *grid_xw, *grid_yw);
2842 
2843  do {
2844  double _r[2] = {0};
2845  double _w[2] = {0};
2846 
2847  /* raster is already aligned */
2848  if (FLT_EQ(*grid_xw, extent.UpperLeftX) && FLT_EQ(*grid_yw, extent.UpperLeftY)) {
2849  RASTER_DEBUG(3, "Skipping raster alignment as it is already aligned to grid");
2850  break;
2851  }
2852 
2853  extent.UpperLeftX = rast->ipX;
2854  extent.UpperLeftY = rast->ipY;
2855  rt_raster_set_offsets(rast, *grid_xw, *grid_yw);
2856 
2857  /* process upper-left corner */
2859  rast,
2860  extent.UpperLeftX, extent.UpperLeftY,
2861  &(_r[0]), &(_r[1]),
2862  NULL
2863  ) != ES_NONE) {
2864  rterror("rt_raster_gdal_rasterize: Could not compute raster pixel for spatial coordinates");
2865 
2867  OGR_G_DestroyGeometry(src_geom);
2869  /* OGRCleanupAll(); */
2870 
2871  return NULL;
2872  }
2873 
2875  rast,
2876  _r[0], _r[1],
2877  &(_w[0]), &(_w[1]),
2878  NULL
2879  ) != ES_NONE) {
2880  rterror("rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
2881 
2883  OGR_G_DestroyGeometry(src_geom);
2885  /* OGRCleanupAll(); */
2886 
2887  return NULL;
2888  }
2889 
2890  /* shift occurred */
2891  if (FLT_NEQ(_w[0], extent.UpperLeftX)) {
2892  if (NULL == width)
2893  rast->width++;
2894  else if (NULL == scale_x) {
2895  double _c[2] = {0};
2896 
2898 
2899  /* get upper-right corner */
2901  rast,
2902  rast->width, 0,
2903  &(_c[0]), &(_c[1]),
2904  NULL
2905  ) != ES_NONE) {
2906  rterror("rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
2907 
2909  OGR_G_DestroyGeometry(src_geom);
2911  /* OGRCleanupAll(); */
2912 
2913  return NULL;
2914  }
2915 
2916  rast->scaleX = fabs((_c[0] - _w[0]) / ((double) rast->width));
2917  }
2918  }
2919  if (FLT_NEQ(_w[1], extent.UpperLeftY)) {
2920  if (NULL == height)
2921  rast->height++;
2922  else if (NULL == scale_y) {
2923  double _c[2] = {0};
2924 
2926 
2927  /* get upper-right corner */
2929  rast,
2930  0, rast->height,
2931  &(_c[0]), &(_c[1]),
2932  NULL
2933  ) != ES_NONE) {
2934  rterror("rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
2935 
2937  OGR_G_DestroyGeometry(src_geom);
2939  /* OGRCleanupAll(); */
2940 
2941  return NULL;
2942  }
2943 
2944  rast->scaleY = -1 * fabs((_c[1] - _w[1]) / ((double) rast->height));
2945  }
2946  }
2947 
2948  rt_raster_set_offsets(rast, _w[0], _w[1]);
2949  }
2950  while (0);
2951  }
2952 
2953  /*
2954  after this point, rt_envelope extent is no longer used
2955  */
2956 
2957  /* get key attributes from rast */
2958  _dim[0] = rast->width;
2959  _dim[1] = rast->height;
2961 
2962  /* scale-x is negative or scale-y is positive */
2963  if ((
2964  (NULL != scale_x) && (*scale_x < 0.)
2965  ) || (
2966  (NULL != scale_y) && (*scale_y > 0)
2967  )) {
2968  double _w[2] = {0};
2969 
2970  /* negative scale-x */
2971  if (
2972  (NULL != scale_x) &&
2973  (*scale_x < 0.)
2974  ) {
2975  RASTER_DEBUG(3, "Processing negative scale-x");
2976 
2978  rast,
2979  _dim[0], 0,
2980  &(_w[0]), &(_w[1]),
2981  NULL
2982  ) != ES_NONE) {
2983  rterror("rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
2984 
2986  OGR_G_DestroyGeometry(src_geom);
2988  /* OGRCleanupAll(); */
2989 
2990  return NULL;
2991  }
2992 
2993  _gt[0] = _w[0];
2994  _gt[1] = *scale_x;
2995 
2996  /* check for skew */
2997  if (NULL != skew_x && FLT_NEQ(*skew_x, 0.0))
2998  _gt[2] = *skew_x;
2999  }
3000  /* positive scale-y */
3001  if (
3002  (NULL != scale_y) &&
3003  (*scale_y > 0)
3004  ) {
3005  RASTER_DEBUG(3, "Processing positive scale-y");
3006 
3008  rast,
3009  0, _dim[1],
3010  &(_w[0]), &(_w[1]),
3011  NULL
3012  ) != ES_NONE) {
3013  rterror("rt_raster_gdal_rasterize: Could not compute spatial coordinates for raster pixel");
3014 
3016  OGR_G_DestroyGeometry(src_geom);
3018  /* OGRCleanupAll(); */
3019 
3020  return NULL;
3021  }
3022 
3023  _gt[3] = _w[1];
3024  _gt[5] = *scale_y;
3025 
3026  /* check for skew */
3027  if (NULL != skew_y && FLT_NEQ(*skew_y, 0.0))
3028  _gt[4] = *skew_y;
3029  }
3030  }
3031 
3033  rast = NULL;
3034 
3035  RASTER_DEBUGF(3, "Applied geotransform: %f, %f, %f, %f, %f, %f",
3036  _gt[0], _gt[1], _gt[2], _gt[3], _gt[4], _gt[5]);
3037  RASTER_DEBUGF(3, "Raster dimensions (width x height): %d x %d",
3038  _dim[0], _dim[1]);
3039 
3040  /* load GDAL mem */
3041  if (!rt_util_gdal_driver_registered("MEM")) {
3042  RASTER_DEBUG(4, "Registering MEM driver");
3043  GDALRegister_MEM();
3044  unload_drv = 1;
3045  }
3046  _drv = GDALGetDriverByName("MEM");
3047  if (NULL == _drv) {
3048  rterror("rt_raster_gdal_rasterize: Could not load the MEM GDAL driver");
3049 
3050  OGR_G_DestroyGeometry(src_geom);
3052  /* OGRCleanupAll(); */
3053 
3054  return NULL;
3055  }
3056 
3057  /* unload driver from GDAL driver manager */
3058  if (unload_drv) {
3059  RASTER_DEBUG(4, "Deregistering MEM driver");
3060  GDALDeregisterDriver(_drv);
3061  }
3062 
3063  _ds = GDALCreate(_drv, "", _dim[0], _dim[1], 0, GDT_Byte, NULL);
3064  if (NULL == _ds) {
3065  rterror("rt_raster_gdal_rasterize: Could not create a GDALDataset to rasterize the geometry into");
3066 
3067  OGR_G_DestroyGeometry(src_geom);
3069  /* OGRCleanupAll(); */
3070  if (unload_drv) GDALDestroyDriver(_drv);
3071 
3072  return NULL;
3073  }
3074 
3075  /* set geotransform */
3076  cplerr = GDALSetGeoTransform(_ds, _gt);
3077  if (cplerr != CE_None) {
3078  rterror("rt_raster_gdal_rasterize: Could not set geotransform on GDALDataset");
3079 
3080  OGR_G_DestroyGeometry(src_geom);
3082  /* OGRCleanupAll(); */
3083 
3084  GDALClose(_ds);
3085  if (unload_drv) GDALDestroyDriver(_drv);
3086 
3087  return NULL;
3088  }
3089 
3090  /* set SRS */
3091  if (NULL != arg->src_sr) {
3092  char *_srs = NULL;
3093  OSRExportToWkt(arg->src_sr, &_srs);
3094 
3095  cplerr = GDALSetProjection(_ds, _srs);
3096  CPLFree(_srs);
3097  if (cplerr != CE_None) {
3098  rterror("rt_raster_gdal_rasterize: Could not set projection on GDALDataset");
3099 
3100  OGR_G_DestroyGeometry(src_geom);
3102  /* OGRCleanupAll(); */
3103 
3104  GDALClose(_ds);
3105  if (unload_drv) GDALDestroyDriver(_drv);
3106 
3107  return NULL;
3108  }
3109  }
3110 
3111  /* set bands */
3112  for (i = 0; i < arg->numbands; i++) {
3113  err = 0;
3114 
3115  do {
3116  /* add band */
3117  cplerr = GDALAddBand(_ds, rt_util_pixtype_to_gdal_datatype(arg->pixtype[i]), NULL);
3118  if (cplerr != CE_None) {
3119  rterror("rt_raster_gdal_rasterize: Could not add band to GDALDataset");
3120  err = 1;
3121  break;
3122  }
3123 
3124  _band = GDALGetRasterBand(_ds, i + 1);
3125  if (NULL == _band) {
3126  rterror("rt_raster_gdal_rasterize: Could not get band %d from GDALDataset", i + 1);
3127  err = 1;
3128  break;
3129  }
3130 
3131  /* nodata value */
3132  if (arg->hasnodata[i]) {
3133  RASTER_DEBUGF(4, "Setting NODATA value of band %d to %f", i, arg->nodata[i]);
3134  cplerr = GDALSetRasterNoDataValue(_band, arg->nodata[i]);
3135  if (cplerr != CE_None) {
3136  rterror("rt_raster_gdal_rasterize: Could not set nodata value");
3137  err = 1;
3138  break;
3139  }
3140  RASTER_DEBUGF(4, "NODATA value set to %f", GDALGetRasterNoDataValue(_band, NULL));
3141  }
3142 
3143  /* initial value */
3144  cplerr = GDALFillRaster(_band, arg->init[i], 0);
3145  if (cplerr != CE_None) {
3146  rterror("rt_raster_gdal_rasterize: Could not set initial value");
3147  err = 1;
3148  break;
3149  }
3150  }
3151  while (0);
3152 
3153  if (err) {
3154 
3155  OGR_G_DestroyGeometry(src_geom);
3157 
3158  /* OGRCleanupAll(); */
3159 
3160  GDALClose(_ds);
3161  if (unload_drv) GDALDestroyDriver(_drv);
3162 
3163  return NULL;
3164  }
3165  }
3166 
3167  arg->bandlist = (int *) rtalloc(sizeof(int) * arg->numbands);
3168  for (i = 0; i < arg->numbands; i++) arg->bandlist[i] = i + 1;
3169 
3170  /* burn geometry */
3171  cplerr = GDALRasterizeGeometries(
3172  _ds,
3173  arg->numbands, arg->bandlist,
3174  1, &src_geom,
3175  NULL, NULL,
3176  arg->value,
3177  options,
3178  NULL, NULL
3179  );
3180  if (cplerr != CE_None) {
3181  rterror("rt_raster_gdal_rasterize: Could not rasterize geometry");
3182 
3183  OGR_G_DestroyGeometry(src_geom);
3185  /* OGRCleanupAll(); */
3186 
3187  GDALClose(_ds);
3188  if (unload_drv) GDALDestroyDriver(_drv);
3189 
3190  return NULL;
3191  }
3192 
3193  /* convert gdal dataset to raster */
3194  GDALFlushCache(_ds);
3195  RASTER_DEBUG(3, "Converting GDAL dataset to raster");
3197 
3198  OGR_G_DestroyGeometry(src_geom);
3199  /* OGRCleanupAll(); */
3200 
3201  GDALClose(_ds);
3202  if (unload_drv) GDALDestroyDriver(_drv);
3203 
3204  if (NULL == rast) {
3205  rterror("rt_raster_gdal_rasterize: Could not rasterize geometry");
3206  return NULL;
3207  }
3208 
3209  /* width, height */
3210  _width = rt_raster_get_width(rast);
3211  _height = rt_raster_get_height(rast);
3212 
3213  /* check each band for pixtype */
3214  for (i = 0; i < arg->numbands; i++) {
3215  uint8_t *data = NULL;
3216  rt_band band = NULL;
3217  rt_band oldband = NULL;
3218 
3219  double val = 0;
3220  int nodata = 0;
3221  int hasnodata = 0;
3222  double nodataval = 0;
3223  int x = 0;
3224  int y = 0;
3225 
3226  oldband = rt_raster_get_band(rast, i);
3227  if (oldband == NULL) {
3228  rterror("rt_raster_gdal_rasterize: Could not get band %d of output raster", i);
3231  return NULL;
3232  }
3233 
3234  /* band is of user-specified type */
3235  if (rt_band_get_pixtype(oldband) == arg->pixtype[i])
3236  continue;
3237 
3238  /* hasnodata, nodataval */
3239  hasnodata = rt_band_get_hasnodata_flag(oldband);
3240  if (hasnodata)
3241  rt_band_get_nodata(oldband, &nodataval);
3242 
3243  /* allocate data */
3244  data = rtalloc(rt_pixtype_size(arg->pixtype[i]) * _width * _height);
3245  if (data == NULL) {
3246  rterror("rt_raster_gdal_rasterize: Could not allocate memory for band data");
3249  return NULL;
3250  }
3251  memset(data, 0, rt_pixtype_size(arg->pixtype[i]) * _width * _height);
3252 
3253  /* create new band of correct type */
3255  _width, _height,
3256  arg->pixtype[i],
3257  hasnodata, nodataval,
3258  data
3259  );
3260  if (band == NULL) {
3261  rterror("rt_raster_gdal_rasterize: Could not create band");
3262  rtdealloc(data);
3265  return NULL;
3266  }
3267 
3268  /* give ownership of data to band */
3270 
3271  /* copy pixel by pixel */
3272  for (x = 0; x < _width; x++) {
3273  for (y = 0; y < _height; y++) {
3274  err = rt_band_get_pixel(oldband, x, y, &val, &nodata);
3275  if (err != ES_NONE) {
3276  rterror("rt_raster_gdal_rasterize: Could not get pixel value");
3280  return NULL;
3281  }
3282 
3283  if (nodata)
3284  val = nodataval;
3285 
3286  err = rt_band_set_pixel(band, x, y, val, NULL);
3287  if (err != ES_NONE) {
3288  rterror("rt_raster_gdal_rasterize: Could not set pixel value");
3292  return NULL;
3293  }
3294  }
3295  }
3296 
3297  /* replace band */
3298  oldband = rt_raster_replace_band(rast, band, i);
3299  if (oldband == NULL) {
3300  rterror("rt_raster_gdal_rasterize: Could not replace band %d of output raster", i);
3304  return NULL;
3305  }
3306 
3307  /* free oldband */
3308  rt_band_destroy(oldband);
3309  }
3310 
3312 
3313  RASTER_DEBUG(3, "done");
3314 
3315  return rast;
3316 }
3317 
3318 /******************************************************************************
3319 * rt_raster_from_two_rasters()
3320 ******************************************************************************/
3321 
3322 /*
3323  * Return raster of computed extent specified extenttype applied
3324  * on two input rasters. The raster returned should be freed by
3325  * the caller
3326  *
3327  * @param rast1 : the first raster
3328  * @param rast2 : the second raster
3329  * @param extenttype : type of extent for the output raster
3330  * @param *rtnraster : raster of computed extent
3331  * @param *offset : 4-element array indicating the X,Y offsets
3332  * for each raster. 0,1 for rast1 X,Y. 2,3 for rast2 X,Y.
3333  *
3334  * @return ES_NONE if success, ES_ERROR if error
3335  */
3338  rt_raster rast1, rt_raster rast2,
3339  rt_extenttype extenttype,
3340  rt_raster *rtnraster, double *offset
3341 ) {
3342  int i;
3343 
3344  rt_raster _rast[2] = {rast1, rast2};
3345  double _offset[2][4] = {{0.}};
3346  uint16_t _dim[2][2] = {{0}};
3347 
3348  rt_raster raster = NULL;
3349  int aligned = 0;
3350  int dim[2] = {0};
3351  double gt[6] = {0.};
3352 
3353  assert(NULL != rast1);
3354  assert(NULL != rast2);
3355  assert(NULL != rtnraster);
3356 
3357  /* set rtnraster to NULL */
3358  *rtnraster = NULL;
3359 
3360  /* rasters must be aligned */
3361  if (rt_raster_same_alignment(rast1, rast2, &aligned, NULL) != ES_NONE) {
3362  rterror("rt_raster_from_two_rasters: Could not test for alignment on the two rasters");
3363  return ES_ERROR;
3364  }
3365  if (!aligned) {
3366  rterror("rt_raster_from_two_rasters: The two rasters provided do not have the same alignment");
3367  return ES_ERROR;
3368  }
3369 
3370  /* dimensions */
3371  _dim[0][0] = rast1->width;
3372  _dim[0][1] = rast1->height;
3373  _dim[1][0] = rast2->width;
3374  _dim[1][1] = rast2->height;
3375 
3376  /* get raster offsets */
3378  _rast[1],
3379  _rast[0]->ipX, _rast[0]->ipY,
3380  &(_offset[1][0]), &(_offset[1][1]),
3381  NULL
3382  ) != ES_NONE) {
3383  rterror("rt_raster_from_two_rasters: Could not compute offsets of the second raster relative to the first raster");
3384  return ES_ERROR;
3385  }
3386  _offset[1][0] = -1 * _offset[1][0];
3387  _offset[1][1] = -1 * _offset[1][1];
3388  _offset[1][2] = _offset[1][0] + _dim[1][0] - 1;
3389  _offset[1][3] = _offset[1][1] + _dim[1][1] - 1;
3390 
3391  i = -1;
3392  switch (extenttype) {
3393  case ET_FIRST:
3394  i = 0;
3395  _offset[0][0] = 0.;
3396  _offset[0][1] = 0.;
3397  /* FALLTHROUGH */
3398  case ET_LAST:
3399  case ET_SECOND:
3400  if (i < 0) {
3401  i = 1;
3402  _offset[0][0] = -1 * _offset[1][0];
3403  _offset[0][1] = -1 * _offset[1][1];
3404  _offset[1][0] = 0.;
3405  _offset[1][1] = 0.;
3406  }
3407 
3408  dim[0] = _dim[i][0];
3409  dim[1] = _dim[i][1];
3411  dim[0],
3412  dim[1]
3413  );
3414  if (raster == NULL) {
3415  rterror("rt_raster_from_two_rasters: Could not create output raster");
3416  return ES_ERROR;
3417  }
3418  rt_raster_set_srid(raster, _rast[i]->srid);
3421  break;
3422  case ET_UNION: {
3423  double off[4] = {0};
3424 
3426  RASTER_DEBUGF(4, "gt = (%f, %f, %f, %f, %f, %f)",
3427  gt[0],
3428  gt[1],
3429  gt[2],
3430  gt[3],
3431  gt[4],
3432  gt[5]
3433  );
3434 
3435  /* new raster upper left offset */
3436  off[0] = 0;
3437  if (_offset[1][0] < 0)
3438  off[0] = _offset[1][0];
3439  off[1] = 0;
3440  if (_offset[1][1] < 0)
3441  off[1] = _offset[1][1];
3442 
3443  /* new raster lower right offset */
3444  off[2] = _dim[0][0] - 1;
3445  if ((int) _offset[1][2] >= _dim[0][0])
3446  off[2] = _offset[1][2];
3447  off[3] = _dim[0][1] - 1;
3448  if ((int) _offset[1][3] >= _dim[0][1])
3449  off[3] = _offset[1][3];
3450 
3451  /* upper left corner */
3453  _rast[0],
3454  off[0], off[1],
3455  &(gt[0]), &(gt[3]),
3456  NULL
3457  ) != ES_NONE) {
3458  rterror("rt_raster_from_two_rasters: Could not get spatial coordinates of upper-left pixel of output raster");
3459  return ES_ERROR;
3460  }
3461 
3462  dim[0] = off[2] - off[0] + 1;
3463  dim[1] = off[3] - off[1] + 1;
3464  RASTER_DEBUGF(4, "off = (%f, %f, %f, %f)",
3465  off[0],
3466  off[1],
3467  off[2],
3468  off[3]
3469  );
3470  RASTER_DEBUGF(4, "dim = (%d, %d)", dim[0], dim[1]);
3471 
3473  dim[0],
3474  dim[1]
3475  );
3476  if (raster == NULL) {
3477  rterror("rt_raster_from_two_rasters: Could not create output raster");
3478  return ES_ERROR;
3479  }
3480  rt_raster_set_srid(raster, _rast[0]->srid);
3482  RASTER_DEBUGF(4, "gt = (%f, %f, %f, %f, %f, %f)",
3483  gt[0],
3484  gt[1],
3485  gt[2],
3486  gt[3],
3487  gt[4],
3488  gt[5]
3489  );
3490 
3491  /* get offsets */
3493  _rast[0],
3494  gt[0], gt[3],
3495  &(_offset[0][0]), &(_offset[0][1]),
3496  NULL
3497  ) != ES_NONE) {
3498  rterror("rt_raster_from_two_rasters: Could not get offsets of the FIRST raster relative to the output raster");
3500  return ES_ERROR;
3501  }
3502  _offset[0][0] *= -1;
3503  _offset[0][1] *= -1;
3504 
3506  _rast[1],
3507  gt[0], gt[3],
3508  &(_offset[1][0]), &(_offset[1][1]),
3509  NULL
3510  ) != ES_NONE) {
3511  rterror("rt_raster_from_two_rasters: Could not get offsets of the SECOND raster relative to the output raster");
3513  return ES_ERROR;
3514  }
3515  _offset[1][0] *= -1;
3516  _offset[1][1] *= -1;
3517  break;
3518  }
3519  case ET_INTERSECTION: {
3520  double off[4] = {0};
3521 
3522  /* no intersection */
3523  if (
3524  (_offset[1][2] < 0 || _offset[1][0] > (_dim[0][0] - 1)) ||
3525  (_offset[1][3] < 0 || _offset[1][1] > (_dim[0][1] - 1))
3526  ) {
3527  RASTER_DEBUG(3, "The two rasters provided have no intersection. Returning no band raster");
3528 
3529  raster = rt_raster_new(0, 0);
3530  if (raster == NULL) {
3531  rterror("rt_raster_from_two_rasters: Could not create output raster");
3532  return ES_ERROR;
3533  }
3534  rt_raster_set_srid(raster, _rast[0]->srid);
3535  rt_raster_set_scale(raster, 0, 0);
3536 
3537  /* set offsets if provided */
3538  if (NULL != offset) {
3539  for (i = 0; i < 4; i++)
3540  offset[i] = _offset[i / 2][i % 2];
3541  }
3542 
3543  *rtnraster = raster;
3544  return ES_NONE;
3545  }
3546 
3547  if (_offset[1][0] > 0)
3548  off[0] = _offset[1][0];
3549  if (_offset[1][1] > 0)
3550  off[1] = _offset[1][1];
3551 
3552  off[2] = _dim[0][0] - 1;
3553  if (_offset[1][2] < _dim[0][0])
3554  off[2] = _offset[1][2];
3555  off[3] = _dim[0][1] - 1;
3556  if (_offset[1][3] < _dim[0][1])
3557  off[3] = _offset[1][3];
3558 
3559  dim[0] = off[2] - off[0] + 1;
3560  dim[1] = off[3] - off[1] + 1;
3562  dim[0],
3563  dim[1]
3564  );
3565  if (raster == NULL) {
3566  rterror("rt_raster_from_two_rasters: Could not create output raster");
3567  return ES_ERROR;
3568  }
3569  rt_raster_set_srid(raster, _rast[0]->srid);
3570 
3571  /* get upper-left corner */
3574  _rast[0],
3575  off[0], off[1],
3576  &(gt[0]), &(gt[3]),
3577  gt
3578  ) != ES_NONE) {
3579  rterror("rt_raster_from_two_rasters: Could not get spatial coordinates of upper-left pixel of output raster");
3581  return ES_ERROR;
3582  }
3583 
3585 
3586  /* get offsets */
3588  _rast[0],
3589  gt[0], gt[3],
3590  &(_offset[0][0]), &(_offset[0][1]),
3591  NULL
3592  ) != ES_NONE) {
3593  rterror("rt_raster_from_two_rasters: Could not get pixel coordinates to compute the offsets of the FIRST raster relative to the output raster");
3595  return ES_ERROR;
3596  }
3597  _offset[0][0] *= -1;
3598  _offset[0][1] *= -1;
3599 
3601  _rast[1],
3602  gt[0], gt[3],
3603  &(_offset[1][0]), &(_offset[1][1]),
3604  NULL
3605  ) != ES_NONE) {
3606  rterror("rt_raster_from_two_rasters: Could not get pixel coordinates to compute the offsets of the SECOND raster relative to the output raster");
3608  return ES_ERROR;
3609  }
3610  _offset[1][0] *= -1;
3611  _offset[1][1] *= -1;
3612  break;
3613  }
3614  case ET_CUSTOM:
3615  rterror("rt_raster_from_two_rasters: Extent type ET_CUSTOM is not supported by this function");
3616  break;
3617  }
3618 
3619  /* set offsets if provided */
3620  if (NULL != offset) {
3621  for (i = 0; i < 4; i++)
3622  offset[i] = _offset[i / 2][i % 2];
3623  }
3624 
3625  *rtnraster = raster;
3626  return ES_NONE;
3627 }
#define TRUE
Definition: dbfopen.c:73
#define FALSE
Definition: dbfopen.c:72
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
void lwgeom_geos_error(const char *fmt,...)
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1138
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:312
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:175
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:229
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
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
char * rt_util_gdal_convert_sr(const char *srs, int proj4)
Definition: rt_util.c:214
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_band.c:674
#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
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:630
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.
Definition: rt_geometry.c:803
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
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
Definition: rt_band.c:400
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
LWPOLY * rt_util_envelope_to_lwpoly(rt_envelope ext)
Definition: rt_util.c:440
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:411
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.
int value
Definition: genraster.py:62
int count
Definition: genraster.py:57
band
Definition: ovdump.py:58
src_ds
MAIN.
Definition: ovdump.py:54
data
Definition: ovdump.py:104
ds
Definition: pixval.py:67
nband
Definition: pixval.py:53
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
gt
Definition: window.py:78
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:2164
static void _rti_rasterize_arg_destroy(_rti_rasterize_arg arg)
Definition: rt_raster.c:2441
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:2491
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:1808
struct _rti_rasterize_arg_t * _rti_rasterize_arg
Definition: rt_raster.c:2398
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:3337
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:2415
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
return(psObject)
rt_pixtype * pixtype
Definition: rt_raster.c:2406
OGRSpatialReferenceH src_sr
Definition: rt_raster.c:2404
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 * long_name
Definition: librtcore.h:2475
char * create_options
Definition: librtcore.h:2476
char * short_name
Definition: librtcore.h:2474
uint8_t can_read
Definition: librtcore.h:2477
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
double ipX
Definition: librtcore.h:2296
uint16_t height
Definition: librtcore.h:2303
double scaleY
Definition: librtcore.h:2295
double ipY
Definition: librtcore.h:2297
double skewX
Definition: librtcore.h:2298