-
Notifications
You must be signed in to change notification settings - Fork 0
API Reference
Everything is exported from the package root. Every function that can fail throws an
SImgError subclass, never a raw TypeError from inside a decoder.
The entry point. Two functions, deliberately.
Starts a chain from encoded bytes. Nothing is decoded until toBuffer().
Builds a reusable recipe with no image attached. Pass a stored PipelineSpec to restore
one; it is validated, and a bad field throws InvalidOptionError naming it.
SImg.pipeline(); // empty, build it with the methods below
SImg.pipeline(JSON.parse(saved) as PipelineSpec); // restored, and checkedSImgChain and Pipeline share these. Each returns the same type, so they compose in any
order — and the order you call them in does not matter;
execution is always crop → rotate → flip → resize → format.
All four required, in source pixels. Out of bounds throws InvalidOptionError.
Arbitrary angles, in degrees, clockwise. Multiples of 90 are exact — a pure index permutation, no resampling, no quality loss. Anything else resamples and grows the canvas to fit the corners.
| Option | Type | Default |
|---|---|---|
resampling |
'nearest' | 'bilinear' | 'lanczos3' |
'bilinear' |
background |
RGBA |
transparent, composited at encode time |
maxPixels |
number |
134M (refuses to allocate a bigger canvas) |
horizontal mirrors left-to-right. Named for the direction of motion, not the axis of
reflection — the one place every image library confuses everyone.
| Option | Type | Default | Notes |
|---|---|---|---|
width |
number |
one of width/height required | |
height |
number |
||
fit |
'fill' | 'contain' | 'cover' |
'fill' |
only meaningful when both are given |
upscale |
boolean |
true |
|
resampling |
'nearest' | 'bilinear' | 'lanczos3' |
'bilinear' |
|
background |
RGBA |
white | only used by fit: 'contain'
|
Shrink-only: an image already under size is returned untouched, so capping a folder of
mostly-small files costs almost nothing. Use this rather than resize when you mean "no
bigger than".
Drops EXIF, GPS and colour profiles. Already true by construction — decoding to pixels loses metadata, so nothing is copied through unless it is asked for — and this is the explicit, documented way to say you meant it.
An RGBA tuple, [r, g, b, a], each 0–255. One rule for two jobs: the corners a rotation
exposes, and alpha compositing when the target format has no alpha channel. Decided at encode
time, where the format is actually known. See
Transparency.
The output format and its options. Fully typed per format — toFormat('png', { quality: 80 })
is a compile error, because PNG takes no options. See Formats.
The recipe as plain JSON. Round-trips exactly through JSON.parse(JSON.stringify(spec)).
SImgChain only. Runs everything and returns encoded bytes.
Pipeline only. Runs the recipe against bytes. Reusable — call it as often as you like.
Sniffs the format, decodes to RGBA, applies EXIF orientation.
| Option | Type | Default | Notes |
|---|---|---|---|
hintMaxLongEdge |
number |
Decode small, for a preview. A hint — see Previews | |
maxPixels |
number |
134M | The decompression-bomb guard |
Throws UnsupportedFormatError, CorruptImageError, or ImageTooLargeError.
A RawImage to encoded bytes. Options are typed per format.
Dimensions from the header. No pixel buffer, microseconds. Reports dimensions as stored;
decode applies EXIF orientation, so a rotated photo's probe is transposed relative to its
decode.
{ read: Format[], write: Format[], pending: Format[], unavailable: Format[] }read and write are separate arrays even though they are identical today, because one day
they will not be. pending is "not loaded yet, expected to work". unavailable is "tried,
failed, will not retry".
Loads a lazily-loaded codec now rather than on first touch. Only WebP has one. Useful if you would rather pay the cost at startup than on the user's first WebP.
The format from the magic bytes, or undefined. Does not throw.
Node/Bun only. A thin shim; the only part of the library that imports node:fs. A missing
file throws Node's ENOENT unwrapped.
The lower level under Pipeline. applySpec runs a spec against a RawImage and returns
one; validateSpec checks an unknown value and returns it typed, or throws.
A transparent black RGBA buffer.
A deep copy; and a check that a RawImage's buffer length matches its dimensions.
128 * 1024 * 1024 — 134M pixels, about 512 MB of RGBA.
decodePng, encodePng, probePng, and the same trio for Jpeg, Gif, Bmp, Tiff.
The low-level door for a caller who already knows the format and wants to skip the sniff.
Also readExifOrientation(bytes).
WebP has no synchronous entry point, because its WASM has to load.
Every one is exported and nameable. A library that makes callers write
Parameters<typeof x>[0] to name an argument type has failed at its own API.
| Type | |
|---|---|
RawImage |
{ width, height, data: Uint8ClampedArray } — RGBA, non-premultiplied, top-left origin |
RGBA |
readonly [r, g, b, a], each 0–255 |
Format |
'png' | 'jpeg' | 'webp' | 'gif' | 'bmp' | 'tiff' |
FormatOptions<F> |
The options for one format. FormatOptions<'png'> is {}
|
FormatSupport |
What supportedFormats() returns |
PipelineSpec |
The JSON recipe |
ResizeStage |
ResizeOptions | { maxLongEdge, resampling? } |
CropOptions, ResizeOptions, RotateOptions, FlipOptions
|
|
Resampling |
'nearest' | 'bilinear' | 'lanczos3' |
DecodeOptions |
|
SImgErrorCode |
The union of .code values |
FORMATS is the Format union as a runtime array.
Pure TypeScript image editing for Node and Bun. Core: 23.2 KB min+gzip, replacing a 7 MB ImageMagick bundle.
Using it
Working on it