Expand description
A streaming, demand-driven image processing engine.
Pixels is a libvips-class pipeline engine: images are lazy operation
graphs, pixels are pulled through the graph on demand, and memory stays
bounded regardless of image size. This crate is the facade — the chainable
Image API and the Image::output terminal — over
otf_pixels_core’s engine, otf_pixels_ops’ kernels and the codec
crates.
use otf_pixels::{Format, Image, ImageDescriptor, PixelFormat};
let descriptor = ImageDescriptor::new(4, 4, PixelFormat::Gray8)?;
let pixels: Vec<u8> = (0..16).collect();
// Construction and chaining do no pixel work.
let bytes = Image::from_raw(descriptor, pixels)?
.crop(1, 1, 2, 2)
.flip()
.output(Format::Raw, Default::default())
.bytes()?;
assert_eq!(bytes, [9, 10, 5, 6]);§Errors are deferred, not swallowed
Chaining methods take and return Self rather than Result, so a
pipeline reads as one expression. An error raised mid-chain — a crop window
outside the image, say — is captured and carried to the terminal, where
it surfaces from Output::write or Output::bytes. Nothing is
silently ignored, and no operation runs after a failed one.
§Evaluation
Terminals run the pipeline on the demand-driven tile scheduler: output tiles are evaluated in parallel and delivered to the sink in order, with peak memory bounded by tiles in flight rather than image size.
Every output runs on Scheduler::global unless told otherwise: one pool
of worker threads, one per core, and one tile cache, shared by every
pipeline in the process. That is the right setup for a server or a
runtime handling many images at once, and it needs no code: call
output(...).bytes() from as many threads as you like and the runs share
the workers. Do not build a Scheduler per request, and do not set
Output::threads or Output::scheduler_options to tune a busy host —
both give that run a private pool, spawned and joined each time, which
under concurrency means a pool per request competing for the same cores.
Output::with_scheduler runs on a scheduler you built, for a host that
wants image work confined to a fixed number of threads.
Output::bytes_via_reference runs the same pipeline through the M1
whole-image evaluator instead. That path is slow and holds every
intermediate in full, but it is obviously correct, so it is the oracle the
scheduler is verified against.
§Serving images
What an image endpoint or a runtime’s image API does: bytes in, a thumbnail out. Opening identifies the format from its bytes, turns the image upright, converts its colours to sRGB and enforces input limits; nothing is decoded until the output is pulled, and a JPEG source decodes at a reduced scale when the thumbnail allows it.
use otf_pixels::{
EncodeOptions, Fit, Format, Image, Limits, OpenOptions, ResizeOptions,
};
// Per request: bound what an untrusted upload may allocate.
let options = OpenOptions::default()
.with_limits(Limits::default().with_max_pixels(50_000_000));
let image = Image::from_stream_with(std::io::Cursor::new(upload), options)?;
let meta = image.metadata()?; // free: no pixels decoded
assert_eq!((meta.width, meta.height), (64, 48));
if let Some(animation) = image.animation() {
// v1 processes the first frame; the caller decides whether that is
// acceptable for this animation.
let _ = animation.frame_count;
}
let webp = image
.resize_with(32, 32, ResizeOptions::default().with_fit(Fit::Cover))
.output(Format::WebP, EncodeOptions::with_quality(80)?)
.bytes()?;
assert_eq!(&webp[8..12], b"WEBP");§Scope (v1)
- Formats, all implemented in this workspace and checked against their reference implementations: PNG, GIF, baseline JPEG (progressive decode is wrapped), TIFF, WebP (lossy and lossless) and AVIF, read and written, plus raw pixels.
- Ops: crop, flip/flop, quarter-turn rotation and orientation, resize with sharp’s five fit modes, modulate, convolve/blur/sharpen, composite, flatten, channel extraction, pixel-format and sRGB conversion.
- Metadata: EXIF/HEIF orientation applied on open; ICC profiles converted to sRGB or carried to the output; animation reported, with the first frame processed. Other metadata (EXIF, XMP) is not written out, which also strips location data from uploads.
Not yet: multi-frame (animated) pipelines, arbitrary-angle rotation and
progressive JPEG output. Each will arrive as an addition, not a change:
OpenOptions::animated is already reserved for the first.
Structs§
- Animation
- How an animated image plays: its frames and their timing.
- Avif
Codec - The AVIF entry in a sniffing registry.
- Avif
Decoder - Decodes an AVIF stream.
- Avif
Encoder - Encodes an AVIF still.
- Composite
- Draw
overlayoverbaseat an offset. - Convert
Format - Convert to a different
PixelFormat. - Convolve
- Apply a convolution kernel.
- Crop
- Extract a rectangular window of an image.
- Encode
Options - Encoder tuning shared across formats.
- Extract
Channel - Extract one channel as a greyscale image (SPEC §Core ops).
- Flatten
- Composite an image onto an opaque background, discarding alpha.
- Flip
- Mirror an image vertically: the top row becomes the bottom row.
- Flop
- Mirror an image horizontally: the left column becomes the right column.
- GifCodec
- The GIF entry in a sniffing registry.
- GifDecoder
- Decodes a GIF stream.
- GifEncoder
- Encodes a single-frame GIF.
- Image
- A lazily evaluated image pipeline.
- Image
Descriptor - The shape of an image at a point in the graph.
- Jpeg
Codec - The JPEG entry in a sniffing registry.
- Jpeg
Decoder - Decodes a JPEG stream.
- Jpeg
Encoder - Encodes a baseline JPEG stream.
- Kernel
- A convolution kernel: odd-sized, square or rectangular, small.
- Limits
- Safety limits applied before any pixel memory is allocated.
- Metadata
- Header-only facts about an image.
- Modulate
- Brightness, saturation and hue adjustment (SPEC §Core ops).
- Open
Options - How
Image::open_withandImage::from_stream_withread an image. - Output
- A pipeline with its output format chosen, ready to be pulled.
- Plan
Options - Knobs for
Plan::build. - PngCodec
- The PNG entry in a sniffing registry.
- PngDecoder
- Decodes a PNG stream.
- PngEncoder
- Encodes a PNG stream.
- RawCodec
- Format sniffing for raw streams.
- RawDecoder
- Decodes a raw pixel stream, one row per call.
- RawEncoder
- Encodes rows of pixels as a raw stream.
- RawFormat
- The layout of a raw pixel stream.
- Region
- An axis-aligned rectangle of pixels, in image coordinates.
- Resize
- Resample an image to a new size.
- Resize
Options - Options for
Resize. - Rotate
- Rotate an image by a multiple of 90 degrees.
- RunStats
- Counters describing one run, for tests and diagnostics.
- Scheduler
- A demand-driven, parallel tile evaluator.
- Scheduler
Options - Tuning for a
Scheduler. - Tiff
Codec - The TIFF entry in a sniffing registry.
- Tiff
Decoder - Decodes a TIFF stream.
- Tiff
Encoder - Encodes a baseline TIFF.
- ToSrgb
- Converts pixels in an ICC profile’s colour space to sRGB.
- WebP
Codec - The WebP entry in a sniffing registry.
- WebP
Decoder - Decodes a WebP stream.
- WebP
Encoder - Encodes a WebP stream.
Enums§
- Access
Pattern - The tile shape an op wants its input delivered in.
- Blend
- How the source is combined with the backdrop.
- Channel
Layout - The channel layout of a pixel, independent of sample type.
- Color
Model - The color model a descriptor’s samples are interpreted in.
- Conversion
- What
ToSrgb::from_profilemakes of a profile. - Error
Code - A stable, machine-readable error classification.
- Filter
- A resampling filter kernel (SPEC §Core ops).
- Fit
- How a resize reconciles the requested box with the source aspect ratio, with sharp’s meanings.
- Format
- A container format.
- Limit
- The safety limit that a
PixelsError::LimitExceededrefers to. - Orientation
- One of the eight orientations the EXIF/TIFF
Orientationtag (274) can name. - Pixel
Format - An interleaved pixel format: a
ChannelLayoutover aSampleKind. - Pixels
Error - The error type returned by every fallible engine operation.
- Quarter
- A quarter-turn rotation, clockwise.
- Sample
Kind - The numeric type of one channel sample.
- Scale
- How much of an image a decode produces, as eighths of full size.
- Subsampling
- How much the chroma channels are subsampled relative to luma.
- Tiff
Layout - How an encoder arranges pixels in the file.
- Tile
Shape - The shape tiles take through a segment of the graph.
- Unconvertible
- Why a profile is not converted.
Traits§
- Codec
- Format sniffing.
- Decoder
- Decodes a byte stream into rows of pixels.
- Encoder
- Encodes rows of pixels into a byte stream.
- Sink
- A sink for encoded bytes.
- Source
- A forward-only source of bytes.
Functions§
- evaluate_
reference - Evaluate
imageto a whole-image buffer.
Type Aliases§
- Result
- The engine’s result alias.