ImageScript is a zero-dependency alternative to common JavaScript bitmap image manipulation tools. Every codec and
renderer is written in TypeScript: no WebAssembly, no native binaries, no npm dependencies, no install scripts. The
package is about 160 kB (compressed) and runs in Node.js 22.13 or newer (including Alpine/musl, ARM and bundled
serverless functions), Deno, Bun and browsers. It works with both import and require(), type definitions are included.
npm install imagescript # Node.js, Bun and bundlers
deno add jsr:@matmen/imagescript # Deno (npm:imagescript works too)
toneMapping)maxPixels) are rejected before decoding, so small files declaring huge images
can't exhaust the memorycjxl -e 1, lossy about as small as cjxl -e 5)
, BMPs
, QOIs
, Netpbm images (PBM, PGM, PPM or PAM, whichever is
smallest)
and TGAsimport { Image } from 'imagescript';
import { readFile, writeFile } from 'node:fs/promises';
const image = await Image.decode(await readFile('input.jpg'));
image.resize(256, Image.RESIZE_AUTO).roundCorners(16);
await writeFile('output.png', await image.encode());
With CommonJS:
const { Image } = require('imagescript');
All coordinates are 0-based, (0, 0) is the top left pixel.
A bigger example is the README image generation.
Upgrading from 1.x? Version 3 has breaking changes (0-based coordinates, lossy WebP encoding as encodeWebP({ quality }),
Node.js 22.13+, ...), see the changelog.
bench/ compares ImageScript to Jimp, image-js, Photon, sharp and @napi-rs/canvas: speed of decoding, encoding, image operations and rendering, encoded file sizes and install sizes. It runs for every release.
The deflate/inflate implementation is derived from fflate and the CRC-32 from Fast CRC32 in JavaScript, both by Arjun Barrett. The JPEG codec is based in part on the work of the Independent JPEG Group (libjpeg) and on pdf.js, the glyph rasterizer is translated from font-rs. The WebP codecs follow RFC 9649 and RFC 6386 and reproduce libwebp's color conversion, the lossy WebP encoder is ported from libwebp's, the TrueType hinting follows FreeType's interpreter (portions of this software are copyright © 2026 The FreeType Project), the text shaping is ported from HarfBuzz and uses data of the Unicode Character Database. The AV1 decoder is ported from dav1d, AVIFs are converted to RGB like libavif does, the JPEG XL decoder is ported from jxl-oxide and libjxl, the JPEG XL encoders follow libjxl's fast lossless encoder and its lossy heuristics, the AV1 encoder mirrors the decoder and uses libaom's symbol encoder. See THIRD_PARTY_NOTICES.md for their licenses.
If you have any additional questions, feel free to join the discord support server.