Skip to content

Latest commit

 

History

History
479 lines (327 loc) · 15.5 KB

File metadata and controls

479 lines (327 loc) · 15.5 KB

Transform parameters

imgx uses a /image/<OPTIONS>/<SOURCE-IMAGE> URL convention: a fixed image/ prefix, then an OPTIONS segment, then the source image path. imgx treats the segment immediately after the prefix as the options segment when it contains =. Separate multiple parameters with commas.

GET /image/<options>/<image-path>
GET /image/w=400,h=300,f=webp,q=85/photos/hero.jpg

The source-image segment is normally a relative path, resolved against IMGX_ORIGIN_BASE_URL. It may instead be an absolute http:///https:// URL, fetched directly instead of from the configured origin — but only when the operator has set IMGX_ALLOW_REMOTE_SOURCES=true (default false); otherwise such a request returns 403 Forbidden before any network call. See IMGX_ALLOW_REMOTE_SOURCES in Configuration for the security guards this enables and the risk it accepts.

GET /image/w=400/https://example.com/photos/hero.jpg

Dimensions

w / width

Output width in pixels, resized according to the current fit mode.

  • Range: 1–8192
  • Default: original width
/image/w=400/photo.jpg
/image/width=400/photo.jpg

h / height

Output height in pixels.

  • Range: 1–8192
  • Default: original height
/image/h=300/photo.jpg
/image/w=400,h=300/photo.jpg

When you specify only one dimension, imgx derives the other from the source aspect ratio.

dpr

Device pixel ratio. Multiplies w and h for retina and HiDPI displays. The effective dimensions are clamped to 8192.

  • Range: 1.0–5.0
  • Default: 1.0
# 400px at 2x = 800px actual output
/image/w=400,dpr=2/photo.jpg

Quality

q / quality

Compression quality for lossy formats (JPEG, WebP, AVIF). Higher values produce larger files with fewer artifacts. Has no effect on PNG.

  • Range: 1–100, or a perceptual quality string: high, medium-high, medium-low, low
  • Default: 80
/image/q=90/photo.jpg
/image/w=400,q=60/photo.jpg
/image/quality=high/photo.jpg

:::info Perceptual quality strings map to high=90, medium-high=80, medium-low=60, low=40 — a spec-derived mapping (Cloudflare documents the strings but not exact integer values). See docs/CLOUDFLARE_PARITY.md gap 4. :::

scq / slow-connection-quality

Overrides quality when the request's client-hint headers (rtt, save-data, ect, downlink) indicate a slow connection: rtt over 150ms, save-data: on, ect in slow-2g/2g/3g, or downlink under 5Mbps.

  • Range: same as quality — 1–100, or a perceptual quality string
  • Default: unset (no override)
/image/q=80,scq=40/photo.jpg

:::info Because the effective quality changes based on the requesting client's headers, imgx caches the two variants separately — a request with the override applied and one without are different cache entries, even for the same URL. See docs/CLOUDFLARE_PARITY.md gap 8. :::

compression

Prioritizes encoding speed over output quality/size. Accepts fast, which biases format selection away from AVIF/WebP (the slowest encoders) toward JPEG — this applies even when an explicit format=avif/format=webp is requested.

  • Values: fast
  • Default: unset
/image/compression=fast/photo.jpg

Format

f / fmt / format

Output format. When set to auto or omitted, imgx negotiates the format from the client's Accept header.

  • Values: jpeg, jpg, png, webp, avif, gif, baseline-jpeg, json, auto
  • Default: auto
/image/f=webp/photo.jpg
/image/format=avif/photo.jpg
/image/fmt=png/photo.jpg
/image/f=gif/animation.gif
/image/f=baseline-jpeg/photo.jpg
/image/w=200,format=json/photo.jpg

baseline-jpeg produces non-progressive (baseline sequential) JPEG — the same encode path as jpeg today (libvips defaults to baseline unless progressive encoding is explicitly requested).

format=json returns a metadata-only JSON response instead of image bytes:

{
  "original": { "width": 2000, "height": 1500, "file_size": 123456 },
  "transformed": { "width": 200, "height": 150, "format": "webp", "file_size": 4821 }
}

transformed.format/transformed.file_size are computed by actually negotiating and encoding a real codec — real numbers, not placeholders. See docs/CLOUDFLARE_PARITY.md gap 5 for the schema's provenance (spec-derived — Cloudflare doesn't publish an exact field-by-field schema).

Fit mode

fit

Controls how the image fits the target dimensions.

Value Aliases Behavior
contain scale-down Scale down to fit within the dimensions. Preserves aspect ratio. Never upscales. (default)
cover Scale and crop to fill the exact dimensions. Uses gravity to pick the crop anchor. Upscales if needed.
fill squeeze Stretch to exactly fill the dimensions. Ignores aspect ratio.
inside Same as contain.
outside scale-up Scale up to cover the dimensions. Preserves aspect ratio. Never downscales.
pad Resize like contain, then letterbox onto the target canvas using the background color.
crop Fill the target area like cover, but never upscales — behaves like contain when the source is smaller than the target.
aspect-crop Crop to the target aspect ratio. Downscales (never upscales) when the source is large enough to cover the target; otherwise crops the original-size image directly to the target ratio.
/image/w=400,h=400,fit=cover/photo.jpg
/image/w=400,h=300,fit=fill/photo.jpg
/image/w=400,h=400,fit=crop/photo.jpg
/image/w=400,h=200,fit=aspect-crop/photo.jpg

With fit=pad, set both w and h to force a fixed output canvas. The padding color comes from bg/background and defaults to white. For animated output, fit=pad currently behaves like contain.

scale-down, squeeze, and scale-up are Cloudflare Images' names for pixel-dimension-equivalent behavior imgx already had under contain, fill, and outside respectively — see docs/CLOUDFLARE_PARITY.md gap 3 for the equivalence proof. imgx's own default (contain) is unchanged.

Gravity

g / gravity

When fit=cover crops the image, this controls which region to keep.

Value Aliases Behavior
center centre Crop from center (default)
north n, top Keep the top edge
south s, bottom Keep the bottom edge
east e, right Keep the right edge
west w, left Keep the left edge
northeast ne Keep the top-right corner
northwest nw Keep the top-left corner
southeast se Keep the bottom-right corner
southwest sw Keep the bottom-left corner
smart auto Entropy-based detection (keeps high-detail areas)
attention att Attention-based detection (keeps visually interesting areas)
/image/w=400,h=400,fit=cover,g=smart/photo.jpg
/image/w=400,h=400,fit=cover,g=north/photo.jpg
/image/w=400,h=400,fit=cover,g=auto/photo.jpg
/image/w=400,h=400,fit=cover,g=top/photo.jpg

top/bottom/left/right and auto are Cloudflare Images' own gravity vocabulary — aliased onto imgx's existing compass words and smart respectively (same meaning, verified against Cloudflare's docs). Cloudflare's face (face-detection-based gravity) and XxY relative-coordinate focal points are not implemented — see docs/CLOUDFLARE_PARITY.md gap 12.

:::info For content-aware cropping, use smart/auto or attention. Directional values (north, south, and others) fall back to center cropping. :::

Effects

sharpen

Unsharp mask with the given sigma value.

  • Range: 0.0–10.0
/image/sharpen=1.5/photo.jpg
/image/w=400,sharpen=2.0/photo.jpg

blur

Gaussian blur with the given sigma value.

  • Range: 0.1–250.0
/image/blur=3.0/photo.jpg
/image/w=400,blur=10.0/photo.jpg

brightness

  • Range: 0.0–2.0 (1.0 is normal)
/image/brightness=1.2/photo.jpg

contrast

  • Range: 0.0–2.0 (1.0 is normal)
/image/contrast=1.3/photo.jpg

saturation

  • Range: 0.0–2.0 (1.0 is normal)
/image/saturation=0.0/photo.jpg

gamma

Gamma correction.

  • Range: 0.1–10.0
/image/gamma=2.2/photo.jpg

rotate

  • Values: 0, 90, 180, 270
/image/rotate=90/photo.jpg

flip

  • Values: h (horizontal), v (vertical), hv (both)
/image/flip=h/photo.jpg

bg / background

Hex RGB color used for fit=pad canvas fill and alpha flattening before encoding. Useful when converting transparent PNGs to JPEG.

  • Format: 6-character hex, no # prefix
/image/f=jpeg,bg=ffffff/photo.png

border / border.color / border.top / border.right / border.bottom / border.left

Draws a solid-color border around the image, applied after resizing. Border widths scale with dpr.

  • border: uniform width in pixels on all four sides
  • border.color: 6-character hex, no # prefix (default: 000000)
  • border.top/.right/.bottom/.left: per-side width, overriding border for that side
/image/border=10/photo.jpg
/image/border=4,border.color=ff0000/photo.jpg
/image/border.top=2,border.left=8/photo.jpg

:::info Cloudflare's border is available only through its Workers API, with no published URL-interface syntax — the key names above are spec-derived to match imgx's existing dotted-key conventions. See docs/CLOUDFLARE_PARITY.md gap 10. :::

trim

Detect and crop uniform borders around the image (border-color-aware).

  • Range: 1.0–100.0 (threshold)
/image/trim=10/photo.jpg

trim.top / trim.right / trim.bottom / trim.left

Crop a fixed amount from one or more edges independently — NOT border-color aware (unlike trim above), and may be combined with each other or with trim.

  • Values: an integer pixel count, or a decimal 0.01.0 fraction of that side's dimension
/image/trim.top=100,trim.left=50/photo.jpg
/image/trim.left=0.1,trim.right=0.1/photo.jpg

See docs/CLOUDFLARE_PARITY.md gap 9 for what's implemented (per-side keys) versus not yet (the combined top;right;bottom;left syntax, trim.height/trim.width).

metadata

Controls EXIF and ICC metadata in the output.

  • Values: strip (default), keep, copyright
/image/metadata=keep/photo.jpg

Animation

anim

Controls whether animated images (GIF, animated WebP) preserve animation in the output.

Value Aliases Behavior
auto true Preserve animation when the input is animated and the output format supports it. (default)
static false Strip animation. Serve the first frame only.
animate Request animated output. Degrade to static if the format does not support animation.
# Serve an animated GIF, resized
/image/w=64/spinner.gif

# Strip animation (Cloudflare-compatible syntax)
/image/anim=false/spinner.gif

# Strip animation (imgx syntax)
/image/anim=static/spinner.gif

When anim=auto and no explicit format is set, imgx negotiates an animated-capable format from the Accept header: WebP > GIF. If the client accepts neither, the output degrades to a static first frame in the best available format.

frame

Extract a specific 0-indexed frame from an animated image and serve it as a static image.

  • Range: 0–999
  • Default: none (all frames preserved)
/image/frame=0,f=png/spinner.gif
/image/frame=2/spinner.gif

If the index exceeds the number of frames, imgx returns the last frame.

Animation safety limits

Limit Default Environment variable
Max frames 100 IMGX_TRANSFORM_MAX_FRAMES
Max total pixels (width x height x frames) 50,000,000 IMGX_TRANSFORM_MAX_ANIMATED_PIXELS

When the pixel budget is exceeded, the output falls back to a static first frame. When the frame count exceeds max_frames, only that many frames load.


Content negotiation

When the output format is auto (the default), imgx picks the best format from the client's Accept header.

Static images: AVIF > WebP > JPEG > PNG

Animated images: WebP > GIF

The negotiation follows these rules:

  1. Explicit format wins. If you set f=webp, imgx always outputs WebP regardless of Accept.
  2. Animation preservation. For animated sources, imgx prefers animated-capable formats (WebP, GIF).
  3. Alpha channel handling. When the source has transparency, JPEG is deprioritized because it cannot represent alpha.
  4. Client support. Only formats the client advertises in Accept are considered.
  5. Fallback. If no acceptable format matches, JPEG is the universal fallback.

The response includes a Vary: Accept header so CDNs cache different format variants correctly.


Caching behavior

imgx caches transform results using a deterministic key built from the image path, transform parameters, and resolved output format.

Key format: <image-path>|<transform-string>|<format>

Example: photos/hero.jpg|w=400,h=300|webp

Parameter order does not matter. w=400,h=300 and h=300,w=400 produce the same cache key.


Error responses

Invalid transforms return structured JSON errors:

Condition Status Example
Unknown parameter 400 banana=42
Empty value 400 w=
Invalid format 400 f=bmp
Out of range 422 w=0, w=9000, q=101
{"error":{"status":400,"message":"Bad Request","detail":"invalid transform parameters"}}

onerror

Opt-in per-request behavior when the transform pipeline itself fails (a corrupt/unsupported source, an unavailable codec, etc). By default (no onerror), imgx falls back to serving the raw origin bytes as-is. Setting onerror=redirect instead returns a 302 redirect to the origin image URL — only for HTTP origins (not R2, which has no public URL to redirect to).

  • Values: redirect
  • Default: unset (raw-bytes fallback)
/image/w=400,onerror=redirect/photo.jpg

draw (overlays) — opt-in, off by default

draw.<N>.url, draw.<N>.width/.height, .top/.left/.bottom/.right, .opacity, .repeat, .background, .rotate, .fit, .gravity parse and validate (an array of overlays, indexed by <N> starting at 0). By default (IMGX_ALLOW_DRAW_OVERLAYS=false), every request naming a draw overlay returns 403 Forbidden before any network call. Set IMGX_ALLOW_DRAW_OVERLAYS=true to enable fetching draw[].url overlay images through imgx's SSRF-safe remote fetcher (see IMGX_ALLOW_REMOTE_SOURCES in Configuration — this is a separate flag, so an operator can enable overlays without enabling arbitrary remote main-image sources). See docs/CLOUDFLARE_PARITY.md gap 11 for the full status.

/image/draw.0.url=https://example.com/logo.png,draw.0.opacity=0.5/photo.jpg
→ 403 Forbidden by default; composites the overlay onto the base image when IMGX_ALLOW_DRAW_OVERLAYS=true

Full example

GET /image/w=800,h=600,fit=cover,g=attention,f=auto,q=85,dpr=2,sharpen=0.5/products/shoe-red.png

This request:

  1. Fetches products/shoe-red.png from the origin
  2. Resizes to 1600x1200 effective pixels (800x600 at dpr 2)
  3. Crops to fill using attention-based gravity
  4. Negotiates the output format from the client's Accept header
  5. Encodes at quality 85
  6. Applies a light sharpen (sigma 0.5)
  7. Caches the result for subsequent requests