PostGIS  3.4.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 
123 rt_band
125  uint16_t width, uint16_t height,
126  rt_pixtype pixtype,
127  uint32_t hasnodata, double nodataval,
128  uint8_t bandNum, const char* path
129 ) {
130  rt_band band = NULL;
131  int pathlen = 0;
132 
133  assert(NULL != path);
134 
135  band = rtalloc(sizeof(struct rt_band_t));
136  if (band == NULL) {
137  rterror("rt_band_new_offline: Out of memory allocating rt_band");
138  return NULL;
139  }
140 
141  RASTER_DEBUGF(3, "Created rt_band @ %p with pixtype %s",
142  band, rt_pixtype_name(pixtype)
143  );
144 
145  band->pixtype = pixtype;
146  band->offline = 1;
147  band->width = width;
148  band->height = height;
149  band->hasnodata = hasnodata ? 1 : 0;
150  band->nodataval = 0;
151  band->isnodata = FALSE; /* we don't know if the offline band is NODATA */
152  band->ownsdata = 0; /* offline, flag is useless as all offline data cache is owned internally */
153  band->raster = NULL;
154 
155  /* properly set nodataval as it may need to be constrained to the data type */
156  if (hasnodata && rt_band_set_nodata(band, nodataval, NULL) != ES_NONE) {
157  rterror("rt_band_new_offline: Could not set NODATA value");
159  return NULL;
160  }
161 
162  band->data.offline.bandNum = bandNum;
163 
164  /* memory for data.offline.path is managed internally */
165  pathlen = strlen(path);
166  band->data.offline.path = rtalloc(sizeof(char) * (pathlen + 1));
167  if (band->data.offline.path == NULL) {
168  rterror("rt_band_new_offline: Out of memory allocating offline path");
170  return NULL;
171  }
172  memcpy(band->data.offline.path, path, pathlen);
173  band->data.offline.path[pathlen] = '\0';
174 
175  band->data.offline.mem = NULL;
176 
177  return band;
178 }
179 
198 rt_band
200  uint16_t width,
201  uint16_t height,
202  int hasnodata,
203  double nodataval,
204  uint8_t bandNum,
205  const char* path,
206  int force
207 ) {
208  GDALDatasetH hdsSrc = NULL;
209  int nband = 0;
210  GDALRasterBandH hbandSrc = NULL;
211 
212  GDALDataType gdpixtype;
213  rt_pixtype pt = PT_END;
214 
215  /* open outdb raster file */
217  hdsSrc = rt_util_gdal_open(path, GA_ReadOnly, 1);
218  if (hdsSrc == NULL && !force) {
219  rterror("rt_band_new_offline_from_path: Cannot open offline raster: %s", path);
220  return NULL;
221  }
222 
223  nband = GDALGetRasterCount(hdsSrc);
224  if (!nband && !force) {
225  rterror("rt_band_new_offline_from_path: No bands found in offline raster: %s", path);
226  GDALClose(hdsSrc);
227  return NULL;
228  }
229  /* bandNum is 1-based */
230  else if (bandNum > nband && !force) {
231  rterror(
232  "rt_band_new_offline_from_path: Specified band %d not found in offline raster: %s",
233  bandNum,
234  path
235  );
236  GDALClose(hdsSrc);
237  return NULL;
238  }
239 
240  hbandSrc = GDALGetRasterBand(hdsSrc, bandNum);
241  if (hbandSrc == NULL && !force) {
242  rterror(
243  "rt_band_new_offline_from_path: Cannot get band %d from GDAL dataset",
244  bandNum
245  );
246  GDALClose(hdsSrc);
247  return NULL;
248  }
249 
250  gdpixtype = GDALGetRasterDataType(hbandSrc);
251  pt = rt_util_gdal_datatype_to_pixtype(gdpixtype);
252  if (pt == PT_END && !force) {
253  rterror(
254  "rt_band_new_offline_from_path: Unsupported pixel type %s of band %d from GDAL dataset",
255  GDALGetDataTypeName(gdpixtype),
256  bandNum
257  );
258  GDALClose(hdsSrc);
259  return NULL;
260  }
261 
262  /* use out-db band's nodata value if nodataval not already set */
263  if (!hasnodata)
264  nodataval = GDALGetRasterNoDataValue(hbandSrc, &hasnodata);
265 
266  GDALClose(hdsSrc);
267 
268  return rt_band_new_offline(
269  width, height,
270  pt,
271  hasnodata, nodataval,
272  bandNum - 1, path
273  );
274 }
275 
286 rt_band
288  rt_band rtn = NULL;
289 
290  assert(band != NULL);
291 
292  /* offline */
293  if (band->offline) {
294  rtn = rt_band_new_offline(
295  band->width, band->height,
296  band->pixtype,
297  band->hasnodata, band->nodataval,
298  band->data.offline.bandNum, (const char *) band->data.offline.path
299  );
300  }
301  /* online */
302  else {
303  uint8_t *data = NULL;
304  data = rtalloc(rt_pixtype_size(band->pixtype) * band->width * band->height);
305  if (data == NULL) {
306  rterror("rt_band_duplicate: Out of memory allocating online band data");
307  return NULL;
308  }
309  memcpy(data, band->data.mem, rt_pixtype_size(band->pixtype) * band->width * band->height);
310 
311  rtn = rt_band_new_inline(
312  band->width, band->height,
313  band->pixtype,
314  band->hasnodata, band->nodataval,
315  data
316  );
317  rt_band_set_ownsdata_flag(rtn, 1); /* we DO own this data!!! */
318  }
319 
320  if (rtn == NULL) {
321  rterror("rt_band_duplicate: Could not copy band");
322  return NULL;
323  }
324 
325  return rtn;
326 }
327 
328 int
330  assert(NULL != band);
331  return band->offline ? 1 : 0;
332 }
333 
339 void
341  if (band == NULL)
342  return;
343 
344  RASTER_DEBUGF(3, "Destroying rt_band @ %p", band);
345 
346  /* offline band */
347  if (band->offline) {
348  /* memory cache */
349  if (band->data.offline.mem != NULL)
350  rtdealloc(band->data.offline.mem);
351  /* offline file path */
352  if (band->data.offline.path != NULL)
353  rtdealloc(band->data.offline.path);
354  }
355  /* inline band and band owns the data */
356  else if (band->data.mem != NULL && band->ownsdata)
357  rtdealloc(band->data.mem);
358 
359  rtdealloc(band);
360 }
361 
362 const char*
364 
365  assert(NULL != band);
366 
367 
368  if (!band->offline) {
369  RASTER_DEBUG(3, "rt_band_get_ext_path: Band is not offline");
370  return NULL;
371  }
372  return band->data.offline.path;
373 }
374 
377  assert(NULL != band);
378  assert(NULL != bandnum);
379 
380  *bandnum = 0;
381 
382  if (!band->offline) {
383  RASTER_DEBUG(3, "rt_band_get_ext_band_num: Band is not offline");
384  return ES_ERROR;
385  }
386 
387  *bandnum = band->data.offline.bandNum;
388 
389  return ES_NONE;
390 }
391 
399 void *
401  assert(NULL != band);
402 
403  if (band->offline) {
404  if (band->data.offline.mem != NULL)
405  return band->data.offline.mem;
406 
408  return NULL;
409  else
410  return band->data.offline.mem;
411  }
412  else
413  return band->data.mem;
414 }
415 
416 /* variable for PostgreSQL GUC: postgis.enable_outdb_rasters */
418 
430  GDALDatasetH hdsSrc = NULL;
431  int nband = 0;
432  VRTDatasetH hdsDst = NULL;
433  VRTSourcedRasterBandH hbandDst = NULL;
434  double ogt[6] = {0};
435  double offset[2] = {0};
436 
437  rt_raster _rast = NULL;
438  rt_band _band = NULL;
439  int aligned = 0;
440  int err = ES_NONE;
441 
442  assert(band != NULL);
443  assert(band->raster != NULL);
444 
445  if (!band->offline) {
446  rterror("rt_band_load_offline_data: Band is not offline");
447  return ES_ERROR;
448  }
449  else if (!strlen(band->data.offline.path)) {
450  rterror("rt_band_load_offline_data: Offline band does not a have a specified file");
451  return ES_ERROR;
452  }
453 
454  /* offline_data is disabled */
455  if (!enable_outdb_rasters) {
456  rterror("rt_band_load_offline_data: Access to offline bands disabled");
457  return ES_ERROR;
458  }
459 
461  hdsSrc = rt_util_gdal_open(band->data.offline.path, GA_ReadOnly, 1);
462  if (hdsSrc == NULL) {
463  rterror("rt_band_load_offline_data: Cannot open offline raster: %s", band->data.offline.path);
464  return ES_ERROR;
465  }
466 
467  /* # of bands */
468  nband = GDALGetRasterCount(hdsSrc);
469  if (!nband) {
470  rterror("rt_band_load_offline_data: No bands found in offline raster: %s", band->data.offline.path);
471  GDALClose(hdsSrc);
472  return ES_ERROR;
473  }
474  /* bandNum is 0-based */
475  else if (band->data.offline.bandNum + 1 > nband) {
476  rterror("rt_band_load_offline_data: Specified band %d not found in offline raster: %s", band->data.offline.bandNum, band->data.offline.path);
477  GDALClose(hdsSrc);
478  return ES_ERROR;
479  }
480 
481  /* get offline raster's geotransform */
482  if (GDALGetGeoTransform(hdsSrc, ogt) != CE_None) {
483  RASTER_DEBUG(4, "Using default geotransform matrix (0, 1, 0, 0, 0, -1)");
484  ogt[0] = 0;
485  ogt[1] = 1;
486  ogt[2] = 0;
487  ogt[3] = 0;
488  ogt[4] = 0;
489  ogt[5] = -1;
490  }
491  RASTER_DEBUGF(3, "Offline geotransform (%f, %f, %f, %f, %f, %f)",
492  ogt[0], ogt[1], ogt[2], ogt[3], ogt[4], ogt[5]);
493 
494  /* are rasters aligned? */
495  _rast = rt_raster_new(1, 1);
497  rt_raster_set_srid(_rast, band->raster->srid);
498  err = rt_raster_same_alignment(band->raster, _rast, &aligned, NULL);
499  rt_raster_destroy(_rast);
500 
501  if (err != ES_NONE) {
502  rterror("rt_band_load_offline_data: Could not test alignment of in-db representation of out-db raster");
503  GDALClose(hdsSrc);
504  return ES_ERROR;
505  }
506  else if (!aligned) {
507  rtwarn("The in-db representation of the out-db raster is not aligned. Band data may be incorrect");
508  }
509 
510  /* get offsets */
512  band->raster,
513  ogt[0], ogt[3],
514  &(offset[0]), &(offset[1]),
515  NULL
516  );
517 
518  RASTER_DEBUGF(4, "offsets: (%f, %f)", offset[0], offset[1]);
519 
520  /* create VRT dataset */
521  hdsDst = VRTCreate(band->width, band->height);
522  GDALSetGeoTransform(hdsDst, ogt);
523  /*
524  GDALSetDescription(hdsDst, "/tmp/offline.vrt");
525  */
526 
527  /* add band as simple sources */
528  GDALAddBand(hdsDst, rt_util_pixtype_to_gdal_datatype(band->pixtype), NULL);
529  hbandDst = (VRTSourcedRasterBandH) GDALGetRasterBand(hdsDst, 1);
530 
531  if (band->hasnodata)
532  GDALSetRasterNoDataValue(hbandDst, band->nodataval);
533 
534  VRTAddSimpleSource(
535  hbandDst, GDALGetRasterBand(hdsSrc, band->data.offline.bandNum + 1),
536  fabs(offset[0]), fabs(offset[1]),
537  band->width, band->height,
538  0, 0,
539  band->width, band->height,
540  "near", VRT_NODATA_UNSET
541  );
542 
543  /* make sure VRT reflects all changes */
544  VRTFlushCache(hdsDst);
545 
546  /* convert VRT dataset to rt_raster */
547  _rast = rt_raster_from_gdal_dataset(hdsDst);
548 
549  GDALClose(hdsDst);
550  GDALClose(hdsSrc);
551  /*
552  {
553  FILE *fp;
554  fp = fopen("/tmp/gdal_open_files.log", "w");
555  GDALDumpOpenDatasets(fp);
556  fclose(fp);
557  }
558  */
559 
560  if (_rast == NULL) {
561  rterror("rt_band_load_offline_data: Cannot load data from offline raster: %s", band->data.offline.path);
562  return ES_ERROR;
563  }
564 
565  _band = rt_raster_get_band(_rast, 0);
566  if (_band == NULL) {
567  rterror("rt_band_load_offline_data: Cannot load data from offline raster: %s", band->data.offline.path);
568  rt_raster_destroy(_rast);
569  return ES_ERROR;
570  }
571 
572  /* band->data.offline.mem not NULL, free first */
573  if (band->data.offline.mem != NULL) {
574  rtdealloc(band->data.offline.mem);
575  band->data.offline.mem = NULL;
576  }
577 
578  band->data.offline.mem = _band->data.mem;
579 
580  rtdealloc(_band); /* cannot use rt_band_destroy */
581  rt_raster_destroy(_rast);
582 
583  return ES_NONE;
584 }
585 
587  VSIStatBufL sStat;
588 
589  assert(NULL != band);
590  if (!band->offline) {
591  rterror("rt_band_get_file_size: Band is not offline");
592  return 0;
593  }
594  /* offline_data is disabled */
595  if (!enable_outdb_rasters) {
596  rterror("rt_band_get_file_size: Access to offline bands disabled");
597  return 0;
598  }
599 
600  if( VSIStatL(band->data.offline.path, &sStat) != 0 ) {
601  rterror("rt_band_get_file_size: Cannot access file");
602  return 0;
603  }
604 
605  return sStat.st_size;
606 }
607 
609  VSIStatBufL sStat;
610 
611  assert(NULL != band);
612  if (!band->offline) {
613  rterror("rt_band_get_file_timestamp: Band is not offline");
614  return 0;
615  }
616  /* offline_data is disabled */
617  if (!enable_outdb_rasters) {
618  rterror("rt_band_get_file_timestamp: Access to offline bands disabled");
619  return 0;
620  }
621 
622  if( VSIStatL(band->data.offline.path, &sStat) != 0 ) {
623  rterror("rt_band_get_file_timestamp: Cannot access file");
624  return 0;
625  }
626 
627  return sStat.st_mtime;
628 }
629 
632 
633  assert(NULL != band);
634 
635 
636  return band->pixtype;
637 }
638 
639 uint16_t
641 
642  assert(NULL != band);
643 
644 
645  return band->width;
646 }
647 
648 uint16_t
650 
651  assert(NULL != band);
652 
653 
654  return band->height;
655 }
656 
657 /* Get ownsdata flag */
658 int
660  assert(NULL != band);
661 
662  return band->ownsdata ? 1 : 0;
663 }
664 
665 /* set ownsdata flag */
666 void
668  assert(NULL != band);
669 
670  band->ownsdata = flag ? 1 : 0;
671 }
672 
673 int
675  assert(NULL != band);
676 
677  return band->hasnodata ? 1 : 0;
678 }
679 
680 void
682 
683  assert(NULL != band);
684 
685  band->hasnodata = (flag) ? 1 : 0;
686 
687  /* isnodata depends on hasnodata */
688  if (!band->hasnodata && band->isnodata) {
689  RASTER_DEBUG(3, "Setting isnodata to FALSE as band no longer has NODATA");
690  band->isnodata = 0;
691  }
692 }
693 
696  assert(NULL != band);
697 
698  if (!band->hasnodata) {
699  /* silently permit setting isnodata flag to FALSE */
700  if (!flag)
701  band->isnodata = 0;
702  else {
703  rterror("rt_band_set_isnodata_flag: Cannot set isnodata flag as band has no NODATA");
704  return ES_ERROR;
705  }
706  }
707  else
708  band->isnodata = (flag) ? 1 : 0;
709 
710  return ES_NONE;
711 }
712 
713 int
715  assert(NULL != band);
716 
717  if (band->hasnodata)
718  return band->isnodata ? 1 : 0;
719  else
720  return 0;
721 }
722 
733 rt_band_set_nodata(rt_band band, double val, int *converted) {
734  rt_pixtype pixtype = PT_END;
735  int32_t checkvalint = 0;
736  uint32_t checkvaluint = 0;
737  float checkvalfloat = 0;
738  double checkvaldouble = 0;
739 
740  assert(NULL != band);
741 
742  if (converted != NULL)
743  *converted = 0;
744 
745  pixtype = band->pixtype;
746 
747  RASTER_DEBUGF(3, "rt_band_set_nodata: setting nodata value %g with band type %s", val, rt_pixtype_name(pixtype));
748 
749  /* return -1 on out of range */
750  switch (pixtype) {
751  case PT_1BB: {
752  band->nodataval = rt_util_clamp_to_1BB(val);
753  checkvalint = band->nodataval;
754  break;
755  }
756  case PT_2BUI: {
757  band->nodataval = rt_util_clamp_to_2BUI(val);
758  checkvalint = band->nodataval;
759  break;
760  }
761  case PT_4BUI: {
762  band->nodataval = rt_util_clamp_to_4BUI(val);
763  checkvalint = band->nodataval;
764  break;
765  }
766  case PT_8BSI: {
767  band->nodataval = rt_util_clamp_to_8BSI(val);
768  checkvalint = band->nodataval;
769  break;
770  }
771  case PT_8BUI: {
772  band->nodataval = rt_util_clamp_to_8BUI(val);
773  checkvalint = band->nodataval;
774  break;
775  }
776  case PT_16BSI: {
777  band->nodataval = rt_util_clamp_to_16BSI(val);
778  checkvalint = band->nodataval;
779  break;
780  }
781  case PT_16BUI: {
782  band->nodataval = rt_util_clamp_to_16BUI(val);
783  checkvalint = band->nodataval;
784  break;
785  }
786  case PT_32BSI: {
787  band->nodataval = rt_util_clamp_to_32BSI(val);
788  checkvalint = band->nodataval;
789  break;
790  }
791  case PT_32BUI: {
792  band->nodataval = rt_util_clamp_to_32BUI(val);
793  checkvaluint = band->nodataval;
794  break;
795  }
796  case PT_32BF: {
797  band->nodataval = rt_util_clamp_to_32F(val);
798  checkvalfloat = band->nodataval;
799  break;
800  }
801  case PT_64BF: {
802  band->nodataval = val;
803  checkvaldouble = band->nodataval;
804  break;
805  }
806  default: {
807  rterror("rt_band_set_nodata: Unknown pixeltype %d", pixtype);
808  band->hasnodata = 0;
809  return ES_ERROR;
810  }
811  }
812 
813  RASTER_DEBUGF(3, "rt_band_set_nodata: band->hasnodata = %d", band->hasnodata);
814  RASTER_DEBUGF(3, "rt_band_set_nodata: band->nodataval = %f", band->nodataval);
815  /* the nodata value was just set, so this band has NODATA */
816  band->hasnodata = 1;
817 
818  /* also set isnodata flag to false */
819  band->isnodata = 0;
820 
822  val,
823  checkvalint, checkvaluint,
824  checkvalfloat, checkvaldouble,
825  pixtype
826  ) && converted != NULL) {
827  *converted = 1;
828  }
829 
830  return ES_NONE;
831 }
832 
854  rt_band band,
855  int x, int y,
856  void *vals, uint32_t len
857 ) {
858  rt_pixtype pixtype = PT_END;
859  int size = 0;
860  uint8_t *data = NULL;
861  uint32_t offset = 0;
862 
863  assert(NULL != band);
864  assert(vals != NULL && len > 0);
865 
866  RASTER_DEBUGF(3, "length of values = %d", len);
867 
868  if (band->offline) {
869  rterror("rt_band_set_pixel_line not implemented yet for OFFDB bands");
870  return ES_ERROR;
871  }
872 
873  pixtype = band->pixtype;
874  size = rt_pixtype_size(pixtype);
875 
876  if (
877  x < 0 || x >= band->width ||
878  y < 0 || y >= band->height
879  ) {
880  rterror("rt_band_set_pixel_line: Coordinates out of range (%d, %d) vs (%d, %d)", x, y, band->width, band->height);
881  return ES_ERROR;
882  }
883 
885  offset = x + (y * band->width);
886  RASTER_DEBUGF(4, "offset = %d", offset);
887 
888  /* make sure len of values to copy don't exceed end of data */
889  if (len > (band->width * band->height) - offset) {
890  rterror("rt_band_set_pixel_line: Could not apply pixels as values length exceeds end of data");
891  return ES_ERROR;
892  }
893 
894  switch (pixtype) {
895  case PT_1BB:
896  case PT_2BUI:
897  case PT_4BUI:
898  case PT_8BUI:
899  case PT_8BSI: {
900  uint8_t *ptr = data;
901  ptr += offset;
902  memcpy(ptr, vals, size * len);
903  break;
904  }
905  case PT_16BUI: {
906  uint16_t *ptr = (uint16_t *) data;
907  ptr += offset;
908  memcpy(ptr, vals, size * len);
909  break;
910  }
911  case PT_16BSI: {
912  int16_t *ptr = (int16_t *) data;
913  ptr += offset;
914  memcpy(ptr, vals, size * len);
915  break;
916  }
917  case PT_32BUI: {
918  uint32_t *ptr = (uint32_t *) data;
919  ptr += offset;
920  memcpy(ptr, vals, size * len);
921  break;
922  }
923  case PT_32BSI: {
924  int32_t *ptr = (int32_t *) data;
925  ptr += offset;
926  memcpy(ptr, vals, size * len);
927  break;
928  }
929  case PT_32BF: {
930  float *ptr = (float *) data;
931  ptr += offset;
932  memcpy(ptr, vals, size * len);
933  break;
934  }
935  case PT_64BF: {
936  double *ptr = (double *) data;
937  ptr += offset;
938  memcpy(ptr, vals, size * len);
939  break;
940  }
941  default: {
942  rterror("rt_band_set_pixel_line: Unknown pixeltype %d", pixtype);
943  return ES_ERROR;
944  }
945  }
946 
947 #if POSTGIS_DEBUG_LEVEL > 0
948  {
949  double value;
950  rt_band_get_pixel(band, x, y, &value, NULL);
951  RASTER_DEBUGF(4, "pixel at (%d, %d) = %f", x, y, value);
952  }
953 #endif
954 
955  /* set band's isnodata flag to FALSE */
958 
959  return ES_NONE;
960 }
961 
975  rt_band band,
976  int x, int y,
977  double val,
978  int *converted
979 ) {
980  rt_pixtype pixtype = PT_END;
981  uint8_t *data = NULL;
982  uint32_t offset = 0;
983 
984  int32_t checkvalint = 0;
985  uint32_t checkvaluint = 0;
986  float checkvalfloat = 0;
987  double checkvaldouble = 0;
988 
989  assert(NULL != band);
990 
991  if (converted != NULL)
992  *converted = 0;
993 
994  if (band->offline) {
995  rterror("rt_band_set_pixel not implemented yet for OFFDB bands");
996  return ES_ERROR;
997  }
998 
999  pixtype = band->pixtype;
1000 
1001  if (
1002  x < 0 || x >= band->width ||
1003  y < 0 || y >= band->height
1004  ) {
1005  rterror("rt_band_set_pixel: Coordinates out of range");
1006  return ES_ERROR;
1007  }
1008 
1009  /* check that clamped value isn't clamped NODATA */
1010  if (band->hasnodata && pixtype != PT_64BF) {
1011  double newval;
1012  int corrected;
1013 
1014  rt_band_corrected_clamped_value(band, val, &newval, &corrected);
1015 
1016  if (corrected) {
1017 #if POSTGIS_RASTER_WARN_ON_TRUNCATION > 0
1018  rtwarn("Value for pixel %d x %d has been corrected as clamped value becomes NODATA", x, y);
1019 #endif
1020  val = newval;
1021 
1022  if (converted != NULL)
1023  *converted = 1;
1024  }
1025  }
1026 
1028  offset = x + (y * band->width);
1029 
1030  switch (pixtype) {
1031  case PT_1BB: {
1032  data[offset] = rt_util_clamp_to_1BB(val);
1033  checkvalint = data[offset];
1034  break;
1035  }
1036  case PT_2BUI: {
1037  data[offset] = rt_util_clamp_to_2BUI(val);
1038  checkvalint = data[offset];
1039  break;
1040  }
1041  case PT_4BUI: {
1042  data[offset] = rt_util_clamp_to_4BUI(val);
1043  checkvalint = data[offset];
1044  break;
1045  }
1046  case PT_8BSI: {
1047  data[offset] = (uint8_t)rt_util_clamp_to_8BSI(val);
1048  checkvalint = (int8_t) data[offset];
1049  break;
1050  }
1051  case PT_8BUI: {
1052  data[offset] = rt_util_clamp_to_8BUI(val);
1053  checkvalint = data[offset];
1054  break;
1055  }
1056  case PT_16BSI: {
1057  int16_t *ptr = (int16_t*) data; /* we assume correct alignment */
1058  ptr[offset] = rt_util_clamp_to_16BSI(val);
1059  checkvalint = (int16_t) ptr[offset];
1060  break;
1061  }
1062  case PT_16BUI: {
1063  uint16_t *ptr = (uint16_t*) data; /* we assume correct alignment */
1064  ptr[offset] = rt_util_clamp_to_16BUI(val);
1065  checkvalint = ptr[offset];
1066  break;
1067  }
1068  case PT_32BSI: {
1069  int32_t *ptr = (int32_t*) data; /* we assume correct alignment */
1070  ptr[offset] = rt_util_clamp_to_32BSI(val);
1071  checkvalint = (int32_t) ptr[offset];
1072  break;
1073  }
1074  case PT_32BUI: {
1075  uint32_t *ptr = (uint32_t*) data; /* we assume correct alignment */
1076  ptr[offset] = rt_util_clamp_to_32BUI(val);
1077  checkvaluint = ptr[offset];
1078  break;
1079  }
1080  case PT_32BF: {
1081  float *ptr = (float*) data; /* we assume correct alignment */
1082  ptr[offset] = rt_util_clamp_to_32F(val);
1083  checkvalfloat = ptr[offset];
1084  break;
1085  }
1086  case PT_64BF: {
1087  double *ptr = (double*) data; /* we assume correct alignment */
1088  ptr[offset] = val;
1089  checkvaldouble = ptr[offset];
1090  break;
1091  }
1092  default: {
1093  rterror("rt_band_set_pixel: Unknown pixeltype %d", pixtype);
1094  return ES_ERROR;
1095  }
1096  }
1097 
1098  /* If the stored value is not NODATA, reset the isnodata flag */
1100  RASTER_DEBUG(3, "Band has a value that is not NODATA. Setting isnodata to FALSE");
1101  band->isnodata = FALSE;
1102  }
1103 
1104  /* Overflow checking */
1106  val,
1107  checkvalint, checkvaluint,
1108  checkvalfloat, checkvaldouble,
1109  pixtype
1110  ) && converted != NULL) {
1111  *converted = 1;
1112  }
1113 
1114  return ES_NONE;
1115 }
1116 
1138  rt_band band,
1139  int x, int y,
1140  uint16_t len,
1141  void **vals, uint16_t *nvals
1142 ) {
1143  uint8_t *_vals = NULL;
1144  int pixsize = 0;
1145  uint8_t *data = NULL;
1146  uint32_t offset = 0;
1147  uint16_t _nvals = 0;
1148  int maxlen = 0;
1149  uint8_t *ptr = NULL;
1150 
1151  assert(NULL != band);
1152  assert(vals != NULL && nvals != NULL);
1153 
1154  /* initialize to no values */
1155  *nvals = 0;
1156 
1157  if (
1158  x < 0 || x >= band->width ||
1159  y < 0 || y >= band->height
1160  ) {
1161  rtwarn("Attempting to get pixel values with out of range raster coordinates: (%d, %d)", x, y);
1162  return ES_ERROR;
1163  }
1164 
1165  if (len < 1)
1166  return ES_NONE;
1167 
1169  if (data == NULL) {
1170  rterror("rt_band_get_pixel_line: Cannot get band data");
1171  return ES_ERROR;
1172  }
1173 
1174  /* +1 for the nodata value */
1175  offset = x + (y * band->width);
1176  RASTER_DEBUGF(4, "offset = %d", offset);
1177 
1178  pixsize = rt_pixtype_size(band->pixtype);
1179  RASTER_DEBUGF(4, "pixsize = %d", pixsize);
1180 
1181  /* cap _nvals so that it doesn't overflow */
1182  _nvals = len;
1183  maxlen = band->width * band->height;
1184 
1185  if (((int) (offset + _nvals)) > maxlen) {
1186  _nvals = maxlen - offset;
1187  rtwarn("Limiting returning number values to %d", _nvals);
1188  }
1189  RASTER_DEBUGF(4, "_nvals = %d", _nvals);
1190 
1191  ptr = data + (offset * pixsize);
1192 
1193  _vals = rtalloc(_nvals * pixsize);
1194  if (_vals == NULL) {
1195  rterror("rt_band_get_pixel_line: Could not allocate memory for pixel values");
1196  return ES_ERROR;
1197  }
1198 
1199  /* copy pixels */
1200  memcpy(_vals, ptr, _nvals * pixsize);
1201 
1202  *vals = _vals;
1203  *nvals = _nvals;
1204 
1205  return ES_NONE;
1206 }
1207 
1222  rt_band band,
1223  double xr, double yr,
1224  rt_resample_type resample,
1225  double *r_value, int *r_nodata
1226 )
1227 {
1228  if (resample == RT_BILINEAR) {
1230  band, xr, yr, r_value, r_nodata
1231  );
1232  }
1233  else if (resample == RT_NEAREST) {
1234  return rt_band_get_pixel(
1235  band, floor(xr), floor(yr),
1236  r_value, r_nodata
1237  );
1238  }
1239  else {
1240  rtwarn("Invalid resample type requested %d", resample);
1241  return ES_ERROR;
1242  }
1243 
1244 }
1245 
1261  rt_band band,
1262  double xr, double yr,
1263  double *r_value, int *r_nodata)
1264 {
1265  double xcenter, ycenter;
1266  double values[2][2];
1267  double nodatavalue = 0.0;
1268  int nodatas[2][2];
1269  int x[2][2];
1270  int y[2][2];
1271  int xcell, ycell;
1272  int xdir, ydir;
1273  int i, j;
1274  uint16_t width, height;
1275 
1276  /* Cell coordinates */
1277  xcell = (int)floor(xr);
1278  ycell = (int)floor(yr);
1279  xcenter = xcell + 0.5;
1280  ycenter = ycell + 0.5;
1281 
1282  /* Raster geometry */
1283  width = rt_band_get_width(band);
1284  height = rt_band_get_height(band);
1285 
1286  /* Reject out-of-range sample */
1287  if(xcell < 0 || ycell < 0 || xcell >= width || ycell >= height) {
1288  rtwarn("Attempting to get pixel value with out of range raster coordinates: (%d, %d)", xcell, ycell);
1289  return ES_ERROR;
1290  }
1291 
1292  /* Quadrant of 2x2 grid the raster coordinate falls in */
1293  xdir = xr < xcenter ? 1 : 0;
1294  ydir = yr < ycenter ? 1 : 0;
1295 
1297  rt_band_get_nodata(band, &nodatavalue);
1298  }
1299  else {
1300  nodatavalue = 0.0;
1301  }
1302 
1303  /* Read the 2x2 values from the band */
1304  for (i = 0; i < 2; i++) {
1305  for (j = 0; j < 2; j++) {
1306  double value = nodatavalue;
1307  int nodata = 0;
1308  int xij = xcell + (i - xdir);
1309  int yij = ycell + (j - ydir);
1310 
1311  if(xij < 0 || yij < 0 || xij >= width || yij >= height) {
1312  nodata = 1;
1313  }
1314  else {
1316  band, xij, yij,
1317  &value, &nodata
1318  );
1319  if (err != ES_NONE)
1320  nodata = 1;
1321  }
1322  x[i][j] = xij;
1323  y[i][j] = yij;
1324  values[i][j] = value;
1325  nodatas[i][j] = nodata;
1326  }
1327  }
1328 
1329  /* Point falls in nodata cell, just return nodata */
1330  if (nodatas[xdir][ydir]) {
1331  *r_value = nodatavalue;
1332  *r_nodata = 1;
1333  return ES_NONE;
1334  }
1335 
1336  /* Normalize raster coordinate to the bottom left */
1337  /* so we are working on a unit square */
1338  xr = xr - (x[0][0] + 0.5);
1339  yr = yr - (y[0][0] + 0.5);
1340 
1341  /* Point is in cell with values, so we take nodata */
1342  /* neighbors off the table by matching them to the */
1343  /* most controlling cell */
1344  for (i = 0; i < 2; i++) {
1345  for (j = 0; j < 2; j++) {
1346  if (nodatas[i][j])
1347  values[i][j] = values[xdir][ydir];
1348  }
1349  }
1350 
1351  /* Calculate bilinear value */
1352  /* https://en.wikipedia.org/wiki/Bilinear_interpolation#Unit_square */
1353  *r_nodata = 0;
1354  *r_value = values[0][0] * (1-xr) * (1-yr) +
1355  values[1][0] * (1-yr) * xr +
1356  values[0][1] * (1-xr) * yr +
1357  values[1][1] * xr * yr;
1358 
1359  return ES_NONE;
1360 }
1361 
1362 
1377  rt_band band,
1378  int x, int y,
1379  double *value,
1380  int *nodata
1381 ) {
1382  rt_pixtype pixtype = PT_END;
1383  uint8_t* data = NULL;
1384  uint32_t offset = 0;
1385 
1386  assert(NULL != band);
1387  assert(NULL != value);
1388 
1389  /* set nodata to 0 */
1390  if (nodata != NULL)
1391  *nodata = 0;
1392 
1393  if (
1394  x < 0 || x >= band->width ||
1395  y < 0 || y >= band->height
1396  ) {
1397  rtwarn("Attempting to get pixel value with out of range raster coordinates: (%d, %d)", x, y);
1398  return ES_ERROR;
1399  }
1400 
1401  /* band is NODATA */
1402  if (band->isnodata) {
1403  RASTER_DEBUG(3, "Band's isnodata flag is TRUE. Returning NODATA value");
1404  *value = band->nodataval;
1405  if (nodata != NULL) *nodata = 1;
1406  return ES_NONE;
1407  }
1408 
1410  if (data == NULL) {
1411  rterror("rt_band_get_pixel: Cannot get band data");
1412  return ES_ERROR;
1413  }
1414 
1415  /* +1 for the nodata value */
1416  offset = x + (y * band->width);
1417 
1418  pixtype = band->pixtype;
1419 
1420  switch (pixtype) {
1421  case PT_1BB:
1422 #ifdef OPTIMIZE_SPACE
1423  {
1424  int byteOffset = offset / 8;
1425  int bitOffset = offset % 8;
1426  data += byteOffset;
1427 
1428  /* Bit to set is bitOffset into data */
1429  *value = getBits(data, val, 1, bitOffset);
1430  break;
1431  }
1432 #endif
1433  case PT_2BUI:
1434 #ifdef OPTIMIZE_SPACE
1435  {
1436  int byteOffset = offset / 4;
1437  int bitOffset = offset % 4;
1438  data += byteOffset;
1439 
1440  /* Bits to set start at bitOffset into data */
1441  *value = getBits(data, val, 2, bitOffset);
1442  break;
1443  }
1444 #endif
1445  case PT_4BUI:
1446 #ifdef OPTIMIZE_SPACE
1447  {
1448  int byteOffset = offset / 2;
1449  int bitOffset = offset % 2;
1450  data += byteOffset;
1451 
1452  /* Bits to set start at bitOffset into data */
1453  *value = getBits(data, val, 2, bitOffset);
1454  break;
1455  }
1456 #endif
1457  case PT_8BSI: {
1458  int8_t val = (int8_t)data[offset];
1459  *value = val;
1460  break;
1461  }
1462  case PT_8BUI: {
1463  uint8_t val = data[offset];
1464  *value = val;
1465  break;
1466  }
1467  case PT_16BSI: {
1468  int16_t *ptr = (int16_t*) data; /* we assume correct alignment */
1469  *value = ptr[offset];
1470  break;
1471  }
1472  case PT_16BUI: {
1473  uint16_t *ptr = (uint16_t*) data; /* we assume correct alignment */
1474  *value = ptr[offset];
1475  break;
1476  }
1477  case PT_32BSI: {
1478  int32_t *ptr = (int32_t*) data; /* we assume correct alignment */
1479  *value = ptr[offset];
1480  break;
1481  }
1482  case PT_32BUI: {
1483  uint32_t *ptr = (uint32_t*) data; /* we assume correct alignment */
1484  *value = ptr[offset];
1485  break;
1486  }
1487  case PT_32BF: {
1488  float *ptr = (float*) data; /* we assume correct alignment */
1489  *value = ptr[offset];
1490  break;
1491  }
1492  case PT_64BF: {
1493  double *ptr = (double*) data; /* we assume correct alignment */
1494  *value = ptr[offset];
1495  break;
1496  }
1497  default: {
1498  rterror("rt_band_get_pixel: Unknown pixeltype %d", pixtype);
1499  return ES_ERROR;
1500  }
1501  }
1502 
1503  /* set NODATA flag */
1504  if (band->hasnodata && nodata != NULL) {
1506  *nodata = 1;
1507  }
1508 
1509  return ES_NONE;
1510 }
1511 
1530  rt_band band,
1531  int x, int y,
1532  uint16_t distancex, uint16_t distancey,
1533  int exclude_nodata_value,
1534  rt_pixel *npixels
1535 ) {
1536  rt_pixel npixel = NULL;
1537  int extent[4] = {0};
1538  int max_extent[4] = {0};
1539  int d0 = 0;
1540  uint32_t distance[2] = {0};
1541  uint32_t _d[2] = {0};
1542  uint32_t i = 0;
1543  uint32_t j = 0;
1544  uint32_t k = 0;
1545  int _max = 0;
1546  int _x = 0;
1547  int _y = 0;
1548  int *_min = NULL;
1549  double pixval = 0;
1550  double minval = 0;
1551  uint32_t count = 0;
1552  int isnodata = 0;
1553 
1554  int inextent = 0;
1555 
1556  assert(NULL != band);
1557  assert(NULL != npixels);
1558 
1559  RASTER_DEBUG(3, "Starting");
1560 
1561  /* process distance */
1562  distance[0] = distancex;
1563  distance[1] = distancey;
1564 
1565  /* no distance, means get nearest pixels and return */
1566  if (!distance[0] && !distance[1])
1567  d0 = 1;
1568 
1569  RASTER_DEBUGF(4, "Selected pixel: %d x %d", x, y);
1570  RASTER_DEBUGF(4, "Distances: %d x %d", distance[0], distance[1]);
1571 
1572  /* shortcuts if outside band extent */
1573  if (
1574  exclude_nodata_value && (
1575  (x < 0 || x > band->width) ||
1576  (y < 0 || y > band->height)
1577  )
1578  ) {
1579  /* no distances specified, jump to pixel close to extent */
1580  if (d0) {
1581  if (x < 0)
1582  x = -1;
1583  else if (x > band->width)
1584  x = band->width;
1585 
1586  if (y < 0)
1587  y = -1;
1588  else if (y > band->height)
1589  y = band->height;
1590 
1591  RASTER_DEBUGF(4, "Moved selected pixel: %d x %d", x, y);
1592  }
1593  /*
1594  distances specified
1595  if distances won't capture extent of band, return 0
1596  */
1597  else if (
1598  ((x < 0 && (uint32_t) abs(x) > distance[0]) || (x - band->width >= (int)distance[0])) ||
1599  ((y < 0 && (uint32_t) abs(y) > distance[1]) || (y - band->height >= (int)distance[1]))
1600  ) {
1601  RASTER_DEBUG(4, "No nearest pixels possible for provided pixel and distances");
1602  return 0;
1603  }
1604  }
1605 
1606  /* no NODATA, exclude is FALSE */
1607  if (!band->hasnodata)
1608  exclude_nodata_value = FALSE;
1609  /* band is NODATA and excluding NODATA */
1610  else if (exclude_nodata_value && band->isnodata) {
1611  RASTER_DEBUG(4, "No nearest pixels possible as band is NODATA and excluding NODATA values");
1612  return 0;
1613  }
1614 
1615  /* determine the maximum distance to prevent an infinite loop */
1616  if (d0) {
1617  int a, b;
1618 
1619  /* X axis */
1620  a = abs(x);
1621  b = abs(x - band->width);
1622 
1623  if (a > b)
1624  distance[0] = a;
1625  else
1626  distance[0] = b;
1627 
1628  /* Y axis */
1629  a = abs(y);
1630  b = abs(y - band->height);
1631  if (a > b)
1632  distance[1] = a;
1633  else
1634  distance[1] = b;
1635 
1636  RASTER_DEBUGF(4, "Maximum distances: %d x %d", distance[0], distance[1]);
1637  }
1638 
1639  /* minimum possible value for pixel type */
1640  minval = rt_pixtype_get_min_value(band->pixtype);
1641  RASTER_DEBUGF(4, "pixtype: %s", rt_pixtype_name(band->pixtype));
1642  RASTER_DEBUGF(4, "minval: %f", minval);
1643 
1644  /* set variables */
1645  count = 0;
1646  *npixels = NULL;
1647 
1648  /* maximum extent */
1649  max_extent[0] = x - (int)distance[0]; /* min X */
1650  max_extent[1] = y - (int)distance[1]; /* min Y */
1651  max_extent[2] = x + (int)distance[0]; /* max X */
1652  max_extent[3] = y + (int)distance[1]; /* max Y */
1653  RASTER_DEBUGF(4, "Maximum Extent: (%d, %d, %d, %d)",
1654  max_extent[0], max_extent[1], max_extent[2], max_extent[3]);
1655 
1656  _d[0] = 0;
1657  _d[1] = 0;
1658  do {
1659  _d[0]++;
1660  _d[1]++;
1661 
1662  extent[0] = x - (int)_d[0]; /* min x */
1663  extent[1] = y - (int)_d[1]; /* min y */
1664  extent[2] = x + (int)_d[0]; /* max x */
1665  extent[3] = y + (int)_d[1]; /* max y */
1666 
1667  RASTER_DEBUGF(4, "Processing distances: %d x %d", _d[0], _d[1]);
1668  RASTER_DEBUGF(4, "Extent: (%d, %d, %d, %d)",
1669  extent[0], extent[1], extent[2], extent[3]);
1670 
1671  for (i = 0; i < 2; i++) {
1672 
1673  /* by row */
1674  if (i < 1)
1675  _max = extent[2] - extent[0] + 1;
1676  /* by column */
1677  else
1678  _max = extent[3] - extent[1] + 1;
1679  _max = abs(_max);
1680 
1681  for (j = 0; j < 2; j++) {
1682  /* by row */
1683  if (i < 1) {
1684  _x = extent[0];
1685  _min = &_x;
1686 
1687  /* top row */
1688  if (j < 1)
1689  _y = extent[1];
1690  /* bottom row */
1691  else
1692  _y = extent[3];
1693  }
1694  /* by column */
1695  else {
1696  _y = extent[1] + 1;
1697  _min = &_y;
1698 
1699  /* left column */
1700  if (j < 1) {
1701  _x = extent[0];
1702  _max -= 2;
1703  }
1704  /* right column */
1705  else
1706  _x = extent[2];
1707  }
1708 
1709  RASTER_DEBUGF(4, "_min, _max: %d, %d", *_min, _max);
1710  for (k = 0; k < (uint32_t) _max; k++) {
1711  /* check that _x and _y are not outside max extent */
1712  if (
1713  _x < max_extent[0] || _x > max_extent[2] ||
1714  _y < max_extent[1] || _y > max_extent[3]
1715  ) {
1716  (*_min)++;
1717  continue;
1718  }
1719 
1720  /* outside band extent, set to NODATA */
1721  if (
1722  (_x < 0 || _x >= band->width) ||
1723  (_y < 0 || _y >= band->height)
1724  ) {
1725  /* no NODATA, set to minimum possible value */
1726  if (!band->hasnodata)
1727  pixval = minval;
1728  /* has NODATA, use NODATA */
1729  else
1730  pixval = band->nodataval;
1731  RASTER_DEBUGF(4, "NODATA pixel outside band extent: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1732  inextent = 0;
1733  isnodata = 1;
1734  }
1735  else {
1736  if (rt_band_get_pixel(
1737  band,
1738  _x, _y,
1739  &pixval,
1740  &isnodata
1741  ) != ES_NONE) {
1742  rterror("rt_band_get_nearest_pixel: Could not get pixel value");
1743  if (count) rtdealloc(*npixels);
1744  return -1;
1745  }
1746  RASTER_DEBUGF(4, "Pixel: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1747  inextent = 1;
1748  }
1749 
1750  /* use pixval? */
1751  if (!exclude_nodata_value || (exclude_nodata_value && !isnodata)) {
1752  /* add pixel to result set */
1753  RASTER_DEBUGF(4, "Adding pixel to set of nearest pixels: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1754  count++;
1755 
1756  if (*npixels == NULL)
1757  *npixels = (rt_pixel) rtalloc(sizeof(struct rt_pixel_t) * count);
1758  else
1759  *npixels = (rt_pixel) rtrealloc(*npixels, sizeof(struct rt_pixel_t) * count);
1760  if (*npixels == NULL) {
1761  rterror("rt_band_get_nearest_pixel: Could not allocate memory for nearest pixel(s)");
1762  return -1;
1763  }
1764 
1765  npixel = &((*npixels)[count - 1]);
1766  npixel->x = _x;
1767  npixel->y = _y;
1768  npixel->value = pixval;
1769 
1770  /* special case for when outside band extent */
1771  if (!inextent && !band->hasnodata)
1772  npixel->nodata = 1;
1773  else
1774  npixel->nodata = 0;
1775  }
1776 
1777  (*_min)++;
1778  }
1779  }
1780  }
1781 
1782  /* distance threshholds met */
1783  if (_d[0] >= distance[0] && _d[1] >= distance[1])
1784  break;
1785  else if (d0 && count)
1786  break;
1787  }
1788  while (1);
1789 
1790  RASTER_DEBUGF(3, "Nearest pixels in return: %d", count);
1791 
1792  return count;
1793 }
1794 
1795 
1796 
1808 int
1810  rt_band band, int exclude_nodata_value,
1811  double *searchset, int searchcount,
1812  rt_pixel *pixels
1813 ) {
1814  int x;
1815  int y;
1816  int i;
1817  double pixval;
1818  int err;
1819  int count = 0;
1820  int isnodata = 0;
1821  int isequal = 0;
1822 
1823  rt_pixel pixel = NULL;
1824 
1825  assert(NULL != band);
1826  assert(NULL != pixels);
1827  assert(NULL != searchset && searchcount > 0);
1828 
1829  if (!band->hasnodata)
1830  exclude_nodata_value = FALSE;
1831  /* band is NODATA and exclude_nodata_value = TRUE, nothing to search */
1832  else if (exclude_nodata_value && band->isnodata) {
1833  RASTER_DEBUG(4, "Pixels cannot be searched as band is NODATA and excluding NODATA values");
1834  return 0;
1835  }
1836 
1837  for (x = 0; x < band->width; x++) {
1838  for (y = 0; y < band->height; y++) {
1839  err = rt_band_get_pixel(band, x, y, &pixval, &isnodata);
1840  if (err != ES_NONE) {
1841  rterror("rt_band_get_pixel_of_value: Cannot get band pixel");
1842  return -1;
1843  }
1844  else if (exclude_nodata_value && isnodata)
1845  continue;
1846 
1847  for (i = 0; i < searchcount; i++) {
1848  if (rt_pixtype_compare_clamped_values(band->pixtype, searchset[i], pixval, &isequal) != ES_NONE) {
1849  continue;
1850  }
1851 
1852  if (FLT_NEQ(pixval, searchset[i]) || !isequal)
1853  continue;
1854 
1855  /* match found */
1856  count++;
1857  if (*pixels == NULL)
1858  *pixels = (rt_pixel) rtalloc(sizeof(struct rt_pixel_t) * count);
1859  else
1860  *pixels = (rt_pixel) rtrealloc(*pixels, sizeof(struct rt_pixel_t) * count);
1861  if (*pixels == NULL) {
1862  rterror("rt_band_get_pixel_of_value: Could not allocate memory for pixel(s)");
1863  return -1;
1864  }
1865 
1866  pixel = &((*pixels)[count - 1]);
1867  pixel->x = x;
1868  pixel->y = y;
1869  pixel->nodata = 0;
1870  pixel->value = pixval;
1871  }
1872  }
1873  }
1874 
1875  return count;
1876 }
1877 
1887 rt_band_get_nodata(rt_band band, double *nodata) {
1888  assert(NULL != band);
1889  assert(NULL != nodata);
1890 
1891  *nodata = band->nodataval;
1892 
1893  if (!band->hasnodata) {
1894  rterror("rt_band_get_nodata: Band has no NODATA value");
1895  return ES_ERROR;
1896  }
1897 
1898  return ES_NONE;
1899 }
1900 
1901 double
1903  assert(NULL != band);
1904 
1905  return rt_pixtype_get_min_value(band->pixtype);
1906 }
1907 
1908 int
1910  int i, j, err;
1911  double pxValue;
1912  int isnodata = 0;
1913 
1914  assert(NULL != band);
1915  band->isnodata = FALSE;
1916 
1917  /* Check if band has nodata value */
1918  if (!band->hasnodata) {
1919  RASTER_DEBUG(3, "Band has no NODATA value");
1920  return FALSE;
1921  }
1922 
1923  pxValue = band->nodataval;
1924 
1925  /* Check all pixels */
1926  for (i = 0; i < band->width; i++) {
1927  for (j = 0; j < band->height; j++) {
1928  err = rt_band_get_pixel(band, i, j, &pxValue, &isnodata);
1929  if (err != ES_NONE) {
1930  rterror("rt_band_check_is_nodata: Cannot get band pixel");
1931  return FALSE;
1932  }
1933  else if (!isnodata) {
1934  band->isnodata = FALSE;
1935  return FALSE;
1936  }
1937  }
1938  }
1939 
1940  band->isnodata = TRUE;
1941  return TRUE;
1942 }
1943 
1954 int
1956  int isequal = 0;
1957 
1958  assert(NULL != band);
1959 
1960  /* no NODATA, so never equal */
1961  if (!band->hasnodata)
1962  return 0;
1963 
1964  /* value is exactly NODATA */
1965  if (FLT_EQ(val, band->nodataval))
1966  return 2;
1967 
1968  /* ignore error from rt_pixtype_compare_clamped_values */
1970  band->pixtype,
1971  val, band->nodataval,
1972  &isequal
1973  );
1974 
1975  return isequal ? 1 : 0;
1976 }
1977 
1992  rt_band band,
1993  double val,
1994  double *newval, int *corrected
1995 ) {
1996  double minval = 0.;
1997 
1998  assert(NULL != band);
1999  assert(NULL != newval);
2000 
2001  if (corrected != NULL)
2002  *corrected = 0;
2003 
2004  /* no need to correct if clamped values IS NOT clamped NODATA */
2005  if (rt_band_clamped_value_is_nodata(band, val) != 1) {
2006  *newval = val;
2007  return ES_NONE;
2008  }
2009 
2010  minval = rt_pixtype_get_min_value(band->pixtype);
2011  *newval = val;
2012 
2013  switch (band->pixtype) {
2014  case PT_1BB:
2015  *newval = !band->nodataval;
2016  break;
2017  case PT_2BUI:
2018  if (rt_util_clamp_to_2BUI(val) == rt_util_clamp_to_2BUI(minval))
2019  (*newval)++;
2020  else
2021  (*newval)--;
2022  break;
2023  case PT_4BUI:
2024  if (rt_util_clamp_to_4BUI(val) == rt_util_clamp_to_4BUI(minval))
2025  (*newval)++;
2026  else
2027  (*newval)--;
2028  break;
2029  case PT_8BSI:
2030  if (rt_util_clamp_to_8BSI(val) == rt_util_clamp_to_8BSI(minval))
2031  (*newval)++;
2032  else
2033  (*newval)--;
2034  break;
2035  case PT_8BUI:
2036  if (rt_util_clamp_to_8BUI(val) == rt_util_clamp_to_8BUI(minval))
2037  (*newval)++;
2038  else
2039  (*newval)--;
2040  break;
2041  case PT_16BSI:
2042  if (rt_util_clamp_to_16BSI(val) == rt_util_clamp_to_16BSI(minval))
2043  (*newval)++;
2044  else
2045  (*newval)--;
2046  break;
2047  case PT_16BUI:
2048  if (rt_util_clamp_to_16BUI(val) == rt_util_clamp_to_16BUI(minval))
2049  (*newval)++;
2050  else
2051  (*newval)--;
2052  break;
2053  case PT_32BSI:
2054  if (rt_util_clamp_to_32BSI(val) == rt_util_clamp_to_32BSI(minval))
2055  (*newval)++;
2056  else
2057  (*newval)--;
2058  break;
2059  case PT_32BUI:
2060  if (rt_util_clamp_to_32BUI(val) == rt_util_clamp_to_32BUI(minval))
2061  (*newval)++;
2062  else
2063  (*newval)--;
2064  break;
2065  case PT_32BF:
2067  *newval += FLT_EPSILON;
2068  else
2069  *newval -= FLT_EPSILON;
2070  break;
2071  case PT_64BF:
2072  break;
2073  default:
2074  rterror("rt_band_corrected_clamped_value: Unknown pixeltype %d", band->pixtype);
2075  return ES_ERROR;
2076  }
2077 
2078  if (corrected != NULL)
2079  *corrected = 1;
2080 
2081  return ES_NONE;
2082 }
2083 
#define TRUE
Definition: dbfopen.c:73
#define FALSE
Definition: dbfopen.c:72
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
Definition: rt_context.c:219
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:159
#define FLT_NEQ(x, y)
Definition: librtcore.h:2386
#define RASTER_DEBUG(level, msg)
Definition: librtcore.h:302
int rt_util_gdal_register_all(int force_register_all)
Definition: rt_util.c:342
#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:731
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
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:808
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:676
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:149
#define FLT_EQ(x, y)
Definition: librtcore.h:2387
rt_raster rt_raster_from_gdal_dataset(GDALDatasetH ds)
Return a raster from a GDAL dataset.
Definition: rt_raster.c:2291
rt_resample_type
Definition: librtcore.h:1450
@ RT_BILINEAR
Definition: librtcore.h:1452
@ RT_NEAREST
Definition: librtcore.h:1451
uint8_t rt_util_clamp_to_2BUI(double value)
Definition: rt_util.c:40
void rtwarn(const char *fmt,...)
Definition: rt_context.c:244
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:389
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:94
pixel
Definition: pixval.py:91
nband
Definition: pixval.py:53
Definition: pixval.py:1
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
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:1809
rt_band rt_band_duplicate(rt_band band)
Create a new band duplicated from source band.
Definition: rt_band.c:287
uint16_t rt_band_get_width(rt_band band)
Return width of this band.
Definition: rt_band.c:640
void rt_band_set_hasnodata_flag(rt_band band, int flag)
Set hasnodata flag value.
Definition: rt_band.c:681
rt_errorstate rt_band_set_isnodata_flag(rt_band band, int flag)
Set isnodata flag value.
Definition: rt_band.c:695
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:363
rt_errorstate rt_band_load_offline_data(rt_band band)
Load offline band's data.
Definition: rt_band.c:429
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_band.c:674
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition: rt_band.c:1376
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
Definition: rt_band.c:714
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:1902
uint64_t rt_band_get_file_size(rt_band band)
Return file size in bytes.
Definition: rt_band.c:586
bool enable_outdb_rasters
Definition: rt_band.c:417
int rt_band_check_is_nodata(rt_band band)
Returns TRUE if the band is only nodata values.
Definition: rt_band.c:1909
rt_errorstate rt_band_set_nodata(rt_band band, double val, int *converted)
Set nodata value.
Definition: rt_band.c:733
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 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
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:1991
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:124
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:376
uint64_t rt_band_get_file_timestamp(rt_band band)
Return file timestamp.
Definition: rt_band.c:608
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:1221
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_band.c:1887
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
Definition: rt_band.c:631
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:199
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:1529
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
Definition: rt_band.c:400
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:1260
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:1955
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:659
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
uint16_t rt_band_get_height(rt_band band)
Return height of this band.
Definition: rt_band.c:649
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:1137
void * mem
Definition: librtcore.h:2480
union rt_band_t::@11 data
double value
Definition: librtcore.h:2491
uint8_t nodata
Definition: librtcore.h:2490