vips-rs
Rust bindings for libvips: fast, low-memory image processing with a safe, ergonomic API.
- Safe wrappers over common libvips APIs
- RAII-style initialization/shutdown management
- Practical helpers for reading, transforming, and writing images
- Lazy pipeline evaluation (libvips demand-driven processing)
Documentation: https://houseme.github.io/vips-rs/vips/
Requirements
- Rust >= 1.85.0 (edition 2024)
- libvips installed on your system
- macOS:
brew install vips - Linux:
apt-get install -y pkg-config libvips libvips-dev(or your distro equivalent)
- macOS:
Installation
Add to your Cargo.toml:
[]
= "0.1"
Quick start
use *;
Working with memory
- Own the pixel buffer (simple and recommended):
let pixels = vec!; // RGB
let img = from_memory?;
let thumb = img.thumbnail?;
thumb.write_to_file?;
- Borrow a pixel buffer (make sure the backing data outlives all derived images):
let pixels = vec!;
let img = from_memory_reference?;
let thumb = img.thumbnail?;
thumb.write_to_file?;
Lifetimes and common pitfalls
- Prefer owned constructors (
from_file,from_memory) when possible. - Borrowing constructors (
from_memory_reference) tie the image lifetime to the borrowed slice. Do not let the slice drop before all derived images are fully used. - Keep the creator image in scope while using results that reference it. Avoid creating images inside a short inner scope and returning derived results from it.
API highlights
| Area | APIs |
|---|---|
| IO | from_file, from_memory, from_memory_reference, from_buffer, write_to_file, write_to_memory, write_jpeg |
| Geometry | thumbnail, resize, resize_reduce, reduce, shrink_box |
| Properties | width, height, size, bands |
| Drawing | draw_rect, draw_line, draw_circle, draw_flood, … (in-place) |
| Stitching | merge, mosaic, match_, globalbalance, remosaic |
| Interpolation | VipsInterpolate nearest / bilinear / custom |
Performance tips
- Prefer
write_to_fileoverwrite_to_memorywhen the destination is a path (avoids a full in-memory copy). - For large downscales (factor ≳ 3 on multi-megapixel sources), prefer
resize_reduce— it box-pre-shrinks before the final kernel. - Tune
vips::set_concurrency,set_max_operations, andset_max_mem_bytesfor your workload. - libvips pipelines are lazy: operations enqueue work until the image is written or materialized.
Notes
- Initialization: the crate manages
vips_init/vips_shutdownviaVipsInstanceand standard library primitives (OnceLock). - Side effects: most operations return new images; drawing operations modify
self. - If a higher-level wrapper is missing, you can still access lower-level bindings in
vips-sysor usevips::call(...)to invoke libvips operations directly.
Local development
Published builds resolve vips-sys from crates.io. To develop against a sibling checkout, add a
[patch] at the workspace/consumer root (or temporarily in this crate):
[]
= { = "../vips-sys" }
Docker-based check (no local libvips required):
License
Changelog
See CHANGELOG.md.