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