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