maplibre-gl-raster 0.10.0 → 0.11.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 CHANGED
@@ -10,6 +10,7 @@ A MapLibre GL JS plugin for visualizing local and remote raster datasets (GeoTIF
10
10
  ## Features
11
11
 
12
12
  - **Local and remote rasters** - Load Cloud Optimized GeoTIFFs from any CORS-enabled URL, or drag-and-drop local GeoTIFF files
13
+ - **Mosaic VRTs** - Load a `.vrt` that mosaics COGs; its sources are rendered as one layer with a single shared stretch ([details and limits](#mosaic-vrt-support))
13
14
  - **Multiple layers** - Layer list with visibility toggles, reordering, zoom-to, and per-layer settings
14
15
  - **GPU rendering pipeline** - Band compositing, per-band rescale, 90+ colormaps, nodata filtering, linear/sqrt/log stretch, and gamma correction as deck.gl shader modules; parameter changes re-render without re-fetching tiles
15
16
  - **Auto statistics** - Per-band min/max and histograms sampled from COG overviews (or GDAL metadata), with draggable histogram handles for the rescale range
@@ -121,9 +122,9 @@ The main control class implementing MapLibre's `IControl` interface.
121
122
 
122
123
  #### Raster Methods
123
124
 
124
- - `addRaster(source, options?)` - Add a raster from a COG URL (`string`) or a local GeoTIFF `File`; resolves with the layer id
125
+ - `addRaster(source, options?)` - Add a raster from a COG or [mosaic `.vrt`](#mosaic-vrt-support) URL (`string`), or a local GeoTIFF / `.vrt` `File` (a local `.vrt` must name its sources as absolute URLs); resolves with the layer id
125
126
  - `removeRaster(id)` - Remove a raster layer
126
- - `getRaster(id)` / `getRasters()` - Get layer snapshots (`RasterLayerInfo`)
127
+ - `getRaster(id)` / `getRasters()` - Get layer snapshots (`RasterLayerInfo`); for a mosaic VRT, `memberUrls` lists the COGs it expanded to
127
128
  - `setRasterState(id, patch)` - Update visualization state (mode, bands, rescale, colormap, reversed, nodata, opacity, gamma, stretch, visible)
128
129
  - `setVisible(id, visible)` - Show / hide a layer
129
130
  - `selectRaster(id | null)` - Choose which layer the panel's settings edit
@@ -311,7 +312,10 @@ decimal places; omit for a compact auto format), `barLength?` /
311
312
  The package also exports lower-level building blocks for advanced use:
312
313
 
313
314
  - `loadGeoTIFF(url)` - Open a (CORS-safe) GeoTIFF from a URL or blob URL
315
+ - `parseVrt(xml, vrtUrl)` / `loadVrt(url, signal?)` - Parse a [mosaic VRT](#mosaic-vrt-support) into its member COG URLs; throws `VrtUnsupportedError` for a VRT that needs GDAL
316
+ - `isVrtUrl(url)` / `isVrtFile(file)` - Detect a `.vrt` by name
314
317
  - `computeAutoStats(tiff, signal, onProgress?)` - Per-band min/max + histograms
318
+ - `mergeAutoStats(perImage)` / `mergeBandStats(perImage)` - Merge stats sampled from several images onto one range (how a mosaic VRT gets a shared stretch)
315
319
  - `summarizeGeoTIFF(tiff)` - Image / CRS / band / GDAL metadata summary
316
320
  - `readBandNames(tiff)` / `percentileFromHistogram(stats, p)`
317
321
  - `COLORMAP_NAMES` / `COLORMAP_OPTIONS` / `colormapsPngUrl`
@@ -319,10 +323,51 @@ The package also exports lower-level building blocks for advanced use:
319
323
  - `autoRangeFor(stats)` / `statsForBand(autoStats, band)` - resolve a band's effective rescale range
320
324
  - `clamp`, `formatNumericValue`, `generateId`, `debounce`, `throttle`, `classNames`
321
325
 
326
+ ## Mosaic VRT support
327
+
328
+ A `.vrt` is not raster data: it is a GDAL XML manifest describing how to assemble other files. GDAL is not available in the browser, so only the subset that can be honoured without it is supported — **a VRT that mosaics COGs**, which is what `gdalbuildvrt` emits:
329
+
330
+ ```bash
331
+ gdalbuildvrt mosaic.vrt tile_*.tif # then load mosaic.vrt by URL
332
+ ```
333
+
334
+ Each source is loaded as its own COG and rendered as its own tiled layer, georeferenced by its own headers. They appear as **one layer** in the panel: one set of settings, one rescale window, one colorbar. Auto statistics are sampled from every member and merged, so the shared stretch describes the whole mosaic rather than whichever tile happened to be first.
335
+
336
+ Sources may be relative to the `.vrt`, absolute `https://` URLs, or `/vsicurl/https://…`. Every one must be a CORS-enabled COG. Relative sources always resolve against the `.vrt`'s own location: a browser has no working directory, so GDAL's `relativeToVRT="0"` ("relative to the process working directory") has no meaning here.
337
+
338
+ Nodata comes from the sources' `<NODATA>` when they declare one, falling back to the band's `<NoDataValue>`. A source's `<NODATA>` describes values in the member's own pixels — which is what actually gets drawn — while `<NoDataValue>` describes the VRT's output; `gdalbuildvrt` writes both and they usually agree, but `-srcnodata X -vrtnodata Y` makes them differ.
339
+
340
+ ### What is not supported
341
+
342
+ Anything that needs GDAL's pixel machinery is **rejected with an actionable error** rather than rendered approximately — a mis-placed or silently rescaled raster is worse than a clear failure:
343
+
344
+ | Rejected | Because |
345
+ | --- | --- |
346
+ | Warped VRTs (`subClass="VRTWarpedDataset"`, i.e. `gdalwarp -of VRT`) | Reprojects/resamples on the fly |
347
+ | Pixel functions (`VRTDerivedRasterBand`) | Runs inside GDAL |
348
+ | `<LUT>`, `<ScaleRatio>`, `<ScaleOffset>`, `<Exponent>` | Rescales sample values |
349
+ | `<KernelFilteredSource>`, `<AveragedSource>` | Composites pixels |
350
+ | `<UseMaskBand>` (sources with an internal mask band) | GDAL applies each source's mask while compositing; drawn separately, masked-out pixels would render as data |
351
+ | Sources declaring different `<NODATA>` values | Members share one nodata setting |
352
+ | Cropped (`<SrcRect>` sub-window) or rescaled (`<DstRect>` ≠ `<SrcRect>`) sources | Members are drawn from their own georeferencing, so the VRT's placement cannot be honoured |
353
+ | Band remapping (`<SourceBand>` ≠ band number) | Band N is read from band N of each member |
354
+ | Bands built from different file sets | Cannot collapse to one layer per file |
355
+ | `/vsis3/`, `/vsizip/`, … (any handler but `/vsicurl/`) | Needs GDAL driver config the browser cannot reconstruct |
356
+ | Local absolute paths, or relative paths in a **dropped** `.vrt` | A local `.vrt` has no readable directory in the browser, so its siblings on disk cannot be found. Load it from a URL, or use absolute URLs |
357
+ | More than 32 sources | Each becomes its own tiled layer with its own tile cache; a large mosaic would exhaust the browser |
358
+
359
+ For any of these, materialize the VRT first and load the result:
360
+
361
+ ```bash
362
+ gdal_translate mosaic.vrt mosaic.tif -of COG # or gdalwarp, for a warped VRT
363
+ ```
364
+
322
365
  ## CORS requirements for remote COGs
323
366
 
324
367
  Remote COGs must be served with CORS enabled (`Access-Control-Allow-Origin`). The loader includes a workaround for buckets that do not expose `Content-Range` via `Access-Control-Expose-Headers`, so most public S3/R2 buckets work out of the box.
325
368
 
369
+ A mosaic VRT multiplies the number of concurrent range requests by its member count. Hosts that throttle or intermittently fail under that load return error responses without CORS headers, which the browser reports as CORS failures and which show up as missing tiles.
370
+
326
371
  ## Build a GeoLibre plugin zip
327
372
 
328
373
  GeoLibre Desktop loads external plugins from an app data `plugins/` directory. The zip must contain `plugin.json` at the root, plus a bundled ESM entry and optional CSS file.