PostGIS  3.7.0dev-r@@SVN_REVISION@@
rt_band.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) 2018 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 // For stat64()
32 #define _LARGEFILE64_SOURCE 1
33 
34 #include <stdio.h>
35 
36 #include "librtcore.h"
37 #include "librtcore_internal.h"
38 
39 #include "cpl_vsi.h"
40 #include "gdal_vrt.h"
41 
62 rt_band
64  uint16_t width, uint16_t height,
65  rt_pixtype pixtype,
66  uint32_t hasnodata, double nodataval,
67  uint8_t* data
68 ) {
69  rt_band band = NULL;
70 
71  assert(NULL != data);
72 
73  band = rtalloc(sizeof(struct rt_band_t));
74  if (band == NULL) {
75  rterror("rt_band_new_inline: Out of memory allocating rt_band");
76  return NULL;
77  }
78 
79  RASTER_DEBUGF(3, "Created rt_band @ %p with pixtype %s", band, rt_pixtype_name(pixtype));
80 
81  band->pixtype = pixtype;
82  band->offline = 0;
83  band->width = width;
84  band->height = height;
85  band->hasnodata = hasnodata ? 1 : 0;
86  band->isnodata = FALSE; /* we don't know what is in data, so must be FALSE */
87  band->nodataval = 0;
88  band->data.mem = data;
89  band->ownsdata = 0; /* we do NOT own this data!!! */
90  band->raster = NULL;
91 
92  RASTER_DEBUGF(3, "Created rt_band with dimensions %d x %d", band->width, band->height);
93 
94  /* properly set nodataval as it may need to be constrained to the data type */
95  if (hasnodata && rt_band_set_nodata(band, nodataval, NULL) != ES_NONE) {
96  rterror("rt_band_new_inline: Could not set NODATA value");
98  return NULL;
99  }
100 
101  return band;
102 }
103 
111 void
113  rt_band band,
114  double initval
115 ) {
116  assert(band != NULL);
117  assert(band->data.mem != NULL);
118  rt_pixtype pixtype = band->pixtype;
119  uint32_t width = band->width;
120  uint32_t height = band->height;
121  uint32_t numval = width * height;
122  void *mem = band->data.mem;
123  size_t memsize = numval * rt_pixtype_size(pixtype);
124 
125  /* initialize to nodataval */
126  int32_t checkvalint = 0;
127  uint32_t checkvaluint = 0;
128  double checkvaldouble = 0;
129  float checkvalfloat = 0;
130 
131  /* initialize to zero */
132  if (FLT_EQ(initval, 0.0)) {
133  memset(mem, 0, memsize);
134  return;
135  }
136 
137  switch (pixtype) {
138  case PT_1BB:
139  {
140  uint8_t *ptr = mem;
141  uint8_t clamped_initval = rt_util_clamp_to_1BB(initval);
142  for (uint32_t i = 0; i < numval; i++)
143  ptr[i] = clamped_initval;
144  checkvalint = ptr[0];
145  break;
146  }
147  case PT_2BUI:
148  {
149  uint8_t *ptr = mem;
150  uint8_t clamped_initval = rt_util_clamp_to_2BUI(initval);
151  for (uint32_t i = 0; i < numval; i++)
152  ptr[i] = clamped_initval;
153  checkvalint = ptr[0];
154  break;
155  }
156  case PT_4BUI:
157  {
158  uint8_t *ptr = mem;
159  uint8_t clamped_initval = rt_util_clamp_to_4BUI(initval);
160  for (uint32_t i = 0; i < numval; i++)
161  ptr[i] = clamped_initval;
162  checkvalint = ptr[0];
163  break;
164  }
165  case PT_8BSI:
166  {
167  int8_t *ptr = mem;
168  int8_t clamped_initval = rt_util_clamp_to_8BSI(initval);
169  for (uint32_t i = 0; i < numval; i++)
170  ptr[i] = clamped_initval;
171  checkvalint = ptr[0];
172  break;
173  }
174  case PT_8BUI:
175  {
176  uint8_t *ptr = mem;
177  uint8_t clamped_initval = rt_util_clamp_to_8BUI(initval);
178  for (uint32_t i = 0; i < numval; i++)
179  ptr[i] = clamped_initval;
180  checkvalint = ptr[0];
181  break;
182  }
183  case PT_16BSI:
184  {
185  int16_t *ptr = mem;
186  int16_t clamped_initval = rt_util_clamp_to_16BSI(initval);
187  for (uint32_t i = 0; i < numval; i++)
188  ptr[i] = clamped_initval;
189  checkvalint = ptr[0];
190  break;
191  }
192  case PT_16BUI:
193  {
194  uint16_t *ptr = mem;
195  uint16_t clamped_initval = rt_util_clamp_to_16BUI(initval);
196  for (uint32_t i = 0; i < numval; i++)
197  ptr[i] = clamped_initval;
198  checkvalint = ptr[0];
199  break;
200  }
201  case PT_32BSI:
202  {
203  int32_t *ptr = mem;
204  int32_t clamped_initval = rt_util_clamp_to_32BSI(initval);
205  for (uint32_t i = 0; i < numval; i++)
206  ptr[i] = clamped_initval;
207  checkvalint = ptr[0];
208  break;
209  }
210  case PT_32BUI:
211  {
212  uint32_t *ptr = mem;
213  uint32_t clamped_initval = rt_util_clamp_to_32BUI(initval);
214  for (uint32_t i = 0; i < numval; i++)
215  ptr[i] = clamped_initval;
216  checkvaluint = ptr[0];
217  break;
218  }
219  case PT_32BF:
220  {
221  float *ptr = mem;
222  float clamped_initval = rt_util_clamp_to_32F(initval);
223  for (uint32_t i = 0; i < numval; i++)
224  ptr[i] = clamped_initval;
225  checkvalfloat = ptr[0];
226  break;
227  }
228  case PT_64BF:
229  {
230  double *ptr = mem;
231  for (uint32_t i = 0; i < numval; i++)
232  ptr[i] = initval;
233  checkvaldouble = ptr[0];
234  break;
235  }
236  default:
237  {
238  rterror("%s: Unknown pixeltype %d", __func__, pixtype);
239  return;
240  }
241  }
242 
243  /* Overflow checking */
245  initval,
246  checkvalint, checkvaluint,
247  checkvalfloat, checkvaldouble,
248  pixtype
249  );
250 
251  return;
252 }
253 
254 
274 rt_band
276  uint16_t width, uint16_t height,
277  rt_pixtype pixtype,
278  uint32_t hasnodata, double nodataval,
279  uint8_t bandNum, const char* path
280 ) {
281  rt_band band = NULL;
282  int pathlen = 0;
283 
284  assert(NULL != path);
285 
286  band = rtalloc(sizeof(struct rt_band_t));
287  if (band == NULL) {
288  rterror("rt_band_new_offline: Out of memory allocating rt_band");
289  return NULL;
290  }
291 
292  RASTER_DEBUGF(3, "Created rt_band @ %p with pixtype %s",
293  band, rt_pixtype_name(pixtype)
294  );
295 
296  band->pixtype = pixtype;
297  band->offline = 1;
298  band->width = width;
299  band->height = height;
300  band->hasnodata = hasnodata ? 1 : 0;
301  band->nodataval = 0;
302  band->isnodata = FALSE; /* we don't know if the offline band is NODATA */
303  band->ownsdata = 0; /* offline, flag is useless as all offline data cache is owned internally */
304  band->raster = NULL;
305 
306  /* properly set nodataval as it may need to be constrained to the data type */
307  if (hasnodata && rt_band_set_nodata(band, nodataval, NULL) != ES_NONE) {
308  rterror("rt_band_new_offline: Could not set NODATA value");
310  return NULL;
311  }
312 
313  band->data.offline.bandNum = bandNum;
314 
315  /* memory for data.offline.path is managed internally */
316  pathlen = strlen(path);
317  band->data.offline.path = rtalloc(sizeof(char) * (pathlen + 1));
318  if (band->data.offline.path == NULL) {
319  rterror("rt_band_new_offline: Out of memory allocating offline path");
321  return NULL;
322  }
323  memcpy(band->data.offline.path, path, pathlen);
324  band->data.offline.path[pathlen] = '\0';
325 
326  band->data.offline.mem = NULL;
327 
328  return band;
329 }
330 
349 rt_band
351  uint16_t width,
352  uint16_t height,
353  int hasnodata,
354  double nodataval,
355  uint8_t bandNum,
356  const char* path,
357  int force
358 ) {
359  GDALDatasetH hdsSrc = NULL;
360  int nband = 0;
361  GDALRasterBandH hbandSrc = NULL;
362 
363  GDALDataType gdpixtype;
364  rt_pixtype pt = PT_END;
365 
366  /* open outdb raster file */
368  hdsSrc = rt_util_gdal_open(path, GA_ReadOnly, 1);
369  if (hdsSrc == NULL && !force) {
370  rterror("rt_band_new_offline_from_path: Cannot open offline raster: %s", path);
371  return NULL;
372  }
373 
374  nband = GDALGetRasterCount(hdsSrc);
375  if (!nband && !force) {
376  rterror("rt_band_new_offline_from_path: No bands found in offline raster: %s", path);
377  GDALClose(hdsSrc);
378  return NULL;
379  }
380  /* bandNum is 1-based */
381  else if (bandNum > nband && !force) {
382  rterror(
383  "rt_band_new_offline_from_path: Specified band %d not found in offline raster: %s",
384  bandNum,
385  path
386  );
387  GDALClose(hdsSrc);
388  return NULL;
389  }
390 
391  hbandSrc = GDALGetRasterBand(hdsSrc, bandNum);
392  if (hbandSrc == NULL && !force) {
393  rterror(
394  "rt_band_new_offline_from_path: Cannot get band %d from GDAL dataset",
395  bandNum
396  );
397  GDALClose(hdsSrc);
398  return NULL;
399  }
400 
401  gdpixtype = GDALGetRasterDataType(hbandSrc);
402  pt = rt_util_gdal_datatype_to_pixtype(gdpixtype);
403  if (pt == PT_END && !force) {
404  rterror(
405  "rt_band_new_offline_from_path: Unsupported pixel type %s of band %d from GDAL dataset",
406  GDALGetDataTypeName(gdpixtype),
407  bandNum
408  );
409  GDALClose(hdsSrc);
410  return NULL;
411  }
412 
413  /* use out-db band's nodata value if nodataval not already set */
414  if (!hasnodata)
415  nodataval = GDALGetRasterNoDataValue(hbandSrc, &hasnodata);
416 
417  GDALClose(hdsSrc);
418 
419  return rt_band_new_offline(
420  width, height,
421  pt,
422  hasnodata, nodataval,
423  bandNum - 1, path
424  );
425 }
426 
437 rt_band
439  rt_band rtn = NULL;
440 
441  assert(band != NULL);
442 
443  /* offline */
444  if (band->offline) {
445  rtn = rt_band_new_offline(
446  band->width, band->height,
447  band->pixtype,
448  band->hasnodata, band->nodataval,
449  band->data.offline.bandNum, (const char *) band->data.offline.path
450  );
451  }
452  /* online */
453  else {
454  uint8_t *data = NULL;
455  data = rtalloc((size_t)rt_pixtype_size(band->pixtype) * band->width * band->height);
456  if (data == NULL) {
457  rterror("rt_band_duplicate: Out of memory allocating online band data");
458  return NULL;
459  }
460  memcpy(data, band->data.mem, (size_t)rt_pixtype_size(band->pixtype) * band->width * band->height);
461 
462  rtn = rt_band_new_inline(
463  band->width, band->height,
464  band->pixtype,
465  band->hasnodata, band->nodataval,
466  data
467  );
468  rt_band_set_ownsdata_flag(rtn, 1); /* we DO own this data!!! */
469  }
470 
471  if (rtn == NULL) {
472  rterror("rt_band_duplicate: Could not copy band");
473  return NULL;
474  }
475 
476  return rtn;
477 }
478 
479 int
481  assert(NULL != band);
482  return band->offline ? 1 : 0;
483 }
484 
490 void
492  if (band == NULL)
493  return;
494 
495  RASTER_DEBUGF(3, "Destroying rt_band @ %p", band);
496 
497  /* offline band */
498  if (band->offline) {
499  /* memory cache */
500  if (band->data.offline.mem != NULL)
501  rtdealloc(band->data.offline.mem);
502  /* offline file path */
503  if (band->data.offline.path != NULL)
504  rtdealloc(band->data.offline.path);
505  }
506  /* inline band and band owns the data */
507  else if (band->data.mem != NULL && band->ownsdata)
508  rtdealloc(band->data.mem);
509 
510  rtdealloc(band);
511 }
512 
513 const char*
515 
516  assert(NULL != band);
517 
518 
519  if (!band->offline) {
520  RASTER_DEBUG(3, "rt_band_get_ext_path: Band is not offline");
521  return NULL;
522  }
523  return band->data.offline.path;
524 }
525 
528  assert(NULL != band);
529  assert(NULL != bandnum);
530 
531  *bandnum = 0;
532 
533  if (!band->offline) {
534  RASTER_DEBUG(3, "rt_band_get_ext_band_num: Band is not offline");
535  return ES_ERROR;
536  }
537 
538  *bandnum = band->data.offline.bandNum;
539 
540  return ES_NONE;
541 }
542 
550 void *
552  assert(NULL != band);
553 
554  if (band->offline) {
555  if (band->data.offline.mem != NULL)
556  return band->data.offline.mem;
557 
559  return NULL;
560  else
561  return band->data.offline.mem;
562  }
563  else
564  return band->data.mem;
565 }
566 
567 /* variable for PostgreSQL GUC: postgis.enable_outdb_rasters */
569 
581  GDALDatasetH hdsSrc = NULL;
582  int nband = 0;
583  VRTDatasetH hdsDst = NULL;
584  VRTSourcedRasterBandH hbandDst = NULL;
585  double ogt[6] = {0};
586  double offset[2] = {0};
587 
588  rt_raster _rast = NULL;
589  rt_band _band = NULL;
590  int aligned = 0;
591  int err = ES_NONE;
592 
593  assert(band != NULL);
594  assert(band->raster != NULL);
595 
596  if (!band->offline) {
597  rterror("rt_band_load_offline_data: Band is not offline");
598  return ES_ERROR;
599  }
600  else if (!strlen(band->data.offline.path)) {
601  rterror("rt_band_load_offline_data: Offline band does not a have a specified file");
602  return ES_ERROR;
603  }
604 
605  /* offline_data is disabled */
606  if (!enable_outdb_rasters) {
607  rterror("rt_band_load_offline_data: Access to offline bands disabled");
608  return ES_ERROR;
609  }
610 
612  hdsSrc = rt_util_gdal_open(band->data.offline.path, GA_ReadOnly, 1);
613  if (hdsSrc == NULL) {
614  rterror("rt_band_load_offline_data: Cannot open offline raster: %s", band->data.offline.path);
615  return ES_ERROR;
616  }
617 
618  /* # of bands */
619  nband = GDALGetRasterCount(hdsSrc);
620  if (!nband) {
621  rterror("rt_band_load_offline_data: No bands found in offline raster: %s", band->data.offline.path);
622  GDALClose(hdsSrc);
623  return ES_ERROR;
624  }
625  /* bandNum is 0-based */
626  else if (band->data.offline.bandNum + 1 > nband) {
627  rterror("rt_band_load_offline_data: Specified band %d not found in offline raster: %s", band->data.offline.bandNum, band->data.offline.path);
628  GDALClose(hdsSrc);
629  return ES_ERROR;
630  }
631 
632  /* get offline raster's geotransform */
633  if (GDALGetGeoTransform(hdsSrc, ogt) != CE_None) {
634  RASTER_DEBUG(4, "Using default geotransform matrix (0, 1, 0, 0, 0, -1)");
635  ogt[0] = 0;
636  ogt[1] = 1;
637  ogt[2] = 0;
638  ogt[3] = 0;
639  ogt[4] = 0;
640  ogt[5] = -1;
641  }
642  RASTER_DEBUGF(3, "Offline geotransform (%f, %f, %f, %f, %f, %f)",
643  ogt[0], ogt[1], ogt[2], ogt[3], ogt[4], ogt[5]);
644 
645  /* are rasters aligned? */
646  _rast = rt_raster_new(1, 1);
648  rt_raster_set_srid(_rast, band->raster->srid);
649  err = rt_raster_same_alignment(band->raster, _rast, &aligned, NULL);
650  rt_raster_destroy(_rast);
651 
652  if (err != ES_NONE) {
653  rterror("rt_band_load_offline_data: Could not test alignment of in-db representation of out-db raster");
654  GDALClose(hdsSrc);
655  return ES_ERROR;
656  }
657  else if (!aligned) {
658  rtwarn("The in-db representation of the out-db raster is not aligned. Band data may be incorrect");
659  }
660 
661  /* get offsets */
663  band->raster,
664  ogt[0], ogt[3],
665  &(offset[0]), &(offset[1]),
666  NULL
667  );
668 
669  RASTER_DEBUGF(4, "offsets: (%f, %f)", offset[0], offset[1]);
670 
671  /* create VRT dataset */
672  hdsDst = VRTCreate(band->width, band->height);
673  GDALSetGeoTransform(hdsDst, ogt);
674  /*
675  GDALSetDescription(hdsDst, "/tmp/offline.vrt");
676  */
677 
678  /* add band as simple sources */
679  GDALAddBand(hdsDst, rt_util_pixtype_to_gdal_datatype(band->pixtype), NULL);
680  hbandDst = (VRTSourcedRasterBandH) GDALGetRasterBand(hdsDst, 1);
681 
682  if (band->hasnodata)
683  GDALSetRasterNoDataValue(hbandDst, band->nodataval);
684 
685  VRTAddSimpleSource(
686  hbandDst, GDALGetRasterBand(hdsSrc, band->data.offline.bandNum + 1),
687  fabs(offset[0]), fabs(offset[1]),
688  band->width, band->height,
689  0, 0,
690  band->width, band->height,
691  "near", VRT_NODATA_UNSET
692  );
693 
694  /* make sure VRT reflects all changes */
695  VRTFlushCache(hdsDst);
696 
697  /* convert VRT dataset to rt_raster */
698  _rast = rt_raster_from_gdal_dataset(hdsDst);
699 
700  GDALClose(hdsDst);
701  GDALClose(hdsSrc);
702  /*
703  {
704  FILE *fp;
705  fp = fopen("/tmp/gdal_open_files.log", "w");
706  GDALDumpOpenDatasets(fp);
707  fclose(fp);
708  }
709  */
710 
711  if (_rast == NULL) {
712  rterror("rt_band_load_offline_data: Cannot load data from offline raster: %s", band->data.offline.path);
713  return ES_ERROR;
714  }
715 
716  _band = rt_raster_get_band(_rast, 0);
717  if (_band == NULL) {
718  rterror("rt_band_load_offline_data: Cannot load data from offline raster: %s", band->data.offline.path);
719  rt_raster_destroy(_rast);
720  return ES_ERROR;
721  }
722 
723  /* band->data.offline.mem not NULL, free first */
724  if (band->data.offline.mem != NULL) {
725  rtdealloc(band->data.offline.mem);
726  band->data.offline.mem = NULL;
727  }
728 
729  band->data.offline.mem = _band->data.mem;
730 
731  rtdealloc(_band); /* cannot use rt_band_destroy */
732  rt_raster_destroy(_rast);
733 
734  return ES_NONE;
735 }
736 
738  VSIStatBufL sStat;
739 
740  assert(NULL != band);
741  if (!band->offline) {
742  rterror("rt_band_get_file_size: Band is not offline");
743  return 0;
744  }
745  /* offline_data is disabled */
746  if (!enable_outdb_rasters) {
747  rterror("rt_band_get_file_size: Access to offline bands disabled");
748  return 0;
749  }
750 
751  if( VSIStatL(band->data.offline.path, &sStat) != 0 ) {
752  rterror("rt_band_get_file_size: Cannot access file");
753  return 0;
754  }
755 
756  return sStat.st_size;
757 }
758 
760  VSIStatBufL sStat;
761 
762  assert(NULL != band);
763  if (!band->offline) {
764  rterror("rt_band_get_file_timestamp: Band is not offline");
765  return 0;
766  }
767  /* offline_data is disabled */
768  if (!enable_outdb_rasters) {
769  rterror("rt_band_get_file_timestamp: Access to offline bands disabled");
770  return 0;
771  }
772 
773  if( VSIStatL(band->data.offline.path, &sStat) != 0 ) {
774  rterror("rt_band_get_file_timestamp: Cannot access file");
775  return 0;
776  }
777 
778  return sStat.st_mtime;
779 }
780 
783 
784  assert(NULL != band);
785 
786 
787  return band->pixtype;
788 }
789 
790 uint16_t
792 
793  assert(NULL != band);
794 
795 
796  return band->width;
797 }
798 
799 uint16_t
801 
802  assert(NULL != band);
803 
804 
805  return band->height;
806 }
807 
808 /* Get ownsdata flag */
809 int
811  assert(NULL != band);
812 
813  return band->ownsdata ? 1 : 0;
814 }
815 
816 /* set ownsdata flag */
817 void
819  assert(NULL != band);
820 
821  band->ownsdata = flag ? 1 : 0;
822 }
823 
824 int
826  assert(NULL != band);
827 
828  return band->hasnodata ? 1 : 0;
829 }
830 
831 void
833 
834  assert(NULL != band);
835 
836  band->hasnodata = (flag) ? 1 : 0;
837 
838  /* isnodata depends on hasnodata */
839  if (!band->hasnodata && band->isnodata) {
840  RASTER_DEBUG(3, "Setting isnodata to FALSE as band no longer has NODATA");
841  band->isnodata = 0;
842  }
843 }
844 
847  assert(NULL != band);
848 
849  if (!band->hasnodata) {
850  /* silently permit setting isnodata flag to FALSE */
851  if (!flag)
852  band->isnodata = 0;
853  else {
854  rterror("rt_band_set_isnodata_flag: Cannot set isnodata flag as band has no NODATA");
855  return ES_ERROR;
856  }
857  }
858  else
859  band->isnodata = (flag) ? 1 : 0;
860 
861  return ES_NONE;
862 }
863 
864 int
866  assert(NULL != band);
867 
868  if (band->hasnodata)
869  return band->isnodata ? 1 : 0;
870  else
871  return 0;
872 }
873 
884 rt_band_set_nodata(rt_band band, double val, int *converted) {
885  rt_pixtype pixtype = PT_END;
886  int32_t checkvalint = 0;
887  uint32_t checkvaluint = 0;
888  float checkvalfloat = 0;
889  double checkvaldouble = 0;
890 
891  assert(NULL != band);
892 
893  if (converted != NULL)
894  *converted = 0;
895 
896  pixtype = band->pixtype;
897 
898  RASTER_DEBUGF(3, "rt_band_set_nodata: setting nodata value %g with band type %s", val, rt_pixtype_name(pixtype));
899 
900  /* return -1 on out of range */
901  switch (pixtype) {
902  case PT_1BB: {
903  band->nodataval = rt_util_clamp_to_1BB(val);
904  checkvalint = band->nodataval;
905  break;
906  }
907  case PT_2BUI: {
908  band->nodataval = rt_util_clamp_to_2BUI(val);
909  checkvalint = band->nodataval;
910  break;
911  }
912  case PT_4BUI: {
913  band->nodataval = rt_util_clamp_to_4BUI(val);
914  checkvalint = band->nodataval;
915  break;
916  }
917  case PT_8BSI: {
918  band->nodataval = rt_util_clamp_to_8BSI(val);
919  checkvalint = band->nodataval;
920  break;
921  }
922  case PT_8BUI: {
923  band->nodataval = rt_util_clamp_to_8BUI(val);
924  checkvalint = band->nodataval;
925  break;
926  }
927  case PT_16BSI: {
928  band->nodataval = rt_util_clamp_to_16BSI(val);
929  checkvalint = band->nodataval;
930  break;
931  }
932  case PT_16BUI: {
933  band->nodataval = rt_util_clamp_to_16BUI(val);
934  checkvalint = band->nodataval;
935  break;
936  }
937  case PT_32BSI: {
938  band->nodataval = rt_util_clamp_to_32BSI(val);
939  checkvalint = band->nodataval;
940  break;
941  }
942  case PT_32BUI: {
943  band->nodataval = rt_util_clamp_to_32BUI(val);
944  checkvaluint = band->nodataval;
945  break;
946  }
947  case PT_32BF: {
948  band->nodataval = rt_util_clamp_to_32F(val);
949  checkvalfloat = band->nodataval;
950  break;
951  }
952  case PT_64BF: {
953  band->nodataval = val;
954  checkvaldouble = band->nodataval;
955  break;
956  }
957  default: {
958  rterror("rt_band_set_nodata: Unknown pixeltype %d", pixtype);
959  band->hasnodata = 0;
960  return ES_ERROR;
961  }
962  }
963 
964  RASTER_DEBUGF(3, "rt_band_set_nodata: band->hasnodata = %d", band->hasnodata);
965  RASTER_DEBUGF(3, "rt_band_set_nodata: band->nodataval = %f", band->nodataval);
966  /* the nodata value was just set, so this band has NODATA */
967  band->hasnodata = 1;
968 
969  /* also set isnodata flag to false */
970  band->isnodata = 0;
971 
973  val,
974  checkvalint, checkvaluint,
975  checkvalfloat, checkvaldouble,
976  pixtype
977  ) && converted != NULL) {
978  *converted = 1;
979  }
980 
981  return ES_NONE;
982 }
983 
1005  rt_band band,
1006  int x, int y,
1007  void *vals, uint32_t len
1008 ) {
1009  rt_pixtype pixtype = PT_END;
1010  int size = 0;
1011  uint8_t *data = NULL;
1012  uint32_t offset = 0;
1013 
1014  assert(NULL != band);
1015  assert(vals != NULL && len > 0);
1016 
1017  RASTER_DEBUGF(3, "length of values = %d", len);
1018 
1019  if (band->offline) {
1020  rterror("rt_band_set_pixel_line not implemented yet for OFFDB bands");
1021  return ES_ERROR;
1022  }
1023 
1024  pixtype = band->pixtype;
1025  size = rt_pixtype_size(pixtype);
1026 
1027  if (
1028  x < 0 || x >= band->width ||
1029  y < 0 || y >= band->height
1030  ) {
1031  rterror("rt_band_set_pixel_line: Coordinates out of range (%d, %d) vs (%d, %d)", x, y, band->width, band->height);
1032  return ES_ERROR;
1033  }
1034 
1036  offset = x + (y * band->width);
1037  RASTER_DEBUGF(4, "offset = %d", offset);
1038 
1039  /* make sure len of values to copy don't exceed end of data */
1040  if (len > (band->width * band->height) - offset) {
1041  rterror("rt_band_set_pixel_line: Could not apply pixels as values length exceeds end of data");
1042  return ES_ERROR;
1043  }
1044 
1045  switch (pixtype) {
1046  case PT_1BB:
1047  case PT_2BUI:
1048  case PT_4BUI:
1049  case PT_8BUI:
1050  case PT_8BSI: {
1051  uint8_t *ptr = data;
1052  ptr += offset;
1053  memcpy(ptr, vals, (size_t)size * len);
1054  break;
1055  }
1056  case PT_16BUI: {
1057  uint16_t *ptr = (uint16_t *) data;
1058  ptr += offset;
1059  memcpy(ptr, vals, (size_t)size * len);
1060  break;
1061  }
1062  case PT_16BSI: {
1063  int16_t *ptr = (int16_t *) data;
1064  ptr += offset;
1065  memcpy(ptr, vals, (size_t)size * len);
1066  break;
1067  }
1068  case PT_32BUI: {
1069  uint32_t *ptr = (uint32_t *) data;
1070  ptr += offset;
1071  memcpy(ptr, vals, (size_t)size * len);
1072  break;
1073  }
1074  case PT_32BSI: {
1075  int32_t *ptr = (int32_t *) data;
1076  ptr += offset;
1077  memcpy(ptr, vals, (size_t)size * len);
1078  break;
1079  }
1080  case PT_32BF: {
1081  float *ptr = (float *) data;
1082  ptr += offset;
1083  memcpy(ptr, vals, (size_t)size * len);
1084  break;
1085  }
1086  case PT_64BF: {
1087  double *ptr = (double *) data;
1088  ptr += offset;
1089  memcpy(ptr, vals, (size_t)size * len);
1090  break;
1091  }
1092  default: {
1093  rterror("rt_band_set_pixel_line: Unknown pixeltype %d", pixtype);
1094  return ES_ERROR;
1095  }
1096  }
1097 
1098 #if POSTGIS_DEBUG_LEVEL > 0
1099  {
1100  double value;
1101  rt_band_get_pixel(band, x, y, &value, NULL);
1102  RASTER_DEBUGF(4, "pixel at (%d, %d) = %f", x, y, value);
1103  }
1104 #endif
1105 
1106  /* set band's isnodata flag to FALSE */
1109 
1110  return ES_NONE;
1111 }
1112 
1126  rt_band band,
1127  int x, int y,
1128  double val,
1129  int *converted
1130 ) {
1131  rt_pixtype pixtype = PT_END;
1132  uint8_t *data = NULL;
1133  uint32_t offset = 0;
1134 
1135  int32_t checkvalint = 0;
1136  uint32_t checkvaluint = 0;
1137  float checkvalfloat = 0;
1138  double checkvaldouble = 0;
1139 
1140  assert(NULL != band);
1141 
1142  if (converted != NULL)
1143  *converted = 0;
1144 
1145  if (band->offline) {
1146  rterror("rt_band_set_pixel not implemented yet for OFFDB bands");
1147  return ES_ERROR;
1148  }
1149 
1150  pixtype = band->pixtype;
1151 
1152  if (
1153  x < 0 || x >= band->width ||
1154  y < 0 || y >= band->height
1155  ) {
1156  rterror("rt_band_set_pixel: Coordinates out of range");
1157  return ES_ERROR;
1158  }
1159 
1160  /* check that clamped value isn't clamped NODATA */
1161  if (band->hasnodata && pixtype != PT_64BF) {
1162  double newval;
1163  int corrected;
1164 
1165  rt_band_corrected_clamped_value(band, val, &newval, &corrected);
1166 
1167  if (corrected) {
1168 #if POSTGIS_RASTER_WARN_ON_TRUNCATION > 0
1169  rtwarn("Value for pixel %d x %d has been corrected as clamped value becomes NODATA", x, y);
1170 #endif
1171  val = newval;
1172 
1173  if (converted != NULL)
1174  *converted = 1;
1175  }
1176  }
1177 
1179  offset = x + (y * band->width);
1180 
1181  switch (pixtype) {
1182  case PT_1BB: {
1183  data[offset] = rt_util_clamp_to_1BB(val);
1184  checkvalint = data[offset];
1185  break;
1186  }
1187  case PT_2BUI: {
1188  data[offset] = rt_util_clamp_to_2BUI(val);
1189  checkvalint = data[offset];
1190  break;
1191  }
1192  case PT_4BUI: {
1193  data[offset] = rt_util_clamp_to_4BUI(val);
1194  checkvalint = data[offset];
1195  break;
1196  }
1197  case PT_8BSI: {
1198  data[offset] = (uint8_t)rt_util_clamp_to_8BSI(val);
1199  checkvalint = (int8_t) data[offset];
1200  break;
1201  }
1202  case PT_8BUI: {
1203  data[offset] = rt_util_clamp_to_8BUI(val);
1204  checkvalint = data[offset];
1205  break;
1206  }
1207  case PT_16BSI: {
1208  int16_t *ptr = (int16_t*) data; /* we assume correct alignment */
1209  ptr[offset] = rt_util_clamp_to_16BSI(val);
1210  checkvalint = (int16_t) ptr[offset];
1211  break;
1212  }
1213  case PT_16BUI: {
1214  uint16_t *ptr = (uint16_t*) data; /* we assume correct alignment */
1215  ptr[offset] = rt_util_clamp_to_16BUI(val);
1216  checkvalint = ptr[offset];
1217  break;
1218  }
1219  case PT_32BSI: {
1220  int32_t *ptr = (int32_t*) data; /* we assume correct alignment */
1221  ptr[offset] = rt_util_clamp_to_32BSI(val);
1222  checkvalint = (int32_t) ptr[offset];
1223  break;
1224  }
1225  case PT_32BUI: {
1226  uint32_t *ptr = (uint32_t*) data; /* we assume correct alignment */
1227  ptr[offset] = rt_util_clamp_to_32BUI(val);
1228  checkvaluint = ptr[offset];
1229  break;
1230  }
1231  case PT_32BF: {
1232  float *ptr = (float*) data; /* we assume correct alignment */
1233  ptr[offset] = rt_util_clamp_to_32F(val);
1234  checkvalfloat = ptr[offset];
1235  break;
1236  }
1237  case PT_64BF: {
1238  double *ptr = (double*) data; /* we assume correct alignment */
1239  ptr[offset] = val;
1240  checkvaldouble = ptr[offset];
1241  break;
1242  }
1243  default: {
1244  rterror("rt_band_set_pixel: Unknown pixeltype %d", pixtype);
1245  return ES_ERROR;
1246  }
1247  }
1248 
1249  /* If the stored value is not NODATA, reset the isnodata flag */
1251  RASTER_DEBUG(3, "Band has a value that is not NODATA. Setting isnodata to FALSE");
1252  band->isnodata = FALSE;
1253  }
1254 
1255  /* Overflow checking */
1257  val,
1258  checkvalint, checkvaluint,
1259  checkvalfloat, checkvaldouble,
1260  pixtype
1261  ) && converted != NULL) {
1262  *converted = 1;
1263  }
1264 
1265  return ES_NONE;
1266 }
1267 
1289  rt_band band,
1290  int x, int y,
1291  uint16_t len,
1292  void **vals, uint16_t *nvals
1293 ) {
1294  uint8_t *_vals = NULL;
1295  int pixsize = 0;
1296  uint8_t *data = NULL;
1297  uint32_t offset = 0;
1298  uint16_t _nvals = 0;
1299  int maxlen = 0;
1300  uint8_t *ptr = NULL;
1301 
1302  assert(NULL != band);
1303  assert(vals != NULL && nvals != NULL);
1304 
1305  /* initialize to no values */
1306  *nvals = 0;
1307 
1308  if (
1309  x < 0 || x >= band->width ||
1310  y < 0 || y >= band->height
1311  ) {
1312  rtwarn("Attempting to get pixel values with out of range raster coordinates: (%d, %d)", x, y);
1313  return ES_ERROR;
1314  }
1315 
1316  if (len < 1)
1317  return ES_NONE;
1318 
1320  if (data == NULL) {
1321  rterror("rt_band_get_pixel_line: Cannot get band data");
1322  return ES_ERROR;
1323  }
1324 
1325  /* +1 for the nodata value */
1326  offset = x + (y * band->width);
1327  RASTER_DEBUGF(4, "offset = %d", offset);
1328 
1329  pixsize = rt_pixtype_size(band->pixtype);
1330  RASTER_DEBUGF(4, "pixsize = %d", pixsize);
1331 
1332  /* cap _nvals so that it doesn't overflow */
1333  _nvals = len;
1334  maxlen = band->width * band->height;
1335 
1336  if (((int) (offset + _nvals)) > maxlen) {
1337  _nvals = maxlen - offset;
1338  rtwarn("Limiting returning number values to %d", _nvals);
1339  }
1340  RASTER_DEBUGF(4, "_nvals = %d", _nvals);
1341 
1342  ptr = data + ((size_t)offset * pixsize);
1343 
1344  _vals = rtalloc((size_t)_nvals * pixsize);
1345  if (_vals == NULL) {
1346  rterror("rt_band_get_pixel_line: Could not allocate memory for pixel values");
1347  return ES_ERROR;
1348  }
1349 
1350  /* copy pixels */
1351  memcpy(_vals, ptr, (size_t)_nvals * pixsize);
1352 
1353  *vals = _vals;
1354  *nvals = _nvals;
1355 
1356  return ES_NONE;
1357 }
1358 
1373  rt_band band,
1374  double xr, double yr,
1375  rt_resample_type resample,
1376  double *r_value, int *r_nodata
1377 )
1378 {
1379  if (resample == RT_BILINEAR) {
1381  band, xr, yr, r_value, r_nodata
1382  );
1383  }
1384  else if (resample == RT_NEAREST) {
1385  return rt_band_get_pixel(
1386  band, floor(xr), floor(yr),
1387  r_value, r_nodata
1388  );
1389  }
1390  else {
1391  rtwarn("Invalid resample type requested %d", resample);
1392  return ES_ERROR;
1393  }
1394 
1395 }
1396 
1412  rt_band band,
1413  double xr, double yr,
1414  double *r_value, int *r_nodata)
1415 {
1416  double xcenter, ycenter;
1417  double values[2][2];
1418  double nodatavalue = 0.0;
1419  int nodatas[2][2];
1420  int x[2][2];
1421  int y[2][2];
1422  int xcell, ycell;
1423  int xdir, ydir;
1424  int i, j;
1425  uint16_t width, height;
1426 
1427  /* Cell coordinates */
1428  xcell = (int)floor(xr);
1429  ycell = (int)floor(yr);
1430  xcenter = xcell + 0.5;
1431  ycenter = ycell + 0.5;
1432 
1433  /* Raster geometry */
1434  width = rt_band_get_width(band);
1435  height = rt_band_get_height(band);
1436 
1437  /* Reject out-of-range sample */
1438  if(xcell < 0 || ycell < 0 || xcell >= width || ycell >= height) {
1439  rtwarn("Attempting to get pixel value with out of range raster coordinates: (%d, %d)", xcell, ycell);
1440  return ES_ERROR;
1441  }
1442 
1443  /* Quadrant of 2x2 grid the raster coordinate falls in */
1444  xdir = xr < xcenter ? 1 : 0;
1445  ydir = yr < ycenter ? 1 : 0;
1446 
1448  rt_band_get_nodata(band, &nodatavalue);
1449  }
1450  else {
1451  nodatavalue = 0.0;
1452  }
1453 
1454  /* Read the 2x2 values from the band */
1455  for (i = 0; i < 2; i++) {
1456  for (j = 0; j < 2; j++) {
1457  double value = nodatavalue;
1458  int nodata = 0;
1459  int xij = xcell + (i - xdir);
1460  int yij = ycell + (j - ydir);
1461 
1462  if(xij < 0 || yij < 0 || xij >= width || yij >= height) {
1463  nodata = 1;
1464  }
1465  else {
1467  band, xij, yij,
1468  &value, &nodata
1469  );
1470  if (err != ES_NONE)
1471  nodata = 1;
1472  }
1473  x[i][j] = xij;
1474  y[i][j] = yij;
1475  values[i][j] = value;
1476  nodatas[i][j] = nodata;
1477  }
1478  }
1479 
1480  /* Point falls in nodata cell, just return nodata */
1481  if (nodatas[xdir][ydir]) {
1482  *r_value = nodatavalue;
1483  *r_nodata = 1;
1484  return ES_NONE;
1485  }
1486 
1487  /* Normalize raster coordinate to the bottom left */
1488  /* so we are working on a unit square */
1489  xr = xr - (x[0][0] + 0.5);
1490  yr = yr - (y[0][0] + 0.5);
1491 
1492  /* Point is in cell with values, so we take nodata */
1493  /* neighbors off the table by matching them to the */
1494  /* most controlling cell */
1495  for (i = 0; i < 2; i++) {
1496  for (j = 0; j < 2; j++) {
1497  if (nodatas[i][j])
1498  values[i][j] = values[xdir][ydir];
1499  }
1500  }
1501 
1502  /* Calculate bilinear value */
1503  /* https://en.wikipedia.org/wiki/Bilinear_interpolation#Unit_square */
1504  *r_nodata = 0;
1505  *r_value = values[0][0] * (1-xr) * (1-yr) +
1506  values[1][0] * (1-yr) * xr +
1507  values[0][1] * (1-xr) * yr +
1508  values[1][1] * xr * yr;
1509 
1510  return ES_NONE;
1511 }
1512 
1513 
1528  rt_band band,
1529  int x, int y,
1530  double *value,
1531  int *nodata
1532 ) {
1533  rt_pixtype pixtype = PT_END;
1534  uint8_t* data = NULL;
1535  uint32_t offset = 0;
1536 
1537  assert(NULL != band);
1538  assert(NULL != value);
1539 
1540  /* set nodata to 0 */
1541  if (nodata != NULL)
1542  *nodata = 0;
1543 
1544  if (
1545  x < 0 || x >= band->width ||
1546  y < 0 || y >= band->height
1547  ) {
1548  rtwarn("Attempting to get pixel value with out of range raster coordinates: (%d, %d)", x, y);
1549  return ES_ERROR;
1550  }
1551 
1552  /* band is NODATA */
1553  if (band->isnodata) {
1554  RASTER_DEBUG(3, "Band's isnodata flag is TRUE. Returning NODATA value");
1555  *value = band->nodataval;
1556  if (nodata != NULL) *nodata = 1;
1557  return ES_NONE;
1558  }
1559 
1561  if (data == NULL) {
1562  rterror("rt_band_get_pixel: Cannot get band data");
1563  return ES_ERROR;
1564  }
1565 
1566  /* +1 for the nodata value */
1567  offset = x + (y * band->width);
1568 
1569  pixtype = band->pixtype;
1570 
1571  switch (pixtype) {
1572  case PT_1BB:
1573 #ifdef OPTIMIZE_SPACE
1574  {
1575  int byteOffset = offset / 8;
1576  int bitOffset = offset % 8;
1577  data += byteOffset;
1578 
1579  /* Bit to set is bitOffset into data */
1580  *value = getBits(data, val, 1, bitOffset);
1581  break;
1582  }
1583 #endif
1584  case PT_2BUI:
1585 #ifdef OPTIMIZE_SPACE
1586  {
1587  int byteOffset = offset / 4;
1588  int bitOffset = offset % 4;
1589  data += byteOffset;
1590 
1591  /* Bits to set start at bitOffset into data */
1592  *value = getBits(data, val, 2, bitOffset);
1593  break;
1594  }
1595 #endif
1596  case PT_4BUI:
1597 #ifdef OPTIMIZE_SPACE
1598  {
1599  int byteOffset = offset / 2;
1600  int bitOffset = offset % 2;
1601  data += byteOffset;
1602 
1603  /* Bits to set start at bitOffset into data */
1604  *value = getBits(data, val, 2, bitOffset);
1605  break;
1606  }
1607 #endif
1608  case PT_8BSI: {
1609  int8_t val = (int8_t)data[offset];
1610  *value = val;
1611  break;
1612  }
1613  case PT_8BUI: {
1614  uint8_t val = data[offset];
1615  *value = val;
1616  break;
1617  }
1618  case PT_16BSI: {
1619  int16_t *ptr = (int16_t*) data; /* we assume correct alignment */
1620  *value = ptr[offset];
1621  break;
1622  }
1623  case PT_16BUI: {
1624  uint16_t *ptr = (uint16_t*) data; /* we assume correct alignment */
1625  *value = ptr[offset];
1626  break;
1627  }
1628  case PT_32BSI: {
1629  int32_t *ptr = (int32_t*) data; /* we assume correct alignment */
1630  *value = ptr[offset];
1631  break;
1632  }
1633  case PT_32BUI: {
1634  uint32_t *ptr = (uint32_t*) data; /* we assume correct alignment */
1635  *value = ptr[offset];
1636  break;
1637  }
1638  case PT_32BF: {
1639  float *ptr = (float*) data; /* we assume correct alignment */
1640  *value = ptr[offset];
1641  break;
1642  }
1643  case PT_64BF: {
1644  double *ptr = (double*) data; /* we assume correct alignment */
1645  *value = ptr[offset];
1646  break;
1647  }
1648  default: {
1649  rterror("rt_band_get_pixel: Unknown pixeltype %d", pixtype);
1650  return ES_ERROR;
1651  }
1652  }
1653 
1654  /* set NODATA flag */
1655  if (band->hasnodata && nodata != NULL) {
1657  *nodata = 1;
1658  }
1659 
1660  return ES_NONE;
1661 }
1662 
1681  rt_band band,
1682  int x, int y,
1683  uint16_t distancex, uint16_t distancey,
1684  int exclude_nodata_value,
1685  rt_pixel *npixels
1686 ) {
1687  rt_pixel npixel = NULL;
1688  int extent[4] = {0};
1689  int max_extent[4] = {0};
1690  int d0 = 0;
1691  uint32_t distance[2] = {0};
1692  uint32_t _d[2] = {0};
1693  uint32_t i = 0;
1694  uint32_t j = 0;
1695  uint32_t k = 0;
1696  int _max = 0;
1697  int _x = 0;
1698  int _y = 0;
1699  int *_min = NULL;
1700  double pixval = 0;
1701  double minval = 0;
1702  uint32_t count = 0;
1703  int isnodata = 0;
1704 
1705  int inextent = 0;
1706 
1707  assert(NULL != band);
1708  assert(NULL != npixels);
1709 
1710  RASTER_DEBUG(3, "Starting");
1711 
1712  /* process distance */
1713  distance[0] = distancex;
1714  distance[1] = distancey;
1715 
1716  /* no distance, means get nearest pixels and return */
1717  if (!distance[0] && !distance[1])
1718  d0 = 1;
1719 
1720  RASTER_DEBUGF(4, "Selected pixel: %d x %d", x, y);
1721  RASTER_DEBUGF(4, "Distances: %d x %d", distance[0], distance[1]);
1722 
1723  /* shortcuts if outside band extent */
1724  if (
1725  exclude_nodata_value && (
1726  (x < 0 || x > band->width) ||
1727  (y < 0 || y > band->height)
1728  )
1729  ) {
1730  /* no distances specified, jump to pixel close to extent */
1731  if (d0) {
1732  if (x < 0)
1733  x = -1;
1734  else if (x > band->width)
1735  x = band->width;
1736 
1737  if (y < 0)
1738  y = -1;
1739  else if (y > band->height)
1740  y = band->height;
1741 
1742  RASTER_DEBUGF(4, "Moved selected pixel: %d x %d", x, y);
1743  }
1744  /*
1745  distances specified
1746  if distances won't capture extent of band, return 0
1747  */
1748  else if (
1749  ((x < 0 && (uint32_t) abs(x) > distance[0]) || (x - band->width >= (int)distance[0])) ||
1750  ((y < 0 && (uint32_t) abs(y) > distance[1]) || (y - band->height >= (int)distance[1]))
1751  ) {
1752  RASTER_DEBUG(4, "No nearest pixels possible for provided pixel and distances");
1753  return 0;
1754  }
1755  }
1756 
1757  /* no NODATA, exclude is FALSE */
1758  if (!band->hasnodata)
1759  exclude_nodata_value = FALSE;
1760  /* band is NODATA and excluding NODATA */
1761  else if (exclude_nodata_value && band->isnodata) {
1762  RASTER_DEBUG(4, "No nearest pixels possible as band is NODATA and excluding NODATA values");
1763  return 0;
1764  }
1765 
1766  /* determine the maximum distance to prevent an infinite loop */
1767  if (d0) {
1768  int a, b;
1769 
1770  /* X axis */
1771  a = abs(x);
1772  b = abs(x - band->width);
1773 
1774  if (a > b)
1775  distance[0] = a;
1776  else
1777  distance[0] = b;
1778 
1779  /* Y axis */
1780  a = abs(y);
1781  b = abs(y - band->height);
1782  if (a > b)
1783  distance[1] = a;
1784  else
1785  distance[1] = b;
1786 
1787  RASTER_DEBUGF(4, "Maximum distances: %d x %d", distance[0], distance[1]);
1788  }
1789 
1790  /* minimum possible value for pixel type */
1791  minval = rt_pixtype_get_min_value(band->pixtype);
1792  RASTER_DEBUGF(4, "pixtype: %s", rt_pixtype_name(band->pixtype));
1793  RASTER_DEBUGF(4, "minval: %f", minval);
1794 
1795  /* set variables */
1796  count = 0;
1797  *npixels = NULL;
1798 
1799  /* maximum extent */
1800  max_extent[0] = x - (int)distance[0]; /* min X */
1801  max_extent[1] = y - (int)distance[1]; /* min Y */
1802  max_extent[2] = x + (int)distance[0]; /* max X */
1803  max_extent[3] = y + (int)distance[1]; /* max Y */
1804  RASTER_DEBUGF(4, "Maximum Extent: (%d, %d, %d, %d)",
1805  max_extent[0], max_extent[1], max_extent[2], max_extent[3]);
1806 
1807  _d[0] = 0;
1808  _d[1] = 0;
1809  do {
1810  _d[0]++;
1811  _d[1]++;
1812 
1813  extent[0] = x - (int)_d[0]; /* min x */
1814  extent[1] = y - (int)_d[1]; /* min y */
1815  extent[2] = x + (int)_d[0]; /* max x */
1816  extent[3] = y + (int)_d[1]; /* max y */
1817 
1818  RASTER_DEBUGF(4, "Processing distances: %d x %d", _d[0], _d[1]);
1819  RASTER_DEBUGF(4, "Extent: (%d, %d, %d, %d)",
1820  extent[0], extent[1], extent[2], extent[3]);
1821 
1822  for (i = 0; i < 2; i++) {
1823 
1824  /* by row */
1825  if (i < 1)
1826  _max = extent[2] - extent[0] + 1;
1827  /* by column */
1828  else
1829  _max = extent[3] - extent[1] + 1;
1830  _max = abs(_max);
1831 
1832  for (j = 0; j < 2; j++) {
1833  /* by row */
1834  if (i < 1) {
1835  _x = extent[0];
1836  _min = &_x;
1837 
1838  /* top row */
1839  if (j < 1)
1840  _y = extent[1];
1841  /* bottom row */
1842  else
1843  _y = extent[3];
1844  }
1845  /* by column */
1846  else {
1847  _y = extent[1] + 1;
1848  _min = &_y;
1849 
1850  /* left column */
1851  if (j < 1) {
1852  _x = extent[0];
1853  _max -= 2;
1854  }
1855  /* right column */
1856  else
1857  _x = extent[2];
1858  }
1859 
1860  RASTER_DEBUGF(4, "_min, _max: %d, %d", *_min, _max);
1861  for (k = 0; k < (uint32_t) _max; k++) {
1862  /* check that _x and _y are not outside max extent */
1863  if (
1864  _x < max_extent[0] || _x > max_extent[2] ||
1865  _y < max_extent[1] || _y > max_extent[3]
1866  ) {
1867  (*_min)++;
1868  continue;
1869  }
1870 
1871  /* outside band extent, set to NODATA */
1872  if (
1873  (_x < 0 || _x >= band->width) ||
1874  (_y < 0 || _y >= band->height)
1875  ) {
1876  /* no NODATA, set to minimum possible value */
1877  if (!band->hasnodata)
1878  pixval = minval;
1879  /* has NODATA, use NODATA */
1880  else
1881  pixval = band->nodataval;
1882  RASTER_DEBUGF(4, "NODATA pixel outside band extent: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1883  inextent = 0;
1884  isnodata = 1;
1885  }
1886  else {
1887  if (rt_band_get_pixel(
1888  band,
1889  _x, _y,
1890  &pixval,
1891  &isnodata
1892  ) != ES_NONE) {
1893  rterror("rt_band_get_nearest_pixel: Could not get pixel value");
1894  if (count) rtdealloc(*npixels);
1895  return -1;
1896  }
1897  RASTER_DEBUGF(4, "Pixel: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1898  inextent = 1;
1899  }
1900 
1901  /* use pixval? */
1902  if (!exclude_nodata_value || (exclude_nodata_value && !isnodata)) {
1903  /* add pixel to result set */
1904  RASTER_DEBUGF(4, "Adding pixel to set of nearest pixels: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1905  count++;
1906 
1907  if (*npixels == NULL)
1908  *npixels = (rt_pixel) rtalloc(sizeof(struct rt_pixel_t) * count);
1909  else
1910  *npixels = (rt_pixel) rtrealloc(*npixels, sizeof(struct rt_pixel_t) * count);
1911  if (*npixels == NULL) {
1912  rterror("rt_band_get_nearest_pixel: Could not allocate memory for nearest pixel(s)");
1913  return -1;
1914  }
1915 
1916  npixel = &((*npixels)[count - 1]);
1917  npixel->x = _x;
1918  npixel->y = _y;
1919  npixel->value = pixval;
1920 
1921  /* special case for when outside band extent */
1922  if (!inextent && !band->hasnodata)
1923  npixel->nodata = 1;
1924  else
1925  npixel->nodata = 0;
1926  }
1927 
1928  (*_min)++;
1929  }
1930  }
1931  }
1932 
1933  /* distance thresholds met */
1934  if (_d[0] >= distance[0] && _d[1] >= distance[1])
1935  break;
1936  else if (d0 && count)
1937  break;
1938  }
1939  while (1);
1940 
1941  RASTER_DEBUGF(3, "Nearest pixels in return: %d", count);
1942 
1943  return count;
1944 }
1945 
1946 
1947 
1959 int
1961  rt_band band, int exclude_nodata_value,
1962  double *searchset, int searchcount,
1963  rt_pixel *pixels
1964 ) {
1965  int x;
1966  int y;
1967  int i;
1968  double pixval;
1969  int err;
1970  int count = 0;
1971  int isnodata = 0;
1972  int isequal = 0;
1973 
1974  rt_pixel pixel = NULL;
1975 
1976  assert(NULL != band);
1977  assert(NULL != pixels);
1978  assert(NULL != searchset && searchcount > 0);
1979 
1980  if (!band->hasnodata)
1981  exclude_nodata_value = FALSE;
1982  /* band is NODATA and exclude_nodata_value = TRUE, nothing to search */
1983  else if (exclude_nodata_value && band->isnodata) {
1984  RASTER_DEBUG(4, "Pixels cannot be searched as band is NODATA and excluding NODATA values");
1985  return 0;
1986  }
1987 
1988  for (x = 0; x < band->width; x++) {
1989  for (y = 0; y < band->height; y++) {
1990  err = rt_band_get_pixel(band, x, y, &pixval, &isnodata);
1991  if (err != ES_NONE) {
1992  rterror("rt_band_get_pixel_of_value: Cannot get band pixel");
1993  return -1;
1994  }
1995  else if (exclude_nodata_value && isnodata)
1996  continue;
1997 
1998  for (i = 0; i < searchcount; i++) {
1999  if (rt_pixtype_compare_clamped_values(band->pixtype, searchset[i], pixval, &isequal) != ES_NONE) {
2000  continue;
2001  }
2002 
2003  if (FLT_NEQ(pixval, searchset[i]) || !isequal)
2004  continue;
2005 
2006  /* match found */
2007  count++;
2008  if (*pixels == NULL)
2009  *pixels = (rt_pixel) rtalloc(sizeof(struct rt_pixel_t) * count);
2010  else
2011  *pixels = (rt_pixel) rtrealloc(*pixels, sizeof(struct rt_pixel_t) * count);
2012  if (*pixels == NULL) {
2013  rterror("rt_band_get_pixel_of_value: Could not allocate memory for pixel(s)");
2014  return -1;
2015  }
2016 
2017  pixel = &((*pixels)[count - 1]);
2018  pixel->x = x;
2019  pixel->y = y;
2020  pixel->nodata = 0;
2021  pixel->value = pixval;
2022  }
2023  }
2024  }
2025 
2026  return count;
2027 }
2028 
2038 rt_band_get_nodata(rt_band band, double *nodata) {
2039  assert(NULL != band);
2040  assert(NULL != nodata);
2041 
2042  *nodata = band->nodataval;
2043 
2044  if (!band->hasnodata) {
2045  rterror("rt_band_get_nodata: Band has no NODATA value");
2046  return ES_ERROR;
2047  }
2048 
2049  return ES_NONE;
2050 }
2051 
2052 double
2054  assert(NULL != band);
2055 
2056  return rt_pixtype_get_min_value(band->pixtype);
2057 }
2058 
2059 int
2061  int i, j, err;
2062  double pxValue;
2063  int isnodata = 0;
2064 
2065  assert(NULL != band);
2066  band->isnodata = FALSE;
2067 
2068  /* Check if band has nodata value */
2069  if (!band->hasnodata) {
2070  RASTER_DEBUG(3, "Band has no NODATA value");
2071  return FALSE;
2072  }
2073 
2074  pxValue = band->nodataval;
2075 
2076  /* Check all pixels */
2077  for (i = 0; i < band->width; i++) {
2078  for (j = 0; j < band->height; j++) {
2079  err = rt_band_get_pixel(band, i, j, &pxValue, &isnodata);
2080  if (err != ES_NONE) {
2081  rterror("rt_band_check_is_nodata: Cannot get band pixel");
2082  return FALSE;
2083  }
2084  else if (!isnodata) {
2085  band->isnodata = FALSE;
2086  return FALSE;
2087  }
2088  }
2089  }
2090 
2091  band->isnodata = TRUE;
2092  return TRUE;
2093 }
2094 
2105 int
2107  int isequal = 0;
2108 
2109  assert(NULL != band);
2110 
2111  /* no NODATA, so never equal */
2112  if (!band->hasnodata)
2113  return 0;
2114 
2115  /* value is exactly NODATA */
2116  if (FLT_EQ(val, band->nodataval))
2117  return 2;
2118 
2119  /* ignore error from rt_pixtype_compare_clamped_values */
2121  band->pixtype,
2122  val, band->nodataval,
2123  &isequal
2124  );
2125 
2126  return isequal ? 1 : 0;
2127 }
2128 
2143  rt_band band,
2144  double val,
2145  double *newval, int *corrected
2146 ) {
2147  double minval = 0.;
2148 
2149  assert(NULL != band);
2150  assert(NULL != newval);
2151 
2152  if (corrected != NULL)
2153  *corrected = 0;
2154 
2155  /* no need to correct if clamped values IS NOT clamped NODATA */
2156  if (rt_band_clamped_value_is_nodata(band, val) != 1) {
2157  *newval = val;
2158  return ES_NONE;
2159  }
2160 
2161  minval = rt_pixtype_get_min_value(band->pixtype);
2162  *newval = val;
2163 
2164  switch (band->pixtype) {
2165  case PT_1BB:
2166  *newval = !band->nodataval;
2167  break;
2168  case PT_2BUI:
2169  if (rt_util_clamp_to_2BUI(val) == rt_util_clamp_to_2BUI(minval))
2170  (*newval)++;
2171  else
2172  (*newval)--;
2173  break;
2174  case PT_4BUI:
2175  if (rt_util_clamp_to_4BUI(val) == rt_util_clamp_to_4BUI(minval))
2176  (*newval)++;
2177  else
2178  (*newval)--;
2179  break;
2180  case PT_8BSI:
2181  if (rt_util_clamp_to_8BSI(val) == rt_util_clamp_to_8BSI(minval))
2182  (*newval)++;
2183  else
2184  (*newval)--;
2185  break;
2186  case PT_8BUI:
2187  if (rt_util_clamp_to_8BUI(val) == rt_util_clamp_to_8BUI(minval))
2188  (*newval)++;
2189  else
2190  (*newval)--;
2191  break;
2192  case PT_16BSI:
2193  if (rt_util_clamp_to_16BSI(val) == rt_util_clamp_to_16BSI(minval))
2194  (*newval)++;
2195  else
2196  (*newval)--;
2197  break;
2198  case PT_16BUI:
2199  if (rt_util_clamp_to_16BUI(val) == rt_util_clamp_to_16BUI(minval))
2200  (*newval)++;
2201  else
2202  (*newval)--;
2203  break;
2204  case PT_32BSI:
2205  if (rt_util_clamp_to_32BSI(val) == rt_util_clamp_to_32BSI(minval))
2206  (*newval)++;
2207  else
2208  (*newval)--;
2209  break;
2210  case PT_32BUI:
2211  if (rt_util_clamp_to_32BUI(val) == rt_util_clamp_to_32BUI(minval))
2212  (*newval)++;
2213  else
2214  (*newval)--;
2215  break;
2216  case PT_32BF:
2218  *newval += FLT_EPSILON;
2219  else
2220  *newval -= FLT_EPSILON;
2221  break;
2222  case PT_64BF:
2223  break;
2224  default:
2225  rterror("rt_band_corrected_clamped_value: Unknown pixeltype %d", band->pixtype);
2226  return ES_ERROR;
2227  }
2228 
2229  if (corrected != NULL)
2230  *corrected = 1;
2231 
2232  return ES_NONE;
2233 }
#define TRUE
Definition: dbfopen.c:73
#define FALSE
Definition: dbfopen.c:72
void rterror(const char *fmt,...) __attribute__((format(printf
Wrappers used for reporting errors and info.
void * rtalloc(size_t size)
Wrappers used for managing memory.
Definition: rt_context.c:191
rt_pixtype rt_util_gdal_datatype_to_pixtype(GDALDataType gdt)
Convert GDALDataType to rt_pixtype.
Definition: rt_util.c:162
#define FLT_NEQ(x, y)
Definition: librtcore.h:2423
#define RASTER_DEBUG(level, msg)
Definition: librtcore.h:302
int rt_util_gdal_register_all(int force_register_all)
Definition: rt_util.c:347
#define RASTER_DEBUGF(level, msg,...)
Definition: librtcore.h:306
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster's geotransform using 6-element array.
Definition: rt_raster.c:609
int8_t rt_util_clamp_to_8BSI(double value)
Definition: rt_util.c:50
uint8_t rt_util_clamp_to_1BB(double value)
Definition: rt_util.c:35
void void void rtwarn(const char *fmt,...) __attribute__((format(printf
int32_t rt_util_clamp_to_32BSI(double value)
Definition: rt_util.c:70
rt_errorstate rt_raster_geopoint_to_cell(rt_raster raster, double xw, double yw, double *xr, double *yr, double *igt)
Convert an xw, yw map point to a xr, yr raster point.
Definition: rt_raster.c:686
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:86
rt_pixtype
Definition: librtcore.h:187
@ PT_32BUI
Definition: librtcore.h:196
@ PT_2BUI
Definition: librtcore.h:189
@ PT_32BSI
Definition: librtcore.h:195
@ PT_END
Definition: librtcore.h:199
@ PT_4BUI
Definition: librtcore.h:190
@ PT_32BF
Definition: librtcore.h:197
@ PT_1BB
Definition: librtcore.h:188
@ PT_16BUI
Definition: librtcore.h:194
@ PT_8BSI
Definition: librtcore.h:191
@ PT_16BSI
Definition: librtcore.h:193
@ PT_64BF
Definition: librtcore.h:198
@ PT_8BUI
Definition: librtcore.h:192
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
Definition: rt_raster.c:52
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:681
GDALDataType rt_util_pixtype_to_gdal_datatype(rt_pixtype pt)
Convert rt_pixtype to GDALDataType.
Definition: rt_util.c:124
double rt_pixtype_get_min_value(rt_pixtype pixtype)
Return minimum value possible for pixel type.
Definition: rt_pixel.c:150
struct rt_pixel_t * rt_pixel
Definition: librtcore.h:148
#define FLT_EQ(x, y)
Definition: librtcore.h:2424
rt_raster rt_raster_from_gdal_dataset(GDALDatasetH ds)
Return a raster from a GDAL dataset.
Definition: rt_raster.c:2175
rt_resample_type
Definition: librtcore.h:1476
@ RT_BILINEAR
Definition: librtcore.h:1478
@ RT_NEAREST
Definition: librtcore.h:1477
uint8_t rt_util_clamp_to_2BUI(double value)
Definition: rt_util.c:40
rt_errorstate rt_pixtype_compare_clamped_values(rt_pixtype pixtype, double val, double refval, int *isequal)
Test to see if two values are equal when clamped.
Definition: rt_pixel.c:202
uint8_t rt_util_clamp_to_8BUI(double value)
Definition: rt_util.c:55
GDALDatasetH rt_util_gdal_open(const char *fn, GDALAccess fn_access, int shared)
Definition: rt_util.c:394
rt_errorstate
Enum definitions.
Definition: librtcore.h:181
@ ES_NONE
Definition: librtcore.h:182
@ ES_ERROR
Definition: librtcore.h:183
int16_t rt_util_clamp_to_16BSI(double value)
Definition: rt_util.c:60
void * rtrealloc(void *mem, size_t size)
Definition: rt_context.c:199
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
Definition: rt_raster.c:367
uint8_t rt_util_clamp_to_4BUI(double value)
Definition: rt_util.c:45
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
void rtdealloc(void *mem)
Definition: rt_context.c:206
uint16_t rt_util_clamp_to_16BUI(double value)
Definition: rt_util.c:65
uint32_t rt_util_clamp_to_32BUI(double value)
Definition: rt_util.c:75
float rt_util_clamp_to_32F(double value)
Definition: rt_util.c:80
rt_errorstate rt_raster_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
int rt_pixtype_size(rt_pixtype pixtype)
Return size in bytes of a value in the given pixtype.
Definition: rt_pixel.c:39
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
Definition: rt_raster.c:385
This library is the generic raster handling section of PostGIS.
static double distance(double x1, double y1, double x2, double y2)
Definition: lwtree.c:1032
int value
Definition: genraster.py:62
int count
Definition: genraster.py:57
band
Definition: ovdump.py:58
data
Definition: ovdump.py:104
pixval
Definition: pixval.py:95
pixel
Definition: pixval.py:92
nband
Definition: pixval.py:54
Definition: pixval.py:1
void rt_band_init_value(rt_band band, double initval)
Fill in the cells of a band with a starting value frequently used to init with nodata value.
Definition: rt_band.c:112
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:818
int rt_band_get_pixel_of_value(rt_band band, int exclude_nodata_value, double *searchset, int searchcount, rt_pixel *pixels)
Search band for pixel(s) with search values.
Definition: rt_band.c:1960
rt_band rt_band_duplicate(rt_band band)
Create a new band duplicated from source band.
Definition: rt_band.c:438
uint16_t rt_band_get_width(rt_band band)
Return width of this band.
Definition: rt_band.c:791
void rt_band_set_hasnodata_flag(rt_band band, int flag)
Set hasnodata flag value.
Definition: rt_band.c:832
rt_errorstate rt_band_set_isnodata_flag(rt_band band, int flag)
Set isnodata flag value.
Definition: rt_band.c:846
const char * rt_band_get_ext_path(rt_band band)
Return band's external path (only valid when rt_band_is_offline returns non-zero).
Definition: rt_band.c:514
rt_errorstate rt_band_load_offline_data(rt_band band)
Load offline band's data.
Definition: rt_band.c:580
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_band.c:825
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition: rt_band.c:1527
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
Definition: rt_band.c:865
double rt_band_get_min_value(rt_band band)
Returns the minimal possible value for the band according to the pixel type.
Definition: rt_band.c:2053
uint64_t rt_band_get_file_size(rt_band band)
Return file size in bytes.
Definition: rt_band.c:737
bool enable_outdb_rasters
Definition: rt_band.c:568
int rt_band_check_is_nodata(rt_band band)
Returns TRUE if the band is only nodata values.
Definition: rt_band.c:2060
rt_errorstate rt_band_set_nodata(rt_band band, double val, int *converted)
Set nodata value.
Definition: rt_band.c:884
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:1125
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:1004
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition: rt_band.c:491
rt_errorstate rt_band_corrected_clamped_value(rt_band band, double val, double *newval, int *corrected)
Correct value when clamped value is equal to clamped NODATA value.
Definition: rt_band.c:2142
rt_band rt_band_new_offline(uint16_t width, uint16_t height, rt_pixtype pixtype, uint32_t hasnodata, double nodataval, uint8_t bandNum, const char *path)
Create an out-db rt_band.
Definition: rt_band.c:275
rt_errorstate rt_band_get_ext_band_num(rt_band band, uint8_t *bandnum)
Return bands' external band number (only valid when rt_band_is_offline returns non-zero).
Definition: rt_band.c:527
uint64_t rt_band_get_file_timestamp(rt_band band)
Return file timestamp.
Definition: rt_band.c:759
rt_errorstate rt_band_get_pixel_resample(rt_band band, double xr, double yr, rt_resample_type resample, double *r_value, int *r_nodata)
Retrieve a point value from the raster using a world coordinate and selected interpolation.
Definition: rt_band.c:1372
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_band.c:2038
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
Definition: rt_band.c:782
rt_band rt_band_new_offline_from_path(uint16_t width, uint16_t height, int hasnodata, double nodataval, uint8_t bandNum, const char *path, int force)
Create an out-db rt_band from path.
Definition: rt_band.c:350
uint32_t rt_band_get_nearest_pixel(rt_band band, int x, int y, uint16_t distancex, uint16_t distancey, int exclude_nodata_value, rt_pixel *npixels)
Get nearest pixel(s) with value (not NODATA) to specified pixel.
Definition: rt_band.c:1680
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
Definition: rt_band.c:551
rt_errorstate rt_band_get_pixel_bilinear(rt_band band, double xr, double yr, double *r_value, int *r_nodata)
Retrieve a point value from the raster using a world coordinate and bilinear interpolation.
Definition: rt_band.c:1411
int rt_band_clamped_value_is_nodata(rt_band band, double val)
Compare clamped value to band's clamped NODATA value.
Definition: rt_band.c:2106
int rt_band_get_ownsdata_flag(rt_band band)
Return 0 (FALSE) or non-zero (TRUE) indicating if rt_band is responsible for managing the memory for ...
Definition: rt_band.c:810
int rt_band_is_offline(rt_band band)
Return non-zero if the given band data is on the filesystem.
Definition: rt_band.c:480
uint16_t rt_band_get_height(rt_band band)
Return height of this band.
Definition: rt_band.c:800
rt_errorstate rt_band_get_pixel_line(rt_band band, int x, int y, uint16_t len, void **vals, uint16_t *nvals)
Get values of multiple pixels.
Definition: rt_band.c:1288
union rt_band_t::@12 data
void * mem
Definition: librtcore.h:2517
double value
Definition: librtcore.h:2528
uint8_t nodata
Definition: librtcore.h:2527