Image output
output() produces one transformed image: keep or change the format, and
set quality, target size, resize and the other route-honored controls along the
way.
It is the single image-transform verb. You do not pick an operation — the SDK resolves the route from your input format and requested output format:
- Same format (or no format given) → the optimiser route.
- Format change → the transcoder route.
How much the SDK checks for you depends on the kind of mistake:
- An option key no image route recognises is rejected as soon as you call
output(), before any upload. - A real key that the resolved route does not honor (for example
progressiveon a format change) is caught when the recipe lowers, which both SDKs run before the upload — a route-invalid option never costs you bytes. - A value outside the option's enum (for example
metadata: 'keep'on AVIF or SVG) is caught before upload on the same-format route — the SDK checks the requested value against the format's accepted enum, not just the contract'splannedmarkers.
- TypeScript
- PHP
// Omit the format to keep the input format.
const result = await client
.file('photo.jpg')
.output(undefined, { quality: 80 })
.run({ maxWait: '2m' });
// Or change format.
const webp = await client
.file('photo.jpg')
.output('webp', { quality: 80 })
.run({ maxWait: '2m' });
// Omit the format to keep the input format.
$client->file('photo.jpg')
->output(options: ['quality' => 80])
->run(maxWait: '2m');
// Or change format.
$client->file('photo.jpg')
->output('webp', ['quality' => 80])
->run(maxWait: '2m');
Hitting a target size
Set encoding_mode: 'target_size' and give target_size_bytes (minimum 1024).
The encoder aims for that size instead of a quality slider. Honored on
same-format avif, jpeg and webp.
- TypeScript
- PHP
const result = await client
.file('photo.jpg')
.output(undefined, {
encoding_mode: 'target_size',
target_size_bytes: 200 * 1024,
})
.run({ maxWait: '2m' });
$client->file('photo.jpg')
->output(options: [
'encoding_mode' => 'target_size',
'target_size_bytes' => 200 * 1024,
])
->run(maxWait: '2m');
target_size_bytes is in bytes. For "200 KB", write 200 * 1024.
Resizing
resize() is part of the output transform, not a separate artifact — it merges
into the preceding output() step, so you get one image out. If nothing
precedes it, it adds a same-format output step carrying the resize. It never
emits a thumbnail.
Height is optional; width-only preserves the aspect ratio. fit takes max,
crop or scale.
- TypeScript
- PHP
// Width-only — aspect ratio preserved.
await client.file('photo.jpg').resize(1200).run({ maxWait: '2m' });
// Merged into the output() step — still one artifact.
await client
.file('photo.jpg')
.output('webp', { quality: 80 })
.resize(1200, 800, 'crop')
.run({ maxWait: '2m' });
// Width-only — aspect ratio preserved.
$client->file('photo.jpg')->resize(1200)->run(maxWait: '2m');
// Merged into the output() step — still one artifact.
$client->file('photo.jpg')
->output('webp', ['quality' => 80])
->resize(1200, 800, 'crop')
->run(maxWait: '2m');
You can equally pass width / height / fit straight to output() — same
result, same single operation.
Resize is raster-only. A vector input such as SVG has no resize on its route and throws when the recipe lowers.
Stripping metadata
metadata defaults to strip. Pass keep to preserve EXIF and friends on
same-format jpeg, png, webp, gif and tiff. On a format change it is planned,
so asking for it there is rejected rather than silently keeping metadata.
keep is not offered for AVIF or SVG — AVIF is re-encoded from pixels and
SVG is optimised as markup, so neither can carry the original metadata through.
Those routes accept strip only, and the SDK rejects metadata: 'keep' on an
AVIF or SVG base before upload rather than letting the server reject it.
auto_orient rotates per the EXIF orientation flag — worth pairing with
metadata: 'strip', since stripping EXIF otherwise discards the orientation
that some viewers rely on. Honored on the raster routes; SVG honors only
metadata. auto_orient on an SVG format change is rejected before upload
(SVG is vector — it cannot be auto-oriented).
- TypeScript
- PHP
await client
.file('photo.jpg')
.output(undefined, { metadata: 'keep', auto_orient: true })
.run({ maxWait: '2m' });
$client->file('photo.jpg')
->output(options: ['metadata' => 'keep', 'auto_orient' => true])
->run(maxWait: '2m');
Colour profile and chroma
color_profile handles the embedded ICC profile: keep, srgb (convert), or
strip. Availability depends on the route and value.
chroma_subsampling takes 420 (smallest), 422 or 444 (highest fidelity),
and is honored on same-format JPEG only.
- TypeScript
- PHP
await client
.file('photo.jpg')
.output(undefined, { color_profile: 'srgb', chroma_subsampling: '444' })
.run({ maxWait: '2m' });
$client->file('photo.jpg')
->output(options: ['color_profile' => 'srgb', 'chroma_subsampling' => '444'])
->run(maxWait: '2m');
All options
| Option | Type | Honored on |
|---|---|---|
quality | 1–100 | Same-format avif/jpeg/png/webp/gif/tiff, and lossy format changes. |
encoding_mode | quality | target_size | Same-format avif/jpeg/webp. |
target_size_bytes | number (≥ 1024) | With encoding_mode: 'target_size'. |
chroma_subsampling | 420 | 422 | 444 | Same-format jpeg. |
width / height | number | Raster routes. 1–16384; width × height ≤ 16MP. |
fit | max | crop | scale | When width or height is set. |
background | hex string | Format change to jpeg — fills transparency. |
progressive | boolean | Same-format jpeg. |
optimization_level | number | Same-format png (lossless effort). |
avif_speed | number | Same-format avif (encode speed). |
metadata | strip | keep | Same-format. keep not offered on avif/svg. Planned on format change. |
color_profile | keep | srgb | strip | Route- and value-dependent. |
auto_orient | boolean | Raster routes. Not honored on svg. |
lossless | boolean | Same-format jpeg/webp. |
Passing a format in the options bag is rejected — the first argument owns it.