This workspace features a set of small,independent and performant image codecs that can be used for decoding maniuplating and sometimes encoding images in a variety of formats.
The set of codecs aim to have the following features in order of priority
- Performance: Performance should be on par with or better than reference libraries. For example,
zune-jpeg
should easily replacelibjpeg-turbo
without any noticeable speed loss. - Safety: Minimal
unsafe
code, with the sole exception of SIMD intrinsics which currently requireunsafe
. - Robustness: All decoders should be fuzz tested and found bugs fixed promptly.
- Ease of use: Consistent API across decoders and encoders.
- Fast compile times: No dependencies on huge crates. Minimal and relatively well commented code.
-
Single interface:
- One image struct holds all the types, including 8-bit,16-bit animated, non-animated images, this makes your API easier.
-
Fast :
- Fast image decoders and encoders:
zune-*
image decoders are some of the fastest, see benchmarks - Image filters are also optimized for speed
- Benchmarks are prevalent to catch regressions, with crates like zune-imageprocs containing micro-benchmarks for filters
- Highly optimized simd routines, for things that need the extra juice, e.g IDCT in zune-jpeg, filter algorithms in zune-png and alpha pre-multiplication (using portable simd) in zune-imageprocs
- We utilize multiple threads to speed up compute heavy operations
- Fast image decoders and encoders:
-
Extensive
- Support for
u8
,u16
andf32
images. This means we support HDR image processing. This isn't limited to image decoders and encoders but image filters support it to. - Image decoders preserve image depth up until you want to change it, this means hdr is handled as hdr, 16-bit png is handled as 16 bit png.
- Multiple image filters, we have common image manipulation filters like exposure, contrast, HSL, blurring, computer vision filters like sobel, mean filter, bilateral filters
- Multiple color conversion routines which preserve bit depth, one can go from CMYK to HLS as easy
as
image.convert_color
- A lot of testing, lossless decoders have bit-identical tests with other decoders, lossy decoders have their own type, see more on Adding a Test on how we do that
- Support for
-
Easy to use api
- Image decoders implement
decode_headers
which allows one to retrieve image information without decoding the image - All image decoders implement
new
andnew_with_options
, with the former using default options and the latter using custom options allowing you to customize decoding - Image decoders implement common functions like
depth
for image depth,colorspace
for image colorspace,dimensions
for image dimensions - All image operations implement
OperationsTrait
, decodersDecoderTrait
and encodersEncoderTrait
- Image decoders implement
-
Safe
- We (99.9%) won't segfault on you, unless you do something silly.
- Decoders are fuzz tested in CI when a feature is added and also fuzz tested every day to catch bugs.
- Safety is kept to almost zero in most crates, with some having
#![forbid(unsafe)]
most unsafe comes fromSIMD
routines which will reduce when portable-simd becomes mainstream - Image crashes are treated with the seriousness they deserve, i.e we fix as quickly as possible and acknowledge,whether it's a less common decoder or a useful routine.
-
A command line application.
-
Bindings to other languages:
- Python via zune-python
- C-bindings via zune-capi
- JS/TS via zune-wasm
-
(Limited) support for animated images
Image Format | Decoder | Encoder | no_std Support |
---|---|---|---|
jpeg | zune-jpeg | jpeg-encoder | Yes |
png | zune-png | - | Yes |
ppm | zune-ppm | zune-ppm | Yes |
qoi | zune-qoi | zune-qoi | Yes |
farbfeld | zune-farbfeld | zune-farbfeld | Yes |
psd | zune-psd | - | Yes |
jpeg-xl | jxl-oxide | zune-jpegxl | Yes [^1] |
hdr | zune-hdr | zune-hdr | No [^2] |
- [^1] You lose threading capabilities.
- [^2] Lack of existence of
floor
andexp
in thecore
library.
This workspace allows only 1 type of unsafe: platform specific intrinsics (e.g. SIMD), and only where speed really matters.
All other types are explicitly forbidden.
crates
Contain main image code, each crate is prefixed withzune-
. The crates are divided into image formats, likezune-png
deals withpng
decodingzune-imageprocs
deals with image processing routines, etc etctests
: Image testing routines, they mainly read fromtest-images
benchmarks
: Benchmarking routines, they test the library routines with other popular image libraries.fuzz-corpus
: Some interesting image files used for fuzzing.test-images
: Images for testing various aspects of the decoderdocs
: Documentation on various parts of the library
Rust already has a good image library i.e https://github.com/image-rs/image
But I'll let the overall speed of operations (decoding, applying image operations like blurring) speak for itself when compared to other implementations.
Library benchmarks are available online and also reproducible offline
To reproduce benchmarks you can run the following commands
Tested, on Linux, but should work for most operating systems
git clone https://github.com/etemesi254/zune-image
cd ./zune-image
cargo bench --workspace
This will create a criterion directory in target which will contain benchmark results of most image decoding operations.
Most decoders are tested in CI to ensure new changes do not introduce regressions.
Critical decoders are fuzz tested in CI once every day to catch any potential issue/bug.