Getting Started
Rust-powered image processing for Node.js: resize, convert and optimize JPEG, PNG, WebP, AVIF and more. Prebuilt native addons handle server and build-script workloads; a WebAssembly build powers browser applications with a Worker and cross-origin isolation.
Use Transformer for thumbnails, format conversion, SVG rasterization and compositing. Use the standalone PNG and JPEG optimizers when you want to keep the input format.
Install
npm install @napi-rs/image
# or: yarn add @napi-rs/image
# or: pnpm add @napi-rs/image
Use a current Node.js LTS release. On supported platforms, npm installs a prebuilt native addon without a local Rust compiler or node-gyp build.
Quick start
Save this as transform.mjs, put a JPEG at input.jpg, and run node transform.mjs:
import { readFile, writeFile } from 'node:fs/promises'
import { Transformer, ResizeFilterType } from '@napi-rs/image'
const input = await readFile('./input.jpg')
const output = await new Transformer(input)
.rotate() // apply EXIF orientation
.resize(800, null, ResizeFilterType.Lanczos3)
.webp(80)
await writeFile('./output.webp', output)
The constructor accepts encoded bytes. Use Transformer.fromSvg(svg) for SVG strings or bytes, and Transformer.fromRgbaPixels(pixels, width, height) for raw RGBA8 input.
Keep the same format
Standalone optimizers return new encoded bytes; they do not modify your input file. Output sizes depend on the source and settings.
import { readFile, writeFile } from 'node:fs/promises'
import { compressJpeg, losslessCompressPng, pngQuantize } from '@napi-rs/image'
const png = await readFile('./input.png')
await writeFile('./optimized.png', await losslessCompressPng(png))
await writeFile('./palette.png', await pngQuantize(png, { maxQuality: 75 })) // lossy
await writeFile('./optimized.jpg', await compressJpeg(await readFile('./input.jpg')))
compressJpeg() uses lossless coefficient optimization by default. Passing { quality: 75 } selects a lossy re-encode. Transformer.jpeg(75) encodes an image from any supported input format.
Async or sync?
Async encoders, optimizers and metadata readers return a Promise and run their work on a background thread pool. Prefer them on servers. *Sync methods block the calling thread and can be useful in scripts. In the browser, follow the async Worker pattern below.
const webp = await new Transformer(input).webp(80)
const webpSync = new Transformer(input).webpSync(80)
Supported formats
This table describes the published 1.15.0 API. The API processes still images and does not expose animation. Color-type support varies by encoder.
| Format | Input | Output | Notes |
|---|---|---|---|
| JPEG | Yes | Yes | Baseline/progressive input; baseline output |
| PNG | Yes | Yes | Includes alpha and 16-bit input |
| WebP | Yes | Yes | Lossy or lossless output |
| AVIF | Yes | Yes | Decoded to 8-bit pixels |
| HEIC / HEIF | macOS / Windows | macOS / Windows | HEVC-in-HEIF; requires an OS codec |
| TIFF | Yes | Yes | Baseline, LZW and PackBits input; no fax support |
| BMP | Yes | Yes | |
| ICO | Yes | Yes | |
| PNM | Yes | Yes | PBM, PGM, PPM and PAM input |
| TGA | No | Yes | Input cannot be auto-detected by Transformer |
| DDS | Yes | No | DXT1, DXT3 and DXT5 input |
| HDR (Radiance) | Yes | No | |
| SVG | Transformer.fromSvg() |
No | Rasterized before further transforms |
| Raw pixels | Transformer.fromRgbaPixels() |
rawPixels() |
Input: RGBA8; output: native-endian bytes in the image's color type |
GIF, OpenEXR and farbfeld codecs are not enabled in the published build. The declared farbfeld() and farbfeldSync() methods currently reject with an unsupported-format error. See Format Guides for HEIC restrictions.
Platforms
Prebuilt native packages are published for:
| Platform | Architectures |
|---|---|
| macOS | x64, arm64 |
| Windows | x64, arm64, ia32 (MSVC) |
| Linux, glibc | x64, arm64, armv7 (gnueabihf) |
| Linux, musl | x64, arm64 |
| Android | arm64 |
| FreeBSD | x64 |
Keep npm optional dependencies enabled so the matching native package can be installed. Browser applications need the separate @napi-rs/image-wasm32-wasi package and the setup below; installing the native package alone does not make every runtime supported.
Browser WebAssembly
The playground is the reference browser integration. It runs images locally in a dedicated Worker and uses the same async API. Browser integration needs more than the Node.js install:
- Install
@napi-rs/image-wasm32-wasiandbuffer. Keep the WASM and main package versions aligned (for example, both1.15.0). - Use a module Worker. Initialize
globalThis.Bufferbefore dynamically importing the image module. Use async image methods so the worker can service nested thread requests. - Configure the bundler to emit ES module workers and include the WASI worker and
.wasmasset. The existing Vite setup aliases@napi-rs/imageto@napi-rs/image-wasm32-wasiand setsworker: { format: 'es' }. - Serve over HTTPS (or localhost) with cross-origin isolation. The document needs both headers below; verify
self.crossOriginIsolated === trueand thatSharedArrayBufferis available.
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
The playground also sends Cross-Origin-Embedder-Policy: require-corp and Cross-Origin-Resource-Policy: same-origin on its worker/assets responses. Resources loaded across origins need compatible CORS or resource-policy headers. Apply these policies in development, preview and production.
The working setup is in vite.config.ts, worker.ts, the Worker client and void.json. The Vite middleware also handles a nested WASI-worker URL quirk in development. Copy the complete integration when using this setup, not just the alias. The worker copies output into a regular ArrayBuffer before transferring it back, because WASM memory may be shared.
To run the existing integration locally from the repository root:
yarn install --immutable
yarn workspace website dev
Open http://localhost:5173/playground, load the sample and run a conversion. HEIC is unavailable in WASM. Hosts without Workers, shared memory or the required isolation policies cannot use this browser setup.
Where to next
- API Reference — methods and options, with links to the full TypeScript declarations.
- Format Guides — codec settings and platform restrictions.
- Recipes — thumbnails, SVG, compositing, migration and batch optimization.
- Playground — compare output formats on your own image.