Repository navigation
v0.3.2
⚠️ YANKED — this version has been pulled from crates.io. It contains a use-after-free inStreamingDecoder::update(fixed in 0.3.4) plus other soundness issues fixed across the 0.2.x / 0.3.x series. Use 0.3.4 or later — or, recommended for new projects, switch tozenwebp, which is#![forbid(unsafe_code)]and has no FFI exposure.
0.3.2 — full zencodec trait integration, trivial swap between webpx and zenwebp.
Recommendation: Use zenwebp instead
For new projects, zenwebp is the recommended choice — equally or more capable than webpx (full feature parity with libwebp, native wasm32-unknown-unknown support that webpx cannot offer, performance and compression within noise on average), and built with #![forbid(unsafe_code)] so the whole class of FFI / memory-safety bug is structurally impossible. libwebp has a documented high-severity CVE history (CVE-2023-4863 was an actively-exploited 0-click heap overflow patched out of band in every major browser), and every libwebp wrapper that has been audited — webpx included — has shipped soundness bugs.
Trivial swap with zenwebp
webpx and zenwebp now expose identical pub mod zencodec surfaces — the same wrapper-type names, the same constructors, implementing the same zencodec traits. Switching backends is a one-line change:
// One line changes:
use webpx::zencodec::WebpEncoderConfig; // libwebp FFI backend
// use zenwebp::zencodec::WebpEncoderConfig; // pure-Rust backend
// Everything below is identical:
use zencodec::encode::{EncoderConfig, EncodeJob, Encoder};
let cfg = WebpEncoderConfig::lossy().with_generic_quality(85.0);
let webp = cfg.job().encoder()?.encode(pixel_slice)?.into_vec();See examples/zencodec_swap.rs for the swap pattern end-to-end.
Added
zencodecCargo feature with a newpub mod zencodecexposingWebpEncoderConfig,WebpEncodeJob,WebpEncoder,WebpAnimationFrameEncoder,WebpDecoderConfig,WebpDecodeJob,WebpDecoder,WebpStreamingDecoder,WebpAnimationFrameDecoder. Type names and method signatures mirrorzenwebp::zencodecexactly.- All four executor traits wired:
zencodec::encode::EncoderonWebpEncoder— RGBA / BGRA / RGB input, ICC / EXIF / XMP metadata, generic-quality / generic-effort calibration,Limitspropagation.zencodec::encode::AnimationFrameEncoderonWebpAnimationFrameEncoder— accepts per-framePixelSlices, converts cumulative-timestamp on the trait side to webpx's timestamp-per-frame model, embeds metadata after assembly.zencodec::decode::DecodeonWebpDecoder— full single-image decode with caller-preferred descriptor selection.zencodec::decode::AnimationFrameDecoderonWebpAnimationFrameDecoder— frame-by-frame and sink-based rendering, withframe_count/loop_countaccessors.zencodec::decode::StreamingDecodeonWebpStreamingDecoder— buffered approach (full input → single batch). A row-batch implementation against libwebp's incremental decoder is a future iteration.
From<webpx::Limits> for zencodec::ResourceLimitsand reverse. Field-for-field mirror minus webpx'smax_metadata_bytes(no zencodec counterpart, drops on round-trip).
Testing
- 7 integration tests in
tests/zencodec_integration.rs(encoder/decoder roundtrip, lossless preservation, animation roundtrip through trait surface, streaming decode through trait surface, limits propagation, capabilities table, Limits round-trip). examples/zencodec_swap.rsdemonstrates the swap pattern end-to-end.
Pinned to zencodec = 0.1.13 (matching zenwebp) so trait impls land on the same semver line. cargo semver-checks: no breaking changes.
Full changelog: https://github.com/imazen/webpx/blob/main/CHANGELOG.md