As commented in issues https://github.com/shssoichiro/oxipng/issues/444 and https://github.com/shssoichiro/oxipng/issues/518, there is some user interest for distributing binaries for each unstable commit, and target ARM64 platforms. Personally, I think both suggestions are useful for the project, as uploading binary artifacts for each commit might help interested users to catch regressions and give feedback earlier, and powerful ARM64 platforms are becoming increasingly popular due to some cloud services (e.g., Amazon EC2, Azure VMs, Oracle Cloud) offering cheaper plans for this hardware, in addition to the well-known push for ARM by Apple with their custom M1 chips. These changes make the CI target ARM64 as a first-class citizen. Because the public GitHub actions runners can only be hosted on x64 for now, I resorted to cross-compilation, [Debian's multiarch](https://elinux.org/images/d/d8/Multiarch_and_Why_You_Should_Care-_Running%2C_Installing_and_Crossbuilding_With_Multiple_Architectures.pdf), and QEMU to build, get ARM64 C library dependencies, and run tests, respectively. When the CI workflow finishes, a release CLI binary artifact is now uploaded, which can be downloaded from the workflow run page on the GitHub web interface. In addition, these changes also introduce some cleanup and miscellaneous improvements and changes to the CI workflow: - Tests are run using [`nextest`](https://nexte.st/) instead of `cargo test`, which substantially speeds up their execution. (On my development workstation, `cargo test --release` takes around 10.67 s, while `cargo nextest run --release` takes around 6.02 s.) - The dependencies on unmaintained `actions-rs` actions were dropped in favor of running Cargo commands directly, or using `giraffate/clippy-action` for pretty inline annotations for Clippy. This gets rid of the deprecation warnings for each workflow run. - Most CI steps are run with a nightly Rust toolchain now, which allows to take advantage of the latest Clippy lints and codegen improvements. In my experience, when not relying on specific nightly features or compiler internals, Rust does a pretty good job at making it possible to rely on a rolling-release compiler for CI, as breakage is extremely rare and thus offset by the improved features. - The MSRV check was moved to a separate job with less steps, so that it takes less of a toll on total workflow run minutes. ## Pending tasks - [x] Generate universal macOS binaries with `lipo` (i.e., containing both `aarch64` and `x64` code) - [x] Tirelessly fix the stupid errors that tend to happen when deploying a new CI workflow for the first time - [x] Think what to do with the `deploy.yml` workflow. Should it fetch artifacts from the CI job instead of building them again? - [x] Maybe bring back 32-bit Windows binaries. Are they actually useful for somebody, or just a way to remember the good old days? --------- Co-authored-by: Josh Holmer <jholmer.in@gmail.com> |
||
|---|---|---|
| .cargo | ||
| .github | ||
| benches | ||
| scripts | ||
| src | ||
| tests | ||
| .editorconfig | ||
| .gitattributes | ||
| .gitignore | ||
| .pre-commit-hooks.yaml | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| Dockerfile | ||
| index.html | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| README.template.md | ||
Oxipng
Overview
Oxipng is a multithreaded lossless PNG compression optimizer. It can be used via a command-line interface or as a library in other Rust programs.
Installing
Oxipng for Windows can be downloaded from the Releases link on the GitHub page.
For MacOS or Linux, it is recommended to install from your distro's package repository, if possible.
Alternatively, oxipng can be installed from Cargo, via the following command:
cargo install oxipng
Oxipng can be built from source using the latest stable or nightly Rust. This is primarily useful for developing on oxipng.
git clone https://github.com/shssoichiro/oxipng.git
cd oxipng
cargo build --release
cp target/release/oxipng /usr/local/bin
The current minimum supported Rust version is 1.65.0.
Oxipng follows Semantic Versioning.
Usage
Oxipng is a command-line utility. Basic usage looks similar to the following:
oxipng -o 4 -i 1 --strip safe *.png
The most commonly used options are as follows:
- Optimization:
-o 1through-o 6, lower is faster, higher is better compression. The default (-o 2) is sufficiently fast on a modern CPU and provides 30-50% compression gains over an unoptimized PNG.-o 4is 6 times slower than-o 2but can provide 5-10% extra compression over-o 2. Using any setting higher than-o 4is unlikely to give any extra compression gains and is not recommended. - Interlacing:
-i 1will enable Adam7 PNG interlacing on any images that are processed.-i 0will remove interlacing from all processed images. Not specifying either will keep the same interlacing state as the input image. Note: Interlacing can add 25-50% to the size of an optimized image. Only use it if you believe the benefits outweigh the costs for your use case. - Strip: Used to remove metadata info from processed images. Used via
--strip [safe,all]. Can save a few kilobytes if you don't need the metadata. "Safe" removes only metadata that will never affect rendering of the image. "All" removes all metadata that is not critical to the image. You can also pass a comma-separated list of specific metadata chunks to remove.-scan be used as a shorthand for--strip safe.
More advanced options can be found by running oxipng -h.
Git integration via Trunk
Trunk is an extendable superlinter which can be used to run oxipng to automatically optimize pngs when committing them into a git repo, or to gate any pngs being added to a git repo on whether they are optimized. The trunk oxipng integration is here.
To enable oxipng via trunk:
# to get the latest version:
trunk check enable oxipng
# to get a specific version:
trunk check enable oxipng@8.0.0
or modify .trunk/trunk.yaml in your repo to contain:
lint:
enabled:
- oxipng@8.0.0
Then just run:
# to optimize a png:
trunk fmt <file>
# to check if a png is already optimized:
trunk check <file>
You can setup trunk to manage your git hooks and automatically optimize any pngs you commit to git, when you git commit. To enable this, run:
trunk actions enable trunk-fmt-pre-commit
Library Usage
Although originally intended to be used as an executable, oxipng can also be used as a library in
other Rust projects. To do so, simply add oxipng as a dependency in your Cargo.toml,
then extern crate oxipng in your project. You should then have access to all of the library
functions documented here. The simplest
method of usage involves creating an
Options struct and
passing it, along with an input filename, into the
optimize function.
It is recommended to disable the "binary" feature when including oxipng as a library. Currently, there is
no simple way to just disable one feature in Cargo, it has to be done by disabling default features
and specifying the desired ones, for example:
oxipng = { version = "8.0", features = ["parallel", "zopfli", "filetime"], default-features = false }
History
Oxipng began as a complete rewrite of the OptiPNG project, which was assumed to be dead as no commit had been made to it since March 2014. (OptiPNG has since released a new version, after Oxipng was first released.) The name has been changed to avoid confusion and potential legal issues.
The core goal of rewriting OptiPNG was to implement multithreading, which would be very difficult to do within the existing C codebase of OptiPNG. This also served as an opportunity to choose a more modern, safer language (Rust).
Contributing
Any contributions are welcome and will be accepted via pull request on GitHub. Bug reports can be filed via GitHub issues. Please include as many details as possible. If you have the capability to submit a fix with the bug report, it is preferred that you do so via pull request, however you do not need to be a Rust developer to contribute. Other contributions (such as improving documentation or translations) are also welcome via GitHub.
License
Oxipng is open-source software, distributed under the MIT license.
Benchmarks
Tested oxipng 5.0.0 (compiled on rustc 1.55.0-nightly (7a16cfcff 2021-07-11)) against OptiPNG version 0.7.7 on AMD Ryzen 7 4800H with Radeon Graphics with 16 logical cores
Benchmark #1: ./target/release/oxipng -P ./tests/files/rgb_16_should_be_grayscale_8.png
Time (mean ± σ): 128.8 ms ± 14.2 ms [User: 296.0 ms, System: 14.3 ms]
Range (min … max): 98.8 ms … 152.3 ms 21 runs
Benchmark #2: optipng -simulate ./tests/files/rgb_16_should_be_grayscale_8.png
Time (mean ± σ): 254.2 ms ± 16.0 ms [User: 252.8 ms, System: 1.2 ms]
Range (min … max): 208.4 ms … 263.8 ms 14 runs
Summary
'./target/release/oxipng -P ./tests/files/rgb_16_should_be_grayscale_8.png' ran
1.97 ± 0.25 times faster than 'optipng -simulate ./tests/files/rgb_16_should_be_grayscale_8.png'
Benchmark #1: ./target/release/oxipng -o4 -P ./tests/files/rgb_16_should_be_grayscale_8.png
Time (mean ± σ): 141.4 ms ± 14.9 ms [User: 611.7 ms, System: 21.1 ms]
Range (min … max): 100.2 ms … 160.4 ms 23 runs
Benchmark #2: optipng -o 4 -simulate ./tests/files/rgb_16_should_be_grayscale_8.png
Time (mean ± σ): 730.0 ms ± 25.9 ms [User: 728.0 ms, System: 1.2 ms]
Range (min … max): 713.3 ms … 768.2 ms 10 runs
Summary
'./target/release/oxipng -o4 -P ./tests/files/rgb_16_should_be_grayscale_8.png' ran
5.16 ± 0.58 times faster than 'optipng -o 4 -simulate ./tests/files/rgb_16_should_be_grayscale_8.png'