statumen is a Rust whole-slide image (WSI) reader. It owns container
probing, metadata normalization, slide / scene / series / level geometry,
tile addressing, region composition, associated images, and .svcache
read-through policy. JPEG and JPEG 2000 codec work is delegated to the
signinum-* crates.
The main crate forbids unsafe code. The workspace also includes an optional
OpenSlide-compatible C ABI shim for tools that already load libopenslide.
cargo add statumenThe simplest public API reads a region in level coordinates and returns an
image::RgbaImage.
use statumen::{
LevelIdx, PlaneIdx, RegionRequest, SceneId, SeriesId, Slide,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let slide = Slide::open("sample.svs")?;
let region = RegionRequest {
scene: SceneId(0),
series: SeriesId(0),
level: LevelIdx(0),
plane: PlaneIdx::default(),
origin_px: (0, 0),
size_px: (1024, 1024),
};
let image = slide.read_region_rgba(®ion)?;
image.save("region.png")?;
Ok(())
}Use tile-level APIs when you are writing a viewer, cache, benchmark, or compressed-tile workflow that needs exact tile coordinates.
use statumen::{PlaneSelection, Slide, TileOutputPreference, TilePixels, TileRequest};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let slide = Slide::open("sample.svs")?;
let req = TileRequest {
scene: 0,
series: 0,
level: 0,
plane: PlaneSelection::default(),
col: 0,
row: 0,
};
match slide.read_tile(&req, TileOutputPreference::cpu())? {
TilePixels::Cpu(tile) => {
println!("{}x{} tile with {} channels", tile.width, tile.height, tile.channels);
}
TilePixels::Device(_) => unreachable!("CPU output was requested"),
}
Ok(())
}Associated images such as labels, macros, and thumbnails are exposed through
the dataset metadata and read_associated:
use statumen::Slide;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let slide = Slide::open("sample.svs")?;
if slide.dataset().associated_images.contains_key("thumbnail") {
let thumbnail = slide.read_associated("thumbnail")?;
println!("thumbnail: {}x{}", thumbnail.width, thumbnail.height);
}
Ok(())
}If you are asking an LLM to use this repository, give it this instruction:
Use
statumento open whole-slide image files and read regions or tiles. UseSlide::openplusread_region_rgbafor the first working prototype. Useread_tile/read_tilesonly when exact source tile coordinates or compressed-tile behavior matters.
For a quick script, ask the LLM to:
- Add
statumenas a Rust dependency. - Open the slide with
Slide::open("path/to/slide.svs"). - Build a
RegionRequestfor scene 0, series 0, level 0. - Call
read_region_rgba. - Save the returned image or pass it to the next analysis step.
Statumen detects the container, normalizes slide geometry, and delegates codec decode to Signinum.
| Input family | Typical paths | Notes |
|---|---|---|
| TIFF-family WSI | .svs, .tif, .tiff, .ndpi, .scn, .bif |
Includes common Aperio, Hamamatsu NDPI, Leica, Philips, Ventana, Trestle, and generic tiled TIFF layouts where metadata is available. |
| DICOM VL WSI | .dcm files or a DICOM series directory |
Opens single instances or sibling pyramid instances from the same series. Supports JPEG baseline, JPEG 2000, HTJ2K transfer syntaxes, RLE lossless 8-bit frames, native uncompressed little/big endian 8-bit frames, associated images, and sparse tiled frame maps. |
| Zeiss | .czi, .zvi |
Reads Zeiss CZI and legacy ZVI slide data. |
| MIRAX | .mrxs plus sibling data files |
Reads slide metadata and tiles through the Statumen format adapter. |
| Hamamatsu VMS/VMU | .vms, .vmu plus sibling image files |
Reads legacy Hamamatsu multi-file slides. |
| Olympus VSI | .vsi plus the matching _<stem>_ ETS companion directory |
Reads Olympus whole-slide containers backed by frame_t.ets data. |
| Raw JPEG 2000 codestream | .j2k, .j2c |
Single-image raw codestream workflow for fixtures and codec tests. JP2 boxes are not the raw-file entry point. |
.svcache |
.svcache |
Statumen's zstd-compressed cache format for prebuilt display tiles and associated images. |
Unsupported or incomplete sources return WsiError; they should not silently
produce black or partial pixels.
Slide::open uses the built-in registry with deterministic cache defaults and
does not silently rewrite a source path to .svcache. Use
Slide::open_with_options when callers need explicit cache budgets,
read-through .svcache lookup, custom format registries, region limits, or
decode execution settings.
use statumen::{CacheConfig, Slide, SlideOpenOptions, SvcachePolicy};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let options = SlideOpenOptions::default()
.with_cache_config(
CacheConfig::deterministic()
.with_shared_tile_bytes(256 * 1024 * 1024)
.with_display_tile_bytes(32 * 1024 * 1024),
)
.with_svcache_policy(SvcachePolicy::PreferFresh);
let slide = Slide::open_with_options("sample.svs", options)?;
println!("{} scene(s)", slide.dataset().scenes.len());
Ok(())
}Build .svcache files with the library functions or the svcache binary:
cargo run --release --bin svcache -- build sample.svs --out sample.svs.svcache
cargo run --release --bin svcache -- build-window sample.svs --size 2048x2048 --center 10000,10000The workspace includes statumen-openslide-shim, a C ABI library that exports
OpenSlide-compatible symbols and routes reads through Statumen. Use it when an
existing tool already loads libopenslide and you want to try Statumen without
rewriting that tool.
Build the shim:
cargo build -p statumen-openslide-shim --releaseThen point a test client at the produced dynamic library with a local loader path, or install it into a private prefix:
cargo run -p statumen-openslide-shim --bin statumen-openslide-install -- \
install --shim target/release/libstatumen_openslide_shim.dylib \
--prefix /tmp/statumen-openslideOn Linux the library suffix is .so; on macOS it is .dylib. Prefer a private
prefix while testing. The installer writes a restore manifest and can restore
backed-up libraries with:
cargo run -p statumen-openslide-shim --bin statumen-openslide-install -- \
restore --prefix /tmp/statumen-openslideSee statumen-openslide-shim/README.md
for ABI coverage and loader-path notes.
| Feature | Default | Description |
|---|---|---|
metal |
off | Enables Metal-backed device payload plumbing through signinum-jpeg-metal and signinum-j2k-metal on macOS. |
cuda |
off | Reserved for CUDA-backed payloads. |
bench |
off | Builds benchmark and cache-gate binaries that have no system dependencies. |
openslide-bench |
off | Builds OpenSlide comparison binaries; requires libopenslide through pkg-config. |
parity-openslide |
off | Enables OpenSlide compatibility-oracle parity tests and benches through libloading. |
parity-metal |
off | Enables Metal-backed parity comparisons on macOS. |
The metal feature opts in to device-resident output. Applications that create
Metal sessions directly should also depend on the adapter crates they name.
[dependencies]
statumen = { version = "0.3.0", features = ["metal"] }
metal = "0.31"
signinum-jpeg-metal = "0.4"
signinum-j2k-metal = "0.4"use statumen::{PlaneSelection, Slide, TileOutputPreference, TilePixels, TileRequest};
let device = metal::Device::system_default()
.ok_or_else(|| std::io::Error::other("no system Metal device"))?;
let sessions = statumen::output::metal::MetalBackendSessions::new(
signinum_jpeg_metal::MetalBackendSession::new(device.clone()),
signinum_j2k_metal::MetalBackendSession::new(device),
);
let slide = Slide::open("sample.svs")?;
let req = TileRequest {
scene: 0,
series: 0,
level: 0,
plane: PlaneSelection::default(),
col: 0,
row: 0,
};
let output = TileOutputPreference::prefer_device_auto_with_metal_and_compressed_decode(sessions);
match slide.read_tile(&req, output)? {
TilePixels::Device(device_tile) => {
// Upload or sample the resident Metal buffer in the caller's renderer.
let _ = device_tile;
}
TilePixels::Cpu(cpu_tile) => {
// `PreferDevice` can fall back to CPU. Use
// `require_device_auto_with_metal_and_compressed_decode` to reject fallback.
let _ = cpu_tile;
}
}
# Ok::<(), Box<dyn std::error::Error>>(())| Target | CPU pipeline | Metal feature |
|---|---|---|
x86_64-unknown-linux-gnu |
yes | no |
x86_64-apple-darwin |
yes | yes |
aarch64-apple-darwin |
yes | yes |
x86_64-pc-windows-msvc |
yes | no |
This crate tracks the latest stable Rust toolchain. The current MSRV is
declared in Cargo.toml as rust-version = "1.94". Bumping the MSRV is
treated as a minor-version change and is recorded in CHANGELOG.md.
CPU JPEG tile batches route through Signinum's scoped batch decoder by default when jobs share the same TIFF/DICOM color transform and exact decoded tile dimensions. Mixed or irregular JPEG jobs fall back to the conservative per-tile path with the same output behavior.
Benchmark tools live in the repository under benches/, scripts/, and
src/bin/ and are excluded from the published crate tarball. Useful entry
points include:
cargo test
cargo test --features parity-openslide --test openslide_parity
cargo xtask bench-check
cargo xtask bench
cargo run --release --features bench --bin wsi_bench -- path/to/slide.svs
cargo run --release --features "bench openslide-bench" --bin bench_driver -- path/to/slide.svs thumbnailcargo xtask bench-check compiles the Rust benchmark targets without running
timings and is part of the default validation gate. cargo xtask bench runs
the synthetic Criterion read-path benchmarks locally without requiring a WSI
corpus.
Optional Iris comparison is wired through scripts/iris_bench.py and
bench_driver. Iris consumes pre-encoded .iris slides, so set
WSI_BENCH_INCLUDE_IRIS=1 plus either WSI_IRIS_SLIDE_PATH=/path/file.iris
or WSI_IRIS_SLIDE_DIR=/path/to/iris-slides. Set WSI_BENCH_GATE_IRIS=1
only when the run should fail if Statumen is slower than Iris.
The repository uses an xtask wrapper for CI-style checks:
cargo xtask fmt
cargo xtask clippy
cargo xtask bench-check
cargo xtask nextest
cargo xtask doc
cargo xtask validate
cargo xtask feature-check
cargo xtask depscargo xtask validate runs the default local gate (fmt, clippy,
bench-check, nextest, and doc). cargo xtask ci runs that gate plus
package checks. Some parity tests require local WSI corpora or external
libraries; those tests are ignored unless the documented environment variables
are set.
The extended checks use cargo-nextest, cargo-hack, cargo-deny, and
cargo-machete. CI installs these tools before running the corresponding
xtask targets.
Production JPEG and JPEG 2000 decode is delegated to the signinum-* crate
family. Cite the relevant Signinum artifact for codec methods, ROI /
restart-marker APIs, batch decode, or decode-performance claims. Cite this
workspace separately for reader behavior, container parsing, normalized slide
geometry, and OpenSlide shim behavior.
See CONTRIBUTING.md and our
CODE_OF_CONDUCT.md. The change log lives in
CHANGELOG.md.
Apache-2.0. See LICENSE.