cog-tiler-wasm 0.2.6 → 0.3.1
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 +3 -18
- package/cog_tiler_wasm_bg.wasm +0 -0
- package/package.json +2 -1
- package/sampling.js +33 -0
package/cog-tiler.js
CHANGED
|
@@ -25,6 +25,7 @@ import initTiler, { colorize, colormap_names } from "./cog_tiler_wasm.js";
|
|
|
25
25
|
import proj4 from "proj4";
|
|
26
26
|
import * as GeoTIFF from "geotiff";
|
|
27
27
|
import geokeysToProj4 from "geotiff-geokeys-to-proj4";
|
|
28
|
+
import { sampleWindowBilinear } from "./sampling.js";
|
|
28
29
|
|
|
29
30
|
const OS = 20037508.342789244; // Web Mercator half-extent (m)
|
|
30
31
|
const TILE = 256; // output tile size (px)
|
|
@@ -224,22 +225,6 @@ function bilin(v00, v10, v01, v11, tx, ty) {
|
|
|
224
225
|
return top + (bot - top) * ty;
|
|
225
226
|
}
|
|
226
227
|
|
|
227
|
-
// Bilinear sample of a row-major window at fractional (fc,fr). Returns NaN when
|
|
228
|
-
// the cell center is outside the window so out-of-raster pixels stay transparent
|
|
229
|
-
// (no edge smear); falls back to nearest at the window edge / next to nodata.
|
|
230
|
-
function sampleWindowBilinear(buf, w, h, fc, fr) {
|
|
231
|
-
const c0 = Math.floor(fc), r0 = Math.floor(fr);
|
|
232
|
-
if (c0 < 0 || c0 >= w || r0 < 0 || r0 >= h) return NaN;
|
|
233
|
-
const c1 = Math.min(c0 + 1, w - 1), r1 = Math.min(r0 + 1, h - 1);
|
|
234
|
-
const v00 = buf[r0 * w + c0];
|
|
235
|
-
if (Number.isNaN(v00)) return NaN;
|
|
236
|
-
const v10 = buf[r0 * w + c1], v01 = buf[r1 * w + c0], v11 = buf[r1 * w + c1];
|
|
237
|
-
if (Number.isNaN(v10) || Number.isNaN(v01) || Number.isNaN(v11)) return v00; // edge/nodata
|
|
238
|
-
const tx = fc - c0, ty = fr - r0;
|
|
239
|
-
const top = v00 + (v10 - v00) * tx, bot = v01 + (v11 - v01) * tx;
|
|
240
|
-
return top + (bot - top) * ty;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
228
|
// Build a byte reader from a URL string, a Blob/File, or an in-memory source
|
|
244
229
|
// (ArrayBuffer, Uint8Array). `range(a,b)` yields bytes [a..b]; `openTiff()`
|
|
245
230
|
// returns a geotiff.js GeoTIFF for reading the CRS / color table from the header.
|
|
@@ -569,7 +554,7 @@ export class CogSource {
|
|
|
569
554
|
// RGB composite: bilinear-sample each band, rescale -> curve -> gamma.
|
|
570
555
|
let ok = true;
|
|
571
556
|
for (let k = 0; k < 3; k++) {
|
|
572
|
-
const v = sampleWindowBilinear(bufs[k], ww, hh, fcol, frow);
|
|
557
|
+
const v = sampleWindowBilinear(bufs[k], ww, hh, fcol, frow, ndSet ? nodata : undefined);
|
|
573
558
|
if (!isFinite(v) || (ndSet && v === nodata)) { ok = false; break; }
|
|
574
559
|
const [mn, mx] = rescales[k] || rescales[0];
|
|
575
560
|
const t = transferCurve(Math.max(0, Math.min(1, (v - mn) / ((mx - mn) || 1))), stretch, gamma);
|
|
@@ -579,7 +564,7 @@ export class CogSource {
|
|
|
579
564
|
else { out[o] = out[o + 1] = out[o + 2] = 0; }
|
|
580
565
|
} else {
|
|
581
566
|
// Continuous single band: bilinear; colormap applied below.
|
|
582
|
-
const v = sampleWindowBilinear(bufs[0], ww, hh, fcol, frow);
|
|
567
|
+
const v = sampleWindowBilinear(bufs[0], ww, hh, fcol, frow, ndSet ? nodata : undefined);
|
|
583
568
|
if (!isFinite(v) || (ndSet && v === nodata)) continue;
|
|
584
569
|
grid[py * outW + px] = v;
|
|
585
570
|
}
|
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.
|
|
8
|
+
"version": "0.3.1",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"cog_tiler_wasm.js",
|
|
17
17
|
"cog_tiler_wasm.d.ts",
|
|
18
18
|
"cog-tiler.js",
|
|
19
|
+
"sampling.js",
|
|
19
20
|
"cog-tiler.d.ts",
|
|
20
21
|
"README.md",
|
|
21
22
|
"LICENSE"
|
package/sampling.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure resampling helpers, kept dependency-free so they can be unit-tested
|
|
3
|
+
* without loading the wasm/geotiff stack that `cog-tiler.js` pulls in.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Bilinear sample of a row-major window at fractional (fc,fr). Returns NaN when
|
|
7
|
+
// the cell center is outside the window so out-of-raster pixels stay transparent
|
|
8
|
+
// (no edge smear); falls back to nearest at the window edge / next to nodata.
|
|
9
|
+
//
|
|
10
|
+
// `nodata` is the declared sentinel, when the dataset has one. It must be tested
|
|
11
|
+
// here rather than only on the result: interpolating across the boundary blends
|
|
12
|
+
// the sentinel into the value, and the product matches neither the sentinel nor
|
|
13
|
+
// NaN, so a caller's `v === nodata` check cannot recognize it. With a large
|
|
14
|
+
// negative sentinel (-9999 is the GDAL convention) the blend lands far below the
|
|
15
|
+
// rescale window, clamps to its low end, and paints a ring of the colormap's
|
|
16
|
+
// first color around every nodata boundary -- e.g. a blue border along a swath
|
|
17
|
+
// edge under `jet`. Treating a sentinel neighbor exactly like a NaN one keeps
|
|
18
|
+
// the boundary pixel at its own valid value instead.
|
|
19
|
+
export function sampleWindowBilinear(buf, w, h, fc, fr, nodata) {
|
|
20
|
+
const c0 = Math.floor(fc), r0 = Math.floor(fr);
|
|
21
|
+
if (c0 < 0 || c0 >= w || r0 < 0 || r0 >= h) return NaN;
|
|
22
|
+
const c1 = Math.min(c0 + 1, w - 1), r1 = Math.min(r0 + 1, h - 1);
|
|
23
|
+
// `nodata` is undefined when the dataset declares none; `v === undefined` is
|
|
24
|
+
// false for every numeric sample, so the test costs nothing in that case.
|
|
25
|
+
const isVoid = (v) => Number.isNaN(v) || v === nodata;
|
|
26
|
+
const v00 = buf[r0 * w + c0];
|
|
27
|
+
if (isVoid(v00)) return NaN;
|
|
28
|
+
const v10 = buf[r0 * w + c1], v01 = buf[r1 * w + c0], v11 = buf[r1 * w + c1];
|
|
29
|
+
if (isVoid(v10) || isVoid(v01) || isVoid(v11)) return v00; // edge/nodata
|
|
30
|
+
const tx = fc - c0, ty = fr - r0;
|
|
31
|
+
const top = v00 + (v10 - v00) * tx, bot = v01 + (v11 - v01) * tx;
|
|
32
|
+
return top + (bot - top) * ty;
|
|
33
|
+
}
|