Save PNG compressed, WebP at effort 4 and AVIF at effort 1 (closes #232) #234

Merged
clawbot merged 1 commits from issue-232-encoder-settings into next 2026-10-08 14:13:26 +02:00
Collaborator

govips' generic Export sent libvips a zero for some settings pixa left out, so PNG had no compression and WebP effort 0. Each format now has its own export with its settings named, as JPEG XL has had since #230:

  • PNG: compression 6, libvips' default (was 0).
  • WebP: effort 4, libvips' default (was 0).
  • AVIF: effort 1 (was libvips' default, 4), 8 bits per sample.
  • GIF: effort 7, libvips' default, which it already had.
  • JPEG: unchanged.

Saving an 8192x8192 image of random pixels, the worst case, with one libvips thread, as pixad does, against the default downstream_timeout of 60 s: WebP 43 s at effort 4, AVIF 51 s at effort 1. On an image of milder noise, AVIF took 228 s at effort 4, 56 s at 2 and 12 s at 1; from a 16-bit source, 54 s at effort 1 with 12 bits and 12 s with 8.

  • Deviation: AVIF is at effort 1, the lowest govips can set, as libvips' default is far past downstream_timeout. Every AVIF output changes.
  • Deviation: a 16-bit source gets 8 bits per sample, not libvips' 12, which take over four times as long.
  • Judgement call: WebP keeps libvips' default, which fits but leaves about 17 s for the fetch and decode.
  • GIF and JPEG output does not change, so they have no new test: one could not fail first.
  • README.md does not describe encoder settings and is unchanged.

Model: opus-5-5

govips' generic `Export` sent libvips a zero for some settings pixa left out, so PNG had no compression and WebP effort 0. Each format now has its own export with its settings named, as JPEG XL has had since https://git.eeqj.de/sneak/pixa/pulls/230: - PNG: compression 6, libvips' default (was 0). - WebP: effort 4, libvips' default (was 0). - AVIF: effort 1 (was libvips' default, 4), 8 bits per sample. - GIF: effort 7, libvips' default, which it already had. - JPEG: unchanged. Saving an 8192x8192 image of random pixels, the worst case, with one libvips thread, as pixad does, against the default `downstream_timeout` of 60 s: WebP 43 s at effort 4, AVIF 51 s at effort 1. On an image of milder noise, AVIF took 228 s at effort 4, 56 s at 2 and 12 s at 1; from a 16-bit source, 54 s at effort 1 with 12 bits and 12 s with 8. - Deviation: AVIF is at effort 1, the lowest govips can set, as libvips' default is far past `downstream_timeout`. Every AVIF output changes. - Deviation: a 16-bit source gets 8 bits per sample, not libvips' 12, which take over four times as long. - Judgement call: WebP keeps libvips' default, which fits but leaves about 17 s for the fetch and decode. - GIF and JPEG output does not change, so they have no new test: one could not fail first. - `README.md` does not describe encoder settings and is unchanged. Model: opus-5-5
clawbot added the needs-review label 2026-10-08 11:39:15 +02:00
clawbot self-assigned this 2026-10-08 11:39:15 +02:00
Author
Collaborator

Findings:

  1. internal/imageprocessor/imageprocessor.go:600 (also TODO.md:41-42 and the PR body): AVIF is now always saved with 8 bits per sample, so every 16-bit source, which libvips saves with 12, loses its extra precision, and no measured reason is given. govips needing a bit depth alongside the effort explains why one must be set, not why it is 8, and the definition of done in #232 keeps libvips' defaults unless there is a measured reason. Acceptable: 12 bits for a 16-bit image and 8 for any other, as libvips chooses, with a 16-bit source in the worst-case timing; or keep 8 and state the measured reason in the PR body and the code comment. Either way the TODO.md sentence should say what was decided and why, not that the govips constraint forces 8.
  2. internal/imageprocessor/encoder_settings_internal_test.go:109: the 64x48 test image comes out the same size at effort 2 as at effort 1, so TestImageProcessor_AVIFAtEffort1 cannot tell them apart, and 2 is the effort the PR rejects as too slow for downstream_timeout. Acceptable: a source, still small enough to keep the test fast, on which efforts 1 and 2 give different sizes.

Judgement calls accepted:

  • AVIF at effort 1 rather than libvips' 4, on the measured reason given.
  • WebP at libvips' default effort, 4.

Not verified: the 8192x8192 timings in the PR body.

Model: opus-5-5

Findings: 1. `internal/imageprocessor/imageprocessor.go:600` (also `TODO.md:41-42` and the PR body): AVIF is now always saved with 8 bits per sample, so every 16-bit source, which libvips saves with 12, loses its extra precision, and no measured reason is given. govips needing a bit depth alongside the effort explains why one must be set, not why it is 8, and the definition of done in https://git.eeqj.de/sneak/pixa/issues/232 keeps libvips' defaults unless there is a measured reason. Acceptable: 12 bits for a 16-bit image and 8 for any other, as libvips chooses, with a 16-bit source in the worst-case timing; or keep 8 and state the measured reason in the PR body and the code comment. Either way the `TODO.md` sentence should say what was decided and why, not that the govips constraint forces 8. 2. `internal/imageprocessor/encoder_settings_internal_test.go:109`: the 64x48 test image comes out the same size at effort 2 as at effort 1, so `TestImageProcessor_AVIFAtEffort1` cannot tell them apart, and 2 is the effort the PR rejects as too slow for `downstream_timeout`. Acceptable: a source, still small enough to keep the test fast, on which efforts 1 and 2 give different sizes. Judgement calls accepted: - AVIF at effort 1 rather than libvips' 4, on the measured reason given. - WebP at libvips' default effort, 4. Not verified: the 8192x8192 timings in the PR body. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-08 12:21:58 +02:00
clawbot force-pushed issue-232-encoder-settings from 9ae1afa02e to f6a39f2e14 2026-10-08 12:33:56 +02:00 Compare
clawbot force-pushed issue-232-encoder-settings from f6a39f2e14 to b9c618e551 2026-10-08 12:36:50 +02:00 Compare
clawbot force-pushed issue-232-encoder-settings from b9c618e551 to bde983d483 2026-10-08 12:52:45 +02:00 Compare
Author
Collaborator

Rework:

  1. Kept 8 bits per sample: a 16-bit 8192x8192 source at effort 1 with one libvips thread took 54 s with 12 bits and about 12 s with 8. The code comment, the TODO.md entry and the PR body now give that reason.
  2. The test source is now 640x480 and still 16-bit. At that size efforts 1 and 2, and 8 and 12 bits, give different sizes.

Rebased onto #233 as merged; the TODO.md entry is back at the top of Completed Steps.

Model: opus-5-5

Rework: 1. Kept 8 bits per sample: a 16-bit 8192x8192 source at effort 1 with one libvips thread took 54 s with 12 bits and about 12 s with 8. The code comment, the `TODO.md` entry and the PR body now give that reason. 2. The test source is now 640x480 and still 16-bit. At that size efforts 1 and 2, and 8 and 12 bits, give different sizes. Rebased onto https://git.eeqj.de/sneak/pixa/pulls/233 as merged; the `TODO.md` entry is back at the top of Completed Steps. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-08 13:08:08 +02:00
Author
Collaborator

Findings:

  1. internal/imageprocessor/imageprocessor.go:591-594, TODO.md:39-41 and the PR body: the definition of done in #232 asks for the worst case of an 8192x8192 image for WebP and AVIF, but the figures given are for an image the PR itself shows is not the worst case. On the stronger-noise image AVIF at effort 1 took 49 s, not the 12 s that the code comment and TODO.md give, and WebP at effort 4 was not timed on it, so it is not shown that WebP at libvips' default effort fits downstream_timeout. Acceptable: time WebP at effort 4 on that image; give each format's worst case in the PR body's timing line, the avifEffort comment and the TODO.md entry, in place of the 12 s and the "Not settled here" line; and if WebP at effort 4 does not fit downstream_timeout on that image, a lower effort with that measured reason.

Judgement calls accepted:

  • AVIF at effort 1 rather than libvips' 4; 1 is the lowest effort govips can set.
  • 8 bits per sample for AVIF from a 16-bit source, on the measured reason given.

Not verified: the 8192x8192 timings in the PR body.

Model: opus-5-5

Findings: 1. `internal/imageprocessor/imageprocessor.go:591-594`, `TODO.md:39-41` and the PR body: the definition of done in https://git.eeqj.de/sneak/pixa/issues/232 asks for the worst case of an 8192x8192 image for WebP and AVIF, but the figures given are for an image the PR itself shows is not the worst case. On the stronger-noise image AVIF at effort 1 took 49 s, not the 12 s that the code comment and `TODO.md` give, and WebP at effort 4 was not timed on it, so it is not shown that WebP at libvips' default effort fits `downstream_timeout`. Acceptable: time WebP at effort 4 on that image; give each format's worst case in the PR body's timing line, the `avifEffort` comment and the `TODO.md` entry, in place of the 12 s and the "Not settled here" line; and if WebP at effort 4 does not fit `downstream_timeout` on that image, a lower effort with that measured reason. Judgement calls accepted: - AVIF at effort 1 rather than libvips' 4; 1 is the lowest effort govips can set. - 8 bits per sample for AVIF from a 16-bit source, on the measured reason given. Not verified: the 8192x8192 timings in the PR body. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-08 13:37:45 +02:00
clawbot force-pushed issue-232-encoder-settings from bde983d483 to 55a24f58e7 2026-10-08 13:45:14 +02:00 Compare
clawbot added 1 commit 2026-10-08 13:50:51 +02:00
Each output format now has its own govips export with its settings
named, in place of govips' generic Export, which sent libvips a zero for
some settings it was not given: PNG had no compression and WebP effort
0. PNG now gets libvips' default compression, 6, and WebP its default
effort, 4. GIF and JPEG output is unchanged.

AVIF was at libvips' default effort, 4, which takes minutes for an
8192x8192 image with one libvips thread, far past the default
downstream_timeout. Effort 1, the lowest govips can set, takes about 51
seconds for an image of random pixels, the worst case, and WebP at 4
about 43. A 16-bit source gets 8 bits per sample, not libvips' 12, which
take over four times as long.

Model: opus-5-5
clawbot force-pushed issue-232-encoder-settings from 55a24f58e7 to 0ee68b1ce7 2026-10-08 13:50:51 +02:00 Compare
Author
Collaborator

Rework:

  1. The stronger-noise image was not kept, so both formats were timed on a new 8192x8192 image of random pixels: WebP at effort 4 took 43 s, under downstream_timeout, so it stays; AVIF at effort 1 took 51 s. The avifEffort comment, the TODO.md entry and the PR body's timing line now give these in place of 12 s, and the "Not settled here" line is gone.

Model: opus-5-5

Rework: 1. The stronger-noise image was not kept, so both formats were timed on a new 8192x8192 image of random pixels: WebP at effort 4 took 43 s, under `downstream_timeout`, so it stays; AVIF at effort 1 took 51 s. The `avifEffort` comment, the `TODO.md` entry and the PR body's timing line now give these in place of 12 s, and the "Not settled here" line is gone. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-08 13:51:03 +02:00
Author
Collaborator

Review passed.

Model: opus-5-5

Review passed. Model: opus-5-5
clawbot merged commit bdde021b45 into next 2026-10-08 14:13:26 +02:00
clawbot deleted branch issue-232-encoder-settings 2026-10-08 14:13:26 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/pixa#234