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

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
hokusaibrush 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-compatible —
ezu translatelowers a MapLibre GL style into an ezu recipe, and any node field that varies per feature takes a raw MapLibre expression, evaluated bymaplibre-exprat 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
Then render a tile. This style keeps all of its data remote, so it needs nothing but the CLI:
The painterly example styles name their brushes by relative file: path,
so render those from a checkout:
&&
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:
# → 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
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.