Skip to content
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

[FR] Optimize png with oxipng #95

Open
murlakatamenka opened this issue Mar 1, 2024 · 3 comments
Open

[FR] Optimize png with oxipng #95

murlakatamenka opened this issue Mar 1, 2024 · 3 comments

Comments

@murlakatamenka
Copy link

png by default is a reasonable choice. However, it's surely doesn't offer the best compression as of today. For instance, lossless webp consistently beats png in terms of compression ratio.

I suggest adding a separate flag to optimize png output via awesome oxipng crate, something like:

wayshot --extension png --optimize -f /tmp/test.png

It is easy via oxipng::optimize_from_memory:

let opts = oxipng::Options::default(); // = preset 2
// let opts = oxipng::Options::from_preset(<u8 from 0 to 6>);
let optimized_png_buf = oxipng::optimize_from_memory(&png_buf, &opts)?;

Here is a little script to evaluate the savings:

mkdir /tmp/wayshot && cd /tmp/wayshot

wayshot -f wayshot.png

for i in {0..6}; do
  time oxipng --opt "$i" --pretend wayshot.png
done

Results for a sample image (2560x1080, 414 KiB) on Ryzen 5600:

oxipng 9.0
293709 bytes (30.67% smaller)
oxipng --opt "$i" --pretend wayshot.png  0.14s user 0.00s system 99% cpu 0.143 total
---
279314 bytes (34.07% smaller)
oxipng --opt "$i" --pretend wayshot.png  0.31s user 0.01s system 99% cpu 0.322 total
---
274489 bytes (35.21% smaller)
oxipng --opt "$i" --pretend wayshot.png  0.63s user 0.02s system 129% cpu 0.500 total
---
265868 bytes (37.24% smaller)
oxipng --opt "$i" --pretend wayshot.png  2.23s user 0.02s system 264% cpu 0.852 total
---
265107 bytes (37.42% smaller)
oxipng --opt "$i" --pretend wayshot.png  3.77s user 0.03s system 303% cpu 1.252 total
---
265107 bytes (37.42% smaller)
oxipng --opt "$i" --pretend wayshot.png  8.67s user 0.04s system 580% cpu 1.498 total
---
265107 bytes (37.42% smaller)
oxipng --opt "$i" --pretend wayshot.png  12.80s user 0.05s system 781% cpu 1.643 total

Pretty good imo, and using oxipng from Rust itself will be even faster (no CLI args parsing, no buffer copy).

Reasonable tradeoff of little extra CPU for decent savings in file size even with fast-ish presets 0-2.


Surely I can do the plumbing myself, wayshot --stdout | <best-image-encoder> - <name.ext>, but I think wayshot and its users will benefit from implementing this feature.

@Shinyzenith
Copy link
Member

I actually wouldn't mind making this a default. This sounds like a good FR. Is there any way we can natively implement this optimization set using just the image crate? I'd prefer not expanding the dependency graph unless needed.

@murlakatamenka
Copy link
Author

So far I don't think you can avoid pulling oxipng as a dependency.

Seeing your positive reaction I'll work on PR, we'll see how it goes there.

@Shinyzenith
Copy link
Member

That sounds great, I wouldn't mind a PR for further discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants