-
Notifications
You must be signed in to change notification settings - Fork 673
Replace in-tree JPEG encoder with jpeg-encoder crate #2636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Note that while jpeg-encoder reports IJG license due to SIMD code ported from libjpeg-turbo, it's actually ZLIB licensed according to https://github.com/libjpeg-turbo/libjpeg-turbo/blob/main/LICENSE.md Both licenses are permissive so it shouldn't be a problem regardless |
|
Now that #2624 is merged I've incorporated its changes into this PR. |
…cy. It is a highly permissive license comparable to MIT.
This PR replaces the in-tree JPEG encoder with the jpeg-encoder crate. Closes #1885 and #2500.
Background
jpeg-encoder is a fork of our in-tree JPEG encoder with multiple enhancements (optimized huffman tables, more subsampling options, AVX optimizations). It is already used in production by Glycin (GNOME) instead of our built-in encoder.
Correctness
This encoder used by Glycin so it is pretty well tested. I've added tests for roundtripping Exif and ICC.
Performance
The end-to-end time for converting from PNG to JPEG with
wondermagickgoes down 2x, so the speedup for JPEG encoding alone has to be more than 2x. On x86 with AVX2 anyway; ARM doesn't gain as much because jpeg-encoder doesn't have a NEON implementation.Safety
Thanks to Rust 1.86 making most SIMD intrinsics safe, I've removed the vast majority of unsafe code in vstroebel/jpeg-encoder#17 and vstroebel/jpeg-encoder#18. The remaining small amount of
unsafeis trivial.New functionality
This PR also exposes functions to control chroma subsampling factor. Our old encoder only supported 4:2:2, while jpeg-encoder supports 4:4:4, 4:2:2, 4:2:0, and a bunch of more obscure configurations. This should improve compression ratio.
This PR also lets the user opt into optimizing the Huffman tables of the generated JPEG file, further reducing file size.
Breaking changes
A casualty of this migration is a JPEG-exclusive option to generate an image on the fly via a
GenericImageView, but with the planned changes to image views this would have to be removed anyway.pub fn encode()is also removed because its signature would have to change and there is no reason to keep it around when it just duplicateswrite_image()exactly.Future work
TODO: handle
PixelDensityUnit::PixelAspectRatiovariant: vstroebel/jpeg-encoder#21jpeg-encoder supports more in-depth customization of the encoding process such as encoding progressive JPEGs, restart markets, etc. Exposing that functionality is not part of this PR.