No description
Find a file
dependabot[bot] fb9be2f5d2
chore(deps): bump the rust-dependencies group across 1 directory with 4 updates (#738)
Bumps the rust-dependencies group with 4 updates in the / directory:
[zopfli](https://github.com/zopfli-rs/zopfli),
[indexmap](https://github.com/indexmap-rs/indexmap),
[libdeflater](https://github.com/libdeflater/libdeflater) and
[clap](https://github.com/clap-rs/clap).

Updates `zopfli` from 0.8.2 to 0.8.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/zopfli-rs/zopfli/releases">zopfli's
releases</a>.</em></p>
<blockquote>
<h2>v0.8.3</h2>
<h2>What's Changed</h2>
<ul>
<li>Add DeflateEncoder::get_ref/get_mut by <a
href="https://github.com/roblabla"><code>@​roblabla</code></a> in <a
href="https://redirect.github.com/zopfli-rs/zopfli/pull/69">zopfli-rs/zopfli#69</a>.</li>
<li>Updated dependencies.</li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/roblabla"><code>@​roblabla</code></a>
made their first contribution in <a
href="https://redirect.github.com/zopfli-rs/zopfli/pull/69">zopfli-rs/zopfli#69</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/zopfli-rs/zopfli/compare/v0.8.2...v0.8.3">https://github.com/zopfli-rs/zopfli/compare/v0.8.2...v0.8.3</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="91a34e5d2c"><code>91a34e5</code></a>
Bump Zopfli version to 0.8.3 🎉</li>
<li><a
href="684d9da6bd"><code>684d9da</code></a>
docs: better describe what the nightly feature does</li>
<li><a
href="5b539d0df1"><code>5b539d0</code></a>
chore: update dependencies</li>
<li><a
href="8106f7e415"><code>8106f7e</code></a>
Add DeflateEncoder::get_ref/get_mut (<a
href="https://redirect.github.com/zopfli-rs/zopfli/issues/69">#69</a>)</li>
<li><a
href="c6c7a42fc3"><code>c6c7a42</code></a>
chore(deps): update actions/checkout action to v5 (<a
href="https://redirect.github.com/zopfli-rs/zopfli/issues/68">#68</a>)</li>
<li><a
href="0b5a4c92de"><code>0b5a4c9</code></a>
chore: remove dependency on removed nightly feature</li>
<li><a
href="aacd1aabf8"><code>aacd1aa</code></a>
chore: fix new Clippy lint</li>
<li><a
href="1652084abb"><code>1652084</code></a>
chore: update dependencies</li>
<li><a
href="b8d149ab75"><code>b8d149a</code></a>
ci: drop usage of <code>cargo nono</code></li>
<li><a
href="812da6d545"><code>812da6d</code></a>
chore(deps): update rust crate proptest-derive to 0.6.0 (<a
href="https://redirect.github.com/zopfli-rs/zopfli/issues/66">#66</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/zopfli-rs/zopfli/compare/v0.8.2...v0.8.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `indexmap` from 2.11.4 to 2.12.0
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md">indexmap's
changelog</a>.</em></p>
<blockquote>
<h2>2.12.0 (2025-10-17)</h2>
<ul>
<li><strong>MSRV</strong>: Rust 1.82.0 or later is now required.</li>
<li>Updated the <code>hashbrown</code> dependency to 0.16 alone.</li>
<li>Error types now implement <code>core::error::Error</code>.</li>
<li>Added <code>pop_if</code> methods to <code>IndexMap</code> and
<code>IndexSet</code>, similar to the
method for <code>Vec</code> added in Rust 1.86.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="0e68f8a360"><code>0e68f8a</code></a>
Merge pull request <a
href="https://redirect.github.com/indexmap-rs/indexmap/issues/422">#422</a>
from cuviper/msrv-1.82</li>
<li><a
href="61c9c94672"><code>61c9c94</code></a>
ci: only run full miri in the merge queue</li>
<li><a
href="db43f1945a"><code>db43f19</code></a>
Release 2.12.0</li>
<li><a
href="b46a32a585"><code>b46a32a</code></a>
Move more to the lints table</li>
<li><a
href="4849b1679f"><code>4849b16</code></a>
Make use of RFC2145 type privacy for sealed traits</li>
<li><a
href="cfff4b7d03"><code>cfff4b7</code></a>
Use bounds in associated type position</li>
<li><a
href="c7178d73c4"><code>c7178d7</code></a>
Use <code>core::error::Error</code></li>
<li><a
href="76b459b82c"><code>76b459b</code></a>
Use more precise capturing for some <code>impl Trait</code></li>
<li><a
href="b3d9cc355e"><code>b3d9cc3</code></a>
Use the primitive slice's <code>is_sorted</code> methods</li>
<li><a
href="09db3cce19"><code>09db3cc</code></a>
Use inherent <code>usize::div_ceil</code></li>
<li>Additional commits viewable in <a
href="https://github.com/indexmap-rs/indexmap/compare/2.11.4...2.12.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `libdeflater` from 1.24.0 to 1.25.0
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/libdeflater/libdeflater/blob/master/CHANGELOG.md">libdeflater's
changelog</a>.</em></p>
<blockquote>
<h2>[1.25.0]</h2>
<ul>
<li>Updated libdeflate to v1.25 (<a
href="https://redirect.github.com/libdeflater/libdeflater/issues/50">#50</a>,
thanks <a
href="https://github.com/musicinmybrain"><code>@​musicinmybrain</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="2acaaa9afa"><code>2acaaa9</code></a>
Link v1.25.0 to <a
href="https://redirect.github.com/libdeflater/libdeflater/issues/50">#50</a>,
credit <a
href="https://github.com/musicinmybrain"><code>@​musicinmybrain</code></a></li>
<li><a
href="429baa4557"><code>429baa4</code></a>
Merge pull request <a
href="https://redirect.github.com/libdeflater/libdeflater/issues/50">#50</a>
from musicinmybrain/v1.25.0</li>
<li><a
href="96156b7cd4"><code>96156b7</code></a>
Fix unnecessary parentheses that produced a warning</li>
<li><a
href="36e84d153a"><code>36e84d1</code></a>
Update libdeflate to v1.25</li>
<li><a
href="0dccb7831c"><code>0dccb78</code></a>
Replace mentions of adamkewley/lideflater with libdeflater/libdeflater
(<a
href="https://redirect.github.com/libdeflater/libdeflater/issues/48">#48</a>)</li>
<li>See full diff in <a
href="https://github.com/libdeflater/libdeflater/compare/1.24.0...1.25.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `clap` from 4.5.48 to 4.5.51
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/clap-rs/clap/releases">clap's
releases</a>.</em></p>
<blockquote>
<h2>v4.5.51</h2>
<h2>[4.5.51] - 2025-10-29</h2>
<h3>Fixes</h3>
<ul>
<li><em>(help)</em> Correctly calculate padding for short flags that
take a value</li>
<li><em>(help)</em> Don't panic on short flags using
<code>ArgAction::Count</code></li>
</ul>
<h2>v4.5.50</h2>
<h2>[4.5.50] - 2025-10-20</h2>
<h3>Features</h3>
<ul>
<li>Accept <code>Cow</code> where <code>String</code> and
<code>&amp;str</code> are accepted</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/clap-rs/clap/blob/master/CHANGELOG.md">clap's
changelog</a>.</em></p>
<blockquote>
<h2>[4.5.51] - 2025-10-29</h2>
<h3>Fixes</h3>
<ul>
<li><em>(help)</em> Correctly calculate padding for short flags that
take a value</li>
<li><em>(help)</em> Don't panic on short flags using
<code>ArgAction::Count</code></li>
</ul>
<h2>[4.5.50] - 2025-10-20</h2>
<h3>Features</h3>
<ul>
<li>Accept <code>Cow</code> where <code>String</code> and
<code>&amp;str</code> are accepted</li>
</ul>
<h2>[4.5.49] - 2025-10-13</h2>
<h3>Fixes</h3>
<ul>
<li><em>(help)</em> Correctly wrap when ANSI escape codes are
present</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b49dae25ec"><code>b49dae2</code></a>
chore: Release</li>
<li><a
href="d37b0b57ab"><code>d37b0b5</code></a>
docs: Update changelog</li>
<li><a
href="3398b6ab10"><code>3398b6a</code></a>
Merge pull request <a
href="https://redirect.github.com/clap-rs/clap/issues/6009">#6009</a>
from gtema/complete_try_generate</li>
<li><a
href="21fc9e46d4"><code>21fc9e4</code></a>
feat(clap-complete): Introduce fallible generator</li>
<li><a
href="bd01bdc0ff"><code>bd01bdc</code></a>
Merge pull request <a
href="https://redirect.github.com/clap-rs/clap/issues/6012">#6012</a>
from epage/sub</li>
<li><a
href="ed0c63deba"><code>ed0c63d</code></a>
docs(derive): Specify arg_required_else_help is set for users</li>
<li><a
href="e2188d9af3"><code>e2188d9</code></a>
chore(deps): Update Rust Stable to v1.87 (<a
href="https://redirect.github.com/clap-rs/clap/issues/6004">#6004</a>)</li>
<li><a
href="e01f2b7640"><code>e01f2b7</code></a>
docs: Cleanup unused links</li>
<li><a
href="6b12a81baf"><code>6b12a81</code></a>
chore: Release</li>
<li><a
href="8dd92a792d"><code>8dd92a7</code></a>
docs: Update changelog</li>
<li>Additional commits viewable in <a
href="https://github.com/clap-rs/clap/compare/clap_complete-v4.5.48...clap_complete-v4.5.51">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-03 18:05:10 +01:00
.cargo Update runners, rust, and dependencies (#724) 2025-08-25 14:49:59 +02:00
.github chore(deps): bump github/codeql-action from 3 to 4 (#735) 2025-10-23 18:40:01 +02:00
benches Allow brute filter configuration (#720) 2025-09-25 23:20:29 +02:00
scripts Move manpages generation to an xtask (#645) 2024-11-24 13:57:29 +01:00
src Small tweaks (#734) 2025-10-04 11:46:47 +02:00
tests Small tweaks (#734) 2025-10-04 11:46:47 +02:00
xtask Add max_uncompressed_size (#732) 2025-09-25 22:46:35 +02:00
.dockerignore Improved Docker image + publish on ghcr.io (#642) 2024-11-24 14:08:11 +01:00
.editorconfig Update .editorconfig 2023-04-22 23:37:16 -04:00
.gitattributes Enforce LF 2023-04-27 19:44:05 -04:00
.gitignore Create assets dir relative to OUT_DIR 2024-04-23 14:55:18 +12:00
.pre-commit-hooks.yaml Add pre-commit hook declaration (#431) 2022-01-14 21:55:48 -05:00
Cargo.lock chore(deps): bump the rust-dependencies group across 1 directory with 4 updates (#738) 2025-11-03 18:05:10 +01:00
Cargo.toml chore(deps): bump the rust-dependencies group across 1 directory with 4 updates (#738) 2025-11-03 18:05:10 +01:00
CHANGELOG.md Change repository name reference + Docker registry URL 2025-06-23 19:38:43 -04:00
Dockerfile Update runners, rust, and dependencies (#724) 2025-08-25 14:49:59 +02:00
LICENSE Add MIT License 2016-01-01 00:46:40 -05:00
MANUAL.txt Bump version to 9.1.5 (#697) 2025-04-26 01:19:57 +02:00
README.md BC breaks for v10 (#715) 2025-09-20 17:16:22 +02:00
SECURITY.md Change repository name reference + Docker registry URL 2025-06-23 19:38:43 -04:00

Oxipng

Build Status Version License Docs

Overview

Oxipng is a multithreaded lossless PNG/APNG 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 via the Releases section on its GitHub page. Recently, however, Oxipng has also been made available through package managers. Check the list below for up-to-date options.

For MacOS or Linux, it is recommended to install from your distro's package repository, provided Oxipng is available there in a not too outdated version for your use case.

Oxipng is known to be packaged for the environments listed below.

Packaging status

Alternatively, Oxipng can be installed from Cargo, via the following command:

cargo install oxipng

Oxipng can also be built from source using the latest stable or nightly Rust. This is primarily useful for developing on Oxipng.

git clone https://github.com/oxipng/oxipng.git
cd oxipng
cargo build --release
cp target/release/oxipng /usr/local/bin

The current minimum supported Rust version is 1.85.1.

Oxipng follows Semantic Versioning.

Usage

Oxipng is a command-line utility. An example usage, suitable for web, may be the following:

oxipng -o 4 --strip safe --alpha *.png

The most commonly used options are as follows:

  • Optimization: -o 0 through -o 6 (or -o max), lower is faster, higher is better compression. The default (-o 2) is quite fast and provides good compression. Higher levels can be notably better* but generally have increasingly diminishing returns.
  • 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. -s can be used as a shorthand for --strip safe.
  • Alpha: --alpha can improve compression of images with transparency, by altering the color values of fully transparent pixels. This is generally recommended, but take care as this is technically a lossy transformation and may be unsuitable for some specific applications.

More advanced options can be found by running oxipng --help, or viewed here.

Some options have both short (-a) and long (--alpha) forms. Which form you use is just a matter of preference. Multiple short options can be combined together, e.g.: -savvo6 is equivalent to to --strip safe --alpha --verbose --verbose --opt 6. All options are case-sensitive.

* Note that oxipng is not a brute-force optimizer. This means that while higher optimization levels are almost always better or equal to lower levels, this is not guaranteed and it is possible in rare circumstances that a lower level may give a marginally smaller output. Similarly, using Zopfli compression (-z) is not guaranteed to always be better than without.

Git integration via pre-commit

Create a .pre-commit-config.yaml file like this, or add the lines after the repos map preamble to an already existing one:

repos:
  - repo: https://github.com/oxipng/oxipng
    rev: v9.1.5
    hooks:
      - id: oxipng
        args: ["-o", "4", "--strip", "safe", "--alpha"]

Docker

A Docker image is availlable at ghcr.io/oxipng/oxipng for linux/amd64 and linux/arm64.

You can use it the following way:

docker run --rm -v $(pwd):/work ghcr.io/oxipng/oxipng -o 4 /work/file.png

Some older images are also available at ghcr.io/shssoichiro/oxipng.

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. 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 = "9.0", features = ["parallel", "zopfli", "filetime"], default-features = false }

Software using Oxipng

  • ImageOptim: Mac app and web service for optimizing images
  • Squoosh: Web app for optimizing images
  • FileOptimizer: Windows app for optimizing files
  • Curtail: Linux app for optimizing images
  • pyoxipng: Python wrapper for Oxipng
  • jSquash: Collection of WebAssembly image codecs
  • Trunk: Developer experience toolkit for managing code

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).

Note that, while similar, Oxipng is not a drop-in replacement for OptiPNG. If you are migrating from OptiPNG, please check the help before using.

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 9.0.0 (commit c16519b38b0519988db625913be919d4f0e42f5d, compiled on rustc 1.74.0-nightly (7b4d9e155 2023-09-28)) against OptiPNG version 0.7.7, as packaged by Debian unstable, on a Linux 6.5.0-2-amd64 kernel, Intel Core i7-12700 CPU (8 performance cores, 4 efficiency cores, 20 threads), DDR5-5200 RAM in dual channel configuration.


Benchmark 1: ./target/release/oxipng -P ./tests/files/rgb_16_should_be_grayscale_8.png
  Time (mean ± σ):      59.6 ms ±   7.7 ms    [User: 77.4 ms, System: 3.6 ms]
  Range (min … max):    53.3 ms …  89.9 ms    32 runs

Benchmark 2: optipng -simulate ./tests/files/rgb_16_should_be_grayscale_8.png
  Time (mean ± σ):     132.4 ms ±   0.8 ms    [User: 132.5 ms, System: 0.6 ms]
  Range (min … max):   131.8 ms … 134.4 ms    22 runs

Summary
  ./target/release/oxipng -P ./tests/files/rgb_16_should_be_grayscale_8.png ran
    2.22 ± 0.29 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 ± σ):      88.7 ms ±   4.3 ms    [User: 270.3 ms, System: 11.0 ms]
  Range (min … max):    86.8 ms … 109.4 ms    26 runs

Benchmark 2: optipng -o 4 -simulate ./tests/files/rgb_16_should_be_grayscale_8.png
  Time (mean ± σ):     444.9 ms ±   0.3 ms    [User: 444.8 ms, System: 0.7 ms]
  Range (min … max):   444.4 ms … 445.6 ms    10 runs

Summary
  ./target/release/oxipng -o4 -P ./tests/files/rgb_16_should_be_grayscale_8.png ran
    5.01 ± 0.25 times faster than optipng -o 4 -simulate ./tests/files/rgb_16_should_be_grayscale_8.png