PostGIS 3.0.6dev-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 36 of file rt_wkb.c.

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