PostGIS  2.5.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 #include <stdio.h>
32 
33 #include "librtcore.h"
34 #include "librtcore_internal.h"
35 
36 #include "gdal_vrt.h"
37 
58 rt_band
60  uint16_t width, uint16_t height,
61  rt_pixtype pixtype,
62  uint32_t hasnodata, double nodataval,
63  uint8_t* data
64 ) {
65  rt_band band = NULL;
66 
67  assert(NULL != data);
68 
69  band = rtalloc(sizeof(struct rt_band_t));
70  if (band == NULL) {
71  rterror("rt_band_new_inline: Out of memory allocating rt_band");
72  return NULL;
73  }
74 
75  RASTER_DEBUGF(3, "Created rt_band @ %p with pixtype %s", band, rt_pixtype_name(pixtype));
76 
77  band->pixtype = pixtype;
78  band->offline = 0;
79  band->width = width;
80  band->height = height;
81  band->hasnodata = hasnodata ? 1 : 0;
82  band->isnodata = FALSE; /* we don't know what is in data, so must be FALSE */
83  band->nodataval = 0;
84  band->data.mem = data;
85  band->ownsdata = 0; /* we do NOT own this data!!! */
86  band->raster = NULL;
87 
88  RASTER_DEBUGF(3, "Created rt_band with dimensions %d x %d", band->width, band->height);
89 
90  /* properly set nodataval as it may need to be constrained to the data type */
91  if (hasnodata && rt_band_set_nodata(band, nodataval, NULL) != ES_NONE) {
92  rterror("rt_band_new_inline: Could not set NODATA value");
93  rt_band_destroy(band);
94  return NULL;
95  }
96 
97  return band;
98 }
99 
119 rt_band
121  uint16_t width, uint16_t height,
122  rt_pixtype pixtype,
123  uint32_t hasnodata, double nodataval,
124  uint8_t bandNum, const char* path
125 ) {
126  rt_band band = NULL;
127  int pathlen = 0;
128 
129  assert(NULL != path);
130 
131  band = rtalloc(sizeof(struct rt_band_t));
132  if (band == NULL) {
133  rterror("rt_band_new_offline: Out of memory allocating rt_band");
134  return NULL;
135  }
136 
137  RASTER_DEBUGF(3, "Created rt_band @ %p with pixtype %s",
138  band, rt_pixtype_name(pixtype)
139  );
140 
141  band->pixtype = pixtype;
142  band->offline = 1;
143  band->width = width;
144  band->height = height;
145  band->hasnodata = hasnodata ? 1 : 0;
146  band->nodataval = 0;
147  band->isnodata = FALSE; /* we don't know if the offline band is NODATA */
148  band->ownsdata = 0; /* offline, flag is useless as all offline data cache is owned internally */
149  band->raster = NULL;
150 
151  /* properly set nodataval as it may need to be constrained to the data type */
152  if (hasnodata && rt_band_set_nodata(band, nodataval, NULL) != ES_NONE) {
153  rterror("rt_band_new_offline: Could not set NODATA value");
154  rt_band_destroy(band);
155  return NULL;
156  }
157 
158  band->data.offline.bandNum = bandNum;
159 
160  /* memory for data.offline.path is managed internally */
161  pathlen = strlen(path);
162  band->data.offline.path = rtalloc(sizeof(char) * (pathlen + 1));
163  if (band->data.offline.path == NULL) {
164  rterror("rt_band_new_offline: Out of memory allocating offline path");
165  rt_band_destroy(band);
166  return NULL;
167  }
168  memcpy(band->data.offline.path, path, pathlen);
169  band->data.offline.path[pathlen] = '\0';
170 
171  band->data.offline.mem = NULL;
172 
173  return band;
174 }
175 
194 rt_band
196  uint16_t width,
197  uint16_t height,
198  int hasnodata,
199  double nodataval,
200  uint8_t bandNum,
201  const char* path,
202  int force
203 ) {
204  GDALDatasetH hdsSrc = NULL;
205  int nband = 0;
206  GDALRasterBandH hbandSrc = NULL;
207 
208  GDALDataType gdpixtype;
209  rt_pixtype pt = PT_END;
210 
211  /* open outdb raster file */
213  hdsSrc = rt_util_gdal_open(path, GA_ReadOnly, 1);
214  if (hdsSrc == NULL && !force) {
215  rterror("rt_band_new_offline_from_path: Cannot open offline raster: %s", path);
216  return NULL;
217  }
218 
219  nband = GDALGetRasterCount(hdsSrc);
220  if (!nband && !force) {
221  rterror("rt_band_new_offline_from_path: No bands found in offline raster: %s", path);
222  GDALClose(hdsSrc);
223  return NULL;
224  }
225  /* bandNum is 1-based */
226  else if (bandNum > nband && !force) {
227  rterror(
228  "rt_band_new_offline_from_path: Specified band %d not found in offline raster: %s",
229  bandNum,
230  path
231  );
232  GDALClose(hdsSrc);
233  return NULL;
234  }
235 
236  hbandSrc = GDALGetRasterBand(hdsSrc, bandNum);
237  if (hbandSrc == NULL && !force) {
238  rterror(
239  "rt_band_new_offline_from_path: Cannot get band %d from GDAL dataset",
240  bandNum
241  );
242  GDALClose(hdsSrc);
243  return NULL;
244  }
245 
246  gdpixtype = GDALGetRasterDataType(hbandSrc);
247  pt = rt_util_gdal_datatype_to_pixtype(gdpixtype);
248  if (pt == PT_END && !force) {
249  rterror(
250  "rt_band_new_offline_from_path: Unsupported pixel type %s of band %d from GDAL dataset",
251  GDALGetDataTypeName(gdpixtype),
252  bandNum
253  );
254  GDALClose(hdsSrc);
255  return NULL;
256  }
257 
258  /* use out-db band's nodata value if nodataval not already set */
259  if (!hasnodata)
260  nodataval = GDALGetRasterNoDataValue(hbandSrc, &hasnodata);
261 
262  GDALClose(hdsSrc);
263 
264  return rt_band_new_offline(
265  width, height,
266  pt,
267  hasnodata, nodataval,
268  bandNum - 1, path
269  );
270 }
271 
282 rt_band
284  rt_band rtn = NULL;
285 
286  assert(band != NULL);
287 
288  /* offline */
289  if (band->offline) {
290  rtn = rt_band_new_offline(
291  band->width, band->height,
292  band->pixtype,
293  band->hasnodata, band->nodataval,
294  band->data.offline.bandNum, (const char *) band->data.offline.path
295  );
296  }
297  /* online */
298  else {
299  uint8_t *data = NULL;
300  data = rtalloc(rt_pixtype_size(band->pixtype) * band->width * band->height);
301  if (data == NULL) {
302  rterror("rt_band_duplicate: Out of memory allocating online band data");
303  return NULL;
304  }
305  memcpy(data, band->data.mem, rt_pixtype_size(band->pixtype) * band->width * band->height);
306 
307  rtn = rt_band_new_inline(
308  band->width, band->height,
309  band->pixtype,
310  band->hasnodata, band->nodataval,
311  data
312  );
313  rt_band_set_ownsdata_flag(rtn, 1); /* we DO own this data!!! */
314  }
315 
316  if (rtn == NULL) {
317  rterror("rt_band_duplicate: Could not copy band");
318  return NULL;
319  }
320 
321  return rtn;
322 }
323 
324 int
326  assert(NULL != band);
327  return band->offline ? 1 : 0;
328 }
329 
335 void
337  if (band == NULL)
338  return;
339 
340  RASTER_DEBUGF(3, "Destroying rt_band @ %p", band);
341 
342  /* offline band */
343  if (band->offline) {
344  /* memory cache */
345  if (band->data.offline.mem != NULL)
346  rtdealloc(band->data.offline.mem);
347  /* offline file path */
348  if (band->data.offline.path != NULL)
349  rtdealloc(band->data.offline.path);
350  }
351  /* inline band and band owns the data */
352  else if (band->data.mem != NULL && band->ownsdata)
353  rtdealloc(band->data.mem);
354 
355  rtdealloc(band);
356 }
357 
358 const char*
360 
361  assert(NULL != band);
362 
363 
364  if (!band->offline) {
365  RASTER_DEBUG(3, "rt_band_get_ext_path: Band is not offline");
366  return NULL;
367  }
368  return band->data.offline.path;
369 }
370 
373  assert(NULL != band);
374  assert(NULL != bandnum);
375 
376  *bandnum = 0;
377 
378  if (!band->offline) {
379  RASTER_DEBUG(3, "rt_band_get_ext_band_num: Band is not offline");
380  return ES_ERROR;
381  }
382 
383  *bandnum = band->data.offline.bandNum;
384 
385  return ES_NONE;
386 }
387 
395 void *
397  assert(NULL != band);
398 
399  if (band->offline) {
400  if (band->data.offline.mem != NULL)
401  return band->data.offline.mem;
402 
403  if (rt_band_load_offline_data(band) != ES_NONE)
404  return NULL;
405  else
406  return band->data.offline.mem;
407  }
408  else
409  return band->data.mem;
410 }
411 
412 /* variable for PostgreSQL GUC: postgis.enable_outdb_rasters */
414 
426  GDALDatasetH hdsSrc = NULL;
427  int nband = 0;
428  VRTDatasetH hdsDst = NULL;
429  VRTSourcedRasterBandH hbandDst = NULL;
430  double ogt[6] = {0};
431  double offset[2] = {0};
432 
433  rt_raster _rast = NULL;
434  rt_band _band = NULL;
435  int aligned = 0;
436  int err = ES_NONE;
437 
438  assert(band != NULL);
439  assert(band->raster != NULL);
440 
441  if (!band->offline) {
442  rterror("rt_band_load_offline_data: Band is not offline");
443  return ES_ERROR;
444  }
445  else if (!strlen(band->data.offline.path)) {
446  rterror("rt_band_load_offline_data: Offline band does not a have a specified file");
447  return ES_ERROR;
448  }
449 
450  /* offline_data is disabled */
451  if (!enable_outdb_rasters) {
452  rterror("rt_band_load_offline_data: Access to offline bands disabled");
453  return ES_ERROR;
454  }
455 
457  hdsSrc = rt_util_gdal_open(band->data.offline.path, GA_ReadOnly, 1);
458  if (hdsSrc == NULL) {
459  rterror("rt_band_load_offline_data: Cannot open offline raster: %s", band->data.offline.path);
460  return ES_ERROR;
461  }
462 
463  /* # of bands */
464  nband = GDALGetRasterCount(hdsSrc);
465  if (!nband) {
466  rterror("rt_band_load_offline_data: No bands found in offline raster: %s", band->data.offline.path);
467  GDALClose(hdsSrc);
468  return ES_ERROR;
469  }
470  /* bandNum is 0-based */
471  else if (band->data.offline.bandNum + 1 > nband) {
472  rterror("rt_band_load_offline_data: Specified band %d not found in offline raster: %s", band->data.offline.bandNum, band->data.offline.path);
473  GDALClose(hdsSrc);
474  return ES_ERROR;
475  }
476 
477  /* get offline raster's geotransform */
478  if (GDALGetGeoTransform(hdsSrc, ogt) != CE_None) {
479  RASTER_DEBUG(4, "Using default geotransform matrix (0, 1, 0, 0, 0, -1)");
480  ogt[0] = 0;
481  ogt[1] = 1;
482  ogt[2] = 0;
483  ogt[3] = 0;
484  ogt[4] = 0;
485  ogt[5] = -1;
486  }
487  RASTER_DEBUGF(3, "Offline geotransform (%f, %f, %f, %f, %f, %f)",
488  ogt[0], ogt[1], ogt[2], ogt[3], ogt[4], ogt[5]);
489 
490  /* are rasters aligned? */
491  _rast = rt_raster_new(1, 1);
493  rt_raster_set_srid(_rast, band->raster->srid);
494  err = rt_raster_same_alignment(band->raster, _rast, &aligned, NULL);
495  rt_raster_destroy(_rast);
496 
497  if (err != ES_NONE) {
498  rterror("rt_band_load_offline_data: Could not test alignment of in-db representation of out-db raster");
499  GDALClose(hdsSrc);
500  return ES_ERROR;
501  }
502  else if (!aligned) {
503  rtwarn("The in-db representation of the out-db raster is not aligned. Band data may be incorrect");
504  }
505 
506  /* get offsets */
508  band->raster,
509  ogt[0], ogt[3],
510  &(offset[0]), &(offset[1]),
511  NULL
512  );
513 
514  RASTER_DEBUGF(4, "offsets: (%f, %f)", offset[0], offset[1]);
515 
516  /* create VRT dataset */
517  hdsDst = VRTCreate(band->width, band->height);
518  GDALSetGeoTransform(hdsDst, ogt);
519  /*
520  GDALSetDescription(hdsDst, "/tmp/offline.vrt");
521  */
522 
523  /* add band as simple sources */
524  GDALAddBand(hdsDst, rt_util_pixtype_to_gdal_datatype(band->pixtype), NULL);
525  hbandDst = (VRTSourcedRasterBandH) GDALGetRasterBand(hdsDst, 1);
526 
527  if (band->hasnodata)
528  GDALSetRasterNoDataValue(hbandDst, band->nodataval);
529 
530  VRTAddSimpleSource(
531  hbandDst, GDALGetRasterBand(hdsSrc, band->data.offline.bandNum + 1),
532  fabs(offset[0]), fabs(offset[1]),
533  band->width, band->height,
534  0, 0,
535  band->width, band->height,
536  "near", VRT_NODATA_UNSET
537  );
538 
539  /* make sure VRT reflects all changes */
540  VRTFlushCache(hdsDst);
541 
542  /* convert VRT dataset to rt_raster */
543  _rast = rt_raster_from_gdal_dataset(hdsDst);
544 
545  GDALClose(hdsDst);
546  GDALClose(hdsSrc);
547  /*
548  {
549  FILE *fp;
550  fp = fopen("/tmp/gdal_open_files.log", "w");
551  GDALDumpOpenDatasets(fp);
552  fclose(fp);
553  }
554  */
555 
556  if (_rast == NULL) {
557  rterror("rt_band_load_offline_data: Cannot load data from offline raster: %s", band->data.offline.path);
558  return ES_ERROR;
559  }
560 
561  _band = rt_raster_get_band(_rast, 0);
562  if (_band == NULL) {
563  rterror("rt_band_load_offline_data: Cannot load data from offline raster: %s", band->data.offline.path);
564  rt_raster_destroy(_rast);
565  return ES_ERROR;
566  }
567 
568  /* band->data.offline.mem not NULL, free first */
569  if (band->data.offline.mem != NULL) {
570  rtdealloc(band->data.offline.mem);
571  band->data.offline.mem = NULL;
572  }
573 
574  band->data.offline.mem = _band->data.mem;
575 
576  rtdealloc(_band); /* cannot use rt_band_destroy */
577  rt_raster_destroy(_rast);
578 
579  return ES_NONE;
580 }
581 
584 
585  assert(NULL != band);
586 
587 
588  return band->pixtype;
589 }
590 
591 uint16_t
593 
594  assert(NULL != band);
595 
596 
597  return band->width;
598 }
599 
600 uint16_t
602 
603  assert(NULL != band);
604 
605 
606  return band->height;
607 }
608 
609 /* Get ownsdata flag */
610 int
612  assert(NULL != band);
613 
614  return band->ownsdata ? 1 : 0;
615 }
616 
617 /* set ownsdata flag */
618 void
620  assert(NULL != band);
621 
622  band->ownsdata = flag ? 1 : 0;
623 }
624 
625 int
627  assert(NULL != band);
628 
629  return band->hasnodata ? 1 : 0;
630 }
631 
632 void
634 
635  assert(NULL != band);
636 
637  band->hasnodata = (flag) ? 1 : 0;
638 
639  /* isnodata depends on hasnodata */
640  if (!band->hasnodata && band->isnodata) {
641  RASTER_DEBUG(3, "Setting isnodata to FALSE as band no longer has NODATA");
642  band->isnodata = 0;
643  }
644 }
645 
648  assert(NULL != band);
649 
650  if (!band->hasnodata) {
651  /* silently permit setting isnodata flag to FALSE */
652  if (!flag)
653  band->isnodata = 0;
654  else {
655  rterror("rt_band_set_isnodata_flag: Cannot set isnodata flag as band has no NODATA");
656  return ES_ERROR;
657  }
658  }
659  else
660  band->isnodata = (flag) ? 1 : 0;
661 
662  return ES_NONE;
663 }
664 
665 int
667  assert(NULL != band);
668 
669  if (band->hasnodata)
670  return band->isnodata ? 1 : 0;
671  else
672  return 0;
673 }
674 
685 rt_band_set_nodata(rt_band band, double val, int *converted) {
686  rt_pixtype pixtype = PT_END;
687  int32_t checkvalint = 0;
688  uint32_t checkvaluint = 0;
689  float checkvalfloat = 0;
690  double checkvaldouble = 0;
691 
692  assert(NULL != band);
693 
694  if (converted != NULL)
695  *converted = 0;
696 
697  pixtype = band->pixtype;
698 
699  RASTER_DEBUGF(3, "rt_band_set_nodata: setting nodata value %g with band type %s", val, rt_pixtype_name(pixtype));
700 
701  /* return -1 on out of range */
702  switch (pixtype) {
703  case PT_1BB: {
704  band->nodataval = rt_util_clamp_to_1BB(val);
705  checkvalint = band->nodataval;
706  break;
707  }
708  case PT_2BUI: {
709  band->nodataval = rt_util_clamp_to_2BUI(val);
710  checkvalint = band->nodataval;
711  break;
712  }
713  case PT_4BUI: {
714  band->nodataval = rt_util_clamp_to_4BUI(val);
715  checkvalint = band->nodataval;
716  break;
717  }
718  case PT_8BSI: {
719  band->nodataval = rt_util_clamp_to_8BSI(val);
720  checkvalint = band->nodataval;
721  break;
722  }
723  case PT_8BUI: {
724  band->nodataval = rt_util_clamp_to_8BUI(val);
725  checkvalint = band->nodataval;
726  break;
727  }
728  case PT_16BSI: {
729  band->nodataval = rt_util_clamp_to_16BSI(val);
730  checkvalint = band->nodataval;
731  break;
732  }
733  case PT_16BUI: {
734  band->nodataval = rt_util_clamp_to_16BUI(val);
735  checkvalint = band->nodataval;
736  break;
737  }
738  case PT_32BSI: {
739  band->nodataval = rt_util_clamp_to_32BSI(val);
740  checkvalint = band->nodataval;
741  break;
742  }
743  case PT_32BUI: {
744  band->nodataval = rt_util_clamp_to_32BUI(val);
745  checkvaluint = band->nodataval;
746  break;
747  }
748  case PT_32BF: {
749  band->nodataval = rt_util_clamp_to_32F(val);
750  checkvalfloat = band->nodataval;
751  break;
752  }
753  case PT_64BF: {
754  band->nodataval = val;
755  checkvaldouble = band->nodataval;
756  break;
757  }
758  default: {
759  rterror("rt_band_set_nodata: Unknown pixeltype %d", pixtype);
760  band->hasnodata = 0;
761  return ES_ERROR;
762  }
763  }
764 
765  RASTER_DEBUGF(3, "rt_band_set_nodata: band->hasnodata = %d", band->hasnodata);
766  RASTER_DEBUGF(3, "rt_band_set_nodata: band->nodataval = %f", band->nodataval);
767  /* the nodata value was just set, so this band has NODATA */
768  band->hasnodata = 1;
769 
770  /* also set isnodata flag to false */
771  band->isnodata = 0;
772 
774  val,
775  checkvalint, checkvaluint,
776  checkvalfloat, checkvaldouble,
777  pixtype
778  ) && converted != NULL) {
779  *converted = 1;
780  }
781 
782  return ES_NONE;
783 }
784 
806  rt_band band,
807  int x, int y,
808  void *vals, uint32_t len
809 ) {
810  rt_pixtype pixtype = PT_END;
811  int size = 0;
812  uint8_t *data = NULL;
813  uint32_t offset = 0;
814 
815  assert(NULL != band);
816  assert(vals != NULL && len > 0);
817 
818  RASTER_DEBUGF(3, "length of values = %d", len);
819 
820  if (band->offline) {
821  rterror("rt_band_set_pixel_line not implemented yet for OFFDB bands");
822  return ES_ERROR;
823  }
824 
825  pixtype = band->pixtype;
826  size = rt_pixtype_size(pixtype);
827 
828  if (
829  x < 0 || x >= band->width ||
830  y < 0 || y >= band->height
831  ) {
832  rterror("rt_band_set_pixel_line: Coordinates out of range (%d, %d) vs (%d, %d)", x, y, band->width, band->height);
833  return ES_ERROR;
834  }
835 
836  data = rt_band_get_data(band);
837  offset = x + (y * band->width);
838  RASTER_DEBUGF(4, "offset = %d", offset);
839 
840  /* make sure len of values to copy don't exceed end of data */
841  if (len > (band->width * band->height) - offset) {
842  rterror("rt_band_set_pixel_line: Could not apply pixels as values length exceeds end of data");
843  return ES_ERROR;
844  }
845 
846  switch (pixtype) {
847  case PT_1BB:
848  case PT_2BUI:
849  case PT_4BUI:
850  case PT_8BUI:
851  case PT_8BSI: {
852  uint8_t *ptr = data;
853  ptr += offset;
854  memcpy(ptr, vals, size * len);
855  break;
856  }
857  case PT_16BUI: {
858  uint16_t *ptr = (uint16_t *) data;
859  ptr += offset;
860  memcpy(ptr, vals, size * len);
861  break;
862  }
863  case PT_16BSI: {
864  int16_t *ptr = (int16_t *) data;
865  ptr += offset;
866  memcpy(ptr, vals, size * len);
867  break;
868  }
869  case PT_32BUI: {
870  uint32_t *ptr = (uint32_t *) data;
871  ptr += offset;
872  memcpy(ptr, vals, size * len);
873  break;
874  }
875  case PT_32BSI: {
876  int32_t *ptr = (int32_t *) data;
877  ptr += offset;
878  memcpy(ptr, vals, size * len);
879  break;
880  }
881  case PT_32BF: {
882  float *ptr = (float *) data;
883  ptr += offset;
884  memcpy(ptr, vals, size * len);
885  break;
886  }
887  case PT_64BF: {
888  double *ptr = (double *) data;
889  ptr += offset;
890  memcpy(ptr, vals, size * len);
891  break;
892  }
893  default: {
894  rterror("rt_band_set_pixel_line: Unknown pixeltype %d", pixtype);
895  return ES_ERROR;
896  }
897  }
898 
899 #if POSTGIS_DEBUG_LEVEL > 0
900  {
901  double value;
902  rt_band_get_pixel(band, x, y, &value, NULL);
903  RASTER_DEBUGF(4, "pixel at (%d, %d) = %f", x, y, value);
904  }
905 #endif
906 
907  /* set band's isnodata flag to FALSE */
908  if (rt_band_get_hasnodata_flag(band))
909  rt_band_set_isnodata_flag(band, 0);
910 
911  return ES_NONE;
912 }
913 
927  rt_band band,
928  int x, int y,
929  double val,
930  int *converted
931 ) {
932  rt_pixtype pixtype = PT_END;
933  unsigned char* data = NULL;
934  uint32_t offset = 0;
935 
936  int32_t checkvalint = 0;
937  uint32_t checkvaluint = 0;
938  float checkvalfloat = 0;
939  double checkvaldouble = 0;
940 
941  assert(NULL != band);
942 
943  if (converted != NULL)
944  *converted = 0;
945 
946  if (band->offline) {
947  rterror("rt_band_set_pixel not implemented yet for OFFDB bands");
948  return ES_ERROR;
949  }
950 
951  pixtype = band->pixtype;
952 
953  if (
954  x < 0 || x >= band->width ||
955  y < 0 || y >= band->height
956  ) {
957  rterror("rt_band_set_pixel: Coordinates out of range");
958  return ES_ERROR;
959  }
960 
961  /* check that clamped value isn't clamped NODATA */
962  if (band->hasnodata && pixtype != PT_64BF) {
963  double newval;
964  int corrected;
965 
966  rt_band_corrected_clamped_value(band, val, &newval, &corrected);
967 
968  if (corrected) {
969 #if POSTGIS_RASTER_WARN_ON_TRUNCATION > 0
970  rtwarn("Value for pixel %d x %d has been corrected as clamped value becomes NODATA", x, y);
971 #endif
972  val = newval;
973 
974  if (converted != NULL)
975  *converted = 1;
976  }
977  }
978 
979  data = rt_band_get_data(band);
980  offset = x + (y * band->width);
981 
982  switch (pixtype) {
983  case PT_1BB: {
984  data[offset] = rt_util_clamp_to_1BB(val);
985  checkvalint = data[offset];
986  break;
987  }
988  case PT_2BUI: {
989  data[offset] = rt_util_clamp_to_2BUI(val);
990  checkvalint = data[offset];
991  break;
992  }
993  case PT_4BUI: {
994  data[offset] = rt_util_clamp_to_4BUI(val);
995  checkvalint = data[offset];
996  break;
997  }
998  case PT_8BSI: {
999  data[offset] = rt_util_clamp_to_8BSI(val);
1000  checkvalint = (int8_t) data[offset];
1001  break;
1002  }
1003  case PT_8BUI: {
1004  data[offset] = rt_util_clamp_to_8BUI(val);
1005  checkvalint = data[offset];
1006  break;
1007  }
1008  case PT_16BSI: {
1009  int16_t *ptr = (int16_t*) data; /* we assume correct alignment */
1010  ptr[offset] = rt_util_clamp_to_16BSI(val);
1011  checkvalint = (int16_t) ptr[offset];
1012  break;
1013  }
1014  case PT_16BUI: {
1015  uint16_t *ptr = (uint16_t*) data; /* we assume correct alignment */
1016  ptr[offset] = rt_util_clamp_to_16BUI(val);
1017  checkvalint = ptr[offset];
1018  break;
1019  }
1020  case PT_32BSI: {
1021  int32_t *ptr = (int32_t*) data; /* we assume correct alignment */
1022  ptr[offset] = rt_util_clamp_to_32BSI(val);
1023  checkvalint = (int32_t) ptr[offset];
1024  break;
1025  }
1026  case PT_32BUI: {
1027  uint32_t *ptr = (uint32_t*) data; /* we assume correct alignment */
1028  ptr[offset] = rt_util_clamp_to_32BUI(val);
1029  checkvaluint = ptr[offset];
1030  break;
1031  }
1032  case PT_32BF: {
1033  float *ptr = (float*) data; /* we assume correct alignment */
1034  ptr[offset] = rt_util_clamp_to_32F(val);
1035  checkvalfloat = ptr[offset];
1036  break;
1037  }
1038  case PT_64BF: {
1039  double *ptr = (double*) data; /* we assume correct alignment */
1040  ptr[offset] = val;
1041  checkvaldouble = ptr[offset];
1042  break;
1043  }
1044  default: {
1045  rterror("rt_band_set_pixel: Unknown pixeltype %d", pixtype);
1046  return ES_ERROR;
1047  }
1048  }
1049 
1050  /* If the stored value is not NODATA, reset the isnodata flag */
1051  if (!rt_band_clamped_value_is_nodata(band, val)) {
1052  RASTER_DEBUG(3, "Band has a value that is not NODATA. Setting isnodata to FALSE");
1053  band->isnodata = FALSE;
1054  }
1055 
1056  /* Overflow checking */
1058  val,
1059  checkvalint, checkvaluint,
1060  checkvalfloat, checkvaldouble,
1061  pixtype
1062  ) && converted != NULL) {
1063  *converted = 1;
1064  }
1065 
1066  return ES_NONE;
1067 }
1068 
1090  rt_band band,
1091  int x, int y,
1092  uint16_t len,
1093  void **vals, uint16_t *nvals
1094 ) {
1095  uint8_t *_vals = NULL;
1096  int pixsize = 0;
1097  uint8_t *data = NULL;
1098  uint32_t offset = 0;
1099  uint16_t _nvals = 0;
1100  int maxlen = 0;
1101  uint8_t *ptr = NULL;
1102 
1103  assert(NULL != band);
1104  assert(vals != NULL && nvals != NULL);
1105 
1106  /* initialize to no values */
1107  *nvals = 0;
1108 
1109  if (
1110  x < 0 || x >= band->width ||
1111  y < 0 || y >= band->height
1112  ) {
1113  rtwarn("Attempting to get pixel values with out of range raster coordinates: (%d, %d)", x, y);
1114  return ES_ERROR;
1115  }
1116 
1117  if (len < 1)
1118  return ES_NONE;
1119 
1120  data = rt_band_get_data(band);
1121  if (data == NULL) {
1122  rterror("rt_band_get_pixel_line: Cannot get band data");
1123  return ES_ERROR;
1124  }
1125 
1126  /* +1 for the nodata value */
1127  offset = x + (y * band->width);
1128  RASTER_DEBUGF(4, "offset = %d", offset);
1129 
1130  pixsize = rt_pixtype_size(band->pixtype);
1131  RASTER_DEBUGF(4, "pixsize = %d", pixsize);
1132 
1133  /* cap _nvals so that it doesn't overflow */
1134  _nvals = len;
1135  maxlen = band->width * band->height;
1136 
1137  if (((int) (offset + _nvals)) > maxlen) {
1138  _nvals = maxlen - offset;
1139  rtwarn("Limiting returning number values to %d", _nvals);
1140  }
1141  RASTER_DEBUGF(4, "_nvals = %d", _nvals);
1142 
1143  ptr = data + (offset * pixsize);
1144 
1145  _vals = rtalloc(_nvals * pixsize);
1146  if (_vals == NULL) {
1147  rterror("rt_band_get_pixel_line: Could not allocate memory for pixel values");
1148  return ES_ERROR;
1149  }
1150 
1151  /* copy pixels */
1152  memcpy(_vals, ptr, _nvals * pixsize);
1153 
1154  *vals = _vals;
1155  *nvals = _nvals;
1156 
1157  return ES_NONE;
1158 }
1159 
1174  rt_band band,
1175  int x, int y,
1176  double *value,
1177  int *nodata
1178 ) {
1179  rt_pixtype pixtype = PT_END;
1180  uint8_t* data = NULL;
1181  uint32_t offset = 0;
1182 
1183  assert(NULL != band);
1184  assert(NULL != value);
1185 
1186  /* set nodata to 0 */
1187  if (nodata != NULL)
1188  *nodata = 0;
1189 
1190  if (
1191  x < 0 || x >= band->width ||
1192  y < 0 || y >= band->height
1193  ) {
1194  rtwarn("Attempting to get pixel value with out of range raster coordinates: (%d, %d)", x, y);
1195  return ES_ERROR;
1196  }
1197 
1198  /* band is NODATA */
1199  if (band->isnodata) {
1200  RASTER_DEBUG(3, "Band's isnodata flag is TRUE. Returning NODATA value");
1201  *value = band->nodataval;
1202  if (nodata != NULL) *nodata = 1;
1203  return ES_NONE;
1204  }
1205 
1206  data = rt_band_get_data(band);
1207  if (data == NULL) {
1208  rterror("rt_band_get_pixel: Cannot get band data");
1209  return ES_ERROR;
1210  }
1211 
1212  /* +1 for the nodata value */
1213  offset = x + (y * band->width);
1214 
1215  pixtype = band->pixtype;
1216 
1217  switch (pixtype) {
1218  case PT_1BB:
1219 #ifdef OPTIMIZE_SPACE
1220  {
1221  int byteOffset = offset / 8;
1222  int bitOffset = offset % 8;
1223  data += byteOffset;
1224 
1225  /* Bit to set is bitOffset into data */
1226  *value = getBits(data, val, 1, bitOffset);
1227  break;
1228  }
1229 #endif
1230  case PT_2BUI:
1231 #ifdef OPTIMIZE_SPACE
1232  {
1233  int byteOffset = offset / 4;
1234  int bitOffset = offset % 4;
1235  data += byteOffset;
1236 
1237  /* Bits to set start at bitOffset into data */
1238  *value = getBits(data, val, 2, bitOffset);
1239  break;
1240  }
1241 #endif
1242  case PT_4BUI:
1243 #ifdef OPTIMIZE_SPACE
1244  {
1245  int byteOffset = offset / 2;
1246  int bitOffset = offset % 2;
1247  data += byteOffset;
1248 
1249  /* Bits to set start at bitOffset into data */
1250  *value = getBits(data, val, 2, bitOffset);
1251  break;
1252  }
1253 #endif
1254  case PT_8BSI: {
1255  int8_t val = data[offset];
1256  *value = val;
1257  break;
1258  }
1259  case PT_8BUI: {
1260  uint8_t val = data[offset];
1261  *value = val;
1262  break;
1263  }
1264  case PT_16BSI: {
1265  int16_t *ptr = (int16_t*) data; /* we assume correct alignment */
1266  *value = ptr[offset];
1267  break;
1268  }
1269  case PT_16BUI: {
1270  uint16_t *ptr = (uint16_t*) data; /* we assume correct alignment */
1271  *value = ptr[offset];
1272  break;
1273  }
1274  case PT_32BSI: {
1275  int32_t *ptr = (int32_t*) data; /* we assume correct alignment */
1276  *value = ptr[offset];
1277  break;
1278  }
1279  case PT_32BUI: {
1280  uint32_t *ptr = (uint32_t*) data; /* we assume correct alignment */
1281  *value = ptr[offset];
1282  break;
1283  }
1284  case PT_32BF: {
1285  float *ptr = (float*) data; /* we assume correct alignment */
1286  *value = ptr[offset];
1287  break;
1288  }
1289  case PT_64BF: {
1290  double *ptr = (double*) data; /* we assume correct alignment */
1291  *value = ptr[offset];
1292  break;
1293  }
1294  default: {
1295  rterror("rt_band_get_pixel: Unknown pixeltype %d", pixtype);
1296  return ES_ERROR;
1297  }
1298  }
1299 
1300  /* set NODATA flag */
1301  if (band->hasnodata && nodata != NULL) {
1302  if (rt_band_clamped_value_is_nodata(band, *value))
1303  *nodata = 1;
1304  }
1305 
1306  return ES_NONE;
1307 }
1308 
1327  rt_band band,
1328  int x, int y,
1329  uint16_t distancex, uint16_t distancey,
1330  int exclude_nodata_value,
1331  rt_pixel *npixels
1332 ) {
1333  rt_pixel npixel = NULL;
1334  int extent[4] = {0};
1335  int max_extent[4] = {0};
1336  int d0 = 0;
1337  uint32_t distance[2] = {0};
1338  uint32_t _d[2] = {0};
1339  uint32_t i = 0;
1340  uint32_t j = 0;
1341  uint32_t k = 0;
1342  int _max = 0;
1343  int _x = 0;
1344  int _y = 0;
1345  int *_min = NULL;
1346  double pixval = 0;
1347  double minval = 0;
1348  uint32_t count = 0;
1349  int isnodata = 0;
1350 
1351  int inextent = 0;
1352 
1353  assert(NULL != band);
1354  assert(NULL != npixels);
1355 
1356  RASTER_DEBUG(3, "Starting");
1357 
1358  /* process distance */
1359  distance[0] = distancex;
1360  distance[1] = distancey;
1361 
1362  /* no distance, means get nearest pixels and return */
1363  if (!distance[0] && !distance[1])
1364  d0 = 1;
1365 
1366  RASTER_DEBUGF(4, "Selected pixel: %d x %d", x, y);
1367  RASTER_DEBUGF(4, "Distances: %d x %d", distance[0], distance[1]);
1368 
1369  /* shortcuts if outside band extent */
1370  if (
1371  exclude_nodata_value && (
1372  (x < 0 || x > band->width) ||
1373  (y < 0 || y > band->height)
1374  )
1375  ) {
1376  /* no distances specified, jump to pixel close to extent */
1377  if (d0) {
1378  if (x < 0)
1379  x = -1;
1380  else if (x > band->width)
1381  x = band->width;
1382 
1383  if (y < 0)
1384  y = -1;
1385  else if (y > band->height)
1386  y = band->height;
1387 
1388  RASTER_DEBUGF(4, "Moved selected pixel: %d x %d", x, y);
1389  }
1390  /*
1391  distances specified
1392  if distances won't capture extent of band, return 0
1393  */
1394  else if (
1395  ((x < 0 && (uint32_t) abs(x) > distance[0]) || (x - band->width >= (int)distance[0])) ||
1396  ((y < 0 && (uint32_t) abs(y) > distance[1]) || (y - band->height >= (int)distance[1]))
1397  ) {
1398  RASTER_DEBUG(4, "No nearest pixels possible for provided pixel and distances");
1399  return 0;
1400  }
1401  }
1402 
1403  /* no NODATA, exclude is FALSE */
1404  if (!band->hasnodata)
1405  exclude_nodata_value = FALSE;
1406  /* band is NODATA and excluding NODATA */
1407  else if (exclude_nodata_value && band->isnodata) {
1408  RASTER_DEBUG(4, "No nearest pixels possible as band is NODATA and excluding NODATA values");
1409  return 0;
1410  }
1411 
1412  /* determine the maximum distance to prevent an infinite loop */
1413  if (d0) {
1414  int a, b;
1415 
1416  /* X axis */
1417  a = abs(x);
1418  b = abs(x - band->width);
1419 
1420  if (a > b)
1421  distance[0] = a;
1422  else
1423  distance[0] = b;
1424 
1425  /* Y axis */
1426  a = abs(y);
1427  b = abs(y - band->height);
1428  if (a > b)
1429  distance[1] = a;
1430  else
1431  distance[1] = b;
1432 
1433  RASTER_DEBUGF(4, "Maximum distances: %d x %d", distance[0], distance[1]);
1434  }
1435 
1436  /* minimum possible value for pixel type */
1437  minval = rt_pixtype_get_min_value(band->pixtype);
1438  RASTER_DEBUGF(4, "pixtype: %s", rt_pixtype_name(band->pixtype));
1439  RASTER_DEBUGF(4, "minval: %f", minval);
1440 
1441  /* set variables */
1442  count = 0;
1443  *npixels = NULL;
1444 
1445  /* maximum extent */
1446  max_extent[0] = x - distance[0]; /* min X */
1447  max_extent[1] = y - distance[1]; /* min Y */
1448  max_extent[2] = x + distance[0]; /* max X */
1449  max_extent[3] = y + distance[1]; /* max Y */
1450  RASTER_DEBUGF(4, "Maximum Extent: (%d, %d, %d, %d)",
1451  max_extent[0], max_extent[1], max_extent[2], max_extent[3]);
1452 
1453  _d[0] = 0;
1454  _d[1] = 0;
1455  do {
1456  _d[0]++;
1457  _d[1]++;
1458 
1459  extent[0] = x - _d[0]; /* min x */
1460  extent[1] = y - _d[1]; /* min y */
1461  extent[2] = x + _d[0]; /* max x */
1462  extent[3] = y + _d[1]; /* max y */
1463 
1464  RASTER_DEBUGF(4, "Processing distances: %d x %d", _d[0], _d[1]);
1465  RASTER_DEBUGF(4, "Extent: (%d, %d, %d, %d)",
1466  extent[0], extent[1], extent[2], extent[3]);
1467 
1468  for (i = 0; i < 2; i++) {
1469 
1470  /* by row */
1471  if (i < 1)
1472  _max = extent[2] - extent[0] + 1;
1473  /* by column */
1474  else
1475  _max = extent[3] - extent[1] + 1;
1476  _max = abs(_max);
1477 
1478  for (j = 0; j < 2; j++) {
1479  /* by row */
1480  if (i < 1) {
1481  _x = extent[0];
1482  _min = &_x;
1483 
1484  /* top row */
1485  if (j < 1)
1486  _y = extent[1];
1487  /* bottom row */
1488  else
1489  _y = extent[3];
1490  }
1491  /* by column */
1492  else {
1493  _y = extent[1] + 1;
1494  _min = &_y;
1495 
1496  /* left column */
1497  if (j < 1) {
1498  _x = extent[0];
1499  _max -= 2;
1500  }
1501  /* right column */
1502  else
1503  _x = extent[2];
1504  }
1505 
1506  RASTER_DEBUGF(4, "_min, _max: %d, %d", *_min, _max);
1507  for (k = 0; k < (uint32_t) _max; k++) {
1508  /* check that _x and _y are not outside max extent */
1509  if (
1510  _x < max_extent[0] || _x > max_extent[2] ||
1511  _y < max_extent[1] || _y > max_extent[3]
1512  ) {
1513  (*_min)++;
1514  continue;
1515  }
1516 
1517  /* outside band extent, set to NODATA */
1518  if (
1519  (_x < 0 || _x >= band->width) ||
1520  (_y < 0 || _y >= band->height)
1521  ) {
1522  /* no NODATA, set to minimum possible value */
1523  if (!band->hasnodata)
1524  pixval = minval;
1525  /* has NODATA, use NODATA */
1526  else
1527  pixval = band->nodataval;
1528  RASTER_DEBUGF(4, "NODATA pixel outside band extent: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1529  inextent = 0;
1530  isnodata = 1;
1531  }
1532  else {
1533  if (rt_band_get_pixel(
1534  band,
1535  _x, _y,
1536  &pixval,
1537  &isnodata
1538  ) != ES_NONE) {
1539  rterror("rt_band_get_nearest_pixel: Could not get pixel value");
1540  if (count) rtdealloc(*npixels);
1541  return -1;
1542  }
1543  RASTER_DEBUGF(4, "Pixel: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1544  inextent = 1;
1545  }
1546 
1547  /* use pixval? */
1548  if (!exclude_nodata_value || (exclude_nodata_value && !isnodata)) {
1549  /* add pixel to result set */
1550  RASTER_DEBUGF(4, "Adding pixel to set of nearest pixels: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1551  count++;
1552 
1553  if (*npixels == NULL)
1554  *npixels = (rt_pixel) rtalloc(sizeof(struct rt_pixel_t) * count);
1555  else
1556  *npixels = (rt_pixel) rtrealloc(*npixels, sizeof(struct rt_pixel_t) * count);
1557  if (*npixels == NULL) {
1558  rterror("rt_band_get_nearest_pixel: Could not allocate memory for nearest pixel(s)");
1559  return -1;
1560  }
1561 
1562  npixel = &((*npixels)[count - 1]);
1563  npixel->x = _x;
1564  npixel->y = _y;
1565  npixel->value = pixval;
1566 
1567  /* special case for when outside band extent */
1568  if (!inextent && !band->hasnodata)
1569  npixel->nodata = 1;
1570  else
1571  npixel->nodata = 0;
1572  }
1573 
1574  (*_min)++;
1575  }
1576  }
1577  }
1578 
1579  /* distance threshholds met */
1580  if (_d[0] >= distance[0] && _d[1] >= distance[1])
1581  break;
1582  else if (d0 && count)
1583  break;
1584  }
1585  while (1);
1586 
1587  RASTER_DEBUGF(3, "Nearest pixels in return: %d", count);
1588 
1589  return count;
1590 }
1591 
1603 int
1605  rt_band band, int exclude_nodata_value,
1606  double *searchset, int searchcount,
1607  rt_pixel *pixels
1608 ) {
1609  int x;
1610  int y;
1611  int i;
1612  double pixval;
1613  int err;
1614  int count = 0;
1615  int isnodata = 0;
1616  int isequal = 0;
1617 
1618  rt_pixel pixel = NULL;
1619 
1620  assert(NULL != band);
1621  assert(NULL != pixels);
1622  assert(NULL != searchset && searchcount > 0);
1623 
1624  if (!band->hasnodata)
1625  exclude_nodata_value = FALSE;
1626  /* band is NODATA and exclude_nodata_value = TRUE, nothing to search */
1627  else if (exclude_nodata_value && band->isnodata) {
1628  RASTER_DEBUG(4, "Pixels cannot be searched as band is NODATA and excluding NODATA values");
1629  return 0;
1630  }
1631 
1632  for (x = 0; x < band->width; x++) {
1633  for (y = 0; y < band->height; y++) {
1634  err = rt_band_get_pixel(band, x, y, &pixval, &isnodata);
1635  if (err != ES_NONE) {
1636  rterror("rt_band_get_pixel_of_value: Cannot get band pixel");
1637  return -1;
1638  }
1639  else if (exclude_nodata_value && isnodata)
1640  continue;
1641 
1642  for (i = 0; i < searchcount; i++) {
1643  if (rt_pixtype_compare_clamped_values(band->pixtype, searchset[i], pixval, &isequal) != ES_NONE) {
1644  continue;
1645  }
1646 
1647  if (FLT_NEQ(pixval, searchset[i]) || !isequal)
1648  continue;
1649 
1650  /* match found */
1651  count++;
1652  if (*pixels == NULL)
1653  *pixels = (rt_pixel) rtalloc(sizeof(struct rt_pixel_t) * count);
1654  else
1655  *pixels = (rt_pixel) rtrealloc(*pixels, sizeof(struct rt_pixel_t) * count);
1656  if (*pixels == NULL) {
1657  rterror("rt_band_get_pixel_of_value: Could not allocate memory for pixel(s)");
1658  return -1;
1659  }
1660 
1661  pixel = &((*pixels)[count - 1]);
1662  pixel->x = x;
1663  pixel->y = y;
1664  pixel->nodata = 0;
1665  pixel->value = pixval;
1666  }
1667  }
1668  }
1669 
1670  return count;
1671 }
1672 
1682 rt_band_get_nodata(rt_band band, double *nodata) {
1683  assert(NULL != band);
1684  assert(NULL != nodata);
1685 
1686  *nodata = band->nodataval;
1687 
1688  if (!band->hasnodata) {
1689  rterror("rt_band_get_nodata: Band has no NODATA value");
1690  return ES_ERROR;
1691  }
1692 
1693  return ES_NONE;
1694 }
1695 
1696 double
1698  assert(NULL != band);
1699 
1700  return rt_pixtype_get_min_value(band->pixtype);
1701 }
1702 
1703 int
1705  int i, j, err;
1706  double pxValue;
1707  int isnodata = 0;
1708 
1709  assert(NULL != band);
1710 
1711  /* Check if band has nodata value */
1712  if (!band->hasnodata) {
1713  RASTER_DEBUG(3, "Band has no NODATA value");
1714  band->isnodata = FALSE;
1715  return FALSE;
1716  }
1717 
1718  pxValue = band->nodataval;
1719 
1720  /* Check all pixels */
1721  for (i = 0; i < band->width; i++) {
1722  for (j = 0; j < band->height; j++) {
1723  err = rt_band_get_pixel(band, i, j, &pxValue, &isnodata);
1724  if (err != ES_NONE) {
1725  rterror("rt_band_check_is_nodata: Cannot get band pixel");
1726  return FALSE;
1727  }
1728  else if (!isnodata) {
1729  band->isnodata = FALSE;
1730  return FALSE;
1731  }
1732  }
1733  }
1734 
1735  band->isnodata = TRUE;
1736  return TRUE;
1737 }
1738 
1749 int
1751  int isequal = 0;
1752 
1753  assert(NULL != band);
1754 
1755  /* no NODATA, so never equal */
1756  if (!band->hasnodata)
1757  return 0;
1758 
1759  /* value is exactly NODATA */
1760  if (FLT_EQ(val, band->nodataval))
1761  return 2;
1762 
1763  /* ignore error from rt_pixtype_compare_clamped_values */
1765  band->pixtype,
1766  val, band->nodataval,
1767  &isequal
1768  );
1769 
1770  return isequal ? 1 : 0;
1771 }
1772 
1787  rt_band band,
1788  double val,
1789  double *newval, int *corrected
1790 ) {
1791  double minval = 0.;
1792 
1793  assert(NULL != band);
1794  assert(NULL != newval);
1795 
1796  if (corrected != NULL)
1797  *corrected = 0;
1798 
1799  /* no need to correct if clamped values IS NOT clamped NODATA */
1800  if (rt_band_clamped_value_is_nodata(band, val) != 1) {
1801  *newval = val;
1802  return ES_NONE;
1803  }
1804 
1805  minval = rt_pixtype_get_min_value(band->pixtype);
1806  *newval = val;
1807 
1808  switch (band->pixtype) {
1809  case PT_1BB:
1810  *newval = !band->nodataval;
1811  break;
1812  case PT_2BUI:
1813  if (rt_util_clamp_to_2BUI(val) == rt_util_clamp_to_2BUI(minval))
1814  (*newval)++;
1815  else
1816  (*newval)--;
1817  break;
1818  case PT_4BUI:
1819  if (rt_util_clamp_to_4BUI(val) == rt_util_clamp_to_4BUI(minval))
1820  (*newval)++;
1821  else
1822  (*newval)--;
1823  break;
1824  case PT_8BSI:
1825  if (rt_util_clamp_to_8BSI(val) == rt_util_clamp_to_8BSI(minval))
1826  (*newval)++;
1827  else
1828  (*newval)--;
1829  break;
1830  case PT_8BUI:
1831  if (rt_util_clamp_to_8BUI(val) == rt_util_clamp_to_8BUI(minval))
1832  (*newval)++;
1833  else
1834  (*newval)--;
1835  break;
1836  case PT_16BSI:
1837  if (rt_util_clamp_to_16BSI(val) == rt_util_clamp_to_16BSI(minval))
1838  (*newval)++;
1839  else
1840  (*newval)--;
1841  break;
1842  case PT_16BUI:
1843  if (rt_util_clamp_to_16BUI(val) == rt_util_clamp_to_16BUI(minval))
1844  (*newval)++;
1845  else
1846  (*newval)--;
1847  break;
1848  case PT_32BSI:
1849  if (rt_util_clamp_to_32BSI(val) == rt_util_clamp_to_32BSI(minval))
1850  (*newval)++;
1851  else
1852  (*newval)--;
1853  break;
1854  case PT_32BUI:
1855  if (rt_util_clamp_to_32BUI(val) == rt_util_clamp_to_32BUI(minval))
1856  (*newval)++;
1857  else
1858  (*newval)--;
1859  break;
1860  case PT_32BF:
1862  *newval += FLT_EPSILON;
1863  else
1864  *newval -= FLT_EPSILON;
1865  break;
1866  case PT_64BF:
1867  break;
1868  default:
1869  rterror("rt_band_corrected_clamped_value: Unknown pixeltype %d", band->pixtype);
1870  return ES_ERROR;
1871  }
1872 
1873  if (corrected != NULL)
1874  *corrected = 1;
1875 
1876  return ES_NONE;
1877 }
1878 
rt_errorstate rt_band_set_pixel(rt_band band, int x, int y, double val, int *converted)
Set single pixel&#39;s value.
Definition: rt_band.c:926
char enable_outdb_rasters
Definition: rt_band.c:413
int32_t rt_util_clamp_to_32BSI(double value)
Definition: rt_util.c:69
rt_errorstate rt_band_set_nodata(rt_band band, double val, int *converted)
Set nodata value.
Definition: rt_band.c:685
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:195
int32_t srid
Definition: librtcore.h:2280
uint32_t rt_util_clamp_to_32BUI(double value)
Definition: rt_util.c:74
int rt_util_gdal_register_all(int force_register_all)
Definition: rt_util.c:334
pixel
Definition: pixval.py:90
rt_errorstate rt_raster_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
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:120
struct rt_pixel_t * rt_pixel
Definition: librtcore.h:147
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_band.c:626
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster&#39;s geotransform using 6-element array.
Definition: rt_raster.c:727
rt_raster raster
Definition: librtcore.h:2304
rt_pixtype pixtype
Definition: librtcore.h:2294
band
Definition: ovdump.py:57
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
Definition: rt_band.c:583
#define FLT_EQ(x, y)
Definition: librtcore.h:2214
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
Definition: rt_context.c:199
void * rtalloc(size_t size)
Wrappers used for managing memory.
Definition: rt_context.c:171
data
Definition: ovdump.py:103
void * rtrealloc(void *mem, size_t size)
Definition: rt_context.c:179
uint16_t height
Definition: librtcore.h:2297
double value
Definition: librtcore.h:2318
rt_errorstate
Enum definitions.
Definition: librtcore.h:179
uint16_t rt_band_get_width(rt_band band)
Return width of this band.
Definition: rt_band.c:592
rt_pixtype
Definition: librtcore.h:185
int rt_band_check_is_nodata(rt_band band)
Returns TRUE if the band is only nodata values.
Definition: rt_band.c:1704
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:1089
void rt_band_set_ownsdata_flag(rt_band band, int flag)
Definition: rt_band.c:619
unsigned int uint32_t
Definition: uthash.h:78
uint16_t rt_util_clamp_to_16BUI(double value)
Definition: rt_util.c:64
nband
Definition: pixval.py:52
rt_errorstate rt_band_get_ext_band_num(rt_band band, uint8_t *bandnum)
Return bands&#39; external band number (only valid when rt_band_is_offline returns non-zero).
Definition: rt_band.c:372
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:805
GDALDataType rt_util_pixtype_to_gdal_datatype(rt_pixtype pt)
Convert rt_pixtype to GDALDataType.
Definition: rt_util.c:118
Definition: pixval.py:1
void rtwarn(const char *fmt,...)
Definition: rt_context.c:224
rt_band rt_band_duplicate(rt_band band)
Create a new band duplicated from source band.
Definition: rt_band.c:283
int8_t rt_util_clamp_to_8BSI(double value)
Definition: rt_util.c:49
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:625
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
Definition: rt_raster.c:381
#define FLT_NEQ(x, y)
Definition: librtcore.h:2213
rt_pixtype rt_util_gdal_datatype_to_pixtype(GDALDataType gdt)
Convert GDALDataType to rt_pixtype.
Definition: rt_util.c:153
int8_t ownsdata
Definition: librtcore.h:2302
int count
Definition: genraster.py:56
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition: rt_band.c:1173
double nodataval
Definition: librtcore.h:2301
double rt_pixtype_get_min_value(rt_pixtype pixtype)
Return minimum value possible for pixel type.
Definition: rt_pixel.c:148
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster&#39;s SRID.
Definition: rt_raster.c:363
#define RASTER_DEBUGF(level, msg,...)
Definition: librtcore.h:299
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:82
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:806
uint8_t nodata
Definition: librtcore.h:2317
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
Definition: rt_raster.c:48
uint16_t width
Definition: librtcore.h:2296
Datum distance(PG_FUNCTION_ARGS)
uint8_t rt_util_clamp_to_4BUI(double value)
Definition: rt_util.c:44
uint8_t rt_util_clamp_to_8BUI(double value)
Definition: rt_util.c:54
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition: rt_band.c:336
int rt_pixtype_size(rt_pixtype pixtype)
Return size in bytes of a value in the given pixtype.
Definition: rt_pixel.c:39
uint8_t rt_util_clamp_to_1BB(double value)
Definition: rt_util.c:34
pixval
Definition: pixval.py:93
rt_errorstate rt_band_set_isnodata_flag(rt_band band, int flag)
Set isnodata flag value.
Definition: rt_band.c:647
int rt_band_clamped_value_is_nodata(rt_band band, double val)
Compare clamped value to band&#39;s clamped NODATA value.
Definition: rt_band.c:1750
int32_t offline
Definition: librtcore.h:2295
void rtdealloc(void *mem)
Definition: rt_context.c:186
const char * rt_band_get_ext_path(rt_band band)
Return band&#39;s external path (only valid when rt_band_is_offline returns non-zero).
Definition: rt_band.c:359
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:1786
int32_t isnodata
Definition: librtcore.h:2299
void rt_band_set_hasnodata_flag(rt_band band, int flag)
Set hasnodata flag value.
Definition: rt_band.c:633
#define FALSE
Definition: dbfopen.c:168
uint16_t rt_band_get_height(rt_band band)
Return height of this band.
Definition: rt_band.c:601
#define RASTER_DEBUG(level, msg)
Definition: librtcore.h:295
This library is the generic raster handling section of PostGIS.
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
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:1326
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:611
void * mem
Definition: librtcore.h:2307
int32_t hasnodata
Definition: librtcore.h:2298
uint8_t rt_util_clamp_to_2BUI(double value)
Definition: rt_util.c:39
float rt_util_clamp_to_32F(double value)
Definition: rt_util.c:79
int value
Definition: genraster.py:61
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:59
rt_raster rt_raster_from_gdal_dataset(GDALDatasetH ds)
Return a raster from a GDAL dataset.
Definition: rt_raster.c:2186
rt_errorstate rt_band_load_offline_data(rt_band band)
Load offline band&#39;s data.
Definition: rt_band.c:425
int rt_band_is_offline(rt_band band)
Return non-zero if the given band data is on the filesystem.
Definition: rt_band.c:325
unsigned char uint8_t
Definition: uthash.h:79
#define TRUE
Definition: dbfopen.c:169
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
Definition: rt_band.c:396
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:1697
GDALDatasetH rt_util_gdal_open(const char *fn, GDALAccess fn_access, int shared)
Definition: rt_util.c:379
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:200
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:1604
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
Definition: rt_band.c:666
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_band.c:1682
int16_t rt_util_clamp_to_16BSI(double value)
Definition: rt_util.c:59
union rt_band_t::@8 data