Repository navigation
v1.3.0: WebP encoder
Sdcb.SimdCodecs 1.3.0 adds encoding to Sdcb.SimdCodecs.Webp: lossless, lossy (with transparency) and animation. Before this release the package could only decode. The encoders are pure managed, like the decoders.
dotnet add package Sdcb.SimdCodecs.WebpNew: WebP encoding
- Lossless (VP8L):
WebpEncoder.EncodeLosslesshandles alpha and takes an effort from 0 to 9. It uses a cost-based parse, picks its own transforms and predicts in finer blocks. - Lossy (VP8):
WebpEncoder.EncodeLossytakes a quality from 0 to 100 (on about libwebp's size scale) and an effort from 0 to 6.- Transparency goes into an ALPH plane. It is lossless by default;
AlphaQualitybelow 100 keeps fewer alpha levels.
- Transparency goes into an ALPH plane. It is lossless by default;
- Animation:
WebpAnimationEncoderandWebpEncoder.EncodeAnimationwrite lossy frames by default. They can also write lossless frames, or whichever of the two is smaller for each frame.- Given whole canvases, they write only the rectangle that changed. Given ANMF frames, they write them as they are.
- Metadata: every encoder can embed ICC, Exif and XMP. Any of these makes the output the VP8X extended format.
- Each encoder has an array overload and a
Streamoverload.
WebP decoder fixes
- VP8: the above-right pixels of the right-most macroblocks now come from the reconstructed row, padding included. Before this fix, some lossy files with a width that is not a multiple of 16 decoded differently from libwebp.
- Animation: frame pixels with alpha from 1 to 254 now blend over the canvas with the same rounding as libwebp 1.6.0's
anim_dump. Animations with partly transparent pixels now decode byte-exactly.
Performance
Measured against libwebp on a Ryzen 7 5800X, single thread. A negative BD-rate means fewer bytes than libwebp at the same quality.
| Mode | Size | Speed |
|---|---|---|
| Lossless, effort 6 vs libwebp default (14 images) | 1.4% smaller | 1.14× (2.92 vs 2.56 MP/s) |
| Lossless, effort 9 | 1.7% smaller | 0.37× |
Lossy, effort 4 vs -m 4 (12 opaque images) |
BD-rate PSNR-Y −6.2%, SSIM-Y −4.8% | 1.07× at q75 (18.6 vs 17.4 MP/s) |
| Lossy + alpha (3 images) | BD-rate −4.5% on visible-pixel PSNR-RGB; alpha byte-identical | 1.04× at q75 (0.96× the time) |
Animation, lossless vs img2webp -lossless (5 sequences) |
0.931× the bytes | |
Animation, lossy vs img2webp -lossy |
BD-rate −10.1% |
Every lossy image beats libwebp on both PSNR and SSIM. The full results are in benchmarks/Sdcb.SimdCodecs.Webp.Benchmarks/results/.
Verification
- libwebp's
dwebpandwebpinfodecode and check everything the encoders write. - Every SIMD encoder kernel has a scalar twin, and tests prove they give identical output.
- NativeAOT output matches JIT.
Packaging
- nuget.org now gets its own copy of the root README. The copy has absolute links and no raw HTML, so the package page renders correctly.
Known gaps
- The lossy encoder has no trellis quantisation yet.
cwebp -z 9is still 1.1% smaller than our effort 9, although it is about 7× slower.- Lossless animation output is 3% larger than img2webp's on the sprite sequence and 9% larger on alpha-sprite.
- Lossy + alpha: the sticker image is +0.8% BD-rate (its ALPH plane is about 3% larger than libwebp's) and about 10% slower.
Details are in docs/known-gaps.md.