cog-tiler-wasm 0.2.2 → 0.2.4
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.js +69 -4
- package/cog_tiler_wasm_bg.wasm +0 -0
- package/package.json +1 -1
package/cog-tiler.js
CHANGED
|
@@ -147,6 +147,61 @@ function fitSize(extW, extH, maxSize, width, height) {
|
|
|
147
147
|
: [Math.max(1, Math.round(max * ar)), max];
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Read a TIFF tag from a geotiff.js image across major versions. geotiff v2
|
|
152
|
+
* exposes tags as direct `fileDirectory` properties; v3 defers them behind
|
|
153
|
+
* `fileDirectory.loadValue()` (large arrays such as ColorMap are not actualized
|
|
154
|
+
* eagerly), so a direct property read returns undefined there. Returns the tag
|
|
155
|
+
* value, or undefined when the tag is absent.
|
|
156
|
+
*/
|
|
157
|
+
async function readTiffTag(img, name) {
|
|
158
|
+
const fd = img.fileDirectory;
|
|
159
|
+
if (fd && fd[name] !== undefined) return fd[name]; // geotiff v2
|
|
160
|
+
if (typeof fd?.loadValue === "function") {
|
|
161
|
+
// geotiff v3: skip the load when the tag is absent so loadValue doesn't throw.
|
|
162
|
+
if (typeof fd.hasTag === "function" && !fd.hasTag(name)) return undefined;
|
|
163
|
+
return fd.loadValue(name);
|
|
164
|
+
}
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
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
|
+
|
|
150
205
|
/** Build a 256-entry RGBA palette from a TIFF ColorMap (16-bit R,G,B blocks). */
|
|
151
206
|
function buildPalette(colorMap) {
|
|
152
207
|
if (!colorMap) return null;
|
|
@@ -248,7 +303,7 @@ export async function openCog(source) {
|
|
|
248
303
|
if (stream.epsg !== 3857 || multiBand) {
|
|
249
304
|
tiff = await openTiff();
|
|
250
305
|
img = await tiff.getImage();
|
|
251
|
-
planar = multiBand && img
|
|
306
|
+
planar = multiBand && (await readTiffTag(img, "PlanarConfiguration")) === 2;
|
|
252
307
|
}
|
|
253
308
|
const base = { url: label, range, stream, levels, gt, nodata: stream.nodata, tiff, planar };
|
|
254
309
|
|
|
@@ -264,11 +319,11 @@ export async function openCog(source) {
|
|
|
264
319
|
}
|
|
265
320
|
|
|
266
321
|
// Warp path: read the real source CRS + optional palette from the header.
|
|
267
|
-
const srcDef =
|
|
322
|
+
const srcDef = sourceCrsDef(img.getGeoKeys());
|
|
268
323
|
if (!srcDef) throw new Error("could not derive source CRS from GeoTIFF geokeys");
|
|
269
324
|
const toSource = proj4("EPSG:3857", srcDef); // forward: mercator -> source
|
|
270
325
|
const toLonLat = proj4(srcDef, "EPSG:4326"); // forward: source -> lon/lat
|
|
271
|
-
const palette = buildPalette(img
|
|
326
|
+
const palette = buildPalette(await readTiffTag(img, "ColorMap"));
|
|
272
327
|
|
|
273
328
|
// fitBounds bounds: transform the source corners to lon/lat.
|
|
274
329
|
const fw = levels[0].width, fh = levels[0].height;
|
|
@@ -286,10 +341,20 @@ export async function openCog(source) {
|
|
|
286
341
|
toSource,
|
|
287
342
|
palette,
|
|
288
343
|
boundsLonLat: [Math.min(...lons), Math.min(...lats), Math.max(...lons), Math.max(...lats)],
|
|
289
|
-
crsLabel: "warped from " + (srcDef
|
|
344
|
+
crsLabel: "warped from " + crsLabelForDef(srcDef),
|
|
290
345
|
});
|
|
291
346
|
}
|
|
292
347
|
|
|
348
|
+
/** A short label for a proj4 def: the `+proj=...` token, or the WKT's CRS name,
|
|
349
|
+
* falling back to "custom CRS". */
|
|
350
|
+
function crsLabelForDef(srcDef) {
|
|
351
|
+
const projTag = srcDef.match(/\+proj=\w+/);
|
|
352
|
+
if (projTag) return projTag[0];
|
|
353
|
+
const wktName = srcDef.match(/\b(?:PROJCS|PROJCRS)\s*\[\s*"([^"]+)"/i);
|
|
354
|
+
if (wktName) return wktName[1];
|
|
355
|
+
return "custom CRS";
|
|
356
|
+
}
|
|
357
|
+
|
|
293
358
|
/** A single opened COG. Renders XYZ tiles via {@link CogSource#renderTileRGBA}. */
|
|
294
359
|
export class CogSource {
|
|
295
360
|
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.4",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|