Getting Started
@napi-rs/image is a fast image-processing library for Node.js and the browser. It wraps battle-tested Rust codecs — mozjpeg, oxipng, libwebp, ravif/aom and resvg — behind one small, ergonomic API.
On Node.js it loads a prebuilt native binary (no compiler, no node-gyp). Where a native binary is unavailable it falls back to a WebAssembly build, which is also what powers the in-browser Playground.
Install
npm install @napi-rs/image
yarn add @napi-rs/image
pnpm add @napi-rs/image
Prebuilt binaries ship for macOS (x64 / arm64), Windows (x64 / arm64 / ia32), Linux (gnu + musl, x64 / arm64 / armv7), Android arm64, FreeBSD, and a wasm32-wasi build for everything else. The right one is selected automatically at import time.
60-second example
Decode an image, optimize it, and convert it to a modern format:
import { readFile, writeFile } from 'node:fs/promises'
import { Transformer, ChromaSubsampling } from '@napi-rs/image'
const input = await readFile('./photo.jpg')
// Re-encode to AVIF at quality 75 with 4:2:0 chroma subsampling.
const avif = await new Transformer(input).avif({
quality: 75,
chromaSubsampling: ChromaSubsampling.Yuv420,
})
await writeFile('./photo.avif', avif)
Or compress a file in place, keeping the same format:
import { readFile, writeFile } from 'node:fs/promises'
import { compressJpeg, losslessCompressPng } from '@napi-rs/image'
await writeFile('./small.jpg', await compressJpeg(await readFile('./big.jpg'), { quality: 75 }))
await writeFile('./small.png', await losslessCompressPng(await readFile('./big.png')))
The mental model
There are two entry points, and they cover different jobs:
new Transformer(input) // decode → transform (resize/rotate/crop) → encode to ANY format
.resize()
.rotate() // chainable, returns `this`
.webp() // async encoders → Promise<Buffer>
.webpSync() // sync encoders → Buffer
// Standalone optimizers — same format in → same format out, bytes shrunk IN PLACE:
compressJpeg(bytes)
losslessCompressPng(bytes)
pngQuantize(bytes)
Transformeris for decoding, geometry/color transforms, and converting between formats. Construct it from encoded bytes (new Transformer(bytes)), from SVG (Transformer.fromSvg), or from raw RGBA pixels (Transformer.fromRgbaPixels).- Standalone compressors (
compressJpeg,losslessCompressPng,pngQuantize) take encoded bytes and return smaller encoded bytes of the same format. Use them when you just want a smaller file.
Async or sync?
Every encoder and the metadata reader come in two flavours:
- Async (
webp,avif,png,jpeg,metadata, …) run on a background thread pool and return aPromise. Prefer these on servers so you never block the event loop. They also accept an optionalAbortSignal. - Sync (
webpSync,avifSync,metadataSync, …) run on the calling thread and return immediately. Handy in scripts and CLIs.
const buf = await new Transformer(input).webp(80) // async, off the event loop
const buf2 = new Transformer(input).webpSync(80) // sync, blocks until done
Supported formats
| Format | Decode (input) | Encode (output) |
|---|---|---|
| JPEG | ✅ | ✅ |
| PNG | ✅ | ✅ |
| WebP | ✅ | ✅ |
| AVIF | ✅ | ✅ |
| GIF | ✅ | — |
| TIFF | ✅ | ✅ |
| BMP | ✅ | ✅ |
| ICO | ✅ | ✅ |
| TGA | ✅ | ✅ |
| PNM | ✅ | ✅ |
| Farbfeld | ✅ | ✅ |
| SVG | ✅ (fromSvg) |
— |
Where to next
- API Reference — every method, function and option.
- Format Guides — choosing quality, speed and chroma for WebP, AVIF, PNG and JPEG.
- Recipes — EXIF-correct thumbnails, SVG rasterization, watermarking, batch optimization, cancellation.
- Playground — run all of this in your browser, no install.