whitebox-wasm 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/package.json +1 -1
- package/whitebox-cli.wasm +0 -0
- package/whitebox_wasm.d.ts +31 -0
- package/whitebox_wasm.js +75 -0
- package/whitebox_wasm_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -126,12 +126,42 @@ for (const t of tiles) {
|
|
|
126
126
|
|
|
127
127
|
- `new CogStream(headerBytes)` - parse the IFD chain + tile index (throws if the
|
|
128
128
|
prefix is too short; fetch more and retry).
|
|
129
|
+
- `first_ifd_offset(headerBytes)` - where the directory actually is (see below).
|
|
130
|
+
- `CogStream.from_windows(prefix, tailOffset, tail)` - parse from a front prefix
|
|
131
|
+
plus a window elsewhere in the file.
|
|
129
132
|
- `num_levels`, `epsg`, `nodata`, `geo_transform()`, `levels_json()`
|
|
130
133
|
- `bounding_box()`, `center()`, `center_lonlat()`, `bounds_lonlat()` (same semantics as `GeoTiffReader`)
|
|
131
134
|
- `tiles_for_window(level, x, y, w, h)` -> JSON `[{col,row,offset,length}]`
|
|
132
135
|
- `tile_range(level, col, row)` -> `[offset, length]`
|
|
133
136
|
- `decode_tile_f64(level, tileBytes)` -> `Float64Array` (one decoded tile)
|
|
134
137
|
|
|
138
|
+
#### Plain GeoTIFFs, whose directory sits at the end
|
|
139
|
+
|
|
140
|
+
A COG keeps every IFD at the front of the file, so a 64 KB prefix reaches it. A
|
|
141
|
+
**plain** GeoTIFF - what GDAL and libtiff write unless you ask for a COG - puts
|
|
142
|
+
the directory *after* the pixel data, so growing a front-of-file prefix can only
|
|
143
|
+
reach it by downloading the entire file. Read the offset first and fetch that
|
|
144
|
+
region instead:
|
|
145
|
+
|
|
146
|
+
```js
|
|
147
|
+
import init, { CogStream, first_ifd_offset } from "whitebox-wasm";
|
|
148
|
+
|
|
149
|
+
// An open-ended `Range: bytes=N-` asks for everything from N to the end, so the
|
|
150
|
+
// file's length never has to be looked up.
|
|
151
|
+
const range = (a, b) => fetch(url, { headers: { Range: `bytes=${a}-${b ?? ""}` } })
|
|
152
|
+
.then(r => r.arrayBuffer()).then(b => new Uint8Array(b));
|
|
153
|
+
|
|
154
|
+
const prefix = await range(0, 16383);
|
|
155
|
+
const ifd = first_ifd_offset(prefix); // 74026916 on a 74 MB file
|
|
156
|
+
const stream = ifd < prefix.length
|
|
157
|
+
? new CogStream(prefix) // COG: it is already in hand
|
|
158
|
+
: CogStream.from_windows(prefix, ifd, await range(ifd));
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
That reads under 1 MB of a 74 MB raster. If a tag array happens to sit *before*
|
|
162
|
+
the directory, `from_windows` throws `need more header bytes at offset N`; start
|
|
163
|
+
the tail earlier and retry.
|
|
164
|
+
|
|
135
165
|
Use a higher `level` (overview) for zoomed-out views. See
|
|
136
166
|
[`examples/cog-stream.mjs`](../../examples/cog-stream.mjs) for a full window read
|
|
137
167
|
that fetches only the tiles it needs (about 13% of a 5.7 MiB file for a 256x256
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "whitebox-wasm",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"description": "Pure-Rust geospatial toolkit (raster, vector, LiDAR, projections) compiled to WebAssembly",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.6.0",
|
|
6
6
|
"license": "MIT OR Apache-2.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
package/whitebox-cli.wasm
CHANGED
|
Binary file
|
package/whitebox_wasm.d.ts
CHANGED
|
@@ -75,6 +75,11 @@ export class CogBuilder {
|
|
|
75
75
|
* 2. Pick a level (0 = full res, higher = overviews) and a pixel window.
|
|
76
76
|
* 3. `tiles_for_window(level, x, y, w, h)` returns the tiles and their byte
|
|
77
77
|
* ranges; range-fetch each, then `decode_tile_f64(level, bytes)`.
|
|
78
|
+
*
|
|
79
|
+
* A *plain* (non-COG) GeoTIFF, as GDAL and libtiff write one by default, keeps
|
|
80
|
+
* its directory at the **end** of the file, so no front-of-file prefix short of
|
|
81
|
+
* the whole file can reach it. Use `first_ifd_offset` to locate the directory
|
|
82
|
+
* and `CogStream.from_windows` to parse it from a small tail window.
|
|
78
83
|
*/
|
|
79
84
|
export class CogStream {
|
|
80
85
|
free(): void;
|
|
@@ -101,6 +106,19 @@ export class CogStream {
|
|
|
101
106
|
* come back full-size; clip to the image/window on the JS side.
|
|
102
107
|
*/
|
|
103
108
|
decode_tile_f64(level: number, tile_bytes: Uint8Array): Float64Array;
|
|
109
|
+
/**
|
|
110
|
+
* Parse the tile layout from two disjoint windows of the file: a
|
|
111
|
+
* front-of-file `prefix` and a `tail` starting at absolute byte offset
|
|
112
|
+
* `tail_offset`.
|
|
113
|
+
*
|
|
114
|
+
* This is the path for a plain GeoTIFF whose directory sits at the end of
|
|
115
|
+
* the file. Fetch the first few kilobytes plus the region from
|
|
116
|
+
* `first_ifd_offset` to the end and pass both; the bytes in between are
|
|
117
|
+
* pixel data that header parsing never reads. If a tag array happens to sit
|
|
118
|
+
* *before* the directory, this throws "need more header bytes at offset N" —
|
|
119
|
+
* widen the tail to cover N and retry.
|
|
120
|
+
*/
|
|
121
|
+
static from_windows(prefix: Uint8Array, tail_offset: number, tail: Uint8Array): CogStream;
|
|
104
122
|
/**
|
|
105
123
|
* Level-0 geo-transform `[x_origin, pixel_width, row_rot, y_origin, col_rot,
|
|
106
124
|
* pixel_height]`, or empty if not georeferenced.
|
|
@@ -254,6 +272,17 @@ export function __start(): void;
|
|
|
254
272
|
*/
|
|
255
273
|
export function convex_hull(points_xy: Float64Array): Float64Array;
|
|
256
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Offset of a GeoTIFF's first IFD, read from the file's first 8 (classic TIFF)
|
|
277
|
+
* or 16 (BigTIFF) bytes. An offset past the prefix you already hold means the
|
|
278
|
+
* directory lives further into the file: fetch that region and hand it to
|
|
279
|
+
* `CogStream.from_windows`.
|
|
280
|
+
*
|
|
281
|
+
* Throws on an offset a JS number cannot hold exactly, which only a corrupt
|
|
282
|
+
* header produces: passing it back would address the wrong bytes.
|
|
283
|
+
*/
|
|
284
|
+
export function first_ifd_offset(header_bytes: Uint8Array): number;
|
|
285
|
+
|
|
257
286
|
/**
|
|
258
287
|
* Decode only a GeoTIFF's header and return its metadata as JSON. O(header)
|
|
259
288
|
* memory, so it works on multi-gigabyte rasters that whole-image reads cannot
|
|
@@ -376,6 +405,7 @@ export interface InitOutput {
|
|
|
376
405
|
readonly cogstream_center_lonlat: (a: number, b: number) => void;
|
|
377
406
|
readonly cogstream_decode_tile_f64: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
378
407
|
readonly cogstream_epsg: (a: number) => number;
|
|
408
|
+
readonly cogstream_from_windows: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
379
409
|
readonly cogstream_geo_transform: (a: number, b: number) => void;
|
|
380
410
|
readonly cogstream_levels_json: (a: number, b: number) => void;
|
|
381
411
|
readonly cogstream_new: (a: number, b: number, c: number) => void;
|
|
@@ -384,6 +414,7 @@ export interface InitOutput {
|
|
|
384
414
|
readonly cogstream_tile_range: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
385
415
|
readonly cogstream_tiles_for_window: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
386
416
|
readonly convex_hull: (a: number, b: number, c: number) => void;
|
|
417
|
+
readonly first_ifd_offset: (a: number, b: number, c: number) => void;
|
|
387
418
|
readonly geotiff_info: (a: number, b: number, c: number) => void;
|
|
388
419
|
readonly geotiff_read_band_f64: (a: number, b: number, c: number, d: number) => void;
|
|
389
420
|
readonly geotiff_stats: (a: number, b: number, c: number) => void;
|
package/whitebox_wasm.js
CHANGED
|
@@ -206,8 +206,19 @@ if (Symbol.dispose) CogBuilder.prototype[Symbol.dispose] = CogBuilder.prototype.
|
|
|
206
206
|
* 2. Pick a level (0 = full res, higher = overviews) and a pixel window.
|
|
207
207
|
* 3. `tiles_for_window(level, x, y, w, h)` returns the tiles and their byte
|
|
208
208
|
* ranges; range-fetch each, then `decode_tile_f64(level, bytes)`.
|
|
209
|
+
*
|
|
210
|
+
* A *plain* (non-COG) GeoTIFF, as GDAL and libtiff write one by default, keeps
|
|
211
|
+
* its directory at the **end** of the file, so no front-of-file prefix short of
|
|
212
|
+
* the whole file can reach it. Use `first_ifd_offset` to locate the directory
|
|
213
|
+
* and `CogStream.from_windows` to parse it from a small tail window.
|
|
209
214
|
*/
|
|
210
215
|
export class CogStream {
|
|
216
|
+
static __wrap(ptr) {
|
|
217
|
+
const obj = Object.create(CogStream.prototype);
|
|
218
|
+
obj.__wbg_ptr = ptr;
|
|
219
|
+
CogStreamFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
220
|
+
return obj;
|
|
221
|
+
}
|
|
211
222
|
__destroy_into_raw() {
|
|
212
223
|
const ptr = this.__wbg_ptr;
|
|
213
224
|
this.__wbg_ptr = 0;
|
|
@@ -322,6 +333,41 @@ export class CogStream {
|
|
|
322
333
|
const ret = wasm.cogstream_epsg(this.__wbg_ptr);
|
|
323
334
|
return ret === Number.MAX_SAFE_INTEGER ? undefined : ret;
|
|
324
335
|
}
|
|
336
|
+
/**
|
|
337
|
+
* Parse the tile layout from two disjoint windows of the file: a
|
|
338
|
+
* front-of-file `prefix` and a `tail` starting at absolute byte offset
|
|
339
|
+
* `tail_offset`.
|
|
340
|
+
*
|
|
341
|
+
* This is the path for a plain GeoTIFF whose directory sits at the end of
|
|
342
|
+
* the file. Fetch the first few kilobytes plus the region from
|
|
343
|
+
* `first_ifd_offset` to the end and pass both; the bytes in between are
|
|
344
|
+
* pixel data that header parsing never reads. If a tag array happens to sit
|
|
345
|
+
* *before* the directory, this throws "need more header bytes at offset N" —
|
|
346
|
+
* widen the tail to cover N and retry.
|
|
347
|
+
* @param {Uint8Array} prefix
|
|
348
|
+
* @param {number} tail_offset
|
|
349
|
+
* @param {Uint8Array} tail
|
|
350
|
+
* @returns {CogStream}
|
|
351
|
+
*/
|
|
352
|
+
static from_windows(prefix, tail_offset, tail) {
|
|
353
|
+
try {
|
|
354
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
355
|
+
const ptr0 = passArray8ToWasm0(prefix, wasm.__wbindgen_export2);
|
|
356
|
+
const len0 = WASM_VECTOR_LEN;
|
|
357
|
+
const ptr1 = passArray8ToWasm0(tail, wasm.__wbindgen_export2);
|
|
358
|
+
const len1 = WASM_VECTOR_LEN;
|
|
359
|
+
wasm.cogstream_from_windows(retptr, ptr0, len0, tail_offset, ptr1, len1);
|
|
360
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
361
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
362
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
363
|
+
if (r2) {
|
|
364
|
+
throw takeObject(r1);
|
|
365
|
+
}
|
|
366
|
+
return CogStream.__wrap(r0);
|
|
367
|
+
} finally {
|
|
368
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
325
371
|
/**
|
|
326
372
|
* Level-0 geo-transform `[x_origin, pixel_width, row_rot, y_origin, col_rot,
|
|
327
373
|
* pixel_height]`, or empty if not georeferenced.
|
|
@@ -1016,6 +1062,35 @@ export function convex_hull(points_xy) {
|
|
|
1016
1062
|
}
|
|
1017
1063
|
}
|
|
1018
1064
|
|
|
1065
|
+
/**
|
|
1066
|
+
* Offset of a GeoTIFF's first IFD, read from the file's first 8 (classic TIFF)
|
|
1067
|
+
* or 16 (BigTIFF) bytes. An offset past the prefix you already hold means the
|
|
1068
|
+
* directory lives further into the file: fetch that region and hand it to
|
|
1069
|
+
* `CogStream.from_windows`.
|
|
1070
|
+
*
|
|
1071
|
+
* Throws on an offset a JS number cannot hold exactly, which only a corrupt
|
|
1072
|
+
* header produces: passing it back would address the wrong bytes.
|
|
1073
|
+
* @param {Uint8Array} header_bytes
|
|
1074
|
+
* @returns {number}
|
|
1075
|
+
*/
|
|
1076
|
+
export function first_ifd_offset(header_bytes) {
|
|
1077
|
+
try {
|
|
1078
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
1079
|
+
const ptr0 = passArray8ToWasm0(header_bytes, wasm.__wbindgen_export2);
|
|
1080
|
+
const len0 = WASM_VECTOR_LEN;
|
|
1081
|
+
wasm.first_ifd_offset(retptr, ptr0, len0);
|
|
1082
|
+
var r0 = getDataViewMemory0().getFloat64(retptr + 8 * 0, true);
|
|
1083
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
1084
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
1085
|
+
if (r3) {
|
|
1086
|
+
throw takeObject(r2);
|
|
1087
|
+
}
|
|
1088
|
+
return r0;
|
|
1089
|
+
} finally {
|
|
1090
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1019
1094
|
/**
|
|
1020
1095
|
* Decode only a GeoTIFF's header and return its metadata as JSON. O(header)
|
|
1021
1096
|
* memory, so it works on multi-gigabyte rasters that whole-image reads cannot
|
package/whitebox_wasm_bg.wasm
CHANGED
|
Binary file
|