Quality parameters and compress-to-target
Every converter and compressor lane that writes JPEG, WebP or AVIF — the directional pages, the Image Compressor, Compress JPEG and Image to PDF, which re-encodes each page as JPEG before embedding it — exposes one number called quality, and two of those lanes add a second control: a target file size. The one lossy re-encode without a slider is the Image Resizer, which writes a JPEG or WebP input back to its own format at the capability table's default. This guide explains what the engine does with both controls. Every figure below was computed at build time by the planning module the tools run on your files; none measures a real photograph and none is a recommendation, because the planner cannot see your image and neither can this page. The other guides are listed at /guides/.
One number, two scales
Inside the engine, quality runs from zero to one: the scale the browser's canvas encoder takes,
so the scale the planning module stores and the compress-to-target search brackets over. The two
self-hosted encoders — MozJPEG on the Compress JPEG lane, libavif with aom for AVIF output —
take a whole number from 0 to 100 instead. The tool-page sliders use
the same whole-number scale; the tool pages set their slider bounds to 5 and 95, the search planner's default range (its conversion range tops out higher, at maximum
quality). The bridge is one function, encoderQualityPercent: refuse a non-finite
input, clamp into the engine's range, scale onto 0–100 and round to
the nearest whole number. On illustrative inputs the rounding shows — an engine quality of
0.876 becomes 88, 0.874 becomes 87 — and so
does the clamp: an illustrative 1.7 becomes 100,
−0.2 becomes 0.
Where each default comes from
A default is the quality planConversion records when no override is passed. It is what
the Image Resizer passes, since it has no slider, and where the directional
converter pages start their sliders. The Image Compressor and
Image to PDF are the exceptions: each starts its slider at its own position
and always passes the slider's reading. The capability table lists one default per output format,
and the MozJPEG lane carries its own:
| Output | Takes a quality parameter | Engine default (zero to one) | Default on the encoder scale (0–100) |
|---|---|---|---|
| PNG via canvas | no — lossless | none | none |
| JPEG via canvas | yes | 0.92 | 92 |
| WebP via canvas | yes | 0.85 | 85 |
| AVIF via libavif + aom | yes | 0.5 | 50 |
| JPEG via MozJPEG (Compress JPEG) | yes | 0.75 | 75 |
The JPEG and WebP values are the capability table's defaults for the browser encoder. The AVIF
value is libavif's own default on the encoder's 0–100 scale, stored
by the engine as
0.5 and mapped to 50. The Compress JPEG value is
MozJPEG's own default, 75, and that lane turns progressive scan order
on by default. PNG has no number because it is lossless;
the planner records its quality as null. WebP sits in the lossy column because the
engine's capability table records it as lossy — the canvas path it uses produces lossy WebP and
takes a quality parameter.
What the number is not
The quality value is not a percentage of anything about your file: not the fraction of detail kept, not the fraction of bytes kept, not a score the result will earn. It is an instruction to one particular encoder, and the engine's own notes say that AVIF quality lives on its own scale. This guide therefore makes no quality recommendations. The planner sees formats, numbers and byte counts, never pixels, and it refuses rather than guesses: asked for JPEG at an illustrative quality of 1.2 it replies "Quality must be between 0.05 and 1."; asked for PNG output with any quality at all, "This output format is lossless and has no quality setting."; asked to search toward a target of zero bytes, "Enter a target size greater than zero.". Those are the engine's own messages, rendered at build time.
Compress-to-target is a search, not a formula
"Make this fit under 200 KB" cannot be solved by arithmetic: no formula maps a quality
setting to a byte count for an image not yet encoded. The site solves it by measurement. planCompression is a pure function: given the target in bytes and the encodes made so far — each recorded as the
quality used and the bytes it produced — it returns one of three steps. Encode names the
next quality to try; the client encodes once, measures the blob, appends the attempt and asks again.
Done hands back the largest attempt that fits under the target. Unreachable hands
back the smallest attempt made, because nothing it tried fit and it can go no lower. Between calls
the planner brackets — the highest quality known to fit on one side, the lowest known to overshoot
on the other, the midpoint as the next probe — and stops when an attempt lands within a narrow band
just under the target, when the bracket is too narrow to split, or when the attempt budget is spent;
the
methodology page states the bound as convergence within eight encodes.
The first probe is always the top of the range, 95 on the slider — what the methodology
page calls maximum quality, meaning the top of the search range — and no probe goes below the floor
of 5: handed an overshoot at an illustrative engine quality of
0.08, the planner clamps its next probe to 0.05 rather than halving
further.
A worked search on an invented size curve
This page drives the real planner against an invented curve from quality to byte count. The curve comes from no image and the byte counts below measure nothing; only the quality sequence and the verdicts are the planner's. Target: 204,800 bytes (200 KB).
| Attempt | Quality (engine) | Quality (slider) | Invented bytes | Against the target |
|---|---|---|---|---|
| 1 | 0.95 | 95 | 612,475 | overshoots |
| 2 | 0.475 | 48 | 213,119 | overshoots |
| 3 | 0.237 | 24 | 113,140 | fits |
| 4 | 0.356 | 36 | 154,774 | fits |
| 5 | 0.415 | 42 | 181,613 | fits |
| 6 | 0.445 | 45 | 196,835 | fits |
After 6 attempts the planner returned done with the attempt at engine quality 0.445 — slider 45 — and 196,835 bytes; measured against the target by the function the result row uses, that attempt reads "3.9% smaller". Notice the two phases: while nothing has fit, each probe halves the lowest overshooting quality toward the floor; once one fits, every later probe is the midpoint of the bracket. The accepted result is the largest attempt that fit, not the last one made.
When the target cannot be reached
The same invented curve against a target of 61,440 bytes (60 KB) never fits, so the planner keeps halving toward the floor:
| Attempt | Quality (engine) | Quality (slider) | Invented bytes | Against the target |
|---|---|---|---|---|
| 1 | 0.95 | 95 | 612,475 | overshoots |
| 2 | 0.475 | 48 | 213,119 | overshoots |
| 3 | 0.237 | 24 | 113,140 | overshoots |
| 4 | 0.118 | 12 | 88,215 | overshoots |
| 5 | 0.059 | 6 | 82,054 | overshoots |
After 5 attempts the lowest overshoot sat at engine quality 0.059, and the bracket left between it and the floor of 0.05 was too narrow for the planner to split, so it returned unreachable and named the smallest attempt: 82,054 bytes. The tool page reports the smallest attempt and offers that file. The lever that remains is dimensions, the subject of Resizing math.
When the first encode already fits
Against a target of 1,048,576 bytes (1024 KB) the first probe, at engine quality 0.95, produced 612,475 invented bytes and already fit. The planner returned done after 1 attempt rather than searching above the ceiling of its range, because there is nothing above it to search. A generous target is a one-encode job, and the row reports the top-of-range quality.
Which lanes offer the search
The search is a property of a lane. The canvas-encoded
Image Compressor offers it for JPEG and WebP output. The MozJPEG
lane declares targetSizeSearch as
available, so
Compress JPEG offers it too. The AVIF lane declares it
unavailable, so
JPG to AVIF and PNG to AVIF offer the quality
slider only. Wherever the search is offered, every probe is a full encode in your browser, and none
is transmitted. Every one of those encodes, slider or search, is a re-encode from the canvas's decoded
pixels, which strips all embedded metadata — EXIF (including GPS location, camera model and timestamps),
colour-profile tags, and text chunks — so keep your original; orientation is applied during decoding,
before the metadata is discarded. The
metadata guide lists what goes and what stays.
PNG inputs are converted, and labelled
The methodology page is blunt: PNG inputs are never "PNG-compressed", because a canvas cannot
honestly do that. The capability table is where the rule comes from — PNG is lossless, its
quality is null, and there is no parameter for a search to move. So the
Image Compressor converts a PNG to the lossy format you choose and
labels the conversion on the row. The plan for PNG to JPEG sets
needsBackgroundFlatten to true with a default
background of #ffffff, because JPEG cannot carry transparency; the
plan for PNG to WebP sets it to false. The filename
follows the target — on invented filenames, logo.png becomes logo.jpg or
logo.webp — while a JPEG compressed back to JPEG gains a suffix so the download cannot
shadow the original. The engine's outputFilename takes that suffix as an argument, and
both compressor clients pass -compressed: holiday.jpg becomes
holiday-compressed.jpg. The flattening rule has its own guide,
Transparency and flattening; the directional
page PNG to JPG puts the background control beside the quality slider,
while PNG to WebP has no colour picker because its plan sets
needsBackgroundFlatten to false and never flattens.
Reading the result row
Whatever mode produced the file, the row reports the input blob's true byte count, the output
blob's true byte count, and a percent change computed from those two numbers by
describeSizeChange. On invented byte counts, and only as arithmetic: an original of
745,000 bytes against the 196,835-byte result of the worked search reads
"74% smaller"; 150,000 bytes growing to 158,400 reads "5.6% larger — keep your original";
1,000,000 bytes falling to 999,700 reads "less than 0.1% smaller"; an unchanged count
reads "same size". The growth case matters most: a result can come out larger, and when it
does the row says so and tells you to keep your original. The site publishes no blanket
compression percentages anywhere, because no percentage is true for every image — the figures in
this paragraph are the function's formatting rules applied to numbers this page made up, not a
forecast.
Common misreadings
- "Quality 92 keeps 92% of the image." It keeps whatever the encoder's decisions at parameter 92 keep; the number is an input, not a measurement of the output.
-
"The search found the best quality." It found the largest fitting encode by byte
count — the attempt with the most bytes that still fit under the target — within an attempt budget.
The planner does label that attempt
best, but the word means "most bytes under the target", not a judgement about how the image looks. - "Target mode compresses harder." It encodes at whatever quality the bracket lands on — higher than the slider default when the target is generous; the one-attempt case above ended at the top of the range.
- "Unreachable means the tool failed." The file cannot get that small by quality alone; the smallest attempt is offered, labelled, and the remaining lever is pixel dimensions.
Frequently asked questions
Is the quality number a percentage of the original file size?
No. It is an encoder parameter on the 0–100 scale that the engine derives from its own zero-to-one scale by scaling and rounding. It says nothing about how many bytes the result will have; the only size figures the site shows are the measured byte counts of your own input and output.
Why do the lanes start at different quality values?
The canvas lanes draw their default from the capability table, which is the quality the planner records when no override is passed: 92 for canvas JPEG and 85 for canvas WebP, and 50 for AVIF because that is libavif’s own default. The Compress JPEG lane is separate: its 75 is the MozJPEG lane’s own constant, which the planner does not consult. The directional converter pages start their sliders at the table default; the Image Resizer passes it because it has no slider; the Image Compressor and Image to PDF start their sliders at their own position and always pass the slider’s reading. None of them is a judgement about your image.
How does the target-size mode decide which quality to try next?
It keeps a list of the encodes made so far, each with its quality and its measured bytes. It brackets between the highest quality known to fit under the target and the lowest known to overshoot, tries the midpoint once something has fit — until then it halves the lowest overshooting quality, never below its floor — and stops when an attempt lands close enough under the target, when the bracket collapses, or when the attempt budget runs out. The methodology page states the bound: the search converges within eight encodes.
What happens if the target is smaller than the file can get?
The planner returns an “unreachable” verdict when nothing has fit and either an attempt at its minimum quality overshoots, the bracket above that minimum is too narrow to split, or the attempt budget runs out — the worked 60 KB search above ends by the second route. The tool then reports the smallest size it actually produced and offers that file, instead of handing you a file that misses the target or claiming success. Reducing dimensions with the Image Resizer is the lever that remains.
Why does a PNG I drop on the compressor come back as a JPG or WebP?
Because PNG is lossless and has no quality parameter — asking the planner for one is an error, not a slider. The compressor converts the PNG to the lossy format you choose and labels the conversion on the row. JPEG output flattens transparency onto the background color you pick (the planner sets that flag for PNG to JPEG); WebP output keeps it.
Can the tool tell me how the result will look?
No, and this guide does not either. The planner sees formats, numbers and byte counts, never pixels, so the page makes no visual-quality claims. What the tool can do is verify: the output is sniffed with the same format detector used on inputs and re-decoded to confirm its dimensions before the download button appears.
Local processing: every quality encode and every probe of a target-size search runs inside your browser. Files are decoded, converted, and verified entirely in your browser and never transmitted — see the methodology page for the search algorithm and how to verify the no-upload claim yourself.