PostGIS 3.6.2dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ rt_band_from_wkb()

static rt_band rt_band_from_wkb ( uint16_t  width,
uint16_t  height,
const uint8_t **  ptr,
const uint8_t *  end,
uint8_t  littleEndian 
)
static

Definition at line 38 of file rt_wkb.c.

42 {
43 rt_band band = NULL;
44 int pixbytes = 0;
45 uint8_t type = 0;
46 size_t sz = 0;
47 size_t v = 0;
48
49 assert(NULL != ptr);
50 assert(NULL != end);
51
52 band = rtalloc(sizeof (struct rt_band_t));
53 if (!band) {
54 rterror("rt_band_from_wkb: Out of memory allocating rt_band during WKB parsing");
55 return NULL;
56 }
57 band->ownsdata = 0; /* assume we don't own data */
58
59 if (end - *ptr < 1) {
60 rterror("rt_band_from_wkb: Premature end of WKB on band reading (%s:%d)",
61 __FILE__, __LINE__);
62 rt_band_destroy(band);
63 return NULL;
64 }
65 type = read_uint8(ptr);
66
67 if ((type & BANDTYPE_PIXTYPE_MASK) >= PT_END) {
68 rterror("rt_band_from_wkb: Invalid pixtype %d", type & BANDTYPE_PIXTYPE_MASK);
69 rt_band_destroy(band);
70 return NULL;
71 }
72
73 band->pixtype = type & BANDTYPE_PIXTYPE_MASK;
74 band->offline = BANDTYPE_IS_OFFDB(type) ? 1 : 0;
75 band->hasnodata = BANDTYPE_HAS_NODATA(type) ? 1 : 0;
76 band->isnodata = band->hasnodata ? (BANDTYPE_IS_NODATA(type) ? 1 : 0) : 0;
77 band->width = width;
78 band->height = height;
79
80 RASTER_DEBUGF(3, " Band pixtype:%s, offline:%d, hasnodata:%d",
81 rt_pixtype_name(band->pixtype),
82 band->offline,
83 band->hasnodata
84 );
85
86 /* Check there's enough bytes to read nodata value */
87 pixbytes = rt_pixtype_size(band->pixtype);
88 if (((*ptr) + pixbytes) >= end) {
89 rterror("rt_band_from_wkb: Premature end of WKB on band novalue reading");
90 rt_band_destroy(band);
91 return NULL;
92 }
93
94 /* Read nodata value */
95 switch (band->pixtype) {
96 case PT_1BB: {
97 band->nodataval = ((int) read_uint8(ptr)) & 0x01;
98 break;
99 }
100 case PT_2BUI: {
101 band->nodataval = ((int) read_uint8(ptr)) & 0x03;
102 break;
103 }
104 case PT_4BUI: {
105 band->nodataval = ((int) read_uint8(ptr)) & 0x0F;
106 break;
107 }
108 case PT_8BSI: {
109 band->nodataval = read_int8(ptr);
110 break;
111 }
112 case PT_8BUI: {
113 band->nodataval = read_uint8(ptr);
114 break;
115 }
116 case PT_16BSI: {
117 band->nodataval = read_int16(ptr, littleEndian);
118 break;
119 }
120 case PT_16BUI: {
121 band->nodataval = read_uint16(ptr, littleEndian);
122 break;
123 }
124 case PT_32BSI: {
125 band->nodataval = read_int32(ptr, littleEndian);
126 break;
127 }
128 case PT_32BUI: {
129 band->nodataval = read_uint32(ptr, littleEndian);
130 break;
131 }
132 case PT_32BF: {
133 band->nodataval = read_float32(ptr, littleEndian);
134 break;
135 }
136 case PT_64BF: {
137 band->nodataval = read_float64(ptr, littleEndian);
138 break;
139 }
140 default: {
141 rterror("rt_band_from_wkb: Unknown pixeltype %d", band->pixtype);
142 rt_band_destroy(band);
143 return NULL;
144 }
145 }
146
147 RASTER_DEBUGF(3, " Nodata value: %g, pixbytes: %d, ptr @ %p, end @ %p",
148 band->nodataval, pixbytes, *ptr, end);
149
150 if (band->offline) {
151 if (((*ptr) + 1) >= end) {
152 rterror("rt_band_from_wkb: Premature end of WKB on offline "
153 "band data bandNum reading (%s:%d)",
154 __FILE__, __LINE__
155 );
156 rt_band_destroy(band);
157 return NULL;
158 }
159
160 band->data.offline.bandNum = read_int8(ptr);
161 band->data.offline.mem = NULL;
162
163 {
164 /* check we have a NULL-termination */
165 sz = 0;
166 while ((*ptr)[sz] && &((*ptr)[sz]) < end) ++sz;
167 if (&((*ptr)[sz]) >= end) {
168 rterror("rt_band_from_wkb: Premature end of WKB on band offline path reading");
169 rt_band_destroy(band);
170 return NULL;
171 }
172
173 /* we never own offline band data */
174 band->ownsdata = 0;
175
176 band->data.offline.path = rtalloc(sz + 1);
177 if (band->data.offline.path == NULL) {
178 rterror("rt_band_from_wkb: Out of memory allocating for offline path of band");
179 rt_band_destroy(band);
180 return NULL;
181 }
182
183 memcpy(band->data.offline.path, *ptr, sz);
184 band->data.offline.path[sz] = '\0';
185
186 RASTER_DEBUGF(3, "OFFDB band path is %s (size is %zu)",
187 band->data.offline.path, sz);
188
189 *ptr += sz + 1;
190
191 /* TODO: How could we know if the offline band is a nodata band? */
192 /* trust in the force */
193 /*band->isnodata = FALSE;*/
194 }
195
196 return band;
197 }
198
199 /* This is an on-disk band */
200 sz = (size_t)width * height * pixbytes;
201 if (((*ptr) + sz) > end) {
202 rterror("rt_band_from_wkb: Premature end of WKB on band data reading (%s:%d)",
203 __FILE__, __LINE__);
204 rt_band_destroy(band);
205 return NULL;
206 }
207
208 band->data.mem = rtalloc(sz);
209 if (!band->data.mem) {
210 rterror("rt_band_from_wkb: Out of memory during band creation in WKB parser");
211 rt_band_destroy(band);
212 return NULL;
213 }
214
215 band->ownsdata = 1; /* we DO own this data!!! */
216 memcpy(band->data.mem, *ptr, sz);
217 *ptr += sz;
218
219 /* Should now flip values if > 8bit and
220 * littleEndian != isMachineLittleEndian */
221 if (pixbytes > 1) {
222 if (isMachineLittleEndian() != littleEndian) {
223 void (*flipper)(uint8_t*) = 0;
224 uint8_t *flipme = NULL;
225
226 if (pixbytes == 2)
227 flipper = flip_endian_16;
228 else if (pixbytes == 4)
229 flipper = flip_endian_32;
230 else if (pixbytes == 8)
231 flipper = flip_endian_64;
232 else {
233 rterror("rt_band_from_wkb: Unexpected pix bytes %d", pixbytes);
234 rt_band_destroy(band);
235 return NULL;
236 }
237
238 flipme = band->data.mem;
239 sz = (size_t)width * height;
240 for (v = 0; v < sz; ++v) {
241 flipper(flipme);
242 flipme += pixbytes;
243 }
244 }
245 }
246 /* And should check for invalid values for < 8bit types */
247 else if (
248 band->pixtype == PT_1BB ||
249 band->pixtype == PT_2BUI ||
250 band->pixtype == PT_4BUI
251 ) {
252 uint8_t maxVal = band->pixtype == PT_1BB ? 1 : (band->pixtype == PT_2BUI ? 3 : 15);
253 uint8_t val;
254
255 sz = (size_t)width*height;
256 for (v = 0; v < sz; ++v) {
257 val = ((uint8_t*) band->data.mem)[v];
258 if (val > maxVal) {
259 rterror("rt_band_from_wkb: Invalid value %d for pixel of type %s",
260 val, rt_pixtype_name(band->pixtype));
261 rt_band_destroy(band);
262 return NULL;
263 }
264 }
265 }
266
267 /* And we should check if the band is a nodata band */
268 /* TODO: No!! This is too slow */
269 /*rt_band_check_is_nodata(band);*/
270
271 return band;
272}
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
#define RASTER_DEBUGF(level, msg,...)
Definition librtcore.h:306
@ 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
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition rt_pixel.c:110
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition rt_band.c:491
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 isMachineLittleEndian(void)
void flip_endian_32(uint8_t *d)
void flip_endian_16(uint8_t *d)
uint8_t read_uint8(const uint8_t **from)
double read_float64(const uint8_t **from, uint8_t littleEndian)
float read_float32(const uint8_t **from, uint8_t littleEndian)
void flip_endian_64(uint8_t *d)
int8_t read_int8(const uint8_t **from)
int16_t read_int16(const uint8_t **from, uint8_t littleEndian)
int32_t read_int32(const uint8_t **from, uint8_t littleEndian)
uint32_t read_uint32(const uint8_t **from, uint8_t littleEndian)
uint16_t read_uint16(const uint8_t **from, uint8_t littleEndian)
#define BANDTYPE_HAS_NODATA(x)
#define BANDTYPE_IS_OFFDB(x)
#define BANDTYPE_IS_NODATA(x)
#define BANDTYPE_PIXTYPE_MASK

References BANDTYPE_HAS_NODATA, BANDTYPE_IS_NODATA, BANDTYPE_IS_OFFDB, BANDTYPE_PIXTYPE_MASK, flip_endian_16(), flip_endian_32(), flip_endian_64(), isMachineLittleEndian(), PT_16BSI, PT_16BUI, PT_1BB, PT_2BUI, PT_32BF, PT_32BSI, PT_32BUI, PT_4BUI, PT_64BF, PT_8BSI, PT_8BUI, PT_END, RASTER_DEBUGF, read_float32(), read_float64(), read_int16(), read_int32(), read_int8(), read_uint16(), read_uint32(), read_uint8(), rt_band_destroy(), rt_pixtype_name(), rt_pixtype_size(), rtalloc(), and rterror().

Referenced by rt_raster_from_wkb().

Here is the call graph for this function:
Here is the caller graph for this function: