fovea-io
fovea-io is the file boundary for fovea: decode PNG, JPEG, and BMP bytes into typed fovea::Image<P> values, then let the core crate enforce pixel semantics from there.
The key idea is simple: I/O tells you what the file contains. It does not silently decide how to process it. Metadata travels with pixels, color conversions are explicit, and unsupported encodes are compile-time errors where possible.
Install
No codecs are enabled by default. Enable only the formats you need:
Enable every current codec with:
Features
| Feature | Enables | Pulls in |
|---|---|---|
png |
PNG decode + encode | png |
jpeg |
JPEG decode + encode | jpeg-decoder, jpeg-encoder |
bmp |
BMP decode + encode | no external codec crate |
all-codecs |
PNG, JPEG, and BMP | all optional codec dependencies |
The fovea I/O model
bytes → detect/decode → per-codec enum → concrete Image<P> → explicit transforms → encode
load is convenient when you do not know the file format. Per-codec APIs are better when you do know the format, because their image enums are exhaustive spec sheets.
use ;
let png_sig = ;
assert_eq!;
assert_eq!;
Decode once, then work with types
use ImageView;
use ;
let bytes = read?;
let decoded = decode?;
match decoded.image
After the match, downstream code has concrete pixel types. A resize pipeline can reject gamma-incorrect interpolation; a display path can require display-ready pixels; a camera pipeline can keep raw linear data linear.
Decode → transform → encode
This is the common shape for file tools:
use Size;
use Image;
use ;
use ;
use ;
let bytes = read?;
let decoded = decode?;
let srgb: = match decoded.image ;
// Bilinear resize is done in linear light.
let linear: = convert_image;
let resized: = resize;
let output: = convert_image;
let out_bytes = encode?;
write?;
The I/O crate does not hide the SrgbGamma step. That is deliberate: decoding surfaces information; your pipeline chooses what to do with it.
Which entry point?
| You know... | Use | Why |
|---|---|---|
| Nothing except "these are image bytes" | load / load_reader |
Detects PNG/JPEG/BMP by magic bytes and returns DecodedImage. |
| The file is PNG | png::decode / png::encode |
Exhaustive PNG pixel enum and PNG metadata. |
| The file is JPEG | jpeg::decode / jpeg::encode |
JPEG-specific metadata and supported JPEG pixel shapes. |
| The file is BMP | bmp::decode / bmp::encode |
BMP-specific representation without pulling in PNG/JPEG dependencies. |
| Only the signature matters | detect_format |
Cheap format detection without codec features. |
Metadata is not policy
Decoded values carry metadata alongside pixel data. fovea-io reports what the file said; it does not silently linearize, premultiply alpha, apply profiles, or drop ancillary data on your behalf.
That policy keeps I/O predictable:
- The decode boundary preserves file facts.
- The transform boundary names semantic changes.
- The encode boundary checks whether the target format can represent the requested pixel type.
Crate ecosystem
| Crate | Purpose |
|---|---|
fovea |
Core image types, pixels, transforms, and analysis. |
fovea-io |
File codecs for typed fovea images. |
fovea-display |
Display strategies and debug windows. |
fovea-examples |
Repo-only end-to-end programs using all crates together. |
License
fovea-io itself is licensed under the MIT License.
When the jpeg feature is enabled, this crate depends on jpeg-encoder, which carries an additional IJG (Independent JPEG Group) license requiring this acknowledgement:
This software is based in part on the work of the Independent JPEG Group.
See THIRD-PARTY-LICENSES.txt for full license texts of dependencies and attribution requirements.