PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ 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.

References ovdump::band, BANDTYPE_HAS_NODATA, BANDTYPE_IS_NODATA, BANDTYPE_IS_OFFDB, BANDTYPE_PIXTYPE_MASK, rt_band_t::data, flip_endian_16(), flip_endian_32(), flip_endian_64(), rt_band_t::hasnodata, rt_band_t::height, isMachineLittleEndian(), rt_band_t::isnodata, rt_band_t::mem, rt_band_t::nodataval, rt_band_t::offline, rt_band_t::ownsdata, rt_band_t::pixtype, 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(), rterror(), ovdump::type, and rt_band_t::width.

Referenced by rt_raster_from_wkb().

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 }
rt_pixtype pixtype
Definition: librtcore.h:2265
band
Definition: ovdump.py:57
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
uint16_t height
Definition: librtcore.h:2268
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition: rt_band.c:242
void flip_endian_16(uint8_t *d)
Definition: rt_serialize.c:165
unsigned int uint32_t
Definition: uthash.h:78
int16_t read_int16(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:261
uint32_t read_uint32(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:287
uint16_t read_uint16(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:229
#define BANDTYPE_IS_OFFDB(x)
Definition: rt_serialize.h:43
void flip_endian_32(uint8_t *d)
Definition: rt_serialize.c:172
union rt_band_t::@6 data
int8_t ownsdata
Definition: librtcore.h:2273
#define BANDTYPE_PIXTYPE_MASK
Definition: rt_serialize.h:36
double nodataval
Definition: librtcore.h:2272
#define RASTER_DEBUGF(level, msg,...)
Definition: librtcore.h:299
uint16_t width
Definition: librtcore.h:2267
uint8_t isMachineLittleEndian(void)
Definition: rt_serialize.c:190
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 read_uint8(const uint8_t **from)
Definition: rt_serialize.c:197
int32_t offline
Definition: librtcore.h:2266
int8_t read_int8(const uint8_t **from)
Definition: rt_serialize.c:213
int32_t isnodata
Definition: librtcore.h:2270
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
void * mem
Definition: librtcore.h:2278
int32_t hasnodata
Definition: librtcore.h:2269
type
Definition: ovdump.py:41
int32_t read_int32(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:333
double read_float64(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:389
#define BANDTYPE_HAS_NODATA(x)
Definition: rt_serialize.h:44
float read_float32(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:363
unsigned char uint8_t
Definition: uthash.h:79
#define BANDTYPE_IS_NODATA(x)
Definition: rt_serialize.h:45
void flip_endian_64(uint8_t *d)
Definition: rt_serialize.c:180
Here is the call graph for this function:
Here is the caller graph for this function: