PostGIS  2.1.10dev-r@@SVN_REVISION@@
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 7429 of file rt_api.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(), and rt_band_t::width.

Referenced by rt_raster_from_wkb().

7433  {
7434  rt_band band = NULL;
7435  int pixbytes = 0;
7436  uint8_t type = 0;
7437  unsigned long sz = 0;
7438  uint32_t v = 0;
7439 
7440  assert(NULL != ptr);
7441  assert(NULL != end);
7442 
7443  band = rtalloc(sizeof (struct rt_band_t));
7444  if (!band) {
7445  rterror("rt_band_from_wkb: Out of memory allocating rt_band during WKB parsing");
7446  return NULL;
7447  }
7448  band->ownsdata = 0; /* assume we don't own data */
7449 
7450  if (end - *ptr < 1) {
7451  rterror("rt_band_from_wkb: Premature end of WKB on band reading (%s:%d)",
7452  __FILE__, __LINE__);
7453  rt_band_destroy(band);
7454  return NULL;
7455  }
7456  type = read_uint8(ptr);
7457 
7458  if ((type & BANDTYPE_PIXTYPE_MASK) >= PT_END) {
7459  rterror("rt_band_from_wkb: Invalid pixtype %d", type & BANDTYPE_PIXTYPE_MASK);
7460  rt_band_destroy(band);
7461  return NULL;
7462  }
7463 
7464  band->pixtype = type & BANDTYPE_PIXTYPE_MASK;
7465  band->offline = BANDTYPE_IS_OFFDB(type) ? 1 : 0;
7466  band->hasnodata = BANDTYPE_HAS_NODATA(type) ? 1 : 0;
7467  band->isnodata = band->hasnodata ? (BANDTYPE_IS_NODATA(type) ? 1 : 0) : 0;
7468  band->width = width;
7469  band->height = height;
7470 
7471  RASTER_DEBUGF(3, " Band pixtype:%s, offline:%d, hasnodata:%d",
7472  rt_pixtype_name(band->pixtype),
7473  band->offline,
7474  band->hasnodata
7475  );
7476 
7477  /* Check there's enough bytes to read nodata value */
7478  pixbytes = rt_pixtype_size(band->pixtype);
7479  if (((*ptr) + pixbytes) >= end) {
7480  rterror("rt_band_from_wkb: Premature end of WKB on band novalue reading");
7481  rt_band_destroy(band);
7482  return NULL;
7483  }
7484 
7485  /* Read nodata value */
7486  switch (band->pixtype) {
7487  case PT_1BB: {
7488  band->nodataval = ((int) read_uint8(ptr)) & 0x01;
7489  break;
7490  }
7491  case PT_2BUI: {
7492  band->nodataval = ((int) read_uint8(ptr)) & 0x03;
7493  break;
7494  }
7495  case PT_4BUI: {
7496  band->nodataval = ((int) read_uint8(ptr)) & 0x0F;
7497  break;
7498  }
7499  case PT_8BSI: {
7500  band->nodataval = read_int8(ptr);
7501  break;
7502  }
7503  case PT_8BUI: {
7504  band->nodataval = read_uint8(ptr);
7505  break;
7506  }
7507  case PT_16BSI: {
7508  band->nodataval = read_int16(ptr, littleEndian);
7509  break;
7510  }
7511  case PT_16BUI: {
7512  band->nodataval = read_uint16(ptr, littleEndian);
7513  break;
7514  }
7515  case PT_32BSI: {
7516  band->nodataval = read_int32(ptr, littleEndian);
7517  break;
7518  }
7519  case PT_32BUI: {
7520  band->nodataval = read_uint32(ptr, littleEndian);
7521  break;
7522  }
7523  case PT_32BF: {
7524  band->nodataval = read_float32(ptr, littleEndian);
7525  break;
7526  }
7527  case PT_64BF: {
7528  band->nodataval = read_float64(ptr, littleEndian);
7529  break;
7530  }
7531  default: {
7532  rterror("rt_band_from_wkb: Unknown pixeltype %d", band->pixtype);
7533  rt_band_destroy(band);
7534  return NULL;
7535  }
7536  }
7537 
7538  RASTER_DEBUGF(3, " Nodata value: %g, pixbytes: %d, ptr @ %p, end @ %p",
7539  band->nodataval, pixbytes, *ptr, end);
7540 
7541  if (band->offline) {
7542  if (((*ptr) + 1) >= end) {
7543  rterror("rt_band_from_wkb: Premature end of WKB on offline "
7544  "band data bandNum reading (%s:%d)",
7545  __FILE__, __LINE__
7546  );
7547  rt_band_destroy(band);
7548  return NULL;
7549  }
7550 
7551  band->data.offline.bandNum = read_int8(ptr);
7552  band->data.offline.mem = NULL;
7553 
7554  {
7555  /* check we have a NULL-termination */
7556  sz = 0;
7557  while ((*ptr)[sz] && &((*ptr)[sz]) < end) ++sz;
7558  if (&((*ptr)[sz]) >= end) {
7559  rterror("rt_band_from_wkb: Premature end of WKB on band offline path reading");
7560  rt_band_destroy(band);
7561  return NULL;
7562  }
7563 
7564  /* we never own offline band data */
7565  band->ownsdata = 0;
7566 
7567  band->data.offline.path = rtalloc(sz + 1);
7568  if (band->data.offline.path == NULL) {
7569  rterror("rt_band_from_wkb: Out of memory allocating for offline path of band");
7570  rt_band_destroy(band);
7571  return NULL;
7572  }
7573 
7574  memcpy(band->data.offline.path, *ptr, sz);
7575  band->data.offline.path[sz] = '\0';
7576 
7577  RASTER_DEBUGF(3, "OFFDB band path is %s (size is %d)",
7578  band->data.offline.path, sz);
7579 
7580  *ptr += sz + 1;
7581 
7582  /* TODO: How could we know if the offline band is a nodata band? */
7583  /* trust in the force */
7584  /*band->isnodata = FALSE;*/
7585  }
7586 
7587  return band;
7588  }
7589 
7590  /* This is an on-disk band */
7591  sz = width * height * pixbytes;
7592  if (((*ptr) + sz) > end) {
7593  rterror("rt_band_from_wkb: Premature end of WKB on band data reading (%s:%d)",
7594  __FILE__, __LINE__);
7595  rt_band_destroy(band);
7596  return NULL;
7597  }
7598 
7599  band->data.mem = rtalloc(sz);
7600  if (!band->data.mem) {
7601  rterror("rt_band_from_wkb: Out of memory during band creation in WKB parser");
7602  rt_band_destroy(band);
7603  return NULL;
7604  }
7605 
7606  band->ownsdata = 1; /* we DO own this data!!! */
7607  memcpy(band->data.mem, *ptr, sz);
7608  *ptr += sz;
7609 
7610  /* Should now flip values if > 8bit and
7611  * littleEndian != isMachineLittleEndian */
7612  if (pixbytes > 1) {
7613  if (isMachineLittleEndian() != littleEndian) {
7614  void (*flipper)(uint8_t*) = 0;
7615  uint8_t *flipme = NULL;
7616 
7617  if (pixbytes == 2)
7618  flipper = flip_endian_16;
7619  else if (pixbytes == 4)
7620  flipper = flip_endian_32;
7621  else if (pixbytes == 8)
7622  flipper = flip_endian_64;
7623  else {
7624  rterror("rt_band_from_wkb: Unexpected pix bytes %d", pixbytes);
7625  rt_band_destroy(band);
7626  return NULL;
7627  }
7628 
7629  flipme = band->data.mem;
7630  sz = width * height;
7631  for (v = 0; v < sz; ++v) {
7632  flipper(flipme);
7633  flipme += pixbytes;
7634  }
7635  }
7636  }
7637  /* And should check for invalid values for < 8bit types */
7638  else if (
7639  band->pixtype == PT_1BB ||
7640  band->pixtype == PT_2BUI ||
7641  band->pixtype == PT_4BUI
7642  ) {
7643  uint8_t maxVal = band->pixtype == PT_1BB ? 1 : (band->pixtype == PT_2BUI ? 3 : 15);
7644  uint8_t val;
7645 
7646  sz = width*height;
7647  for (v = 0; v < sz; ++v) {
7648  val = ((uint8_t*) band->data.mem)[v];
7649  if (val > maxVal) {
7650  rterror("rt_band_from_wkb: Invalid value %d for pixel of type %s",
7651  val, rt_pixtype_name(band->pixtype));
7652  rt_band_destroy(band);
7653  return NULL;
7654  }
7655  }
7656  }
7657 
7658  /* And we should check if the band is a nodata band */
7659  /* TODO: No!! This is too slow */
7660  /*rt_band_check_is_nodata(band);*/
7661 
7662  return band;
7663 }
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_api.c:1168
rt_pixtype pixtype
Definition: rt_api.h:2239
#define BANDTYPE_PIXTYPE_MASK
Definition: rt_api.c:7416
Definition: rt_api.h:184
static double read_float64(const uint8_t **from, uint8_t littleEndian)
Definition: rt_api.c:7342
tuple band
Definition: ovdump.py:57
static int32_t read_int32(const uint8_t **from, uint8_t littleEndian)
Definition: rt_api.c:7284
static void flip_endian_64(uint8_t *d)
Definition: rt_api.c:79
uint16_t height
Definition: rt_api.h:2242
static int8_t read_int8(const uint8_t **from)
Definition: rt_api.c:7161
Definition: rt_api.h:173
static void flip_endian_16(uint8_t *d)
Definition: rt_api.c:64
int rt_pixtype_size(rt_pixtype pixtype)
Return size in bytes of a value in the given pixtype.
Definition: rt_api.c:1097
static int16_t read_int16(const uint8_t **from, uint8_t littleEndian)
Definition: rt_api.c:7210
static uint32_t read_uint32(const uint8_t **from, uint8_t littleEndian)
Definition: rt_api.c:7237
#define RASTER_DEBUGF(level, msg,...)
Definition: rt_api.h:285
int8_t ownsdata
Definition: rt_api.h:2247
#define BANDTYPE_HAS_NODATA(x)
Definition: rt_api.c:7424
double nodataval
Definition: rt_api.h:2246
uint16_t width
Definition: rt_api.h:2241
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition: rt_api.c:1650
#define BANDTYPE_IS_NODATA(x)
Definition: rt_api.c:7425
union rt_band_t::@14 data
static void flip_endian_32(uint8_t *d)
Definition: rt_api.c:71
void * rtalloc(size_t size)
Raster core memory management functions.
Definition: rt_api.c:867
void rterror(const char *fmt,...)
Raster core error and info handlers.
Definition: rt_api.c:895
int32_t offline
Definition: rt_api.h:2240
int32_t isnodata
Definition: rt_api.h:2244
void * mem
Definition: rt_api.h:2252
#define BANDTYPE_IS_OFFDB(x)
Definition: rt_api.c:7423
static uint8_t read_uint8(const uint8_t **from)
Definition: rt_api.c:7144
int32_t hasnodata
Definition: rt_api.h:2243
static float read_float32(const uint8_t **from, uint8_t littleEndian)
Definition: rt_api.c:7315
static uint8_t isMachineLittleEndian(void)
Definition: rt_api.c:7137
static uint16_t read_uint16(const uint8_t **from, uint8_t littleEndian)
Definition: rt_api.c:7178

Here is the call graph for this function:

Here is the caller graph for this function: