A pure-Rust, thread-safe image pyramiding engine. Inspired by libvips, built from scratch for the AEC/construction domain.
Takes blueprint PDFs and images, extracts raster data, optionally geo-references it, and generates tile pyramids (DeepZoom, XYZ, Google Maps) suitable for web-based viewers.
Features
- PDF extraction — extract embedded raster images from scanned blueprint PDFs via lopdf (pure Rust, no C dependencies)
- PDF rendering — render vector PDFs (AutoCAD exports, text, paths) via PDFium, with optional memory-budgeted rendering (optional
pdfiumfeature) - Image decoding — JPEG, PNG, TIFF via the
imagecrate - Tile pyramid generation — multi-threaded engine with backpressure, configurable tile size and overlap
- Layout formats — DeepZoom (
.dzi+ directory tree), XYZ (z/x/y), and Google Maps (z/y/x, power-of-2 grids) - Centre support — centre image within the tile grid with even background padding on all sides
- Tile encoding — PNG, JPEG (configurable quality), or raw pixel output
- Blank tile optimization — configurable
BlankTileStrategyto either emit full tiles or write 1-byte placeholders (BLANK_TILE_MARKER) for uniform-color regions, reducing disk usage for sparse images - Edge tile background — configurable background color (
background_rgb) for padding partial tiles at image edges (defaults to white) - Geo-referencing — affine transform mapping pixel coordinates to geographic coordinates, GCP support
- Observability — progress events, per-level callbacks, peak memory tracking
Usage
use ;
use Path;
// Extract raster from a scanned blueprint PDF
let raster = extract_page_image.unwrap;
// Plan the pyramid
let planner = new.unwrap;
let plan = planner.plan;
// Generate tiles to disk
let sink = new;
let config = default
.with_concurrency
.with_blank_tile_strategy;
let result = generate_pyramid.unwrap;
println!;
Modules
| Module | Description |
|---|---|
source |
Image decoding (JPEG, PNG, TIFF) into canonical Raster |
pdf |
PDF parsing (lopdf) and optional rendering (PDFium), including budgeted render |
raster |
Pixel buffer, region views, format normalization |
pixel |
Pixel format definitions (Gray8, RGB8, RGBA8, 16-bit variants) |
planner |
Tile math, level computation, layout generation |
resize |
Downscaling for pyramid levels |
engine |
Multi-threaded tile extraction with backpressure, blank tile detection |
sink |
Tile output (filesystem, memory, slow sink for testing) |
geo |
Affine geo-transform, GCP solving, bounding box computation |
observe |
Progress events, memory tracking |
Features
| Feature | Default | Description |
|---|---|---|
pdfium |
off | Enables render_page_pdfium() and render_page_pdfium_budgeted() for vector PDF rendering. Requires libpdfium at runtime. |
Requirements
- Rust 1.85+ (edition 2024)
- libpdfium shared library (only if using the
pdfiumfeature)
PDFium setup
The pdfium feature requires libpdfium.so at runtime. Pre-compiled binaries built from source are available from libviprs-dep:
# x86_64
# arm64
# Extract and install
See the libviprs-dep pdfium README for building PDFium from source or finding other versions.
Related Crates
| Crate | Description |
|---|---|
| libviprs-cli | Command-line interface (viprs binary) |
| libviprs-tests | Integration tests and fixtures, including end-to-end PDF-to-pyramid tests for blueprint.pdf and blueprint-mix.pdf |
CI
GitHub Actions runs two workflows:
CI (every push and PR) — .github/workflows/ci.yml:
cargo fmt --check— formattingcargo clippy -D warnings— lint (default +pdfiumfeature)cargo test— unit tests
Merge Gate (PRs targeting release, required to merge) — .github/workflows/merge-gate.yml:
cargo +nightly miri test— undefined behavior detection- Loom concurrency tests
Running CI locally
A Makefile mirrors the full CI pipeline. Run everything with:
Or run individual checks:
Prerequisites:
make mirirequires the nightly toolchain with the miri component. Install with:rustup toolchain install nightly --component miri