Skip to content

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

  1. Params go to Sharp verbatim. params is 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.
  2. A parameter that names another image takes one of your assets — {"assetId": "<id>"} — or inline data. That is composite.images[].input, joinChannel.images[], boolean.operand and overlay.input. The asset has to be yours — any other id is 404 not_found when the job is submitted, dry run included, and one still uploading is 400 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 with font.
  3. Three keys are decoder directives, not Sharp methods. autoOrient, density and animated are read before the first byte is decoded, because by then the way the file is opened is already decided. Their position in steps does not matter.
  4. Finishers run last, in your order; maxBytes runs after them. mask, blurRegion, overlay and caption need the finished pixels’ size, so they run once every other step has, as one composite and one encode. A mask declared before a blurRegion erases it. The byte budget is measured on the very end, so it is always the final act.
  5. An unknown key is refused when you save; a wrong parameter shape, when the step runs. Saving checks the key (400 invalid_param on steps[i].operation) and the image parameters of rule 2, not the rest of params — that is Sharp’s signature, and a second copy would drift. Sharp checks it as the step is built: synchronously the call is 400 invalid_param naming the key; in a job the item fails on its first attempt with invalid_param and retryable: 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

KeySharpReplaced byNote
resizeresizeresizekernel and withoutReduction are registry-only; the op takes background with fit: contain only.
extendextendpadextendWith mirror / repeat is registry-only. No background: transparent, white on JPEG.
extractextractcropBefore resize crops then scales; after it scales then crops.
trimtrimtrimlineArt and margin are registry-only.
rotaterotaterotateA number, or {angle, options: {background}}. Does not stack with the default orientation.
flip · flopflipflip · flopVertical / horizontal mirror. Each is a switch, not an action: writing it twice flips once.
affineaffine—Shear and arbitrary affine transforms.
autoOrientautoorient—Every pipeline already orients by EXIF; the only meaningful value is params: false to keep the stored pixels.

Colour

KeySharpReplaced byNote
sharpensharpen—{} or no params is the fast sharpen.
medianmedian—Denoise.
blurblur—Whole-image blur. A region is the blur_region op.
flattenflattenflattenAdded for you when convert / compress writes JPEG.
unflattenunflatten—
gammagamma—A number 1.0–3.0, or {gamma, gammaOut}.
negatenegate—
normalise · normalizenormalise—Stretch contrast between two percentiles.
claheclahe—Local histogram equalisation.
convolveconvolve—{width, height, kernel[], scale, offset}.
thresholdthreshold—A number 0–255, or {value, greyscale}.
booleanboolean—operand is another image: one of your assets, {"assetId": "<id>"} (job lane only), or inline bytes.
linearlinearadjust (contrast){a, b}, per channel as arrays. adjust's contrast is a = c, b = 128 (1 − c).
recombrecomb—A 3×3 or 4×4 colour matrix: sepia, duotone.
modulatemodulateadjustbrightness, saturation, hue, lightness.
tinttint—A CSS colour.
greyscale · grayscalegreyscalegrayscale
pipelineColourspace · pipelineColorspacepipelinecolourspace—rgb16, scrgb: a 16-bit or linear-light pipeline.
toColourspace · toColorspacetocolourspacecolorSpace=srgb (shared)The shared parameter also attaches the profile; other spaces are registry-only.
dilate · erodedilate—Morphology, width in pixels.

Channel

KeySharpReplaced byNote
removeAlpharemovealpha—
ensureAlphaensurealpha—0–1.
extractChannelextractchannel—0–3, or red / green / blue / alpha.
joinChanneljoinchannel—{images: […]}; an entry is one of your assets, {"assetId": "<id>"} (job lane only), or inline — never a string.
bandboolbandbool—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.

KeySharpReplaced byNote
jpegjpegconvert · compressEncoder options pass through; mozjpeg is built in.
pngpngconvert · compresspalette: true is pngquant-style quantisation, often half the bytes — registry-only.
webpwebpconvert · compressAnimated input passes through with frame: all.
gifgifconvertLossless; maxBytes does not apply.
avifavifconvert · compress
heifheif—compression is av1 only (the result is AVIF); hevc is 400.
tifftiffconvertPyramid and tiled TIFF can be written.
toFormattoformat—{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.

KeySharpReplaced byNote
keepExifkeepexif—
withExifwithexif—Replaces the whole EXIF block: camera and GPS are gone with it.
withExifMergewithexifmerge—Merges into the original EXIF — a copyright written this way keeps the GPS too.
keepIccProfilekeepiccprofile—
withIccProfilewithiccprofilecolorSpace=srgb (shared)Built-in names only: srgb, p3, cmyk.
keepXmp · withXmpkeepxmp—
keepMetadatakeepmetadatametadata=keep (shared)EXIF, ICC, XMP and IPTC, all of it.
withMetadatawithmetadata—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.
timeouttimeout—{seconds} for the pipeline.

Composite

KeySharpReplaced byNote
compositecompositeoverlay · caption · mask · padThe 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.

KeySharpReplaced byNote
densitynot a Sharp methoddensity (shared)DPI to rasterise a vector input at (72 when unset); ignored for rasters.
animatednot a Sharp methodframe=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.

KeySharpReplaced byNote
masknot a Sharp methodmask{shape: circle | rounded, radius}.
blurRegionnot a Sharp methodblur_region{left, top, width, height, sigma | pixelate}.
overlaynot a Sharp methodoverlay{input: {"assetId": "<id>"}, gravity, opacity, scale, margin, tile}; job lane only.
captionnot a Sharp methodcaption{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.