PostGIS  2.4.9dev-r@@SVN_REVISION@@
rt_serialize.c
Go to the documentation of this file.
1 /*
2  *
3  * WKTRaster - Raster Types for PostGIS
4  * http://trac.osgeo.org/postgis/wiki/WKTRaster
5  *
6  * Copyright (C) 2011-2013 Regents of the University of California
7  * <bkpark@ucdavis.edu>
8  * Copyright (C) 2010-2011 Jorge Arevalo <jorge.arevalo@deimos-space.com>
9  * Copyright (C) 2010-2011 David Zwarg <dzwarg@azavea.com>
10  * Copyright (C) 2009-2011 Pierre Racine <pierre.racine@sbf.ulaval.ca>
11  * Copyright (C) 2009-2011 Mateusz Loskot <mateusz@loskot.net>
12  * Copyright (C) 2008-2009 Sandro Santilli <strk@kbt.io>
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software Foundation,
26  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27  *
28  */
29 
30 #include "librtcore.h"
31 #include "librtcore_internal.h"
32 #include "rt_serialize.h"
33 
34 /******************************************************************************
35 * Debug and Testing Utilities
36 ******************************************************************************/
37 
38 #if POSTGIS_DEBUG_LEVEL > 2
39 
40 char*
41 d_binary_to_hex(const uint8_t * const raw, uint32_t size, uint32_t *hexsize) {
42  char* hex = NULL;
43  uint32_t i = 0;
44 
45 
46  assert(NULL != raw);
47  assert(NULL != hexsize);
48 
49 
50  *hexsize = size * 2; /* hex is 2 times bytes */
51  hex = (char*) rtalloc((*hexsize) + 1);
52  if (!hex) {
53  rterror("d_binary_to_hex: Out of memory hexifying raw binary");
54  return NULL;
55  }
56  hex[*hexsize] = '\0'; /* Null-terminate */
57 
58  for (i = 0; i < size; ++i) {
59  deparse_hex(raw[i], &(hex[2 * i]));
60  }
61 
62  assert(NULL != hex);
63  assert(0 == strlen(hex) % 2);
64  return hex;
65 }
66 
67 void
68 d_print_binary_hex(const char* msg, const uint8_t * const raw, uint32_t size) {
69  char* hex = NULL;
70  uint32_t hexsize = 0;
71 
72 
73  assert(NULL != msg);
74  assert(NULL != raw);
75 
76 
77  hex = d_binary_to_hex(raw, size, &hexsize);
78  if (NULL != hex) {
79  rtinfo("%s\t%s", msg, hex);
80  rtdealloc(hex);
81  }
82 }
83 
84 size_t
85 d_binptr_to_pos(const uint8_t * const ptr, const uint8_t * const end, size_t size) {
86  assert(NULL != ptr && NULL != end);
87 
88  return (size - (end - ptr));
89 }
90 
91 #endif /* if POSTGIS_DEBUG_LEVEL > 2 */
92 
93 
94 #ifdef OPTIMIZE_SPACE
95 
96 /*
97  * Set given number of bits of the given byte,
98  * starting from given bitOffset (from the first)
99  * to the given value.
100  *
101  * Examples:
102  * char ch;
103  * ch=0; setBits(&ch, 1, 1, 0) -> ch==8
104  * ch=0; setBits(&ch, 3, 2, 1) -> ch==96 (0x60)
105  *
106  * Note that number of bits set must be <= 8-bitOffset
107  *
108  */
109 void
110 setBits(char* ch, double val, int bits, int bitOffset) {
111  char mask = 0xFF >> (8 - bits);
112  char ival = val;
113 
114 
115  assert(ch != NULL);
116  assert(8 - bitOffset >= bits);
117 
118  RASTER_DEBUGF(4, "ival:%d bits:%d mask:%hhx bitoffset:%d\n",
119  ival, bits, mask, bitOffset);
120 
121  /* clear all but significant bits from ival */
122  ival &= mask;
123 #if POSTGIS_RASTER_WARN_ON_TRUNCATION > 0
124  if (ival != val) {
125  rtwarn("Pixel value for %d-bits band got truncated"
126  " from %g to %hhu", bits, val, ival);
127  }
128 #endif /* POSTGIS_RASTER_WARN_ON_TRUNCATION */
129 
130  RASTER_DEBUGF(4, " cleared ival:%hhx\n", ival);
131 
132 
133  /* Shift ival so the significant bits start at
134  * the first bit */
135  ival <<= (8 - bitOffset - bits);
136 
137  RASTER_DEBUGF(4, " ival shifted:%hhx\n", ival);
138  RASTER_DEBUGF(4, " ch:%hhx\n", *ch);
139 
140  /* clear first bits of target */
141  *ch &= ~(mask << (8 - bits - bitOffset));
142 
143  RASTER_DEBUGF(4, " ch cleared:%hhx\n", *ch);
144 
145  /* Set the first bit of target */
146  *ch |= ival;
147 
148  RASTER_DEBUGF(4, " ch ored:%hhx\n", *ch);
149 
150 }
151 #endif /* OPTIMIZE_SPACE */
152 
153 void
155  uint8_t c = 0;
156 
157  assert(NULL != a && NULL != b);
158 
159  c = *a;
160  *a = *b;
161  *b = c;
162 }
163 
164 void
166  assert(NULL != d);
167 
168  swap_char(d, d + 1);
169 }
170 
171 void
173  assert(NULL != d);
174 
175  swap_char(d, d + 3);
176  swap_char(d + 1, d + 2);
177 }
178 
179 void
181  assert(NULL != d);
182 
183  swap_char(d + 7, d);
184  swap_char(d + 6, d + 1);
185  swap_char(d + 5, d + 2);
186  swap_char(d + 4, d + 3);
187 }
188 
189 uint8_t
191  static int endian_check_int = 1; /* dont modify this!!! */
192  /* 0=big endian|xdr -- 1=little endian|ndr */
193  return *((uint8_t *) & endian_check_int);
194 }
195 
196 uint8_t
197 read_uint8(const uint8_t** from) {
198  assert(NULL != from);
199 
200  return *(*from)++;
201 }
202 
203 /* unused up to now
204 void
205 write_uint8(uint8_t** from, uint8_t v) {
206  assert(NULL != from);
207 
208  *(*from)++ = v;
209 }
210 */
211 
212 int8_t
213 read_int8(const uint8_t** from) {
214  assert(NULL != from);
215 
216  return (int8_t) read_uint8(from);
217 }
218 
219 /* unused up to now
220 void
221 write_int8(uint8_t** from, int8_t v) {
222  assert(NULL != from);
223 
224  *(*from)++ = v;
225 }
226 */
227 
228 uint16_t
229 read_uint16(const uint8_t** from, uint8_t littleEndian) {
230  uint16_t ret = 0;
231 
232  assert(NULL != from);
233 
234  if (littleEndian) {
235  ret = (*from)[0] |
236  (*from)[1] << 8;
237  } else {
238  /* big endian */
239  ret = (*from)[0] << 8 |
240  (*from)[1];
241  }
242  *from += 2;
243  return ret;
244 }
245 
246 void
247 write_uint16(uint8_t** to, uint8_t littleEndian, uint16_t v) {
248  assert(NULL != to);
249 
250  if (littleEndian) {
251  (*to)[0] = v & 0x00FF;
252  (*to)[1] = v >> 8;
253  } else {
254  (*to)[1] = v & 0x00FF;
255  (*to)[0] = v >> 8;
256  }
257  *to += 2;
258 }
259 
260 int16_t
261 read_int16(const uint8_t** from, uint8_t littleEndian) {
262  assert(NULL != from);
263 
264  return read_uint16(from, littleEndian);
265 }
266 
267 /* unused up to now
268 void
269 write_int16(uint8_t** to, uint8_t littleEndian, int16_t v) {
270  assert(NULL != to);
271 
272  if ( littleEndian )
273  {
274  (*to)[0] = v & 0x00FF;
275  (*to)[1] = v >> 8;
276  }
277  else
278  {
279  (*to)[1] = v & 0x00FF;
280  (*to)[0] = v >> 8;
281  }
282  *to += 2;
283 }
284 */
285 
286 uint32_t
287 read_uint32(const uint8_t** from, uint8_t littleEndian) {
288  uint32_t ret = 0;
289 
290  assert(NULL != from);
291 
292  if (littleEndian) {
293  ret = (uint32_t) ((*from)[0] & 0xff) |
294  (uint32_t) ((*from)[1] & 0xff) << 8 |
295  (uint32_t) ((*from)[2] & 0xff) << 16 |
296  (uint32_t) ((*from)[3] & 0xff) << 24;
297  } else {
298  /* big endian */
299  ret = (uint32_t) ((*from)[3] & 0xff) |
300  (uint32_t) ((*from)[2] & 0xff) << 8 |
301  (uint32_t) ((*from)[1] & 0xff) << 16 |
302  (uint32_t) ((*from)[0] & 0xff) << 24;
303  }
304 
305  *from += 4;
306  return ret;
307 }
308 
309 /* unused up to now
310 void
311 write_uint32(uint8_t** to, uint8_t littleEndian, uint32_t v) {
312  assert(NULL != to);
313 
314  if ( littleEndian )
315  {
316  (*to)[0] = v & 0x000000FF;
317  (*to)[1] = ( v & 0x0000FF00 ) >> 8;
318  (*to)[2] = ( v & 0x00FF0000 ) >> 16;
319  (*to)[3] = ( v & 0xFF000000 ) >> 24;
320  }
321  else
322  {
323  (*to)[3] = v & 0x000000FF;
324  (*to)[2] = ( v & 0x0000FF00 ) >> 8;
325  (*to)[1] = ( v & 0x00FF0000 ) >> 16;
326  (*to)[0] = ( v & 0xFF000000 ) >> 24;
327  }
328  *to += 4;
329 }
330 */
331 
332 int32_t
333 read_int32(const uint8_t** from, uint8_t littleEndian) {
334  assert(NULL != from);
335 
336  return read_uint32(from, littleEndian);
337 }
338 
339 /* unused up to now
340 void
341 write_int32(uint8_t** to, uint8_t littleEndian, int32_t v) {
342  assert(NULL != to);
343 
344  if ( littleEndian )
345  {
346  (*to)[0] = v & 0x000000FF;
347  (*to)[1] = ( v & 0x0000FF00 ) >> 8;
348  (*to)[2] = ( v & 0x00FF0000 ) >> 16;
349  (*to)[3] = ( v & 0xFF000000 ) >> 24;
350  }
351  else
352  {
353  (*to)[3] = v & 0x000000FF;
354  (*to)[2] = ( v & 0x0000FF00 ) >> 8;
355  (*to)[1] = ( v & 0x00FF0000 ) >> 16;
356  (*to)[0] = ( v & 0xFF000000 ) >> 24;
357  }
358  *to += 4;
359 }
360 */
361 
362 float
363 read_float32(const uint8_t** from, uint8_t littleEndian) {
364 
365  union {
366  float f;
367  uint32_t i;
368  } ret;
369 
370  ret.i = read_uint32(from, littleEndian);
371 
372  return ret.f;
373 }
374 
375 /* unused up to now
376 void
377 write_float32(uint8_t** from, uint8_t littleEndian, float f) {
378  union {
379  float f;
380  uint32_t i;
381  } u;
382 
383  u.f = f;
384  write_uint32(from, littleEndian, u.i);
385 }
386 */
387 
388 double
389 read_float64(const uint8_t** from, uint8_t littleEndian) {
390 
391  union {
392  double d;
393  uint64_t i;
394  } ret;
395 
396  assert(NULL != from);
397 
398  if (littleEndian) {
399  ret.i = (uint64_t) ((*from)[0] & 0xff) |
400  (uint64_t) ((*from)[1] & 0xff) << 8 |
401  (uint64_t) ((*from)[2] & 0xff) << 16 |
402  (uint64_t) ((*from)[3] & 0xff) << 24 |
403  (uint64_t) ((*from)[4] & 0xff) << 32 |
404  (uint64_t) ((*from)[5] & 0xff) << 40 |
405  (uint64_t) ((*from)[6] & 0xff) << 48 |
406  (uint64_t) ((*from)[7] & 0xff) << 56;
407  } else {
408  /* big endian */
409  ret.i = (uint64_t) ((*from)[7] & 0xff) |
410  (uint64_t) ((*from)[6] & 0xff) << 8 |
411  (uint64_t) ((*from)[5] & 0xff) << 16 |
412  (uint64_t) ((*from)[4] & 0xff) << 24 |
413  (uint64_t) ((*from)[3] & 0xff) << 32 |
414  (uint64_t) ((*from)[2] & 0xff) << 40 |
415  (uint64_t) ((*from)[1] & 0xff) << 48 |
416  (uint64_t) ((*from)[0] & 0xff) << 56;
417  }
418 
419  *from += 8;
420  return ret.d;
421 }
422 
423 /* unused up to now
424 void
425 write_float64(uint8_t** to, uint8_t littleEndian, double v) {
426  union {
427  double d;
428  uint64_t i;
429  } u;
430 
431  assert(NULL != to);
432 
433  u.d = v;
434 
435  if ( littleEndian )
436  {
437  (*to)[0] = u.i & 0x00000000000000FFULL;
438  (*to)[1] = ( u.i & 0x000000000000FF00ULL ) >> 8;
439  (*to)[2] = ( u.i & 0x0000000000FF0000ULL ) >> 16;
440  (*to)[3] = ( u.i & 0x00000000FF000000ULL ) >> 24;
441  (*to)[4] = ( u.i & 0x000000FF00000000ULL ) >> 32;
442  (*to)[5] = ( u.i & 0x0000FF0000000000ULL ) >> 40;
443  (*to)[6] = ( u.i & 0x00FF000000000000ULL ) >> 48;
444  (*to)[7] = ( u.i & 0xFF00000000000000ULL ) >> 56;
445  }
446  else
447  {
448  (*to)[7] = u.i & 0x00000000000000FFULL;
449  (*to)[6] = ( u.i & 0x000000000000FF00ULL ) >> 8;
450  (*to)[5] = ( u.i & 0x0000000000FF0000ULL ) >> 16;
451  (*to)[4] = ( u.i & 0x00000000FF000000ULL ) >> 24;
452  (*to)[3] = ( u.i & 0x000000FF00000000ULL ) >> 32;
453  (*to)[2] = ( u.i & 0x0000FF0000000000ULL ) >> 40;
454  (*to)[1] = ( u.i & 0x00FF000000000000ULL ) >> 48;
455  (*to)[0] = ( u.i & 0xFF00000000000000ULL ) >> 56;
456  }
457  *to += 8;
458 }
459 */
460 
461 static uint32_t
463  uint32_t size = sizeof (struct rt_raster_serialized_t);
464  uint16_t i = 0;
465 
466  assert(NULL != raster);
467 
468  RASTER_DEBUGF(3, "Serialized size with just header:%d - now adding size of %d bands",
469  size, raster->numBands);
470 
471  for (i = 0; i < raster->numBands; ++i) {
472  rt_band band = raster->bands[i];
473  rt_pixtype pixtype = band->pixtype;
474  int pixbytes = rt_pixtype_size(pixtype);
475 
476  if (pixbytes < 1) {
477  rterror("rt_raster_serialized_size: Corrupted band: unknown pixtype");
478  return 0;
479  }
480 
481  /* Add space for band type, hasnodata flag and data padding */
482  size += pixbytes;
483 
484  /* Add space for nodata value */
485  size += pixbytes;
486 
487  if (band->offline) {
488  /* Add space for band number */
489  size += 1;
490 
491  /* Add space for null-terminated path */
492  size += strlen(band->data.offline.path) + 1;
493  }
494  else {
495  /* Add space for raster band data */
496  size += pixbytes * raster->width * raster->height;
497  }
498 
499  RASTER_DEBUGF(3, "Size before alignment is %d", size);
500 
501  /* Align size to 8-bytes boundary (trailing padding) */
502  /* XXX jorgearevalo: bug here. If the size is actually 8-bytes aligned,
503  this line will add 8 bytes trailing padding, and it's not necessary */
504  /*size += 8 - (size % 8);*/
505  if (size % 8)
506  size += 8 - (size % 8);
507 
508  RASTER_DEBUGF(3, "Size after alignment is %d", size);
509  }
510 
511  return size;
512 }
513 
520 void*
522  uint32_t size = 0;
523  uint8_t* ret = NULL;
524  uint8_t* ptr = NULL;
525  uint16_t i = 0;
526 
527  assert(NULL != raster);
528 
529  size = rt_raster_serialized_size(raster);
530  ret = (uint8_t*) rtalloc(size);
531  if (!ret) {
532  rterror("rt_raster_serialize: Out of memory allocating %d bytes for serializing a raster", size);
533  return NULL;
534  }
535  memset(ret, '-', size);
536  ptr = ret;
537 
538  RASTER_DEBUGF(3, "sizeof(struct rt_raster_serialized_t):%u",
539  sizeof (struct rt_raster_serialized_t));
540  RASTER_DEBUGF(3, "sizeof(struct rt_raster_t):%u",
541  sizeof (struct rt_raster_t));
542  RASTER_DEBUGF(3, "serialized size:%lu", (long unsigned) size);
543 
544  /* Set size */
545  /* NOTE: Value of rt_raster.size may be updated in
546  * returned object, for instance, by rt_pg layer to
547  * store value calculated by SET_VARSIZE.
548  */
549  raster->size = size;
550 
551  /* Set version */
552  raster->version = 0;
553 
554  /* Copy header */
555  memcpy(ptr, raster, sizeof (struct rt_raster_serialized_t));
556 
557  RASTER_DEBUG(3, "Start hex dump of raster being serialized using 0x2D to mark non-written bytes");
558 
559 #if POSTGIS_DEBUG_LEVEL > 2
560  uint8_t* dbg_ptr = ptr;
561  d_print_binary_hex("HEADER", dbg_ptr, size);
562 #endif
563 
564  ptr += sizeof (struct rt_raster_serialized_t);
565 
566  /* Serialize bands now */
567  for (i = 0; i < raster->numBands; ++i) {
568  rt_band band = raster->bands[i];
569  assert(NULL != band);
570 
571  rt_pixtype pixtype = band->pixtype;
572  int pixbytes = rt_pixtype_size(pixtype);
573  if (pixbytes < 1) {
574  rterror("rt_raster_serialize: Corrupted band: unknown pixtype");
575  rtdealloc(ret);
576  return NULL;
577  }
578 
579  /* Add band type */
580  *ptr = band->pixtype;
581  if (band->offline) {
582 #ifdef POSTGIS_RASTER_DISABLE_OFFLINE
583  rterror("rt_raster_serialize: offdb raster support disabled at compile-time");
584  return NULL;
585 #endif
586  *ptr |= BANDTYPE_FLAG_OFFDB;
587  }
588  if (band->hasnodata) {
589  *ptr |= BANDTYPE_FLAG_HASNODATA;
590  }
591 
592  if (band->isnodata) {
593  *ptr |= BANDTYPE_FLAG_ISNODATA;
594  }
595 
596 #if POSTGIS_DEBUG_LEVEL > 2
597  d_print_binary_hex("PIXTYPE", dbg_ptr, size);
598 #endif
599 
600  ptr += 1;
601 
602  /* Add padding (if needed) */
603  if (pixbytes > 1) {
604  memset(ptr, '\0', pixbytes - 1);
605  ptr += pixbytes - 1;
606  }
607 
608 #if POSTGIS_DEBUG_LEVEL > 2
609  d_print_binary_hex("PADDING", dbg_ptr, size);
610 #endif
611 
612  /* Consistency checking (ptr is pixbytes-aligned) */
613  assert(!((ptr - ret) % pixbytes));
614 
615  /* Add nodata value */
616  switch (pixtype) {
617  case PT_1BB:
618  case PT_2BUI:
619  case PT_4BUI:
620  case PT_8BUI: {
621  uint8_t v = band->nodataval;
622  *ptr = v;
623  ptr += 1;
624  break;
625  }
626  case PT_8BSI: {
627  int8_t v = band->nodataval;
628  *ptr = v;
629  ptr += 1;
630  break;
631  }
632  case PT_16BSI:
633  case PT_16BUI: {
634  uint16_t v = band->nodataval;
635  memcpy(ptr, &v, 2);
636  ptr += 2;
637  break;
638  }
639  case PT_32BSI:
640  case PT_32BUI: {
641  uint32_t v = band->nodataval;
642  memcpy(ptr, &v, 4);
643  ptr += 4;
644  break;
645  }
646  case PT_32BF: {
647  float v = band->nodataval;
648  memcpy(ptr, &v, 4);
649  ptr += 4;
650  break;
651  }
652  case PT_64BF: {
653  memcpy(ptr, &band->nodataval, 8);
654  ptr += 8;
655  break;
656  }
657  default:
658  rterror("rt_raster_serialize: Fatal error caused by unknown pixel type. Aborting.");
659  rtdealloc(ret);
660  return NULL;
661  }
662 
663  /* Consistency checking (ptr is pixbytes-aligned) */
664  assert(!((ptr - ret) % pixbytes));
665 
666 #if POSTGIS_DEBUG_LEVEL > 2
667  d_print_binary_hex("nodata", dbg_ptr, size);
668 #endif
669 
670  if (band->offline) {
671  /* Write band number */
672  *ptr = band->data.offline.bandNum;
673  ptr += 1;
674 
675  /* Write path */
676  strcpy((char*) ptr, band->data.offline.path);
677  ptr += strlen(band->data.offline.path) + 1;
678  }
679  else {
680  /* Write data */
681  uint32_t datasize = raster->width * raster->height * pixbytes;
682  memcpy(ptr, band->data.mem, datasize);
683  ptr += datasize;
684  }
685 
686 #if POSTGIS_DEBUG_LEVEL > 2
687  d_print_binary_hex("BAND", dbg_ptr, size);
688 #endif
689 
690  /* Pad up to 8-bytes boundary */
691  while ((uintptr_t) ptr % 8) {
692  *ptr = 0;
693  ++ptr;
694 
695  RASTER_DEBUGF(3, "PAD at %d", (uintptr_t) ptr % 8);
696  }
697 
698  /* Consistency checking (ptr is pixbytes-aligned) */
699  assert(!((ptr - ret) % pixbytes));
700  } /* for-loop over bands */
701 
702 #if POSTGIS_DEBUG_LEVEL > 2
703  d_print_binary_hex("SERIALIZED RASTER", dbg_ptr, size);
704 #endif
705  return ret;
706 }
707 
716 rt_raster
717 rt_raster_deserialize(void* serialized, int header_only) {
718  rt_raster rast = NULL;
719  const uint8_t *ptr = NULL;
720  const uint8_t *beg = NULL;
721  uint16_t i = 0;
722  uint16_t j = 0;
723  uint8_t littleEndian = isMachineLittleEndian();
724 
725  assert(NULL != serialized);
726 
727  RASTER_DEBUG(2, "rt_raster_deserialize: Entering...");
728 
729  /* NOTE: Value of rt_raster.size may be different
730  * than actual size of raster data being read.
731  * See note on SET_VARSIZE in rt_raster_serialize function above.
732  */
733 
734  /* Allocate memory for deserialized raster header */
735  RASTER_DEBUG(3, "rt_raster_deserialize: Allocating memory for deserialized raster header");
736  rast = (rt_raster) rtalloc(sizeof (struct rt_raster_t));
737  if (!rast) {
738  rterror("rt_raster_deserialize: Out of memory allocating raster for deserialization");
739  return NULL;
740  }
741 
742  /* Deserialize raster header */
743  RASTER_DEBUG(3, "rt_raster_deserialize: Deserialize raster header");
744  memcpy(rast, serialized, sizeof (struct rt_raster_serialized_t));
745 
746  if (0 == rast->numBands || header_only) {
747  rast->bands = 0;
748  return rast;
749  }
750 
751  beg = (const uint8_t*) serialized;
752 
753  /* Allocate registry of raster bands */
754  RASTER_DEBUG(3, "rt_raster_deserialize: Allocating memory for bands");
755  rast->bands = rtalloc(rast->numBands * sizeof (rt_band));
756  if (rast->bands == NULL) {
757  rterror("rt_raster_deserialize: Out of memory allocating bands");
758  rtdealloc(rast);
759  return NULL;
760  }
761 
762  RASTER_DEBUGF(3, "rt_raster_deserialize: %d bands", rast->numBands);
763 
764  /* Move to the beginning of first band */
765  ptr = beg;
766  ptr += sizeof (struct rt_raster_serialized_t);
767 
768  /* Deserialize bands now */
769  for (i = 0; i < rast->numBands; ++i) {
770  rt_band band = NULL;
771  uint8_t type = 0;
772  int pixbytes = 0;
773 
774  band = rtalloc(sizeof(struct rt_band_t));
775  if (!band) {
776  rterror("rt_raster_deserialize: Out of memory allocating rt_band during deserialization");
777  for (j = 0; j < i; j++) rt_band_destroy(rast->bands[j]);
778  rt_raster_destroy(rast);
779  return NULL;
780  }
781 
782  rast->bands[i] = band;
783 
784  type = *ptr;
785  ptr++;
786  band->pixtype = type & BANDTYPE_PIXTYPE_MASK;
787 
788  RASTER_DEBUGF(3, "rt_raster_deserialize: band %d with pixel type %s", i, rt_pixtype_name(band->pixtype));
789 
790  band->offline = BANDTYPE_IS_OFFDB(type) ? 1 : 0;
791  band->hasnodata = BANDTYPE_HAS_NODATA(type) ? 1 : 0;
792  band->isnodata = band->hasnodata ? (BANDTYPE_IS_NODATA(type) ? 1 : 0) : 0;
793  band->width = rast->width;
794  band->height = rast->height;
795  band->ownsdata = 0; /* we do NOT own this data!!! */
796  band->raster = rast;
797 
798  /* Advance by data padding */
799  pixbytes = rt_pixtype_size(band->pixtype);
800  ptr += pixbytes - 1;
801 
802  /* Read nodata value */
803  switch (band->pixtype) {
804  case PT_1BB: {
805  band->nodataval = ((int) read_uint8(&ptr)) & 0x01;
806  break;
807  }
808  case PT_2BUI: {
809  band->nodataval = ((int) read_uint8(&ptr)) & 0x03;
810  break;
811  }
812  case PT_4BUI: {
813  band->nodataval = ((int) read_uint8(&ptr)) & 0x0F;
814  break;
815  }
816  case PT_8BSI: {
817  band->nodataval = read_int8(&ptr);
818  break;
819  }
820  case PT_8BUI: {
821  band->nodataval = read_uint8(&ptr);
822  break;
823  }
824  case PT_16BSI: {
825  band->nodataval = read_int16(&ptr, littleEndian);
826  break;
827  }
828  case PT_16BUI: {
829  band->nodataval = read_uint16(&ptr, littleEndian);
830  break;
831  }
832  case PT_32BSI: {
833  band->nodataval = read_int32(&ptr, littleEndian);
834  break;
835  }
836  case PT_32BUI: {
837  band->nodataval = read_uint32(&ptr, littleEndian);
838  break;
839  }
840  case PT_32BF: {
841  band->nodataval = read_float32(&ptr, littleEndian);
842  break;
843  }
844  case PT_64BF: {
845  band->nodataval = read_float64(&ptr, littleEndian);
846  break;
847  }
848  default: {
849  rterror("rt_raster_deserialize: Unknown pixeltype %d", band->pixtype);
850  for (j = 0; j <= i; j++) rt_band_destroy(rast->bands[j]);
851  rt_raster_destroy(rast);
852  return NULL;
853  }
854  }
855 
856  RASTER_DEBUGF(3, "rt_raster_deserialize: has nodata flag %d", band->hasnodata);
857  RASTER_DEBUGF(3, "rt_raster_deserialize: nodata value %g", band->nodataval);
858 
859  /* Consistency checking (ptr is pixbytes-aligned) */
860  assert(!((ptr - beg) % pixbytes));
861 
862  if (band->offline) {
863  int pathlen = 0;
864 
865  /* Read band number */
866  band->data.offline.bandNum = *ptr;
867  ptr += 1;
868 
869  /* Register path */
870  pathlen = strlen((char*) ptr);
871  band->data.offline.path = rtalloc(sizeof(char) * (pathlen + 1));
872  if (band->data.offline.path == NULL) {
873  rterror("rt_raster_deserialize: Could not allocate memory for offline band path");
874  for (j = 0; j <= i; j++) rt_band_destroy(rast->bands[j]);
875  rt_raster_destroy(rast);
876  return NULL;
877  }
878 
879  memcpy(band->data.offline.path, ptr, pathlen);
880  band->data.offline.path[pathlen] = '\0';
881  ptr += pathlen + 1;
882 
883  band->data.offline.mem = NULL;
884  }
885  else {
886  /* Register data */
887  const uint32_t datasize = rast->width * rast->height * pixbytes;
888  band->data.mem = (uint8_t*) ptr;
889  ptr += datasize;
890  }
891 
892  /* Skip bytes of padding up to 8-bytes boundary */
893 #if POSTGIS_DEBUG_LEVEL > 0
894  const uint8_t *padbeg = ptr;
895 #endif
896  while (0 != ((ptr - beg) % 8)) {
897  ++ptr;
898  }
899 
900  RASTER_DEBUGF(3, "rt_raster_deserialize: skip %d bytes of 8-bytes boundary padding", ptr - padbeg);
901 
902  /* Consistency checking (ptr is pixbytes-aligned) */
903  assert(!((ptr - beg) % pixbytes));
904  }
905 
906  return rast;
907 }
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_serialize.c:717
#define BANDTYPE_FLAG_HASNODATA
Definition: rt_serialize.h:38
raster
Be careful!! Zeros function&#39;s input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
uint16_t numBands
Definition: librtcore.h:2241
void deparse_hex(uint8_t str, char *result)
Convert a char into a human readable hex digit.
Definition: lwgeom_api.c:648
struct rt_raster_t * rt_raster
Types definitions.
Definition: librtcore.h:145
rt_raster raster
Definition: librtcore.h:2275
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_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_serialize.c:521
rt_pixtype
Definition: librtcore.h:185
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition: rt_band.c:242
uint32_t size
Definition: librtcore.h:2236
void flip_endian_16(uint8_t *d)
Definition: rt_serialize.c:165
uint16_t height
Definition: librtcore.h:2253
unsigned int uint32_t
Definition: uthash.h:78
int16_t read_int16(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:261
void write_uint16(uint8_t **to, uint8_t littleEndian, uint16_t v)
Definition: rt_serialize.c:247
uint16_t version
Definition: librtcore.h:2237
uint32_t read_uint32(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:287
static uint32_t rt_raster_serialized_size(rt_raster raster)
Definition: rt_serialize.c:462
uint16_t read_uint16(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:229
void rtwarn(const char *fmt,...)
Definition: rt_context.c:224
#define BANDTYPE_FLAG_OFFDB
Definition: rt_serialize.h:37
#define BANDTYPE_IS_OFFDB(x)
Definition: rt_serialize.h:43
void flip_endian_32(uint8_t *d)
Definition: rt_serialize.c:172
uint16_t width
Definition: librtcore.h:2252
union rt_band_t::@6 data
void rtinfo(const char *fmt,...)
Definition: rt_context.c:211
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
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:82
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
void rtdealloc(void *mem)
Definition: rt_context.c:186
int32_t isnodata
Definition: librtcore.h:2270
#define RASTER_DEBUG(level, msg)
Definition: librtcore.h:295
Struct definitions.
Definition: librtcore.h:2201
This library is the generic raster handling section of PostGIS.
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
rt_band * bands
Definition: librtcore.h:2254
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
void swap_char(uint8_t *a, uint8_t *b)
Definition: rt_serialize.c:154
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
#define BANDTYPE_FLAG_ISNODATA
Definition: rt_serialize.h:39