PostGIS  2.2.7dev-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@keybit.net>
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 /* Read band from WKB as at start of band */
35 static rt_band
37  uint16_t width, uint16_t height,
38  const uint8_t** ptr, const uint8_t* end,
39  uint8_t littleEndian
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 }
271 
272 /* -4 for size, +1 for endian */
273 #define RT_WKB_HDR_SZ (sizeof(struct rt_raster_serialized_t)-4+1)
274 
275 rt_raster
276 rt_raster_from_wkb(const uint8_t* wkb, uint32_t wkbsize) {
277  const uint8_t *ptr = wkb;
278  const uint8_t *wkbend = NULL;
279  rt_raster rast = NULL;
280  uint8_t endian = 0;
281  uint16_t version = 0;
282  uint16_t i = 0;
283  uint16_t j = 0;
284 
285  assert(NULL != ptr);
286 
287  /* Check that wkbsize is >= sizeof(rt_raster_serialized) */
288  if (wkbsize < RT_WKB_HDR_SZ) {
289  rterror("rt_raster_from_wkb: wkb size (%d) < min size (%d)",
290  wkbsize, RT_WKB_HDR_SZ);
291  return NULL;
292  }
293  wkbend = wkb + wkbsize;
294 
295  RASTER_DEBUGF(3, "Parsing header from wkb position %d (expected 0)",
296  d_binptr_to_pos(ptr, wkbend, wkbsize));
297 
298  CHECK_BINPTR_POSITION(ptr, wkbend, wkbsize, 0);
299 
300  /* Read endianness */
301  endian = *ptr;
302  ptr += 1;
303 
304  /* Read version of protocol */
305  version = read_uint16(&ptr, endian);
306  if (version != 0) {
307  rterror("rt_raster_from_wkb: WKB version %d unsupported", version);
308  return NULL;
309  }
310 
311  /* Read other components of raster header */
312  rast = (rt_raster) rtalloc(sizeof (struct rt_raster_t));
313  if (!rast) {
314  rterror("rt_raster_from_wkb: Out of memory allocating raster for wkb input");
315  return NULL;
316  }
317 
318  rast->numBands = read_uint16(&ptr, endian);
319  rast->scaleX = read_float64(&ptr, endian);
320  rast->scaleY = read_float64(&ptr, endian);
321  rast->ipX = read_float64(&ptr, endian);
322  rast->ipY = read_float64(&ptr, endian);
323  rast->skewX = read_float64(&ptr, endian);
324  rast->skewY = read_float64(&ptr, endian);
325  rast->srid = clamp_srid(read_int32(&ptr, endian));
326  rast->width = read_uint16(&ptr, endian);
327  rast->height = read_uint16(&ptr, endian);
328 
329  /* Consistency checking, should have been checked before */
330  assert(ptr <= wkbend);
331 
332  RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster numBands: %d",
333  rast->numBands);
334  RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster scale: %gx%g",
335  rast->scaleX, rast->scaleY);
336  RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster ip: %gx%g",
337  rast->ipX, rast->ipY);
338  RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster skew: %gx%g",
339  rast->skewX, rast->skewY);
340  RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster srid: %d",
341  rast->srid);
342  RASTER_DEBUGF(3, "rt_raster_from_wkb: Raster dims: %dx%d",
343  rast->width, rast->height);
344  RASTER_DEBUGF(3, "Parsing raster header finished at wkb position %d (expected 61)",
345  d_binptr_to_pos(ptr, wkbend, wkbsize));
346 
347  CHECK_BINPTR_POSITION(ptr, wkbend, wkbsize, 61);
348 
349  /* Read all bands of raster */
350  if (!rast->numBands) {
351  /* Here ptr should have been left to right after last used byte */
352  if (ptr < wkbend) {
353  rtwarn("%d bytes of WKB remained unparsed", wkbend - ptr);
354  }
355  else if (ptr > wkbend) {
356  /* Easier to get a segfault before I guess */
357  rtwarn("We parsed %d bytes more then available!", ptr - wkbend);
358  }
359 
360  rast->bands = NULL;
361  return rast;
362  }
363 
364  /* Now read the bands */
365  rast->bands = (rt_band*) rtalloc(sizeof(rt_band) * rast->numBands);
366  if (!rast->bands) {
367  rterror("rt_raster_from_wkb: Out of memory allocating bands for WKB raster decoding");
368  rt_raster_destroy(rast);
369  return NULL;
370  }
371 
372  /* ptr should now point to start of first band */
373  /* we should have checked this before */
374  assert(ptr <= wkbend);
375 
376  for (i = 0; i < rast->numBands; ++i) {
377  RASTER_DEBUGF(3, "Parsing band %d from wkb position %d", i,
378  d_binptr_to_pos(ptr, wkbend, wkbsize));
379 
380  rt_band band = rt_band_from_wkb(rast->width, rast->height,
381  &ptr, wkbend, endian);
382  if (!band) {
383  rterror("rt_raster_from_wkb: Error reading WKB form of band %d", i);
384  for (j = 0; j < i; j++) rt_band_destroy(rast->bands[j]);
385  rt_raster_destroy(rast);
386  return NULL;
387  }
388 
389  band->raster = rast;
390  rast->bands[i] = band;
391  }
392 
393  /* Here ptr should have been left to right after last used byte */
394  if (ptr < wkbend) {
395  rtwarn("%d bytes of WKB remained unparsed", wkbend - ptr);
396  }
397  else if (ptr > wkbend) {
398  /* Easier to get a segfault before I guess */
399  rtwarn("We parsed %d bytes more then available!", ptr - wkbend);
400  }
401 
402  return rast;
403 }
404 
405 rt_raster
406 rt_raster_from_hexwkb(const char* hexwkb, uint32_t hexwkbsize) {
407  rt_raster ret = NULL;
408  uint8_t* wkb = NULL;
409  uint32_t wkbsize = 0;
410  uint32_t i = 0;
411 
412  assert(NULL != hexwkb);
413 
414  RASTER_DEBUGF(3, "input wkb: %s", hexwkb);
415  RASTER_DEBUGF(3, "input wkbsize: %d", hexwkbsize);
416 
417  if (hexwkbsize % 2) {
418  rterror("rt_raster_from_hexwkb: Raster HEXWKB input must have an even number of characters");
419  return NULL;
420  }
421  wkbsize = hexwkbsize / 2;
422 
423  wkb = rtalloc(wkbsize);
424  if (!wkb) {
425  rterror("rt_raster_from_hexwkb: Out of memory allocating memory for decoding HEXWKB");
426  return NULL;
427  }
428 
429  /* parse full hex */
430  for (i = 0; i < wkbsize; ++i) {
431  wkb[i] = parse_hex((char*) & (hexwkb[i * 2]));
432  }
433 
434  ret = rt_raster_from_wkb(wkb, wkbsize);
435  rtdealloc(wkb); /* as long as rt_raster_from_wkb copies memory */
436 
437  return ret;
438 }
439 
440 static uint32_t
442  uint32_t size = RT_WKB_HDR_SZ;
443  uint16_t i = 0;
444 
445  assert(NULL != raster);
446 
447  RASTER_DEBUGF(3, "rt_raster_wkb_size: computing size for %d bands",
448  raster->numBands);
449 
450  for (i = 0; i < raster->numBands; ++i) {
451  rt_band band = raster->bands[i];
452  rt_pixtype pixtype = band->pixtype;
453  int pixbytes = rt_pixtype_size(pixtype);
454 
455  RASTER_DEBUGF(3, "rt_raster_wkb_size: adding size of band %d", i);
456 
457  if (pixbytes < 1) {
458  rterror("rt_raster_wkb_size: Corrupted band: unknown pixtype");
459  return 0;
460  }
461 
462  /* Add space for band type */
463  size += 1;
464 
465  /* Add space for nodata value */
466  size += pixbytes;
467 
468  if (!outasin && band->offline) {
469  /* Add space for band number */
470  size += 1;
471 
472  /* Add space for null-terminated path */
473  size += strlen(band->data.offline.path) + 1;
474  }
475  else {
476  /* Add space for actual data */
477  size += pixbytes * raster->width * raster->height;
478  }
479  }
480 
481  return size;
482 }
483 
493 uint8_t *
494 rt_raster_to_wkb(rt_raster raster, int outasin, uint32_t *wkbsize) {
495 
496 #if POSTGIS_DEBUG_LEVEL > 0
497  const uint8_t *wkbend = NULL;
498 #endif
499 
500  uint8_t *wkb = NULL;
501  uint8_t *ptr = NULL;
502  uint16_t i = 0;
503  uint8_t littleEndian = isMachineLittleEndian();
504 
505  assert(NULL != raster);
506  assert(NULL != wkbsize);
507 
508  RASTER_DEBUG(2, "rt_raster_to_wkb: about to call rt_raster_wkb_size");
509 
510  *wkbsize = rt_raster_wkb_size(raster, outasin);
511  RASTER_DEBUGF(3, "rt_raster_to_wkb: found size: %d", *wkbsize);
512 
513  wkb = (uint8_t*) rtalloc(*wkbsize);
514  if (!wkb) {
515  rterror("rt_raster_to_wkb: Out of memory allocating WKB for raster");
516  return NULL;
517  }
518 
519  ptr = wkb;
520 
521 #if POSTGIS_DEBUG_LEVEL > 2
522  wkbend = ptr + (*wkbsize);
523 #endif
524  RASTER_DEBUGF(3, "Writing raster header to wkb on position %d (expected 0)",
525  d_binptr_to_pos(ptr, wkbend, *wkbsize));
526 
527  /* Write endianness */
528  *ptr = littleEndian;
529  ptr += 1;
530 
531  /* Write version(size - (end - ptr)) */
532  write_uint16(&ptr, littleEndian, 0);
533 
534  /* Copy header (from numBands up) */
535  memcpy(ptr, &(raster->numBands), sizeof (struct rt_raster_serialized_t) - 6);
536  ptr += sizeof (struct rt_raster_serialized_t) - 6;
537 
538  RASTER_DEBUGF(3, "Writing bands header to wkb position %d (expected 61)",
539  d_binptr_to_pos(ptr, wkbend, *wkbsize));
540 
541  /* Serialize bands now */
542  for (i = 0; i < raster->numBands; ++i) {
543  rt_band band = raster->bands[i];
544  rt_pixtype pixtype = band->pixtype;
545  int pixbytes = rt_pixtype_size(pixtype);
546 
547  RASTER_DEBUGF(3, "Writing WKB for band %d", i);
548  RASTER_DEBUGF(3, "Writing band pixel type to wkb position %d",
549  d_binptr_to_pos(ptr, wkbend, *wkbsize));
550 
551  if (pixbytes < 1) {
552  rterror("rt_raster_to_wkb: Corrupted band: unknown pixtype");
553  rtdealloc(wkb);
554  return NULL;
555  }
556 
557  /* Add band type */
558  *ptr = band->pixtype;
559  if (!outasin && band->offline) *ptr |= BANDTYPE_FLAG_OFFDB;
560  if (band->hasnodata) *ptr |= BANDTYPE_FLAG_HASNODATA;
561  if (band->isnodata) *ptr |= BANDTYPE_FLAG_ISNODATA;
562  ptr += 1;
563 
564 #if 0
565  /* no padding required for WKB */
566  /* Add padding (if needed) */
567  if (pixbytes > 1) {
568  memset(ptr, '\0', pixbytes - 1);
569  ptr += pixbytes - 1;
570  }
571  /* Consistency checking (ptr is pixbytes-aligned) */
572  assert(!(((uint64_t) ptr) % pixbytes));
573 #endif
574 
575  RASTER_DEBUGF(3, "Writing band nodata to wkb position %d",
576  d_binptr_to_pos(ptr, wkbend, *wkbsize));
577 
578  /* Add nodata value */
579  switch (pixtype) {
580  case PT_1BB:
581  case PT_2BUI:
582  case PT_4BUI:
583  case PT_8BUI: {
584  uint8_t v = band->nodataval;
585  *ptr = v;
586  ptr += 1;
587  break;
588  }
589  case PT_8BSI: {
590  int8_t v = band->nodataval;
591  *ptr = v;
592  ptr += 1;
593  break;
594  }
595  case PT_16BSI:
596  case PT_16BUI: {
597  uint16_t v = band->nodataval;
598  memcpy(ptr, &v, 2);
599  ptr += 2;
600  break;
601  }
602  case PT_32BSI:
603  case PT_32BUI: {
604  uint32_t v = band->nodataval;
605  memcpy(ptr, &v, 4);
606  ptr += 4;
607  break;
608  }
609  case PT_32BF: {
610  float v = band->nodataval;
611  memcpy(ptr, &v, 4);
612  ptr += 4;
613  break;
614  }
615  case PT_64BF: {
616  memcpy(ptr, &band->nodataval, 8);
617  ptr += 8;
618  break;
619  }
620  default:
621  rterror("rt_raster_to_wkb: Fatal error caused by unknown pixel type. Aborting.");
622  rtdealloc(wkb);
623  abort(); /* shoudn't happen */
624  return 0;
625  }
626 
627 #if 0
628  /* no padding for WKB */
629  /* Consistency checking (ptr is pixbytes-aligned) */
630  assert(!((uint64_t) ptr % pixbytes));
631 #endif
632 
633  if (!outasin && band->offline) {
634  /* Write band number */
635  *ptr = band->data.offline.bandNum;
636  ptr += 1;
637 
638  /* Write path */
639  strcpy((char*) ptr, band->data.offline.path);
640  ptr += strlen(band->data.offline.path) + 1;
641  }
642  else {
643  /* Write data */
644  uint32_t datasize = raster->width * raster->height * pixbytes;
645  RASTER_DEBUGF(4, "rt_raster_to_wkb: Copying %d bytes", datasize);
646 
647  memcpy(ptr, rt_band_get_data(band), datasize);
648 
649  ptr += datasize;
650  }
651 
652 #if 0
653  /* no padding for WKB */
654  /* Pad up to 8-bytes boundary */
655  while ((uint64_t) ptr % 8) {
656  *ptr = 0;
657  ++ptr;
658  }
659 
660  /* Consistency checking (ptr is pixbytes-aligned) */
661  assert(!((uint64_t) ptr % pixbytes));
662 #endif
663  }
664 
665  return wkb;
666 }
667 
668 char *
669 rt_raster_to_hexwkb(rt_raster raster, int outasin, uint32_t *hexwkbsize) {
670  uint8_t *wkb = NULL;
671  char* hexwkb = NULL;
672  uint32_t wkbsize = 0;
673 
674  assert(NULL != raster);
675  assert(NULL != hexwkbsize);
676 
677  RASTER_DEBUG(2, "rt_raster_to_hexwkb: calling rt_raster_to_wkb");
678 
679  wkb = rt_raster_to_wkb(raster, outasin, &wkbsize);
680 
681  RASTER_DEBUG(3, "rt_raster_to_hexwkb: rt_raster_to_wkb returned");
682 
683  *hexwkbsize = wkbsize * 2; /* hex is 2 times bytes */
684  hexwkb = (char*) rtalloc((*hexwkbsize) + 1);
685  if (!hexwkb) {
686  rterror("rt_raster_to_hexwkb: Out of memory hexifying raster WKB");
687  rtdealloc(wkb);
688  return NULL;
689  }
690 
691  char *optr = hexwkb;
692  uint8_t *iptr = wkb;
693  const char hexchar[]="0123456789ABCDEF";
694  while (wkbsize--) {
695  uint8_t v = *iptr++;
696  *optr++ = hexchar[v>>4];
697  *optr++ = hexchar[v & 0x0F];
698  }
699  *optr = '\0'; /* Null-terminate */
700 
701  rtdealloc(wkb); /* we don't need this anymore */
702 
703  RASTER_DEBUGF(3, "rt_raster_to_hexwkb: output wkb: %s", hexwkb);
704  return hexwkb;
705 }
int clamp_srid(int srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition: lwutil.c:350
#define RT_WKB_HDR_SZ
Definition: rt_wkb.c:273
double skewY
Definition: librtcore.h:2261
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:36
int32_t srid
Definition: librtcore.h:2263
#define BANDTYPE_FLAG_HASNODATA
Definition: rt_serialize.h:38
static uint32_t rt_raster_wkb_size(rt_raster raster, int outasin)
Definition: rt_wkb.c:441
uint16_t numBands
Definition: librtcore.h:2253
struct rt_raster_t * rt_raster
Types definitions.
Definition: librtcore.h:157
rt_raster raster
Definition: librtcore.h:2287
rt_pixtype pixtype
Definition: librtcore.h:2277
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
Definition: rt_context.c:199
tuple band
Definition: ovdump.py:57
void * rtalloc(size_t size)
Wrappers used for managing memory.
Definition: rt_context.c:171
tuple rast
Definition: rtpixdump.py:61
uint16_t height
Definition: librtcore.h:2280
double ipY
Definition: librtcore.h:2259
tuple raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
rt_pixtype
Definition: librtcore.h:197
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
uint16_t height
Definition: librtcore.h:2265
#define CHECK_BINPTR_POSITION(ptr, end, size, pos)
Definition: rt_serialize.h:65
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
uint32_t read_uint32(const uint8_t **from, uint8_t littleEndian)
Definition: rt_serialize.c:287
uint8_t * rt_raster_to_wkb(rt_raster raster, int outasin, uint32_t *wkbsize)
Return this raster in WKB form.
Definition: rt_wkb.c:494
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:2264
union rt_band_t::@6 data
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:406
int8_t ownsdata
Definition: librtcore.h:2285
double skewX
Definition: librtcore.h:2260
#define BANDTYPE_PIXTYPE_MASK
Definition: rt_serialize.h:36
double nodataval
Definition: librtcore.h:2284
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
Definition: rt_band.c:302
#define RASTER_DEBUGF(level, msg,...)
Definition: librtcore.h:311
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:82
uint16_t width
Definition: librtcore.h:2279
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
uint8_t parse_hex(char *str)
Convert a single hex digit into the corresponding char.
Definition: lwgeom_api.c:639
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:276
int32_t offline
Definition: librtcore.h:2278
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:2282
#define RASTER_DEBUG(level, msg)
Definition: librtcore.h:307
Struct definitions.
Definition: librtcore.h:2213
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:2266
void * mem
Definition: librtcore.h:2290
int32_t hasnodata
Definition: librtcore.h:2281
double ipX
Definition: librtcore.h:2258
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:669
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
double scaleX
Definition: librtcore.h:2256
#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
double scaleY
Definition: librtcore.h:2257