39#if POSTGIS_DEBUG_LEVEL > 2
42d_binary_to_hex(
const uint8_t *
const raw, uint32_t size, uint32_t *hexsize) {
48 assert(NULL != hexsize);
52 hex = (
char*)
rtalloc((*hexsize) + 1);
54 rterror(
"d_binary_to_hex: Out of memory hexifying raw binary");
59 for (i = 0; i < size; ++i) {
64 assert(0 == strlen(hex) % 2);
69d_print_binary_hex(
const char* msg,
const uint8_t *
const raw, uint32_t size) {
78 hex = d_binary_to_hex(raw, size, &hexsize);
80 rtinfo(
"%s\t%s", msg, hex);
86d_binptr_to_pos(
const uint8_t *
const ptr,
const uint8_t *
const end,
size_t size) {
87 assert(NULL != ptr && NULL != end);
89 return (size - (end - ptr));
111setBits(
char* ch,
double val,
int bits,
int bitOffset) {
112 char mask = 0xFF >> (8 - bits);
117 assert(8 - bitOffset >= bits);
120 ival, bits, mask, bitOffset);
124#if POSTGIS_RASTER_WARN_ON_TRUNCATION > 0
126 rtwarn(
"Pixel value for %d-bits band got truncated"
127 " from %g to %hhu", bits, val, ival);
136 ival <<= (8 - bitOffset - bits);
142 *ch &= ~(mask << (8 - bits - bitOffset));
158 assert(NULL != a && NULL != b);
192 static int endian_check_int = 1;
194 return *((uint8_t *) & endian_check_int);
199 assert(NULL != from);
215 assert(NULL != from);
233 assert(NULL != from);
240 ret = (*from)[0] << 8 |
252 (*to)[0] = v & 0x00FF;
255 (*to)[1] = v & 0x00FF;
263 assert(NULL != from);
291 assert(NULL != from);
294 ret = (uint32_t) ((*from)[0] & 0xff) |
295 (uint32_t) ((*from)[1] & 0xff) << 8 |
296 (uint32_t) ((*from)[2] & 0xff) << 16 |
297 (uint32_t) ((*from)[3] & 0xff) << 24;
300 ret = (uint32_t) ((*from)[3] & 0xff) |
301 (uint32_t) ((*from)[2] & 0xff) << 8 |
302 (uint32_t) ((*from)[1] & 0xff) << 16 |
303 (uint32_t) ((*from)[0] & 0xff) << 24;
335 assert(NULL != from);
397 assert(NULL != from);
400 ret.i = (uint64_t) ((*from)[0] & 0xff) |
401 (uint64_t) ((*from)[1] & 0xff) << 8 |
402 (uint64_t) ((*from)[2] & 0xff) << 16 |
403 (uint64_t) ((*from)[3] & 0xff) << 24 |
404 (uint64_t) ((*from)[4] & 0xff) << 32 |
405 (uint64_t) ((*from)[5] & 0xff) << 40 |
406 (uint64_t) ((*from)[6] & 0xff) << 48 |
407 (uint64_t) ((*from)[7] & 0xff) << 56;
410 ret.i = (uint64_t) ((*from)[7] & 0xff) |
411 (uint64_t) ((*from)[6] & 0xff) << 8 |
412 (uint64_t) ((*from)[5] & 0xff) << 16 |
413 (uint64_t) ((*from)[4] & 0xff) << 24 |
414 (uint64_t) ((*from)[3] & 0xff) << 32 |
415 (uint64_t) ((*from)[2] & 0xff) << 40 |
416 (uint64_t) ((*from)[1] & 0xff) << 48 |
417 (uint64_t) ((*from)[0] & 0xff) << 56;
467 assert(NULL != raster);
469 RASTER_DEBUGF(3,
"Serialized size with just header:%d - now adding size of %d bands",
470 size, raster->numBands);
472 for (i = 0; i < raster->numBands; ++i) {
473 rt_band band = raster->bands[i];
478 rterror(
"rt_raster_serialized_size: Corrupted band: unknown pixtype");
493 size += strlen(band->data.offline.path) + 1;
497 size += pixbytes * raster->width * raster->height;
528 assert(NULL != raster);
533 rterror(
"rt_raster_serialize: Out of memory allocating %d bytes for serializing a raster",
size);
536 memset(ret,
'-',
size);
539 RASTER_DEBUGF(3,
"sizeof(struct rt_raster_serialized_t):%lu",
558 RASTER_DEBUG(3,
"Start hex dump of raster being serialized using 0x2D to mark non-written bytes");
560#if POSTGIS_DEBUG_LEVEL > 2
561 uint8_t* dbg_ptr = ptr;
562 d_print_binary_hex(
"HEADER", dbg_ptr,
size);
568 for (i = 0; i < raster->numBands; ++i) {
569 rt_band band = raster->bands[i];
570 assert(NULL != band);
575 rterror(
"rt_raster_serialize: Corrupted band: unknown pixtype");
581 *ptr = band->pixtype;
583#ifdef POSTGIS_RASTER_DISABLE_OFFLINE
584 rterror(
"rt_raster_serialize: offdb raster support disabled at compile-time");
589 if (band->hasnodata) {
593 if (band->isnodata) {
597#if POSTGIS_DEBUG_LEVEL > 2
598 d_print_binary_hex(
"PIXTYPE", dbg_ptr,
size);
605 memset(ptr,
'\0', pixbytes - 1);
609#if POSTGIS_DEBUG_LEVEL > 2
610 d_print_binary_hex(
"PADDING", dbg_ptr,
size);
614 assert(!((ptr - ret) % pixbytes));
622 uint8_t v = band->nodataval;
628 int8_t v = band->nodataval;
634 int16_t v = band->nodataval;
640 uint16_t v = band->nodataval;
646 int32_t v = band->nodataval;
652 uint32_t v = band->nodataval;
664 float v = band->nodataval;
670 memcpy(ptr, &band->nodataval, 8);
675 rterror(
"rt_raster_serialize: Fatal error caused by unknown pixel type. Aborting.");
681 assert(!((ptr - ret) % pixbytes));
683#if POSTGIS_DEBUG_LEVEL > 2
684 d_print_binary_hex(
"nodata", dbg_ptr,
size);
689 *ptr = band->data.offline.bandNum;
693 strcpy((
char*) ptr, band->data.offline.path);
694 ptr += strlen(band->data.offline.path) + 1;
698 uint32_t datasize = raster->width * raster->height * pixbytes;
699 memcpy(ptr, band->data.mem, datasize);
703#if POSTGIS_DEBUG_LEVEL > 2
704 d_print_binary_hex(
"BAND", dbg_ptr,
size);
708 while ((ptr-ret) % 8) {
714 assert(!((ptr - ret) % pixbytes));
717#if POSTGIS_DEBUG_LEVEL > 2
718 d_print_binary_hex(
"SERIALIZED RASTER", dbg_ptr,
size);
734 const uint8_t *ptr = NULL;
735 const uint8_t *beg = NULL;
738#ifdef WORDS_BIGENDIAN
741 uint8_t littleEndian =
LW_TRUE;
744 assert(NULL != serialized);
754 RASTER_DEBUG(3,
"rt_raster_deserialize: Allocating memory for deserialized raster header");
757 rterror(
"rt_raster_deserialize: Out of memory allocating raster for deserialization");
762 RASTER_DEBUG(3,
"rt_raster_deserialize: Deserialize raster header");
765 if (0 == rast->numBands || header_only) {
770 beg = (
const uint8_t*) serialized;
773 RASTER_DEBUG(3,
"rt_raster_deserialize: Allocating memory for bands");
775 if (rast->bands == NULL) {
776 rterror(
"rt_raster_deserialize: Out of memory allocating bands");
781 RASTER_DEBUGF(3,
"rt_raster_deserialize: %d bands", rast->numBands);
788 for (i = 0; i < rast->numBands; ++i) {
795 rterror(
"rt_raster_deserialize: Out of memory allocating rt_band during deserialization");
801 rast->bands[i] = band;
812 band->width = rast->width;
813 band->height = rast->height;
822 switch (band->pixtype) {
824 band->nodataval = ((int)
read_uint8(&ptr)) & 0x01;
828 band->nodataval = ((int)
read_uint8(&ptr)) & 0x03;
832 band->nodataval = ((int)
read_uint8(&ptr)) & 0x0F;
844 band->nodataval =
read_int16(&ptr, littleEndian);
852 band->nodataval =
read_int32(&ptr, littleEndian);
872 rterror(
"rt_raster_deserialize: Unknown pixeltype %d", band->pixtype);
879 RASTER_DEBUGF(3,
"rt_raster_deserialize: has nodata flag %d", band->hasnodata);
880 RASTER_DEBUGF(3,
"rt_raster_deserialize: nodata value %g", band->nodataval);
883 assert(!((ptr - beg) % pixbytes));
889 band->data.offline.bandNum = *ptr;
893 pathlen = strlen((
char*) ptr);
894 band->data.offline.path =
rtalloc(
sizeof(
char) * (pathlen + 1));
895 if (band->data.offline.path == NULL) {
896 rterror(
"rt_raster_deserialize: Could not allocate memory for offline band path");
902 memcpy(band->data.offline.path, ptr, pathlen);
903 band->data.offline.path[pathlen] =
'\0';
906 band->data.offline.mem = NULL;
910 const uint32_t datasize = rast->width * rast->height * pixbytes;
911 band->data.mem = (uint8_t*) ptr;
916#if POSTGIS_DEBUG_LEVEL > 0
917 const uint8_t *padbeg = ptr;
919 while (0 != ((ptr - beg) % 8)) {
923 RASTER_DEBUGF(3,
"rt_raster_deserialize: skip %ld bytes of 8-bytes boundary padding", ptr - padbeg);
926 assert(!((ptr - beg) % pixbytes));
void deparse_hex(uint8_t str, char *result)
Convert a char into a human readable hex digit.
#define LW_TRUE
Return types for functions with status returns.
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.
#define RASTER_DEBUG(level, msg)
#define RASTER_DEBUGF(level, msg,...)
void void rtinfo(const char *fmt,...) __attribute__((format(printf
void void void rtwarn(const char *fmt,...) __attribute__((format(printf
uint16_t rt_util_float_to_float16(float value)
float rt_util_float16_to_float(uint16_t value)
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
const char * rt_pixtype_name(rt_pixtype pixtype)
void rt_band_destroy(rt_band band)
Destroy a raster band.
void rtdealloc(void *mem)
struct rt_raster_t * rt_raster
Types definitions.
int rt_pixtype_size(rt_pixtype pixtype)
Return size in bytes of a value in the given pixtype.
This library is the generic raster handling section of PostGIS.
void swap_char(uint8_t *a, uint8_t *b)
uint8_t isMachineLittleEndian(void)
void flip_endian_32(uint8_t *d)
void flip_endian_16(uint8_t *d)
static uint32_t rt_raster_serialized_size(rt_raster raster)
uint8_t read_uint8(const uint8_t **from)
void write_uint16(uint8_t **to, uint8_t littleEndian, uint16_t v)
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)
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
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)
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
#define BANDTYPE_FLAG_HASNODATA
#define BANDTYPE_FLAG_OFFDB
#define BANDTYPE_FLAG_ISNODATA
#define BANDTYPE_HAS_NODATA(x)
#define BANDTYPE_IS_OFFDB(x)
#define BANDTYPE_IS_NODATA(x)
#define BANDTYPE_PIXTYPE_MASK