Choosing an automatic quality target

Copy Markdown View Source

Automatic quality gives each image the lowest encoder quality that still looks as good as a target you choose, instead of one fixed quality for every image.

This guide assumes ImagePipe is running in your app (see Getting started with Phoenix) or as image_pipe_server (see Getting started with the server).

Turning on automatic quality

Automatic quality is off by default. Turn it on with the autoquality setting:

Plug

# lib/my_app/application.ex
{ImagePipe, name: MyApp.Images, sources: [...], autoquality: true}

image_pipe_server

[processing]
autoquality = true

These are options on the ImagePipe instance or on forward ... ImagePipe.Plug. JPEG, WebP, and AVIF responses then search for their quality. PNG, lossless WebP, and requests that set q are encoded once.

Choosing a target

The target is an SSIMULACRA2 score from 0 to 100. Higher looks better and costs more bytes: 90 is very high quality, 70 is high, and 50 is medium. The default is 75.

A benchmark over 53 photos and screenshots measured the file size at each target, compared with each format's default quality (JPEG 80, WebP 79, AVIF 63, see q and format-q):

TargetJPEGWebPAVIF
7024% smaller18% smaller38% smaller
7219% smaller12% smaller33% smaller
759% smaller1% larger24% smaller
785% larger19% larger12% smaller
8016% larger33% larger2% smaller
8553% larger87% larger34% larger

WebP can't reach the higher targets for some images even at q96: 13 percent of them at 80, all screenshots, and 38 percent at 85. The WebP sizes at those targets leave them out.

At a fixed quality, scores across the benchmark images varied by about 10 points between the best and worst tenth. At target 75, most images landed within a point of the target, except screenshots that WebP couldn't bring up to it.

Keep 75 unless the table shows a size you can't accept. Set the target next to autoquality:

Plug

{ImagePipe, name: MyApp.Images, sources: [...], autoquality: true, autoquality_target: 80}

image_pipe_server

[processing]
autoquality = true
autoquality_target = 80

Overriding the target per request

A request can set its own target with the autoquality option:

/w=800/autoquality=85/src/photos/beach.jpg

A bare autoquality uses the server's target, autoquality=false turns the search off, and a request that sets q skips the search.

Weighing the search cost

A search makes about three encodes, and decodes and scores each one. A fixed quality makes one encode. With a cache, only the first request for each image pays for the search (see caching processed images).

Checking the result

Turn on debug headers and add the debug option to a request:

/w=800/debug/src/photos/beach.jpg

The response then carries the search's result. A hit with a score at or just above the target means the search worked:

X-ImagePipe-AQ-Target: 75.0
X-ImagePipe-AQ-Score: 75.3
X-ImagePipe-AQ-Outcome: hit

A best_effort outcome means the image was delivered at the highest quality the search tries without reaching the target (see debug headers). In the benchmark at target 75, these were all screenshots. Lower the target if those images come out too large.

Next steps