- Fix docs for entropy filter (fixes#733)
- Improve docs for `--fix` (fixes#728)
- Add tests for alpha optimisation
- Following a recent change to the code here, I realised we don't
actually have any tests covering alpha optimisation. I've adjusted some
of the test images to include lines with both leading transparent and
all transparent pixels, and added dedicated tests for them.
- Change x86_64 macOS build to use the macos-15 runner
- There is a new macos-15-intel runner available but we don't actually
need an intel runner to build x86_64. (As support for x86_64 winds down,
we can probably drop these builds eventually - homebrew is the preferred
installation method for macOS anyway)
Adds an option to skip files when the uncompressed IDAT (or the file
size itself) exceeds a certain size. This provides an effective way to
limit resource usage in constrained environments.
Closes#411.
If no palette reduction occurred (or palette reductions were off), a
fully transparent palette entry may not have been zeroed to black. By
ensuring this gets cleaned in the `indexed_to_channels` transformation,
we may able to achieve a grayscale conversion that would otherwise have
been RGB.
This is the final piece of the puzzle in #649 to achieve better file
sizes on the first run and avoid further changes on a second run.
Results from the images in #649 (combining this PR and #673):
9.1.3 1st run: 2,191,773
9.1.3 2nd run: 2,191,629
PR 1st run: 2,191,380
PR 2nd run: 2,191,380
I've replaced a few tests with synthetic images and removed a number
that I don't believe are relevant anymore.
I've also removed the #553 test without replacement as I don't know how
to synthesise a replacement and the issue is still open anyway.
Going forward I think we should avoid adding any new "issue" tests and
instead synthesise something suitable in one of the other collections.
Closes#655.
This PR makes 3 changes that together reduce binary size by around 25%:
- Sets lto="fat" in cargo.toml
- Sets panic="abort" in cargo.toml
- Sets location-detail=none in RUSTFLAGS
Closes#571
An unrelated change: I've replaced the zopfli test file with a smaller
one that runs much faster, as well as removing the slow test for
issue-133 which was related to an older alpha optimisation that is no
longer relevant.
The filters used during reduction evaluations are normally set to None &
Bigrams, regardless of any options. This PR makes a slight change so
that if only one filter is specified in the options, this filter will be
used for reduction evaluations too.
This resolves an odd situation affecting lower levels (when --fast is
enabled) where you may try to force the filter to a specific value but
it actually ends up different because a reduction evaluation was
smaller. It's particularly helpful if you're wanting it to be as fast as
possible by using `-o0 -f0` which will now exclusively use None instead
of trying the slower Bigrams as well.
As another use, you could try to brute force oxipng by iterating each
filter separately, though this may not actually achieve anything 😂
[edit] I also pulled the options out into a separate file, though this
wasn't relevant to the filter change.
This adds a new palette sorting algorithm that attempts to minimise
entropy by an approximate solution to the Traveling Salesman Problem.
The algorithm comes from "An efficient Re-indexing algorithm for
color-mapped images" by Battiato et al
(https://ieeexplore.ieee.org/document/1344033).
It's fast and effective and works in addition to the luma sort (which
remains the single most effective sort). In order to keep lower presets
fast though, I've only enabled this for o3 and higher.
Results on a set of 190 indexed images at `-o5`:
18,932,727 bytes - master
18,578,306 bytes - PR
18,559,863 bytes - PR + #509
(These images may be particularly suited to alternative sorting methods
- the gains here are not necessarily what should be expected on average)
Note I looked into the 120 different palette sorting methods from
TruePNG, as mentioned in #74 (and seen in action in the Zopfli KrzYmod
fork). They're... largely ineffective. The combination of all 120
methods are outperformed by just the existing luma sort plus this new
one. That's not to say there's nothing further to be gained from them,
but trying to brute force all the combinations definitely seems like a
bad idea. There are other algorithms I hope to explore in future...
@ace-dent Thought this might interest you
UPDATE: I realised a quick tweak to alpha values in the luma sort can
provide a great improvement on images with transparency. The following
numbers were taken with PR #509 as base.
`-o2`:
19,065,549 bytes - base (luma sort)
18,949,747 bytes - modified luma sort
`-o5`:
18,922,165 bytes - base (luma sort)
18,559,863 bytes - new sorting algorithm + luma sort
18,544,813 bytes - new sorting algorithm + modified luma sort
* Fix bKGD conversion from gray to palette
* Allow grayscale reduction from 16 to 4 or less
* Refactor reduction evaluation sequence
* Separate palette into new file
* Fix verbose message
* No cloning when restoring original data
* Make reductions return a new uncompressed image
Partially fixes#145
* Async reduction evaluator
* Assert
* Faster bit depth check
* Also try 4-bit depth for small-depth images
* Skip test when using miniz
* Ensure palette is trimmed after depth reduction
Fixes#159
* Fudge factor for reductions to prefer better reductions even if gzip estimation says otherwise