PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
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/* Read band from WKB as at start of band */
35static 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
276rt_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
406rt_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
440static uint32_t
441rt_raster_wkb_size(rt_raster raster, int outasin) {
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
493uint8_t *
494rt_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 = (uint8_t)v;
592 ptr += 1;
593 break;
594 }
595 case PT_16BSI: {
596 int16_t v = band->nodataval;
597 memcpy(ptr, &v, 2);
598 ptr += 2;
599 break;
600 }
601 case PT_16BUI: {
602 uint16_t v = band->nodataval;
603 memcpy(ptr, &v, 2);
604 ptr += 2;
605 break;
606 }
607 case PT_32BSI: {
608 int32_t v = band->nodataval;
609 memcpy(ptr, &v, 4);
610 ptr += 4;
611 break;
612 }
613 case PT_32BUI: {
614 uint32_t v = band->nodataval;
615 memcpy(ptr, &v, 4);
616 ptr += 4;
617 break;
618 }
619 case PT_32BF: {
620 float v = band->nodataval;
621 memcpy(ptr, &v, 4);
622 ptr += 4;
623 break;
624 }
625 case PT_64BF: {
626 memcpy(ptr, &band->nodataval, 8);
627 ptr += 8;
628 break;
629 }
630 default:
631 rterror("rt_raster_to_wkb: Fatal error caused by unknown pixel type. Aborting.");
632 rtdealloc(wkb);
633 abort(); /* shoudn't happen */
634 return 0;
635 }
636
637#if 0
638 /* no padding for WKB */
639 /* Consistency checking (ptr is pixbytes-aligned) */
640 assert(!((uint64_t) ptr % pixbytes));
641#endif
642
643 if (!outasin && band->offline) {
644 /* Write band number */
645 *ptr = band->data.offline.bandNum;
646 ptr += 1;
647
648 /* Write path */
649 strcpy((char*) ptr, band->data.offline.path);
650 ptr += strlen(band->data.offline.path) + 1;
651 }
652 else {
653 /* Write data */
654 uint32_t datasize = raster->width * raster->height * pixbytes;
655 RASTER_DEBUGF(4, "rt_raster_to_wkb: Copying %d bytes", datasize);
656
657 memcpy(ptr, rt_band_get_data(band), datasize);
658
659 ptr += datasize;
660 }
661
662#if 0
663 /* no padding for WKB */
664 /* Pad up to 8-bytes boundary */
665 while ((uint64_t) ptr % 8) {
666 *ptr = 0;
667 ++ptr;
668 }
669
670 /* Consistency checking (ptr is pixbytes-aligned) */
671 assert(!((uint64_t) ptr % pixbytes));
672#endif
673 }
674
675 return wkb;
676}
677
678char *
679rt_raster_to_hexwkb(rt_raster raster, int outasin, uint32_t *hexwkbsize) {
680 uint8_t *wkb = NULL;
681 char* hexwkb = NULL;
682 uint32_t wkbsize = 0;
683
684 assert(NULL != raster);
685 assert(NULL != hexwkbsize);
686
687 RASTER_DEBUG(2, "rt_raster_to_hexwkb: calling rt_raster_to_wkb");
688
689 wkb = rt_raster_to_wkb(raster, outasin, &wkbsize);
690
691 RASTER_DEBUG(3, "rt_raster_to_hexwkb: rt_raster_to_wkb returned");
692
693 *hexwkbsize = wkbsize * 2; /* hex is 2 times bytes */
694 hexwkb = (char*) rtalloc((*hexwkbsize) + 1);
695 if (!hexwkb) {
696 rterror("rt_raster_to_hexwkb: Out of memory hexifying raster WKB");
697 rtdealloc(wkb);
698 return NULL;
699 }
700
701 char *optr = hexwkb;
702 uint8_t *iptr = wkb;
703 const char hexchar[]="0123456789ABCDEF";
704 while (wkbsize--) {
705 uint8_t v = *iptr++;
706 *optr++ = hexchar[v>>4];
707 *optr++ = hexchar[v & 0x0F];
708 }
709 *optr = '\0'; /* Null-terminate */
710
711 rtdealloc(wkb); /* we don't need this anymore */
712
713 RASTER_DEBUGF(3, "rt_raster_to_hexwkb: output wkb: %s", hexwkb);
714 return hexwkb;
715}
uint8_t parse_hex(char *str)
Convert a single hex digit into the corresponding char.
Definition lwgeom_api.c:489
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:333
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
#define RASTER_DEBUG(level, msg)
Definition librtcore.h:295
#define RASTER_DEBUGF(level, msg,...)
Definition librtcore.h:299
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
Definition rt_band.c:400
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition rt_raster.c:82
rt_pixtype
Definition librtcore.h:185
@ PT_32BUI
Definition librtcore.h:194
@ PT_2BUI
Definition librtcore.h:187
@ PT_32BSI
Definition librtcore.h:193
@ PT_END
Definition librtcore.h:197
@ PT_4BUI
Definition librtcore.h:188
@ PT_32BF
Definition librtcore.h:195
@ PT_1BB
Definition librtcore.h:186
@ PT_16BUI
Definition librtcore.h:192
@ PT_8BSI
Definition librtcore.h:189
@ PT_16BSI
Definition librtcore.h:191
@ PT_64BF
Definition librtcore.h:196
@ PT_8BUI
Definition librtcore.h:190
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition rt_pixel.c:110
void rtwarn(const char *fmt,...)
Definition rt_context.c:224
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition rt_band.c:340
void rtdealloc(void *mem)
Definition rt_context.c:186
struct rt_raster_t * rt_raster
Types definitions.
Definition librtcore.h:145
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.
uint8_t isMachineLittleEndian(void)
void flip_endian_32(uint8_t *d)
void flip_endian_16(uint8_t *d)
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)
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)
#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
#define CHECK_BINPTR_POSITION(ptr, end, size, pos)
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
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
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:679
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
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
#define RT_WKB_HDR_SZ
Definition rt_wkb.c:273
static uint32_t rt_raster_wkb_size(rt_raster raster, int outasin)
Definition rt_wkb.c:441
Struct definitions.
Definition librtcore.h:2251