ImageScript - v3.4.0

ImageScript

Discord Server Documentation Github NPM


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)

  • Decoding images
    • PNGs (grayscale, RGB, indexed colors, 1-16 bit, interlaced) with and without alpha channels
    • JPEGs (baseline and progressive; grayscale, RGB, CMYK)
    • TIFFs (strips and tiles; uncompressed, LZW, deflate, PackBits and JPEG compressed; BigTIFF)
    • WebPs (lossy, lossless and with alpha; bit-exact with libwebp)
    • BMPs (1-64 bit, with any channel masks, alpha, RLE4 and RLE8, embedded JPEGs and PNGs; also OS/2 bitmaps)
    • ICOs and CURs (the largest image: bitmaps with their masks, or PNGs)
    • QOIs
    • Netpbm images: PBM, PGM, PPM (plain and raw, up to 16 bits), PAM and PFM
    • Radiance HDRs (RGBE and XYZE, every orientation), tone mapped to sRGB like Reinhard's operator does (or clamped, toneMapping)
    • TGAs (color mapped, truecolor and greyscale; uncompressed and run length encoded)
    • AVIFs (4:2:0, 4:2:2, 4:4:4 and monochrome, 8-12 bit; grids, alpha, crop, rotation and mirroring; the first frame of image sequences; bit-exact with dav1d and libavif), HDR ones (PQ, HLG) tone mapped to sRGB
    • JPEG XLs (Modular and VarDCT, lossless and lossy, every coding tool: progressive passes and LF frames, patches, splines, noise, restoration filters, upsampling, JPEG recompression, layers and blending, alpha and spot colors, CMYK; animations; within 1 of libjxl's djxl on the conformance suite), XYB ones as sRGB, HDR ones tone mapped to sRGB
    • JPEGs, TIFFs, PNGs and WebPs are rotated as their Exif (or, for PNGs, XMP) orientation says
    • images larger than 268 megapixels (maxPixels) are rejected before decoding, so small files declaring huge images can't exhaust the memory
  • Decoding animations (GIF, APNG, WebP and JPEG XL) with all frames, durations and disposal modes
  • Rendering SVGs (shapes, paths, gradients, strokes, clip paths, masks, CSS; no text, images or filters)
  • Rendering vector fonts (TrueType and OpenType, with complex text shaping in every script, right to left and bidirectional text, outlines, TrueType hinting, fallback fonts and color emoji)
  • Resizing (bilinear, bicubic, area averaging and nearest neighbor)
  • Image manipulation functions (crop , rotate , cropCircle , roundCorners , trim, ...)
  • Filters and color adjustments (blur , sharpen , brightness , hueShift, ...)
  • Compositing with opacity and blend modes (composite), removing backgrounds (colorToAlpha)
  • Color information functions (averageColor , dominantColor, ...)
  • Encoding images as PNGs (smallest lossless color type) , JPEGs , lossless and lossy WebPs (lossy ones byte for byte like libwebp's cwebp) , BMPs , QOIs , Netpbm images (PBM, PGM, PPM or PAM, whichever is smallest) and TGAs
  • Encoding animations as GIF, APNG and lossless or lossy WebP, storing only what changes from frame to frame

import { 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.

Example


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. See THIRD_PARTY_NOTICES.md for their licenses.


If you have any additional questions, feel free to join the discord support server.