Preset steps
A preset is a saved list of steps. Each step is an op from the op catalogue wherever one exists — {op, parameters}, with a closed, validated parameter set. Where no op covers what you need — a sharpen, a colour matrix, a progressive JPEG — a step names one of the processing engine’s own operations instead: {operation, params}. This page is that list. You write it when you author a preset; whatever runs the preset later only names it.
{
"name": "Print sharpen",
"slug": "print-sharpen",
"steps": [
{
"op": "resize",
"parameters": {
"width": 1800,
"height": 1200,
"fit": "inside"
}
},
{
"operation": "sharpen",
"params": {
"sigma": 1.5,
"m1": 1.5,
"m2": 0.7
}
},
{
"operation": "jpeg",
"params": {
"quality": 100,
"progressive": true
}
}
]
}Five rules
- Params go to Sharp verbatim.
paramsis handed to the Sharp method of the same name, so the signature is Sharp’s at the version the processing image pins. Each row below links to it; nothing here restates it. - A parameter that names another image takes one of your assets —
{"assetId": "<id>"}— or inline data. That iscomposite.images[].input,joinChannel.images[],boolean.operandandoverlay.input. The asset has to be yours — any other id is404 not_foundwhen the job is submitted, dry run included, and one still uploading is400 invalid_state— and a step that reads one runs as a job, never synchronously. A string is refused: a storage key is not a caller’s to name, and anything else the engine would read as a path on its own disk. For the same reason a list is refused there (Sharp reads it as paths to join), and so is a{text: {fontfile}}layer — name an installed font withfont. - Three keys are decoder directives, not Sharp methods.
autoOrient,densityandanimatedare read before the first byte is decoded, because by then the way the file is opened is already decided. Their position instepsdoes not matter. - Finishers run last, in your order;
maxBytesruns after them.mask,blurRegion,overlayandcaptionneed the finished pixels’ size, so they run once every other step has, as one composite and one encode. Amaskdeclared before ablurRegionerases it. The byte budget is measured on the very end, so it is always the final act. - An unknown key is refused when you save; a wrong parameter shape, when the step runs. Saving checks the key (
400 invalid_paramonsteps[i].operation) and the image parameters of rule 2, not the rest ofparams— that is Sharp’s signature, and a second copy would drift. Sharp checks it as the step is built: synchronously the call is400 invalid_paramnaming the key; in a job the item fails on its first attempt withinvalid_paramandretryable: false. Never retried, never silently skipped.
One default sits under all of it: every pipeline orients the image by its EXIF tag before your first step, so crop, pad and resize speak the coordinates you see in a viewer. To keep the stored pixels untouched, add {"operation": "autoOrient", "params": false}.
Stability
The keys below are a closed set, and the set is what is promised. A key can be removed once an op replaces it — the replaced by column says which, and a step that can be written as an op should be. Parameter signatures follow the pinned Sharp version; a Sharp upgrade that changes a signature changes it here, without a compatibility layer. Ops keep a stable, validated contract for exactly this reason: prefer them.
Transform
| Key | Sharp | Replaced by | Note |
|---|---|---|---|
resize | resize | resize | kernel and withoutReduction are registry-only; the op takes background with fit: contain only. |
extend | extend | pad | extendWith mirror / repeat is registry-only. No background: transparent, white on JPEG. |
extract | extract | crop | Before resize crops then scales; after it scales then crops. |
trim | trim | trim | lineArt and margin are registry-only. |
rotate | rotate | rotate | A number, or {angle, options: {background}}. Does not stack with the default orientation. |
flip · flop | flip | flip · flop | Vertical / horizontal mirror. Each is a switch, not an action: writing it twice flips once. |
affine | affine | — | Shear and arbitrary affine transforms. |
autoOrient | autoorient | — | Every pipeline already orients by EXIF; the only meaningful value is params: false to keep the stored pixels. |
Colour
| Key | Sharp | Replaced by | Note |
|---|---|---|---|
sharpen | sharpen | — | {} or no params is the fast sharpen. |
median | median | — | Denoise. |
blur | blur | — | Whole-image blur. A region is the blur_region op. |
flatten | flatten | flatten | Added for you when convert / compress writes JPEG. |
unflatten | unflatten | — | |
gamma | gamma | — | A number 1.0–3.0, or {gamma, gammaOut}. |
negate | negate | — | |
normalise · normalize | normalise | — | Stretch contrast between two percentiles. |
clahe | clahe | — | Local histogram equalisation. |
convolve | convolve | — | {width, height, kernel[], scale, offset}. |
threshold | threshold | — | A number 0–255, or {value, greyscale}. |
boolean | boolean | — | operand is another image: one of your assets, {"assetId": "<id>"} (job lane only), or inline bytes. |
linear | linear | adjust (contrast) | {a, b}, per channel as arrays. adjust's contrast is a = c, b = 128 (1 − c). |
recomb | recomb | — | A 3×3 or 4×4 colour matrix: sepia, duotone. |
modulate | modulate | adjust | brightness, saturation, hue, lightness. |
tint | tint | — | A CSS colour. |
greyscale · grayscale | greyscale | grayscale | |
pipelineColourspace · pipelineColorspace | pipelinecolourspace | — | rgb16, scrgb: a 16-bit or linear-light pipeline. |
toColourspace · toColorspace | tocolourspace | colorSpace=srgb (shared) | The shared parameter also attaches the profile; other spaces are registry-only. |
dilate · erode | dilate | — | Morphology, width in pixels. |
Channel
| Key | Sharp | Replaced by | Note |
|---|---|---|---|
removeAlpha | removealpha | — | |
ensureAlpha | ensurealpha | — | 0–1. |
extractChannel | extractchannel | — | 0–3, or red / green / blue / alpha. |
joinChannel | joinchannel | — | {images: […]}; an entry is one of your assets, {"assetId": "<id>"} (job lane only), or inline — never a string. |
bandbool | bandbool | — | and / or / eor. |
Format
The last format step decides the result's Content-Type. With no format step the result keeps the input's format when it is one of the seven below; anything else — a RAW, a HEIF, a PSD, an SVG — comes out in a web format the engine picks (lossless WebP or PNG), so name a format step when the format matters. maxBytes is not an encoder option: on a jpeg, webp, avif or heif step it is the byte budget the engine meets by re-encoding after everything else has run.
| Key | Sharp | Replaced by | Note |
|---|---|---|---|
jpeg | jpeg | convert · compress | Encoder options pass through; mozjpeg is built in. |
png | png | convert · compress | palette: true is pngquant-style quantisation, often half the bytes — registry-only. |
webp | webp | convert · compress | Animated input passes through with frame: all. |
gif | gif | convert | Lossless; maxBytes does not apply. |
avif | avif | convert · compress | |
heif | heif | — | compression is av1 only (the result is AVIF); hevc is 400. |
tiff | tiff | convert | Pyramid and tiled TIFF can be written. |
toFormat | toformat | — | {format, options}; only the seven formats above. |
Metadata
By default the output carries no EXIF, ICC or XMP — only the oriented pixels. Keeping any of it is an explicit step here, or metadata: keep on an op.
| Key | Sharp | Replaced by | Note |
|---|---|---|---|
keepExif | keepexif | — | |
withExif | withexif | — | Replaces the whole EXIF block: camera and GPS are gone with it. |
withExifMerge | withexifmerge | — | Merges into the original EXIF — a copyright written this way keeps the GPS too. |
keepIccProfile | keepiccprofile | — | |
withIccProfile | withiccprofile | colorSpace=srgb (shared) | Built-in names only: srgb, p3, cmyk. |
keepXmp · withXmp | keepxmp | — | |
keepMetadata | keepmetadata | metadata=keep (shared) | EXIF, ICC, XMP and IPTC, all of it. |
withMetadata | withmetadata | — | Sets DPI via density — and keeps every block, GPS included. Setting a print resolution publishes the shooting location. Its icc takes srgb, p3 or cmyk only. |
timeout | timeout | — | {seconds} for the pipeline. |
Composite
| Key | Sharp | Replaced by | Note |
|---|---|---|---|
composite | composite | overlay · caption · mask · pad | The general layer entry, for blends and per-pixel placement the four ops do not express. input is one of your assets — {"assetId": "<id>"} — or {create}, {text} or SVG/PNG bytes; job lane only. |
Decoder directives
Not Sharp methods: these are read before the first byte is decoded, so the engine knows how to open the file.
| Key | Sharp | Replaced by | Note |
|---|---|---|---|
density | not a Sharp method | density (shared) | DPI to rasterise a vector input at (72 when unset); ignored for rasters. |
animated | not a Sharp method | frame=all (shared) | true reads every frame; the default reads the first. |
Finishers
Not Sharp methods: they need the finished pixels' size, so they run after every other step, in the order you declare them, as one composite and one encode. maxBytes always runs last.
| Key | Sharp | Replaced by | Note |
|---|---|---|---|
mask | not a Sharp method | mask | {shape: circle | rounded, radius}. |
blurRegion | not a Sharp method | blur_region | {left, top, width, height, sigma | pixelate}. |
overlay | not a Sharp method | overlay | {input: {"assetId": "<id>"}, gravity, opacity, scale, margin, tile}; job lane only. |
caption | not a Sharp method | caption | {text, font, size, color, gravity, margin, background}. |
What a preset is, how versions and subjects work, and how to run one: presets. Worked examples, ready to save: recipes. The ops themselves, with their parameter contracts: the op catalogue.