Fast image processing
in Rust.
Encode, compress, resize and convert images — JPEG, PNG, WebP, AVIF and more — with a native Node addon that beats sharp.
import { Transformer, ChromaSubsampling } from '@napi-rs/image'
const webp = await new Transformer(input)
.rotate()
.resize(225)
.webp(75)
const avif = await new Transformer(input)
.rotate()
.resize(225)
.avif({
quality: 70,
chromaSubsampling: ChromaSubsampling.Yuv420,
})Faster than sharp
Apple M1 Max · macOS 12.3.1 · node bench/bench.mjs. Pipeline: rotate → resize(225) → encode.
peak speedup
1.8×
faster WebP encode with UV_THREADPOOL_SIZE=10. AVIF lands at near-parity — WebP is where the gap opens up.
Apple M1 Max · macOS 12.3.1 · node bench/bench.mjs. Pipeline: rotate → resize(225) → encode.
See the bytes disappear
Drag to compare original and optimized — same image, a fraction of the size.


new Transformer(PNG).webp(75)Lossy

new Transformer(PNG).avif({ quality: 75 })Lossy

pngQuantize({ maxQuality: 75 })Lossy

new Transformer(PNG).avif({ quality: 100 })Lossless

new Transformer(PNG).webpLossless()Lossless

losslessCompressPng()Lossless

compressJpeg(JPEG, { quality: 75 })Lossy

compressJpeg()LosslessEvery format you need
WebP and AVIF are fully bidirectional — decode and encode. HDR and DDS are decode-only.
| Format | Decode | Encode | Notes |
|---|---|---|---|
| JPEGrw | ✓ | ✓ | |
| PNGrw | ✓ | ✓ | |
| WebPrw | ✓ | ✓ | |
| AVIFrw | ✓ | ✓ | |
| TIFFrw | ✓ | ✓ | |
| BMPrw | ✓ | ✓ | |
| ICOrw | ✓ | ✓ | |
| TGArw | ✓ | ✓ | |
| PNMrw | ✓ | ✓ | |
| farbfeldrw | ✓ | ✓ | |
| RawPixels (RGBA8)rw | ✓ | ✓ | |
| SVG | ✓ | ✗ | input only |
| DDS (DXT1/3/5) | ✓ | ✗ | decode only |
| HDR (Radiance) | ✓ | ✗ | decode only |
14 formats total · 11 bidirectional · 3 decode-only
Built-in filters
grayscale, blur, hue-rotate, contrast and more — applied natively in Rust.







One pipeline
From raw bytes to every format — a few lines, all native.
import { readFileSync, writeFileSync } from 'node:fs'
import { Transformer, losslessCompressPng, ResizeFilterType, ChromaSubsampling } from '@napi-rs/image'
const PNG = readFileSync('./input.png')
writeFileSync('out.png', await losslessCompressPng(PNG))
writeFileSync('out.webp', await new Transformer(PNG).resize(800, null, ResizeFilterType.Lanczos3).webp(75))
writeFileSync('out.avif', await new Transformer(PNG).resize(800, null, ResizeFilterType.Lanczos3)
.avif({ quality: 75, chromaSubsampling: ChromaSubsampling.Yuv420 }))PLAYGROUND
Try it in your browser
The WASM build runs entirely client-side — no install, no upload.