runtime:images

Decode, transform and encode images. The chain is Bun.Image's: new Image(input), transforms that each return a new image, one output format, and an awaited terminal. Nothing is decoded until a terminal or metadata() is awaited, and the work runs off the event loop.

Capability: none for bytes

Bytes in and bytes out need nothing. A runtime:fs file() source needs FileRead and a file() destination FileWrite, checked and jailed as reading or writing that file would be. Status: Available.

Import

JavaScript
import { Image } from "runtime:images";

// Or the default aggregate:
import images from "runtime:images";

new Image(input, options?)

input is a Uint8Array, an ArrayBuffer, any view, a Blob, or a runtime:fs file(). A path string is a TypeError: pass file(path). A SharedArrayBuffer or a resizable buffer is a TypeError. The bytes are copied when a terminal is called. The format is read from the bytes, never from a name.

OptionDefaultEffect
maxPixels268402689Over this many pixels fails at the header with ERR_IMAGE_TOO_MANY_PIXELS, before allocation. Applies with nothing set; pass a number to lower or raise it.
autoOrienttrueApply the orientation the file declares; metadata() reports the upright size.
toSrgbtrueConvert an embedded matrix/TRC ICC profile to sRGB. Off, keep the pixels and write the profile to outputs.
animatedfalseEvery frame. Not yet supported: an animation with this set fails with ERR_IMAGE_FORMAT_UNSUPPORTED. Unset, an animation is its first frame.

Transforms

Each returns a new Image and leaves the original unchanged.

MethodDescription
resize(width, height?, options?)Scale to a size. See Resize options.
crop({ left, top, width, height })Keep a region. Outside the image is a RangeError from the terminal.
rotate(degrees)Clockwise, a multiple of 90.
flip() / flop()Mirror top to bottom / left to right.
modulate({ brightness?, saturation?, hue? })Multipliers (1 unchanged); hue in degrees.
blur(sigma)Gaussian, sigma in pixels.
sharpen(amount = 1)3×3 sharpen.
flatten({ background? })Draw over background (default black), drop alpha.
grayscale()Grey, keeping alpha.
extractChannel(channel)0–3 or "red", "green", "blue", "alpha".

A colour is "#rgb", "#rgba", "#rrggbb", "#rrggbbaa", or { r, g, b, alpha } with alpha from 0 to 1.

Resize options

resize(width, height?, options?) scales to width × height. Omit either side, or pass null, to keep the aspect ratio: resize(400) is 400 pixels wide at the image's own proportions.

OptionDefaultDescription
fit"fill"How the image meets the box. See below.
filter"lanczos3"The resampling kernel. See below.
backgroundtransparentThe padding colour when fit is "contain".
withoutEnlargementfalseNever make the image larger than it is.

fit:

ValueResult
"fill"Exactly width × height; the aspect ratio is not kept.
"inside"As large as fits inside the box, aspect ratio kept.
"outside"As small as covers the box, aspect ratio kept.
"cover"Fills the box, aspect ratio kept; the overflow is cropped from the centre.
"contain"Fits inside the box, aspect ratio kept; the rest is padded with background, centred.

filter:

ValueUse
"lanczos3"Photographs. The sharpest.
"lanczos2"A little softer than "lanczos3", with less ringing.
"mitchell"Balanced sharpness and smoothness.
"catmull-rom"Bicubic. "cubic" is the same filter.
"bilinear"Fast, soft. "linear" is the same filter.
"box"Averages; fast downscaling.
"nearest"Keeps exact pixel values: pixel art, masks.

Output formats

The last format method wins. Without one, the source's format. Never the destination's extension.

MethodOptionsNotes
jpeg()quality 1–100 (80)Baseline. progressive is a TypeError.
png()—compressionLevel, palette, colors, dither are a TypeError.
webp()quality 1–100 (80), losslessLossy by default.
avif()quality 1–100 (80)8-bit 4:2:0. lossless is a TypeError.
gif()—One frame.
tiff()—

Terminals

MethodResolves to
metadata(){ width, height, format, pixelFormat, hasAlpha, animation } at this point in the chain, from the header. animation is { frames, loop, durations } or null.
bytes()Uint8Array.
blob()Blob with the format's media type.
write(file)Bytes written to a runtime:fs file().

EXIF and XMP are never written to an output.

Errors

Code / classWhen
ERR_IMAGE_DECODE_FAILEDThe bytes are not a valid image of their format.
ERR_IMAGE_FORMAT_UNSUPPORTEDAn unknown format, or a valid file using something not implemented.
ERR_IMAGE_TOO_MANY_PIXELSOver maxPixels.
TypeError / RangeErrorA bad argument; from the method, or from the terminal when only the image shows it.

Reading or writing a file() fails with the runtime:fs errors.

Moving from Bun.Image: see Migrating from Bun.

Last updated on
Edit this page