Skip to main content

deck.gl-raster v0.3

· 6 min read
Kyle Barron
Cloud Engineer

deck.gl-raster is enabling GPU-accelerated GeoTIFF and Cloud-Optimized GeoTIFF (COG) visualization in deck.gl.

Here's what's new in v0.3.

Updated Examples

We have a new examples page in the documentation, where we'll continue adding examples.

Example
RGB Cloud-Optimized GeoTIFF
NLCD Land Cover
NAIP Planetary Computer Mosaic

New TypeScript GeoTIFF reader for the web

We're releasing @developmentseed/geotiff, a new, high-level, full-TypeScript GeoTIFF and Cloud-Optimized GeoTIFF (COG) reader for the browser, built on top of @cogeotiff/core.

This includes a number of features:

  • Full TypeScript: The entire project — both public APIs and internal code — is strongly and exhaustively typed in TypeScript.

  • No unnecessary data copies: Image fetching APIs always return data in their original layout, ensuring data copies only happen with the user's explicit consent.

  • Easy access to image tiles: GeoTIFF.fetchTile fetches individual tiles from the source GeoTIFF or COG.

    A single call to fetchTile ensures that there is always one request to the backend COG for the given tile, ensuring network calls are predictable.

  • Convenient access to reduced-resolution overviews: Easily access reduced-resolution overviews to fetch tiles at your desired resolution.

  • Affine transformation handling: Integrates with the new @developmentseed/affine for easy handling of image transforms, associating pixel positions to spatial coordinates.

    All loaded RasterArray instances contain an Affine, tracking the relative image transform of that specific image window.

  • Automatic Nodata Mask handling: nodata masks are automatically associated with their related image data, and are automatically fetched when available.

  • Configurable Web Worker pool for image decoding off the main thread.

  • Full user control over caching and chunking

  • Nearly-identical API to Python's async-geotiff useful for building GeoTIFF image handling across both TypeScript and Python.

Why not geotiff.js?

The initial implementation of deck.gl-raster used geotiff.js, and geotiff.js was great for quickly getting started. But as we move towards production stability, there are a few reasons why we built @developmentseed/geotiff.

  • Full TypeScript: The underlying library @cogeotiff/core is fully typed in expressive TypeScript, making it much more enjoyable to build on top of.

    I tried to submit PRs to move geotiff.js to TypeScript, but contributors there wished to remain in JavaScript + JSDoc.

  • @cogeotiff/core implements a bunch of optimizations, like reading and utilizing the GDAL "ghost header" out of the box. In contrast, geotiff.js can parse but won't automatically use the ghost values.

  • Project scope: geotiff.js has a lot of code unrelated to the needs of deck.gl-raster. Resampling, tile-merging, conversion to RGB, overview selection based on a target resolution, writing GeoTIFFs. These geotiff.js features are unnecessary for us, but make geotiff.js more complex to maintain if we had to fix something.

  • Confidence to build on top of: this is subjective, but geotiff.js feels overly complex. It doesn't feel focused on a targeted, clean API in the way that @cogeotiff/core is.

  • JSDoc is hard to read and contribute to: this is subjective, but I find it much harder to read and contribute to geotiff.js code written with JSDoc instead of pure TypeScript.

  • Code quality: there are various parts of geotiff.js with code just... commented out. And the function has no documentation. Why is it normalizing? The needsNormalization function also has no documentation, and is hard to understand what the equality is checking because it doesn't use TypeScript-standard enums, which would make the code itself readable.

Overall, geotiff.js seems like a fine library, and it was useful to get started quickly. But to build a modern COG rendering stack, we need to have a huge amount of confidence on our foundations, and @cogeotiff/core gives that confidence.

Integration testing against rasterio

@developmentseed/geotiff is integration tested against rasterio for GeoTIFF test cases stored in geotiff-test-data.

Automatic nodata masking in deck.gl-geotiff

In deck.gl-geotiff, the COGLayer will automatically check for and use a nodata mask.

BeforeAfter

New compressed EPSG projection database for the web

We're releasing @developmentseed/epsg. It ships the full EPSG projection database as WKT2 strings, gzip-compressed to 309kb for the web.

import loadEPSG from "@developmentseed/epsg/all";
import proj4 from "proj4";

// Load the EPSG database
const epsg = await loadEPSG();

// Access WKT strings by EPSG code.
const wkt4326 = epsg.get(4326);
const wkt3857 = epsg.get(3857);

// Then use proj4.js as normal
const converter = proj4(wkt4326, wkt3857);
const inputPoint = [1, 52];
const outputPoint = converter.forward(inputPoint);

This can easily be used outside of deck.gl use cases.

New port of rasterio/affine

We're releasing @developmentseed/affine, a port of rasterio/affine for working with affine image transformations.

import type { Affine } from "@developmentseed/affine";
import { apply } from "@developmentseed/affine";

const gt: Affine = [1, 0, 10, 0, 1, 20];
const coord = apply(gt, 5, 5);
// [15, 25]

This is designed as a collection of lightweight pure functions around an Affine, typed as

export type Affine = readonly [
a: number,
b: number,
c: number,
d: number,
e: number,
f: number,
];

This architecture ensures maximum tree-shakability.

This is not yet a full port, but we plan to port over more functions as needed.

New documentation website

We have a new documentation website for deck.gl-raster: developmentseed.org/deck.gl-raster.

This hosts examples and API docs for all modules in this monorepo.