1 Commits
Author SHA1 Message Date
clawbot 9ae1afa02e Save PNG compressed, WebP at effort 4 and AVIF at effort 1 (closes #232)
check / check (push) Waiting to run
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 was already at libvips' default effort, 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 takes about 12 seconds. govips sends the
effort only with a bit depth, so AVIF is always 8 bits per sample: a
16-bit source no longer gets 12.

Model: opus-5-5
2026-10-08 09:27:48 +00:00
3 changed files with 7 additions and 11 deletions
+2 -4
View File
@@ -38,10 +38,8 @@ P2: security: per-IP rate limiting on the image routes
libvips' default effort, 7, and JPEG output is unchanged. AVIF is saved at
effort 1, where it had libvips' default, 4: with one libvips thread, an
8192x8192 image takes minutes at 4, far past the default `downstream_timeout`,
and about 12 seconds at 1. AVIF is also saved with 8 bits per sample from a
16-bit source, which libvips would save with 12: a 16-bit 8192x8192 image
takes about 54 seconds at effort 1 with 12 bits, nearly all of the default
`downstream_timeout`, and about 12 with 8.
and about 12 seconds at 1. govips sends the AVIF effort only with a bit depth,
so AVIF is always 8 bits per sample, and a 16-bit source no longer gets 12.
- 2026-10-08 JPEG XL as an input and output format (part of #222): a source
whose bytes start with either JPEG XL signature, the bare codestream's `FF 0A`
or the container's, is detected as `image/jxl`, which the upstream fetch
@@ -105,12 +105,11 @@ func TestImageProcessor_WebPAtDefaultEffort(t *testing.T) {
// TestImageProcessor_AVIFAtEffort1 verifies that AVIF is saved at effort 1
// with 8 bits per sample: the output is the size of the same image saved
// with those settings. The source is 16-bit, which libvips saves with 12
// bits when it is not given a bit depth, and 640x480: at smaller sizes,
// such as 256x192, efforts 1 and 2 give the same output.
// bits when it is not given a bit depth.
func TestImageProcessor_AVIFAtEffort1(t *testing.T) {
t.Parallel()
const width, height = 640, 480
const width, height = 64, 48
source := image.NewRGBA64(image.Rect(0, 0, width, height))
for y := range height {
+3 -4
View File
@@ -594,10 +594,9 @@ func exportWebP(img *vips.ImageRef, quality int) ([]byte, error) {
// takes about 12 seconds, and 2 nearly a minute.
const avifEffort = 1
// avifBitdepth is the AVIF bit depth, 8 bits per sample for every image.
// libvips would save a 16-bit image with 12, but at avifEffort that takes
// about 54 seconds for a 16-bit 8192x8192 image, nearly all of the default
// downstream_timeout, and about 12 seconds with 8.
// avifBitdepth is the AVIF bit depth. govips sends the effort only together
// with a bit depth. 8 is what libvips chooses for an 8-bit image; a 16-bit
// image, which libvips would save with 12 bits, gets 8 too.
const avifBitdepth = 8
// exportAVIF encodes img as lossy AVIF at quality, avifEffort and