v0.14.0
- add SVG input support rendered through
resvg(static SVG and gzipped SVGZ), usable with every output format - replace the
libavifAVIF decoder with adav1d-based one (dav1d+avif-parse+yuvutils-rs); decoding now links a system-installeddav1d(>= 1.3.0) through pkg-config instead of building libaom from source with cmake - report the side a failure happened on and give every outcome its own exit code:
0success,2usage,3input,4output,5partial, with1left unused because the runtime reports it for a signal or abort, so wrappers keying off the previous0/1must be updated - raise the minimum supported Rust version to 1.95.0 (
rust-version), required by thesysinfodependency behind the newlimitsfeature
- add
-p/--preserve-timestampsto stamp an output with its input's last modification time instead of the time it was written; the temporary file is stamped before the publishing rename, so the output is never observable with the wrong time, and access times and creation times are left alone because birth time cannot be set at all on Linux - resize SVG inputs through the existing
--resizeoption by rendering the SVG vectorly withresvgdirectly at the final target size, so upscaling keeps the vector quality of the source - load system fonts for SVG text and substitute missing fonts with a warning: the serif default and the CJK fallback are resolved once at load time from platform-appropriate seeds (Times New Roman/Liberation Serif/DejaVu Serif, etc., YaHei/PingFang/Noto CJK, etc.), the
serifgeneric alias is pointed at a family that actually exists, and a text span is never dropped for the lack of a font — as a last resort it renders with whatever face the system has - derive the image size ceiling at runtime behind a new
limitsfeature instead of hard-coding it: the ceiling is the intersection of the dimensions a format itself declares as a hard limit (WebP's 16383, AVIF's 65536, and for JPEG and PNG the limit their decoder actually enforces), the memory available to the process divided by--threadsand the peak number of live pixel buffers, and the free space on the destination volume, and it now bounds every decode and encode path - reject oversized inputs from their file header before decoding, reading a bounded 64 KiB prefix: JPEG, PNG, AVIF, TIFF and WebP headers are probed for the dimensions they declare, so an image is refused before the allocation it would have caused
- classify every pipeline failure by the side it happened on, the format it concerns and a stable
kind()slug, with an actionablehintline, in place of the flat upstream enum that named neither direction nor format - add a hidden
--print-limitsdiagnostic that reports the probed budget, the per-format caps, the per-stage cost multipliers and both the pixel and byte ceilings together with the source that produced each, then exits without touching a file
- show warning-level logs by default without
RUST_LOG; drop the spurious premultiply warning that fired on every run without--premultiplyand demote the routine missing-ICC-profile notice to debug level - reject SVG render targets whose three live pixel buffers would exceed the decode budget instead of attempting multi-gigabyte allocations that could terminate the process through out-of-memory; the budget is now derived at runtime like every other ceiling, and the previous 512 MiB constant (currently 44,739,242 pixels) is kept as the fallback for standalone callers
- replace the panics and unchecked arithmetic that would abort the whole process under the release profile's
panic = "abort": guard the AVIF decoder against allocation overflow and out-of-bounds plane access, validate the pixel buffer before handing it toravif, clamp the number of used bits, and reject a buffer whose length disagrees with its dimensions instead of panicking in a worker thread - surface a failing
WebPConfig::new()as an encoder-construction error instead of unwrapping it, and validate the MozJPEG quality at the library boundary, since the public options type accepts anyf32while the encoder asserts on the rest - reject EXIF APP1 payloads above 65533 bytes, where the segment length used to overflow the
u16and wrap into a malformed JPEG - guard the SVG render buffer allocation against
usizeoverflow on 32-bit targets and with extremely large render targets - replace the premultiply
assert!and fiveindices_of().unwrap()call sites with a warning and a defensive fallback, so a user-facing argument-ordering conflict can no longer terminate the run - keep JSON metadata finite when the aspect ratio of a zero-height image is computed, accept a logger that is already installed instead of panicking, and log the reason when the current directory cannot be read
- preserve a source JPEG's EXIF by copying its APP1 segment verbatim, instead of decoding and re-encoding it through
little_exif, which rejects valid files that storeExifVersionas a STRING rather than UNDEF - carry the source JPEG's JFIF pixel density into the MozJPEG output, instead of leaving the default 1x1 aspect-ratio header that tools report as a resolution of 1 with no unit
- encode
--colorspace rgbwithJCS_RGBrather thanJCS_EXT_RGB - cap the WebP and SVG decoder reads at 256 MiB and reject TIFF images above 100 MP before allocating, since a decoder used as a library was otherwise unbounded
- reject dimensions that exceed the
u32limit of the OxiPNG and WebP FFI entry points instead of silently truncating them on 64-bit hosts - derive the JPEG and PNG ceilings from the limit their decoder enforces rather than the larger encoder-side constant, so the pre-check no longer admits a file the decoder then refuses with an unrelated message
- resolve the destination volume's free space against the nearest existing ancestor of the output path: canonicalizing a file that does not exist yet failed outright, and on Windows the verbatim prefix never matched the mount points
sysinforeports, leaving the disk check dead on that platform - divide the memory budget by
--threadsrather than anRIMAGE_THREADSvariable that nothing sets, which left the divisor at 1 while the whole worker pool was in flight - report a memory-derived byte ceiling as a memory limit rather than a disk limit when free space happens to look tighter, and name the source that produced each ceiling
- decode only the first frame of animated WebP and APNG instead of allocating a full-size buffer per frame; the still entry point is now tried first, which also stops forcing an alpha channel on files that do not have one, so such a file decodes as
RGB - give encode failures an output-side hint instead of input-side advice about a truncated file, and stop printing the path twice in failure log lines
- reject degenerate
--resizevalues at parse time (the@and%forms accepted@0,@-2,@nan,@inf,0%and-5%, and theWxHform accepted zero dimensions) and name the offending dimension in the malformedWxHmessage - stop stripping surrounding quotes and trailing backslashes from every
file.listline, which rewrote legitimate Unix file names, remove a warning that could never fire on valid UTF-8, and bound the list at 64 MiB - reject output names Windows would silently rewrite — trailing dots and spaces, and reserved device names such as
CON .png— and escalate the silent root-escape clamp to a warning, since it rewrites where output lands - compile and lint cleanly with decoders and encoders trimmed: gate the
AvailableEncoders::encodevariants, theFiledeclaration and the seek imports on the features that use them, and keep the no-codec andlimits-disabled builds warning-free - generate the CLI help epilogue from the enabled features so a trimmed build stops advertising subcommands that do not exist
- parse
--threadsasu16so hosts with more than 255 cores can actually use them - collapse the repeated metadata segment checks into match guards, clearing the remaining
cargo clippy --all-targets -- -D warningswarnings
- cover the JPEG metadata scanner with tests built from synthetic segments, including the guard that keeps the first APP0/APP1 copy and the XMP-in-APP1 case that stops a bare APP1 marker from claiming the EXIF slot
- replace the hand-written Newton integer square root with
u64::isqrt - document why the ICC profile lock spans the transform, why the SVG intrinsic size is stored unrounded, and what
--subsamplevalues 3 and 4 do, and expand the subsampling introduction in the README and the MozJPEG CLI help - use
CARGO_MANIFEST_DIRin the test fixtures instead of paths that only exist on one development machine - drop the unneeded
unsafefrom the AVIFftyptest fixture, and make the input-side classification infallible so its callers no longer carry a dead fallback
- add
sysinfobehind the newlimitsfeature, the only implementation of the cgroup-aware memory probe and the mount-point lookup the size ceilings depend on - drop
thiserror, whichsrc/error.rsnever referenced - replace the unmaintained
pretty_env_loggerwithenv_logger, with the timestamp disabled to keep the compact single-line style
- auto-detect the MSVC and Windows SDK versions in
ci/msvc-env.shinstead of hard-coding paths that only exist on one machine, withRIMAGE_MSVC_ROOTandRIMAGE_SDK_VERoverrides for non-standard layouts - support ARM64 hosts in the same script by parameterising the toolchain architecture, falling back to the x64-hosted cross tools that Windows on ARM runs emulated
- pin the dav1d clone in the cross image and
build-dav1d.shto a verified commit, since upstream can re-point a tag, and add a usage check while dropping the GNU-onlyrealpathdependency - declare the build script's actual inputs so the resource compilation no longer re-runs whenever any file in the package changes, and tolerate an unset
CARGO_CFG_TARGET_OS
v0.13.0
- append the output suffix directly WITHOUT an automatic
@separator (-s 2xnow yieldsfile2x.jpeg) and update the CLI help accordingly - accept a UTF-8
file.listas an input file list, with one file path per line (blank lines are skipped, surrounding whitespace is ignored, and relative paths are resolved against the current working directory); when afile.listis provided, all other input file arguments are ignored
- expand glob patterns in input paths on all platforms (previously Windows-only), preferring existing literal paths
- add
100land100sresize values that anchor on the longest or shortest side of each image - add
--reduce-onlyand--enlarge-onlyas aliases for--no-upscaleand--no-downscale
- reject malformed width and height
--resizevalues such as1.5worabc100winstead of silently extracting the first run of digits - map each chained
--resizevalue from the size the previous resize left behind, so a chain composes instead of every value mapping the original dimensions - fix a deadlock with a single-threaded pool by acquiring the concurrency permit inside the worker, and return an error instead of panicking when the thread pool cannot be created
- write outputs atomically through unique temporary files and publish them by rename, with a recoverable swap when replacing existing files on Windows
- detect collisions before any processing: duplicate output mappings, outputs overwriting another input, metadata path conflicts, and output paths identical to
--backuppaths (path names are treated as case-insensitive on every platform as a fail-safe default, covering case-insensitive Linux mounts, and aliases are resolved through canonicalization for existing paths) - never overwrite or delete an existing
--backupfile; create backups via hard link with a no-clobber copy fallback and remove the original input only after a successful publish - normalize input paths without canonicalization so symlinked directory layouts are preserved, and reject output parents that resolve outside the output root
- return non-zero exit codes when no inputs are found, an encoder fails, a collision is detected, files fail, or metadata cannot be written
- fix WebP animation encoding by warning and encoding only the first frame; compute per-frame durations from timestamps in the decoder
- guard against empty frame lists in the AVIF, MozJPEG, OxiPNG and WebP encoders instead of panicking
- restrict MozJPEG to 8-bit output and fix OxiPNG 16-bit endianness for non-RGB colorspaces
- apply ICC profiles to 16-bit frames without panicking and preserve frame timing metadata
- prevent integer overflow panics in quantization and resize, and surface resize worker panics as errors
- validate suffixes and output file names (including Windows reserved names) up front, reject recursive inputs without a common root and duplicate output mappings with clear errors
- write JSON metadata atomically and use saturating arithmetic for size and space-saved statistics
- add end-to-end regression tests covering single-thread processing, recursive output layouts, backup collisions, existing-backup protection and non-zero exit codes
- regenerate the AVIF test fixture
- update install steps of dependencies for building on Windows
- bump
zune-imageprocsto 0.5.1 (stable) andregexto 1.13 - bump
jxl-gridto 0.6.2,jxl-oxideto 0.12.6,logto 0.4.33,indicatifto 0.18.6,anyhowto 1.0.103 andserde_jsonto 1.0.150 - replace
winreswithwinresource0.1.31 and makegloba general dependency - pin
ravif0.13.0 without default features foraarch64-unknown-linux-musl
- rewrite the CI workflow: build and test on
mainanddev, Ubuntu 24.04 / Windows 2025 / macOS 15 runners, cross builds foraarch64-unknown-linux-muslwith a pinned image, qemu runner for aarch64 Linux,actions/checkout@v7, concurrency grouping and read-only permissions - use yasm for the libaom build, fix artifact download errors and silence Homebrew tap warnings on macOS
- remove the
config.tomlpre-release override and set the Windows pre-release version inbuild.rs
v0.12.4
0.12.4 (2026-05-23)
- Change default
--threadoption to1to prevent memory allocation failed error in default settings.
- robust path normalization and bounded concurrency to prevent OOM on large images (4b030da)
- add
FinishGuardto manage progress bar updates on drop (c5a3bf0)
- critical bug fixes across codecs and operations: replace
unreachable!()with proper errors, fix crashes on non-existent paths and missing file stems, fix animated image channel count, fix webp loop_count, fix UNC path corruption on Windows, fix race condition in little_exif error suppression (fccd4e2) - prevent DCT overflow with proportional smoothing for high-quality custom quantization tables (e653b40)
- correct channel length calculation in quantization process (f6eb26d)
- retain permit in concurrent image processing for proper resource management (fb76593)
- use
logmodule to submit log infos (729c65d) - refactor path normalization tests for platform compatibility (77b5698)
v0.12.3
0.12.3 (2026-01-29)
- fix icc test error (e82055d)
- simplify image flattening in quantization operation (0d32374)
- update unreachable pattern to use std::prelude::v1::None (b0d9a41)
v0.12.2 (2026-01-20)
- disable wasm32 build due to unresolved issues (41c3b1e)
- suffix's docs conflict with code (c1c0a44)
- fix DCT overflow manually set smooth arg to fix that (75f2cf7)
- add icc to the build-binary feature to fix compilation errors (c28be02)
- suppress
little_exifimages without EXIF (58495bc) - re-fix deprecated rename ravif::ColorSpace to ColorModel (a1e482f)
- cli: 🐛 fixed a bug when little exif panics on png images (159bbab)
v0.12.2
v0.12.2 (2026-01-20)
- disable wasm32 build due to unresolved issues (41c3b1e)
- suffix's docs conflict with code (c1c0a44)
- fix DCT overflow manually set smooth arg to fix that (75f2cf7)
- add icc to the build-binary feature to fix compilation errors (c28be02)
- suppress
little_exifimages without EXIF (58495bc) - re-fix deprecated rename ravif::ColorSpace to ColorModel (a1e482f)
- cli: 🐛 fixed a bug when little exif panics on png images (159bbab)
v0.11.0
- Complete rewrite of the library — now built to work alongside
zune-image. - CLI interface fully redesigned for more flexibility and cleaner structure.
Massive speedup: up to 149x faster in parallel processing compared to v0.10.3.
Performance benchmarks indicate:
- ~14x faster than
rimage-0.10.3on single image operations. - ~15x faster than
squoosh-cli. - ~149x faster on bulk image processing.
-
cli: New progress bar and updated display styles.
-
cli: Added
--quietand--no-progressflags. -
cli: Reshape resize parameter format: now supports
w<value>andh<value>. -
cli: Added CLI warnings for invalid input files.
-
cli: Improved argument parsing and error messages.
-
cli: Alpha premultiply preprocessor added.
-
cli: Support for apply icc profile operation.
-
cli: Restructure of base CLI options, codecs, and preprocessors.
-
codecs: Added TIFF support.
-
codecs: Added EXIF write support for JPEG and PNG.
-
operations: Added new fast resize operation with threading support.
-
operations: Added ICC profile application with multithreaded support.
- Ensure all input images are converted to RGBA8 format.
- Fix file name parsing with dots.
- Fix null error on AVIF decoding.
- Return error when input width or height is 0.
- Prevent panic when no output is present by safely calculating max length.
- Fix float32 image handling in CLI.
- Improve resize value parsing and reduce edge case errors for width/height.
- Fix encoder function logic.
- Update AVIF, MozJPEG, Oxipng, and WebP codecs to new APIs.
- Fix Clippy issues and build warnings.
- Fix trailing slash issues on Windows.
- Correct feature compilation and binary packaging.
v0.11.0-next.3
- cli: 🚑 convert all input images to rgba8 (c980e9a)
- cli: 🐛 fixed incorect handling of file names with dots (1f3275c)
- cli: 🐛 fixed null error on avif decoding (59b6759)
- error if input width or height is 0 (b626fdc)
- cli: 🐛 ensure max length calculation returns 0 instead of panicking when no outputs are present (3d0a3a3)
- cli: 🐛 fixed handling of float32 images (66c3648)
- cli: 🐛 improved resize value parsing by trimming input and refining error handling for invalid formats (2a43c26)
- cli: 🐛 updated parsing logic for width and height to reduce number of edge cases (9bd3ea2)
- operations: 🐛 updated apply icc profile operation to work in threads (b5dee09)
- cli: ✨ update resize value format for width and height to use 'w' and 'h' suffixes instead of 'x_' and '_x' (693ea46)