cog-tiler-wasm 0.2.3 → 0.2.5
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/cog-tiler.d.ts +2 -2
- package/cog-tiler.js +68 -9
- package/cog_tiler_wasm_bg.wasm +0 -0
- package/package.json +1 -1
package/cog-tiler.d.ts
CHANGED
|
@@ -124,8 +124,8 @@ export declare function init(): Promise<unknown>;
|
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
126
|
* Open a COG and return a {@link CogSource} ready to render XYZ tiles. Pass a URL
|
|
127
|
-
* string (read via HTTP range)
|
|
128
|
-
*
|
|
127
|
+
* string (read via HTTP range), a Blob / File (read via ranged slices, so
|
|
128
|
+
* multi-GB local rasters never load whole), or in-memory bytes.
|
|
129
129
|
*/
|
|
130
130
|
export declare function openCog(source: string | ArrayBuffer | Uint8Array | Blob): Promise<CogSource>;
|
|
131
131
|
|
package/cog-tiler.js
CHANGED
|
@@ -165,6 +165,43 @@ async function readTiffTag(img, name) {
|
|
|
165
165
|
return undefined;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
+
// Root keyword of a projected WKT (OGC `PROJCS`/`PROJCRS`, including the ESRI PE
|
|
169
|
+
// string flavour ArcGIS writes). Matching the keyword lets us slice off any
|
|
170
|
+
// `ESRI PE String = ` prefix.
|
|
171
|
+
const PROJECTED_WKT_ROOT = /\b(?:PROJCS|PROJCRS)\s*\[/i;
|
|
172
|
+
|
|
173
|
+
/** Pull a projected WKT/ESRI-PE-string definition out of a GeoTIFF citation geo
|
|
174
|
+
* key, if one is present. Returns the WKT from the `PROJCS`/`PROJCRS` keyword
|
|
175
|
+
* onward, or `null`. */
|
|
176
|
+
function projectedWktFromGeoKeys(geoKeys) {
|
|
177
|
+
for (const citation of [geoKeys.PCSCitationGeoKey, geoKeys.GTCitationGeoKey]) {
|
|
178
|
+
if (typeof citation !== "string") continue;
|
|
179
|
+
const match = PROJECTED_WKT_ROOT.exec(citation);
|
|
180
|
+
if (match) return citation.slice(match.index);
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Resolve the source CRS as a proj4 definition (a `+proj=...` string or a WKT).
|
|
187
|
+
*
|
|
188
|
+
* `geotiff-geokeys-to-proj4` builds the def from the numeric geo keys, but for a
|
|
189
|
+
* projection it cannot express (no `ProjCoordTransGeoKey`, e.g. ESRI world
|
|
190
|
+
* projections such as Mollweide/54009 written only as an `ESRI PE String`) it
|
|
191
|
+
* silently falls back to the bare geographic CRS (`+proj=longlat`, `isGCS`).
|
|
192
|
+
* That would place a projected raster at lon/lat where its metre coordinates
|
|
193
|
+
* are, so it never draws. When the keys carry a projected WKT, prefer it; proj4
|
|
194
|
+
* parses the ESRI/OGC WKT directly.
|
|
195
|
+
*/
|
|
196
|
+
function sourceCrsDef(geoKeys) {
|
|
197
|
+
const result = geokeysToProj4.toProj4(geoKeys);
|
|
198
|
+
if (result.isGCS) {
|
|
199
|
+
const wkt = projectedWktFromGeoKeys(geoKeys);
|
|
200
|
+
if (wkt) return wkt;
|
|
201
|
+
}
|
|
202
|
+
return result.proj4;
|
|
203
|
+
}
|
|
204
|
+
|
|
168
205
|
/** Build a 256-entry RGBA palette from a TIFF ColorMap (16-bit R,G,B blocks). */
|
|
169
206
|
function buildPalette(colorMap) {
|
|
170
207
|
if (!colorMap) return null;
|
|
@@ -203,18 +240,29 @@ function sampleWindowBilinear(buf, w, h, fc, fr) {
|
|
|
203
240
|
return top + (bot - top) * ty;
|
|
204
241
|
}
|
|
205
242
|
|
|
206
|
-
// Build a byte reader from a URL string or an in-memory source
|
|
207
|
-
//
|
|
243
|
+
// Build a byte reader from a URL string, a Blob/File, or an in-memory source
|
|
244
|
+
// (ArrayBuffer, Uint8Array). `range(a,b)` yields bytes [a..b]; `openTiff()`
|
|
208
245
|
// returns a geotiff.js GeoTIFF for reading the CRS / color table from the header.
|
|
209
246
|
async function makeReader(source) {
|
|
210
247
|
if (typeof source === "string") {
|
|
211
248
|
return { label: source, range: rangeFetcher(source), openTiff: () => GeoTIFF.fromUrl(source) };
|
|
212
249
|
}
|
|
250
|
+
// Blob / File: read on demand via ranged slices, mirroring the URL path.
|
|
251
|
+
// Slurping the whole file (blob.arrayBuffer()) throws NotReadableError in
|
|
252
|
+
// Chromium for multi-GB rasters (e.g. the 7 GB GEBCO GeoTIFF) — and only the
|
|
253
|
+
// header prefix and the requested tiles are ever needed.
|
|
254
|
+
if (typeof Blob !== "undefined" && source instanceof Blob) {
|
|
255
|
+
return {
|
|
256
|
+
label: source.name || "(local file)",
|
|
257
|
+
range: async (a, b) => new Uint8Array(await source.slice(a, b + 1).arrayBuffer()),
|
|
258
|
+
openTiff: () => GeoTIFF.fromBlob(source),
|
|
259
|
+
};
|
|
260
|
+
}
|
|
213
261
|
let bytes;
|
|
214
262
|
if (source instanceof Uint8Array) bytes = source;
|
|
215
263
|
else if (source instanceof ArrayBuffer) bytes = new Uint8Array(source);
|
|
216
264
|
else if (source && typeof source.arrayBuffer === "function") {
|
|
217
|
-
bytes = new Uint8Array(await source.arrayBuffer()); // Blob
|
|
265
|
+
bytes = new Uint8Array(await source.arrayBuffer()); // exotic Blob-likes
|
|
218
266
|
} else {
|
|
219
267
|
throw new Error("openCog: expected a URL string, ArrayBuffer, Uint8Array, or Blob");
|
|
220
268
|
}
|
|
@@ -233,10 +281,11 @@ async function makeReader(source) {
|
|
|
233
281
|
|
|
234
282
|
/**
|
|
235
283
|
* Open a COG and return a {@link CogSource} ready to render XYZ tiles. `source`
|
|
236
|
-
* is a URL string (read via HTTP range)
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
* whitebox-wasm 0.4.0
|
|
284
|
+
* is a URL string (read via HTTP range), a Blob / File (read via ranged slices,
|
|
285
|
+
* so multi-GB local rasters never load whole), or in-memory bytes. Detects
|
|
286
|
+
* EPSG:3857 (fast path) vs. any other CRS (warp path), reading the source
|
|
287
|
+
* projection + color table from the GeoTIFF header (which whitebox-wasm 0.4.0
|
|
288
|
+
* does not expose).
|
|
240
289
|
*/
|
|
241
290
|
export async function openCog(source) {
|
|
242
291
|
await init();
|
|
@@ -282,7 +331,7 @@ export async function openCog(source) {
|
|
|
282
331
|
}
|
|
283
332
|
|
|
284
333
|
// Warp path: read the real source CRS + optional palette from the header.
|
|
285
|
-
const srcDef =
|
|
334
|
+
const srcDef = sourceCrsDef(img.getGeoKeys());
|
|
286
335
|
if (!srcDef) throw new Error("could not derive source CRS from GeoTIFF geokeys");
|
|
287
336
|
const toSource = proj4("EPSG:3857", srcDef); // forward: mercator -> source
|
|
288
337
|
const toLonLat = proj4(srcDef, "EPSG:4326"); // forward: source -> lon/lat
|
|
@@ -304,10 +353,20 @@ export async function openCog(source) {
|
|
|
304
353
|
toSource,
|
|
305
354
|
palette,
|
|
306
355
|
boundsLonLat: [Math.min(...lons), Math.min(...lats), Math.max(...lons), Math.max(...lats)],
|
|
307
|
-
crsLabel: "warped from " + (srcDef
|
|
356
|
+
crsLabel: "warped from " + crsLabelForDef(srcDef),
|
|
308
357
|
});
|
|
309
358
|
}
|
|
310
359
|
|
|
360
|
+
/** A short label for a proj4 def: the `+proj=...` token, or the WKT's CRS name,
|
|
361
|
+
* falling back to "custom CRS". */
|
|
362
|
+
function crsLabelForDef(srcDef) {
|
|
363
|
+
const projTag = srcDef.match(/\+proj=\w+/);
|
|
364
|
+
if (projTag) return projTag[0];
|
|
365
|
+
const wktName = srcDef.match(/\b(?:PROJCS|PROJCRS)\s*\[\s*"([^"]+)"/i);
|
|
366
|
+
if (wktName) return wktName[1];
|
|
367
|
+
return "custom CRS";
|
|
368
|
+
}
|
|
369
|
+
|
|
311
370
|
/** A single opened COG. Renders XYZ tiles via {@link CogSource#renderTileRGBA}. */
|
|
312
371
|
export class CogSource {
|
|
313
372
|
constructor(fields) {
|
package/cog_tiler_wasm_bg.wasm
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"Qiusheng Wu <giswqs@gmail.com>"
|
|
6
6
|
],
|
|
7
7
|
"description": "Serverless Cloud Optimized GeoTIFF (COG) dynamic tiling in WebAssembly. TiTiler-style XYZ tiles, no backend.",
|
|
8
|
-
"version": "0.2.
|
|
8
|
+
"version": "0.2.5",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|