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