ezu 0.8.2

Painterly cartography engine: render vector tiles as paintings (umbrella crate)
Documentation

ezu

Crates.io docs.rs CI License: MIT OR Apache-2.0 Docs

Painterly cartography — render vector tiles as paintings — on a pure-Rust, GPU-free CPU renderer with first-class MapLibre compatibility.

ezu pencil-sketch render of central Japan — © OpenStreetMap contributors, © Protomaps

ezu (絵図) is a Rust map rendering engine that turns vector tiles (MVT / PMTiles) into raster tiles on the CPU — no GPU, no headless browser. It does this two ways, and does both at once:

  • Painterly — a style is a typed node graph, not an ordered layer list. It drives the hokusai brush engine and ~80 image-processing ops to render watercolour, ink wash, ukiyo-e and beyond, with the geographic data intact underneath. Dab placement and label collision are deterministic in world space, so tile borders don't show.
  • MapLibre-compatibleezu translate lowers a MapLibre GL style into an ezu recipe, and any node field that varies per feature takes a raw MapLibre expression, evaluated by maplibre-expr at 100 % conformance against MapLibre's official spec fixtures. A 68-layer Protomaps theme renders end to end, labels and icons included, at SSIM 0.80–0.87 against maplibre-gl-js.

Documentation

https://reearth.github.io/ezu/

Render your first tile from a flat colour to a watercolour wash, one node at a time
Guides the CLI, the live editor, the Rust library, the browser, serving tiles
Concepts the node graph, ports and types, determinism, padding, caching
Style reference the spec, and a catalog of all 82 ops with a render of each
MapLibre compatibility layer mapping, measured fidelity, and the known gaps
Gallery what the example styles look like, with the recipes

Rust API documentation is on docs.rs.

Quick start

cargo install ezu-cli

Then render a tile. This style keeps all of its data remote, so it needs nothing but the CLI:

ezu tile \
  --style https://raw.githubusercontent.com/reearth/ezu/main/crates/ezu/examples/styles/hillshade.json \
  --tile 11/1813/807 --out fuji.png

The painterly example styles name their brushes by relative file: path, so render those from a checkout:

git clone https://github.com/reearth/ezu && cd ezu
ezu tile --style crates/ezu/examples/styles/watercolor.json \
  --tile 13/7276/3225 --out tile.png

ezu serve starts the live editor — edit the style and watch the map redraw, schema-validated as you type, with generated controls for the style's params:

ezu serve crates/ezu/examples/styles/pencil-sketch.json
# → http://127.0.0.1:8080

ezu bbox stitches a lon/lat box into one image, ezu tiles bulk-renders an XYZ pyramid, ezu translate converts a MapLibre style, ezu check validates one, and ezu schema prints the style JSON Schema. Full reference: CLI.

Workspace

Crate crates.io Description
ezu Umbrella crate, re-exports + feature flags
ezu-core Tile / world coordinates, deterministic seeding
ezu-features GIS feature parsing (MVT via geozero, GeoJSON) — no remote fetch
ezu-style Style spec parser (serde) — pure data, no rendering
ezu-graph Typed node-DAG evaluator (cache, pad propagation, Rayon)
ezu-paint Painting primitives, the built-in ops, host glue
ezu-translate Lower other engines' styles into ezu recipes — MapLibre GL is the first frontend
ezu-cli The ezu binary — rendering, translate, check, graph, schema, serve
ezu-wasm npm WebAssembly bindings — scalar / SIMD / threads builds for in-browser rendering

The expression engine lives in its own repository, reearth/maplibre-expr-rs. ezu-compare (internal, unpublished) converts a MapLibre style, renders it with ezu, and pixel-compares against a maplibre-gl-js reference.

Performance

On an Apple M1, a converted Protomaps basemap at 512 px evaluates in ~13–30 ms per tile single-threaded across z12–z15, and a full 68-layer theme with labels in ~42–105 ms. End to end, a 251-tile z13–z14 pyramid renders in ~9 s across 8 cores — ~37 ms/tile including HTTP fetch, MVT decode and PNG encode.

A style's first render is far slower than that, because lazily fetched glyphs and neighbour tiles land inside evaluation. Methodology, the per-op breakdown, and what to tune are in performance.

In the browser

npm install @reearth/ezu

The renderer compiles to WebAssembly, in scalar, SIMD and Web-Worker threads builds. The JS side owns all I/O and hands decoded bytes to a stateful Renderer, which returns PNG, lossless WebP, or raw RGBA to blit onto a canvas. See use in the browser.

Contributing

Repository layout, how the tests are structured, and how the docs site's generated pages and images are produced: contributing. Bugs and design questions are both welcome as issues.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.