npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@canetoad/mrd

v0.3.1

Published

Multi Raster Decoder (MRD): browser-native raster decoding for ECW, JPEG 2000, TIFF/BigTIFF, and large range-streamed imagery.

Downloads

606

Readme

@canetoad/mrd

Summary

@canetoad/mrd is the public Multi Raster Decoder package for opening large geospatial rasters from local files, byte buffers, or strict HTTP range sources. It provides a single openRaster entry point plus direct format-specific entries backed by clean-room Rust/WebAssembly decoders. @canetoad/mrd is the only public npm package from this repository; the format implementations are exposed as root namespaces and subpath exports.

Features

  • Auto-detects supported raster families from file signatures.
  • Opens ECW, JPEG 2000, TIFF, and BigTIFF through format-specific WASM cores.
  • Supports streamable JP2 lower-LOD sparse region reconstruction in the Rust/WASM path for reversible 5/3 and irreversible 9/7 codestreams, with small-source full-object overview fallback when sparse plans are too costly.
  • Exposes ecw, jp2, and tiff namespaces from the package root.
  • Keeps unused format engines unloaded when importing the root package.
  • Enforces strict HTTP Range responses for sparse remote reads.
  • Exposes byte-range planning helpers for custom progressive loading.
  • Exposes a browser tile session runtime for queueing, cancellation, worker orchestration, MapLibre protocol integration, and bounded tile caches.
  • Ships ESM JavaScript, TypeScript declarations, WASM assets, README, provenance notes, changelog, and PolyForm Noncommercial license text.

Quick Start

npm install @canetoad/mrd
import { openRaster } from "@canetoad/mrd";

const result = await openRaster(fileOrUrl);
const metadata = result.handle.metadata();

Using The Library

Auto-detect and open

import { openRaster } from "@canetoad/mrd";

const result = await openRaster("https://example.com/scene.tif");

console.log(result.format);
console.log(result.handle.metadata());

openRaster accepts a URL string, a File, a Blob, a Uint8Array, or a custom RasterByteSource with size() and readRange(offset, size). The package probes the first bytes, detects the raster family, then loads the matching format subpath.

Source handling is format-aware:

| Source kind | ECW | JP2/J2K | TIFF/BigTIFF | | --- | --- | --- | --- | | URL string | Sparse HTTP range reads | Sparse header/packet reads with bounded fallback | Sparse HTTP range reads | | File / Blob | Sparse worker reads | Sparse local reads where supported | Sparse local reads | | Custom RasterByteSource | Sparse worker reads | Sparse header/packet reads where supported | Sparse custom reads | | Uint8Array | In-memory full-buffer open | In-memory/header open | In-memory sparse wrapper |

Import a known format directly

import { jp2 } from "@canetoad/mrd";
import { openEcw } from "@canetoad/mrd/ecw";
import { openJp2 } from "@canetoad/mrd/jp2";
import { openTiff } from "@canetoad/mrd/tiff";

const image = await jp2.openJp2(source);

Use direct imports when the caller already knows the input format or wants to keep bundle analysis explicit. The ECW entry uses browser Worker-backed WASM; JP2 and TIFF can also run in Node-style environments that support the package runtime requirements.

Read remote rasters safely

import { httpByteSource, openRaster } from "@canetoad/mrd";

const source = httpByteSource("https://example.com/scene.tif");
const { handle } = await openRaster(source);

httpByteSource, ECW URL streaming, and the private helper packages share the same strict range implementation. They reject range requests when a server ignores the Range header, returns a mismatched Content-Range, or reports an inconsistent Content-Length, and they throw InvalidRangeResponseError with a stable reason field for UI branching. Strict range fetches default to cache: "no-store" and cancel invalid response bodies before throwing, so a 200 OK full-object response is not accepted as a fallback for sparse reads. For direct browser access to cross-origin buckets, the bucket CORS policy must allow GET, HEAD, and request header Range, and expose response headers Content-Range, Accept-Ranges, Content-Length, ETag, and Last-Modified.

Handle decoder errors

import {
  FormatUnsupportedError,
  InvalidRangeResponseError,
  MissingBytesError,
  openRaster,
} from "@canetoad/mrd";

try {
  await openRaster(source);
} catch (error) {
  if (error instanceof MissingBytesError) {
    await fetchAndFeed(error.offset, error.size);
  } else if (error instanceof InvalidRangeResponseError) {
    console.warn(error.reason);
  } else if (error instanceof FormatUnsupportedError) {
    console.warn(error.headerBytes);
  } else {
    throw error;
  }
}

Plan byte ranges

import {
  coalesceByteRanges,
  mapByteRangesWithConcurrency,
  planMissingByteRanges,
} from "@canetoad/mrd";

The byte-range planning helpers are public so applications can build custom byte sources, preload strategies, and progressive fetch queues around the same range model used internally by the decoders.

Render MapLibre tiles

import {
  installMrdMapLibreRasterLayer,
  openPrimaryLocalRasterSession,
  openRasterSession,
} from "@canetoad/mrd";

const openSession =
  sourceDescriptor.kind === "file"
    ? openPrimaryLocalRasterSession
    : openRasterSession;

const session = await openSession({
  sourceDescriptor,
  raster,
  getRenderOptions,
});

const rasterLayer = installMrdMapLibreRasterLayer(maplibregl, map, session, {
  sourceId: "raster",
  layerId: "raster",
  bounds,
  maxzoom,
});

The session owns viewport-priority queueing, stale-tile cancellation, bounded memory and IndexedDB tile caches, overview sharing, and activity snapshots. The default package worker owns the hard-won JP2 and GeoTIFF streaming heuristics, overview fallback limits, projection handling, and worker preemption policy. Applications can still pass a custom workerFactory or renderTileOnMain for special renderers, but the standard MapLibre path does not require copying demo worker code.

GeoTIFF sampling policy is source-aware. Local File, Blob, and byte sources can use refined sampled TIFF tiles in Full quality mode when a broad source window is too large for exact decode, because the cost stays in local worker/disk reads and should remain off the main thread. Remote no-overview GeoTIFFs should remain bounded: integrations should keep those broad sampled tiles in draft quality unless the source has COG/internal overview structure or the application deliberately accepts the larger remote range plan. Use openPrimaryLocalRasterSession for local GeoTIFF/JP2 application layers that should follow the demo-proven primary local runtime contract. It wraps the package session API, requires a local replayable source descriptor, and reports refined local TIFF sampling as geotiff-sampled for compatibility with the demo proof surface.

The session contract exports named TypeScript shapes for RasterSourceDescriptor, RasterRuntimeMetadata, RasterLngLatBounds, RasterProjection, RasterRenderOptions, and RasterSourceInvalidatedEvent. Use those types when bridging an application importer into openRasterSession; they describe the replayable source, placement metadata, render state, and invalidation callbacks the package runtime expects.

installMrdMapLibreRasterLayer installs the MRD protocol, source, and raster layer, then forwards map viewport changes into the session. That viewport bridge lets the package cancel queued tiles and preempt workers that are still fetching tiles no longer needed after the user pans or zooms.

For JP2 sources, the runtime policy is intentionally hybrid. Sparse region and lower-LOD reconstruction stay on the Rust/WASM path for streamable reversible 5/3 and irreversible 9/7 codestreams. Broad lower-LOD JP2 tiles try the Rust packet-index streamer first, fetching only the planned packet ranges needed for the requested region when the codestream exposes enough packet information. Full-object decoded overview fallback remains available for small sources by default, currently capped at 64 MB, or for integrations that explicitly raise jp2OverviewMaxSourceBytes / jp2OverviewSourceByteCap. This keeps interactive opens stable without asking application callers to tune JP2 packet budgets, while avoiding surprise full-source downloads for streamable JP2s.

Runtime And Publishing

@canetoad/mrd is ESM-only and targets modern browsers, Node 20+, and edge runtimes with fetch and WebAssembly. Browser-only engines require Worker support. The source repository is private. The npm package is published publicly with provenance disabled for the private repository and contains only the built runtime artifacts, TypeScript declarations, license, changelog, README, and provenance notes listed in package.json. Source maps, source directories, Rust sources, tests, and examples are not part of the published package.

License

This software is licensed under the PolyForm Noncommercial License 1.0.0.

You may use, copy, modify, and distribute it for non-commercial purposes only, subject to the license terms and required attribution notices.

Commercial use requires a separate written license from Toad AI Pty Ltd. See LICENSE and PROVENANCE.md for license terms and clean-room provenance notes.