PostGIS  3.7.0dev-r@@SVN_REVISION@@
rt_wkb.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 #include <inttypes.h>
35 
36 /* Read band from WKB as at start of band */
37 static rt_band
39  uint16_t width, uint16_t height,
40  const uint8_t** ptr, const uint8_t* end,
41  uint8_t littleEndian
42 ) {
43  rt_band band = NULL;
44  int pixbytes = 0;
45  uint8_t type = 0;
46  size_t sz = 0;
47  size_t v = 0;
48 
49  assert(NULL != ptr);
50  assert(NULL != end);
51 
52  band = rtalloc(sizeof (struct rt_band_t));
53  if (!band) {
54  rterror("rt_band_from_wkb: Out of memory allocating rt_band during WKB parsing");
55  return NULL;
56  }
57  band->ownsdata = 0; /* assume we don't own data */
58 
59  if (end - *ptr < 1) {
60  rterror("rt_band_from_wkb: Premature end of WKB on band reading (%s:%d)",
61  __FILE__, __LINE__);
63  return NULL;
64  }
65  type = read_uint8(ptr);
66 
67  if ((type & BANDTYPE_PIXTYPE_MASK) >= PT_END) {
68  rterror("rt_band_from_wkb: Invalid pixtype %d", type & BANDTYPE_PIXTYPE_MASK);
70  return NULL;
71  }
72 
73  band->pixtype = type & BANDTYPE_PIXTYPE_MASK;
74  band->offline = BANDTYPE_IS_OFFDB(type) ? 1 : 0;
75  band->hasnodata = BANDTYPE_HAS_NODATA(type) ? 1 : 0;
76  band->isnodata = band->hasnodata ? (BANDTYPE_IS_NODATA(type) ? 1 : 0) : 0;
77  band->width = width;
78  band->height = height;
79 
80  RASTER_DEBUGF(3, " Band pixtype:%s, offline:%d, hasnodata:%d",
81  rt_pixtype_name(band->pixtype),
82  band->offline,
83  band->hasnodata
84  );
85 
86  /* Check there's enough bytes to read nodata value */
87  pixbytes = rt_pixtype_size(band->pixtype);
88  if (((*ptr) + pixbytes) >= end) {
89  rterror("rt_band_from_wkb: Premature end of WKB on band novalue reading");
91  return NULL;
92  }
93 
94  /* Read nodata value */
95  switch (band->pixtype) {
96  case PT_1BB: {
97  band->nodataval = ((int) read_uint8(ptr)) & 0x01;
98  break;
99  }
100  case PT_2BUI: {
101  band->nodataval = ((int) read_uint8(ptr)) & 0x03;
102  break;
103  }
104  case PT_4BUI: {
105  band->nodataval = ((int) read_uint8(ptr)) & 0x0F;
106  break;
107  }
108  case PT_8BSI: {
109  band->nodataval = read_int8(ptr);
110  break;
111  }
112  case PT_8BUI: {
113  band->nodataval = read_uint8(ptr);
114  break;
115  }
116  case PT_16BSI: {
117  band->nodataval = read_int16(ptr, littleEndian);
118  break;
119  }
120  case PT_16BUI: {
121  band->nodataval = read_uint16(ptr, littleEndian);
122  break;
123  }
124  case PT_32BSI: {
125  band->nodataval = read_int32(ptr, littleEndian);
126  break;
127  }
128  case PT_32BUI: {
129  band->nodataval = read_uint32(ptr, littleEndian);
130  break;
131  }
132  case PT_32BF: {
133  band->nodataval = read_float32(ptr, littleEndian);
134  break;
135  }
136  case PT_64BF: {
137  band->nodataval = read_float64(ptr, littleEndian);
138  break;
139  }
140  default: {
141  rterror("rt_band_from_wkb: Unknown pixeltype %d", band->pixtype);
143  return NULL;
144  }
145  }
146 
147  RASTER_DEBUGF(3, " Nodata value: %g, pixbytes: %d, ptr @ %p, end @ %p",
148  band->nodataval, pixbytes, *ptr, end);
149 
150  if (band->offline) {
151  if (((*ptr) + 1) >= end) {
152  rterror("rt_band_from_wkb: Premature end of WKB on offline "
153  "band data bandNum reading (%s:%d)",
154  __FILE__, __LINE__
155  );
157  return NULL;
158  }
159 
160  band->data.offline.bandNum = read_int8(ptr);
161  band->data.offline.mem = NULL;
162 
163  {
164  /* check we have a NULL-termination */
165  sz = 0;
166  while ((*ptr)[sz] && &((*ptr)[sz]) < end) ++sz;
167  if (&((*ptr)[sz]) >= end) {
168  rterror("rt_band_from_wkb: Premature end of WKB on band offline path reading");
170  return NULL;
171  }
172 
173  /* we never own offline band data */
174  band->ownsdata = 0;
175 
176  band->data.offline.path = rtalloc(sz + 1);
177  if (band->data.offline.path == NULL) {
178  rterror("rt_band_from_wkb: Out of memory allocating for offline path of band");
180  return NULL;
181  }
182 
183  memcpy(band->data.offline.path, *ptr, sz);
184  band->data.offline.path[sz] = '\0';
185 
186  RASTER_DEBUGF(3, "OFFDB band path is %s (size is %zu)",
187  band->data.offline.path, sz);
188 
189  *ptr += sz + 1;
190 
191  /* TODO: How could we know if the offline band is a nodata band? */
192  /* trust in the force */
193  /*band->isnodata = FALSE;*/
194  }
195 
196  return band;
197  }
198 
199  /* This is an on-disk band */
200  sz = (size_t)width * height * pixbytes;
201  if (((*ptr) + sz) > end) {
202  rterror("rt_band_from_wkb: Premature end of WKB on band data reading (%s:%d)",
203  __FILE__, __LINE__);
205  return NULL;
206  }
207 
208  band->data.mem = rtalloc(sz);
209  if (!band->data.mem) {
210  rterror("rt_band_from_wkb: Out of memory during band creation in WKB parser");
212  return NULL;
213  }
214 
215  band->ownsdata = 1; /* we DO own this data!!! */
216  memcpy(band->data.mem, *ptr, sz);
217  *ptr += sz;
218 
219  /* Should now flip values if > 8bit and
220  * littleEndian != isMachineLittleEndian */
221  if (pixbytes > 1) {
222  if (isMachineLittleEndian() != littleEndian) {
223  void (*flipper)(uint8_t*) = 0;
224  uint8_t *flipme = NULL;
225 
226  if (pixbytes == 2)
227  flipper = flip_endian_16;
228  else if (pixbytes == 4)
229  flipper = flip_endian_32;
230  else if (pixbytes == 8)
231  flipper = flip_endian_64;
232  else {
233  rterror("rt_band_from_wkb: Unexpected pix bytes %d", pixbytes);
235  return NULL;
236  }
237 
238  flipme = band->data.mem;
239  sz = (size_t)width * height;
240  for (v = 0; v < sz; ++v) {
241  flipper(flipme);
242  flipme += pixbytes;
243  }
244  }
245  }
246  /* And should check for invalid values for < 8bit types */
247  else if (
248  band->pixtype == PT_1BB ||
249  band->pixtype == PT_2BUI ||
250  band->pixtype == PT_4BUI
251  ) {
252  uint8_t maxVal = band->pixtype == PT_1BB ? 1 : (band->pixtype == PT_2BUI ? 3 : 15);
253  uint8_t val;
254 
255  sz = (size_t)width*height;
256  for (v = 0; v < sz; ++v) {
257  val = ((uint8_t*) band->data.mem)[v];
258  if (val > maxVal) {
259  rterror("rt_band_from_wkb: Invalid value %d for pixel of type %s",
260  val, rt_pixtype_name(band->pixtype));
262  return NULL;
263  }
264  }
265  }
266 
267  /* And we should check if the band is a nodata band */
268  /* TODO: No!! This is too slow */
269  /*rt_band_check_is_nodata(band);*/
270 
271  return band;
272 }
273 
274 /* -4 for size, +1 for endian */
275 #define RT_WKB_HDR_SZ (sizeof(struct rt_raster_serialized_t)-4+1)
276 
277 rt_raster
278 rt_raster_from_wkb(const uint8_t* wkb, uint32_t wkbsize) {
279  const uint8_t *ptr = wkb;
280  const uint8_t *wkbend = NULL;
281  rt_raster rast = NULL;
282  uint8_t endian = 0;
283  uint16_t version = 0;
284  uint16_t i = 0;
285  uint16_t j = 0;
286 
287  assert(NULL != ptr);
288 
289  /* Check that wkbsize is >= sizeof(rt_raster_serialized) */
290  if (wkbsize < RT_WKB_HDR_SZ) {
291  rterror("rt_raster_from_wkb: wkb size (%" PRIu32
292  ") < min size (%zu)",
293  wkbsize, RT_WKB_HDR_SZ);
294  return NULL;
295  }
296  wkbend = wkb + wkbsize;
297 
298  RASTER_DEBUGF(3, "Parsing header from wkb position %zu (expected 0)",
299  d_binptr_to_pos(ptr, wkbend, wkbsize));
300 
301  CHECK_BINPTR_POSITION(ptr, wkbend, wkbsize, 0);
302 
303  /* Read endianness */
304  endian = *ptr;
305  ptr += 1;
306 
307  /* Read version of protocol */
308  version = read_uint16(&ptr, endian);
309  if (version != 0) {
310  rterror("rt_raster_from_wkb: WKB version %d unsupported", version);
311  return NULL;
312  }
313 
314  /* Read other components of raster header */
315  rast = (rt_raster) rtalloc(sizeof (struct rt_raster_t));
316  if (!rast) {
317  rterror("rt_raster_from_wkb: Out of memory allocating raster for wkb input");
318  return NULL;
319  }
320 
321  rast->numBands = read_uint16(&ptr, endian);
322  rast->scaleX = read_float64(&ptr, endian);
323  rast->scaleY = read_float64(&ptr, endian);
324  rast->ipX = read_float64(&ptr, endian);
325  rast->ipY = read_float64(&ptr, endian);
326  rast->skewX = read_float64(&ptr, endian);
327  rast->skewY = read_float64(&ptr, endian);
328  rast->srid = clamp_srid(read_int32(&ptr, endian));
329  rast->width = read_uint16(&ptr, endian);
330  rast->height = read_uint16(&ptr, endian);
331 
332  /* Consistency checking, should have been checked before */
333  assert(ptr <= wkbend);
334 
335  RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster numBands: %d",
336  rast->numBands);
337  RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster scale: %gx%g",
338  rast->scaleX, rast->scaleY);
339  RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster ip: %gx%g",
340  rast->ipX, rast->ipY);
341  RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster skew: %gx%g",
342  rast->skewX, rast->skewY);
343  RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster srid: %d",
344  rast->srid);
345  RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster dims: %dx%d",
346  rast->width, rast->height);
347  RASTER_DEBUGF(3, "Parsing raster header finished at wkb position %zu (expected 61)",
348  d_binptr_to_pos(ptr, wkbend, wkbsize));
349 
350  CHECK_BINPTR_POSITION(ptr, wkbend, wkbsize, 61);
351 
352  /* Read all bands of raster */
353  if (!rast->numBands) {
354  /* Here ptr should have been left to right after last used byte */
355  if (ptr < wkbend) {
356  rtwarn("%zu bytes of WKB remained unparsed", wkbend - ptr);
357  }
358  else if (ptr > wkbend) {
359  /* Easier to get a segfault before I guess */
360  rtwarn("We parsed %zu bytes more then available!", ptr - wkbend);
361  }
362 
363  rast->bands = NULL;
364  return rast;
365  }
366 
367  /* Now read the bands */
368  rast->bands = (rt_band*) rtalloc(sizeof(rt_band) * rast->numBands);
369  if (!rast->bands) {
370  rterror("rt_raster_from_wkb: Out of memory allocating bands for WKB raster decoding");
372  return NULL;
373  }
374 
375  /* ptr should now point to start of first band */
376  /* we should have checked this before */
377  assert(ptr <= wkbend);
378 
379  for (i = 0; i < rast->numBands; ++i) {
380  RASTER_DEBUGF(3, "Parsing band %d from wkb position %zu", i,
381  d_binptr_to_pos(ptr, wkbend, wkbsize));
382 
383  rt_band band = rt_band_from_wkb(rast->width, rast->height,
384  &ptr, wkbend, endian);
385  if (!band) {
386  rterror("rt_raster_from_wkb: Error reading WKB form of band %d", i);
387  for (j = 0; j < i; j++) rt_band_destroy(rast->bands[j]);
389  return NULL;
390  }
391 
392  band->raster = rast;
393  rast->bands[i] = band;
394  }
395 
396  /* Here ptr should have been left to right after last used byte */
397  if (ptr < wkbend) {
398  rtwarn("%zu bytes of WKB remained unparsed", wkbend - ptr);
399  }
400  else if (ptr > wkbend) {
401  /* Easier to get a segfault before I guess */
402  rtwarn("We parsed %zu bytes more then available!", ptr - wkbend);
403  }
404 
405  return rast;
406 }
407 
408 rt_raster
409 rt_raster_from_hexwkb(const char* hexwkb, uint32_t hexwkbsize) {
410  rt_raster ret = NULL;
411  uint8_t* wkb = NULL;
412  uint32_t wkbsize = 0;
413  uint32_t i = 0;
414 
415  assert(NULL != hexwkb);
416 
417  RASTER_DEBUGF(3, "input wkb: %s", hexwkb);
418  RASTER_DEBUGF(3, "input wkbsize: %d", hexwkbsize);
419 
420  if (hexwkbsize % 2) {
421  rterror("rt_raster_from_hexwkb: Raster HEXWKB input must have an even number of characters");
422  return NULL;
423  }
424  wkbsize = hexwkbsize / 2;
425 
426  wkb = rtalloc(wkbsize);
427  if (!wkb) {
428  rterror("rt_raster_from_hexwkb: Out of memory allocating memory for decoding HEXWKB");
429  return NULL;
430  }
431 
432  /* parse full hex */
433  for (i = 0; i < wkbsize; ++i) {
434  wkb[i] = parse_hex((char*) & (hexwkb[i * 2]));
435  }
436 
437  ret = rt_raster_from_wkb(wkb, wkbsize);
438  rtdealloc(wkb); /* as long as rt_raster_from_wkb copies memory */
439 
440  return ret;
441 }
442 
443 static uint32_t
445  uint32_t size = RT_WKB_HDR_SZ;
446  uint16_t i = 0;
447 
448  assert(NULL != raster);
449 
450  RASTER_DEBUGF(3, "rt_raster_wkb_size: computing size for %d bands",
451  raster->numBands);
452 
453  for (i = 0; i < raster->numBands; ++i) {
454  rt_band band = raster->bands[i];
455  rt_pixtype pixtype = band->pixtype;
456  int pixbytes = rt_pixtype_size(pixtype);
457 
458  RASTER_DEBUGF(3, "rt_raster_wkb_size: adding size of band %d", i);
459 
460  if (pixbytes < 1) {
461  rterror("rt_raster_wkb_size: Corrupted band: unknown pixtype");
462  return 0;
463  }
464 
465  /* Add space for band type */
466  size += 1;
467 
468  /* Add space for nodata value */
469  size += pixbytes;
470 
471  if (!outasin && band->offline) {
472  /* Add space for band number */
473  size += 1;
474 
475  /* Add space for null-terminated path */
476  size += strlen(band->data.offline.path) + 1;
477  }
478  else {
479  /* Add space for actual data */
480  size += pixbytes * raster->width * raster->height;
481  }
482  }
483 
484  return size;
485 }
486 
496 uint8_t *
497 rt_raster_to_wkb(rt_raster raster, int outasin, uint32_t *wkbsize) {
498 
499 #if POSTGIS_DEBUG_LEVEL > 0
500  const uint8_t *wkbend = NULL;
501 #endif
502 
503  uint8_t *wkb = NULL;
504  uint8_t *ptr = NULL;
505  uint16_t i = 0;
506  uint8_t littleEndian = isMachineLittleEndian();
507 
508  assert(NULL != raster);
509  assert(NULL != wkbsize);
510 
511  RASTER_DEBUG(2, "rt_raster_to_wkb: about to call rt_raster_wkb_size");
512 
513  *wkbsize = rt_raster_wkb_size(raster, outasin);
514  RASTER_DEBUGF(3, "rt_raster_to_wkb: found size: %d", *wkbsize);
515 
516  wkb = (uint8_t*) rtalloc(*wkbsize);
517  if (!wkb) {
518  rterror("rt_raster_to_wkb: Out of memory allocating WKB for raster");
519  return NULL;
520  }
521 
522  ptr = wkb;
523 
524 #if POSTGIS_DEBUG_LEVEL > 2
525  wkbend = ptr + (*wkbsize);
526 #endif
527  RASTER_DEBUGF(3, "Writing raster header to wkb on position %zu (expected 0)",
528  d_binptr_to_pos(ptr, wkbend, *wkbsize));
529 
530  /* Write endianness */
531  *ptr = littleEndian;
532  ptr += 1;
533 
534  /* Write version(size - (end - ptr)) */
535  write_uint16(&ptr, littleEndian, 0);
536 
537  /* Copy header (from numBands up) */
538  memcpy(ptr, &(raster->numBands), sizeof (struct rt_raster_serialized_t) - 6);
539  ptr += sizeof (struct rt_raster_serialized_t) - 6;
540 
541  RASTER_DEBUGF(3, "Writing bands header to wkb position %zu (expected 61)",
542  d_binptr_to_pos(ptr, wkbend, *wkbsize));
543 
544  /* Serialize bands now */
545  for (i = 0; i < raster->numBands; ++i) {
546  rt_band band = raster->bands[i];
547  rt_pixtype pixtype = band->pixtype;
548  int pixbytes = rt_pixtype_size(pixtype);
549 
550  RASTER_DEBUGF(3, "Writing WKB for band %d", i);
551  RASTER_DEBUGF(3, "Writing band pixel type to wkb position %zu",
552  d_binptr_to_pos(ptr, wkbend, *wkbsize));
553 
554  if (pixbytes < 1) {
555  rterror("rt_raster_to_wkb: Corrupted band: unknown pixtype");
556  rtdealloc(wkb);
557  return NULL;
558  }
559 
560  /* Add band type */
561  *ptr = band->pixtype;
562  if (!outasin && band->offline) *ptr |= BANDTYPE_FLAG_OFFDB;
563  if (band->hasnodata) *ptr |= BANDTYPE_FLAG_HASNODATA;
564  if (band->isnodata) *ptr |= BANDTYPE_FLAG_ISNODATA;
565  ptr += 1;
566 
567 #if 0
568  /* no padding required for WKB */
569  /* Add padding (if needed) */
570  if (pixbytes > 1) {
571  memset(ptr, '\0', pixbytes - 1);
572  ptr += pixbytes - 1;
573  }
574  /* Consistency checking (ptr is pixbytes-aligned) */
575  assert(!(((uint64_t) ptr) % pixbytes));
576 #endif
577 
578  RASTER_DEBUGF(3, "Writing band nodata to wkb position %zu",
579  d_binptr_to_pos(ptr, wkbend, *wkbsize));
580 
581  /* Add nodata value */
582  switch (pixtype) {
583  case PT_1BB:
584  case PT_2BUI:
585  case PT_4BUI:
586  case PT_8BUI: {
587  uint8_t v = band->nodataval;
588  *ptr = v;
589  ptr += 1;
590  break;
591  }
592  case PT_8BSI: {
593  int8_t v = band->nodataval;
594  *ptr = (uint8_t)v;
595  ptr += 1;
596  break;
597  }
598  case PT_16BSI: {
599  int16_t v = band->nodataval;
600  memcpy(ptr, &v, 2);
601  ptr += 2;
602  break;
603  }
604  case PT_16BUI: {
605  uint16_t v = band->nodataval;
606  memcpy(ptr, &v, 2);
607  ptr += 2;
608  break;
609  }
610  case PT_32BSI: {
611  int32_t v = band->nodataval;
612  memcpy(ptr, &v, 4);
613  ptr += 4;
614  break;
615  }
616  case PT_32BUI: {
617  uint32_t v = band->nodataval;
618  memcpy(ptr, &v, 4);
619  ptr += 4;
620  break;
621  }
622  case PT_32BF: {
623  float v = band->nodataval;
624  memcpy(ptr, &v, 4);
625  ptr += 4;
626  break;
627  }
628  case PT_64BF: {
629  memcpy(ptr, &band->nodataval, 8);
630  ptr += 8;
631  break;
632  }
633  default:
634  rterror("rt_raster_to_wkb: Fatal error caused by unknown pixel type. Aborting.");
635  rtdealloc(wkb);
636  abort(); /* shouldn't happen */
637  return 0;
638  }
639 
640 #if 0
641  /* no padding for WKB */
642  /* Consistency checking (ptr is pixbytes-aligned) */
643  assert(!((uint64_t) ptr % pixbytes));
644 #endif
645 
646  if (!outasin && band->offline) {
647  /* Write band number */
648  *ptr = band->data.offline.bandNum;
649  ptr += 1;
650 
651  /* Write path */
652  strcpy((char*) ptr, band->data.offline.path);
653  ptr += strlen(band->data.offline.path) + 1;
654  }
655  else {
656  /* Write data */
657  uint32_t datasize = raster->width * raster->height * pixbytes;
658  RASTER_DEBUGF(4, "rt_raster_to_wkb: Copying %d bytes", datasize);
659 
660  memcpy(ptr, rt_band_get_data(band), datasize);
661 
662  ptr += datasize;
663  }
664 
665 #if 0
666  /* no padding for WKB */
667  /* Pad up to 8-bytes boundary */
668  while ((uint64_t) ptr % 8) {
669  *ptr = 0;
670  ++ptr;
671  }
672 
673  /* Consistency checking (ptr is pixbytes-aligned) */
674  assert(!((uint64_t) ptr % pixbytes));
675 #endif
676  }
677 
678  return wkb;
679 }
680 
681 char *
682 rt_raster_to_hexwkb(rt_raster raster, int outasin, uint32_t *hexwkbsize) {
683  uint8_t *wkb = NULL;
684  char* hexwkb = NULL;
685  uint32_t wkbsize = 0;
686 
687  assert(NULL != raster);
688  assert(NULL != hexwkbsize);
689 
690  RASTER_DEBUG(2, "rt_raster_to_hexwkb: calling rt_raster_to_wkb");
691 
692  wkb = rt_raster_to_wkb(raster, outasin, &wkbsize);
693 
694  RASTER_DEBUG(3, "rt_raster_to_hexwkb: rt_raster_to_wkb returned");
695 
696  *hexwkbsize = wkbsize * 2; /* hex is 2 times bytes */
697  hexwkb = (char*) rtalloc((*hexwkbsize) + 1);
698  if (!hexwkb) {
699  rterror("rt_raster_to_hexwkb: Out of memory hexifying raster WKB");
700  rtdealloc(wkb);
701  return NULL;
702  }
703 
704  char *optr = hexwkb;
705  uint8_t *iptr = wkb;
706  const char hexchar[]="0123456789ABCDEF";
707  while (wkbsize--) {
708  uint8_t v = *iptr++;
709  *optr++ = hexchar[v>>4];
710  *optr++ = hexchar[v & 0x0F];
711  }
712  *optr = '\0'; /* Null-terminate */
713 
714  rtdealloc(wkb); /* we don't need this anymore */
715 
716  RASTER_DEBUGF(3, "rt_raster_to_hexwkb: output wkb: %s", hexwkb);
717  return hexwkb;
718 }
uint8_t parse_hex(char *str)
Convert a single hex digit into the corresponding char.
Definition: lwgeom_api.c:479
int32_t clamp_srid(int32_t srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition: lwutil.c:339
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.
Definition: rt_context.c:191
#define RASTER_DEBUG(level, msg)
Definition: librtcore.h:302
#define RASTER_DEBUGF(level, msg,...)
Definition: librtcore.h:306
void void void rtwarn(const char *fmt,...) __attribute__((format(printf
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:86
rt_pixtype
Definition: librtcore.h:187
@ PT_32BUI
Definition: librtcore.h:196
@ PT_2BUI
Definition: librtcore.h:189
@ PT_32BSI
Definition: librtcore.h:195
@ PT_END
Definition: librtcore.h:199
@ PT_4BUI
Definition: librtcore.h:190
@ PT_32BF
Definition: librtcore.h:197
@ PT_1BB
Definition: librtcore.h:188
@ PT_16BUI
Definition: librtcore.h:194
@ PT_8BSI
Definition: librtcore.h:191
@ PT_16BSI
Definition: librtcore.h:193
@ PT_64BF
Definition: librtcore.h:198
@ PT_8BUI
Definition: librtcore.h:192
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition: rt_band.c:491
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
void rtdealloc(void *mem)
Definition: rt_context.c:206
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
Definition: rt_band.c:551
struct rt_raster_t * rt_raster
Types definitions.
Definition: librtcore.h:146
int rt_pixtype_size(rt_pixtype pixtype)
Return size in bytes of a value in the given pixtype.
Definition: rt_pixel.c:39
This library is the generic raster handling section of PostGIS.
band
Definition: ovdump.py:58
type
Definition: ovdump.py:42
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
uint8_t isMachineLittleEndian(void)
Definition: rt_serialize.c:190
void flip_endian_32(uint8_t *d)
Definition: rt_serialize.c:172
void flip_endian_16(uint8_t *d)
Definition: rt_serialize.c:165
uint8_t read_uint8(const uint8_t **from)
Definition: rt_serialize.c:197
void write_uint16(uint8_t **to, uint8_t littleEndian, uint16_t v)
Definition: rt_serialize.c:247
double read_float64(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:389
float read_float32(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:363
void flip_endian_64(uint8_t *d)
Definition: rt_serialize.c:180
int8_t read_int8(const uint8_t **from)
Definition: rt_serialize.c:213
int16_t read_int16(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:261
int32_t read_int32(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:333
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_FLAG_HASNODATA
Definition: rt_serialize.h:38
#define BANDTYPE_FLAG_OFFDB
Definition: rt_serialize.h:37
#define BANDTYPE_FLAG_ISNODATA
Definition: rt_serialize.h:39
#define BANDTYPE_HAS_NODATA(x)
Definition: rt_serialize.h:44
#define BANDTYPE_IS_OFFDB(x)
Definition: rt_serialize.h:43
#define BANDTYPE_IS_NODATA(x)
Definition: rt_serialize.h:45
#define BANDTYPE_PIXTYPE_MASK
Definition: rt_serialize.h:36
#define CHECK_BINPTR_POSITION(ptr, end, size, pos)
Definition: rt_serialize.h:65
static rt_band rt_band_from_wkb(uint16_t width, uint16_t height, const uint8_t **ptr, const uint8_t *end, uint8_t littleEndian)
Definition: rt_wkb.c:38
rt_raster rt_raster_from_wkb(const uint8_t *wkb, uint32_t wkbsize)
Construct an rt_raster from a binary WKB representation.
Definition: rt_wkb.c:278
char * rt_raster_to_hexwkb(rt_raster raster, int outasin, uint32_t *hexwkbsize)
Return this raster in HEXWKB form (null-terminated hex)
Definition: rt_wkb.c:682
uint8_t * rt_raster_to_wkb(rt_raster raster, int outasin, uint32_t *wkbsize)
Return this raster in WKB form.
Definition: rt_wkb.c:497
rt_raster rt_raster_from_hexwkb(const char *hexwkb, uint32_t hexwkbsize)
Construct an rt_raster from a text HEXWKB representation.
Definition: rt_wkb.c:409
#define RT_WKB_HDR_SZ
Definition: rt_wkb.c:275
static uint32_t rt_raster_wkb_size(rt_raster raster, int outasin)
Definition: rt_wkb.c:444
Struct definitions.
Definition: librtcore.h:2440