PostGIS 3.6.2dev-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#include <inttypes.h>
35
36/* Read band from WKB as at start of band */
37static 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__);
62 rt_band_destroy(band);
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);
69 rt_band_destroy(band);
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");
90 rt_band_destroy(band);
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);
142 rt_band_destroy(band);
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 );
156 rt_band_destroy(band);
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");
169 rt_band_destroy(band);
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");
179 rt_band_destroy(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__);
204 rt_band_destroy(band);
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");
211 rt_band_destroy(band);
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);
234 rt_band_destroy(band);
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));
261 rt_band_destroy(band);
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
278rt_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");
371 rt_raster_destroy(rast);
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]);
388 rt_raster_destroy(rast);
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
409rt_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
443static uint32_t
444rt_raster_wkb_size(rt_raster raster, int outasin) {
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
496uint8_t *
497rt_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
681char *
682rt_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_band_get_data(rt_band band)
Get pointer to raster band data.
Definition rt_band.c:551
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
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition rt_pixel.c:110
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition rt_band.c:491
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: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: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
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
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
#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