Guides & API Reference

Everything you need to ship image-stitch in production: quick scripts, browser bundles, streaming pipelines, canvas helpers, and the complete API surface.

Installation

image-stitch ships ready for every runtime: native ESM, CommonJS, a tree-shakeable ESM bundle, and a browser-friendly global build. Install it with npm, pnpm, or yarn.

npm install image-stitch

Node.js 18+ is recommended. In browsers, load the prebuilt script tag bundle from https://cdn.jsdelivr.net/npm/image-stitch/dist/browser/image-stitch.min.js or import the module build from https://cdn.jsdelivr.net/npm/image-stitch/dist/bundles/image-stitch.esm.js.

Quick start (Node.js)

import { concatToBuffer } from "image-stitch";
import { readFileSync, writeFileSync } from "node:fs";

const stitched = await concatToBuffer({
  inputs: [
    readFileSync("./pngsuite/png/basi0g08.png"),
    readFileSync("./pngsuite/png/basi2c08.png")
  ],
  layout: { columns: 2 }
});

writeFileSync("spritesheet.png", stitched);

The returned value is a Uint8Array containing the PNG file. Persist it to disk, push it across the network, or convert it into a Blob for browser usage.

Modern browser usage

Use dynamic imports to fetch the ESM bundle from a CDN when prototyping. The library automatically normalizes Blob, File, ArrayBuffer, and HTMLCanvasElement inputs before stitching.

const { concatToBuffer } = await import("https://cdn.jsdelivr.net/npm/image-stitch/dist/bundles/image-stitch.esm.js");

const files = Array.from(document.querySelector("input[type=file]").files ?? []);

const stitched = await concatToBuffer({
  inputs: files,
  layout: { columns: 3 },
  onProgress(current, total) {
    console.log(`Decoded ${current}/${total}`);
  }
});

const blob = new Blob([stitched], { type: "image/png" });
document.querySelector("img.preview").src = URL.createObjectURL(blob);

When building a production bundle, import directly from image-stitch and let your bundler handle tree-shaking.

Canvas helper

The browser bundle exposes concatCanvases so you can stitch existing canvases without converting to blobs yourself. Choose whether to receive a Blob or render into a canvas.

import { concatCanvases } from "image-stitch/browser";

const stitchedCanvas = await concatCanvases({
  canvases: [topLeft, topRight, bottomLeft, bottomRight],
  layout: { rows: 2, columns: 2 },
  output: "canvas",
  onProgress(current, total) {
    progressBar.value = current / total;
  }
});

document.body.appendChild(stitchedCanvas);

Switch output to "blob" to receive a downloadable Blob (PNG by default, configurable via mimeType).

Streaming & pipelines

concatStreaming(options) (async generator)

import { concatStreaming } from "image-stitch";

for await (const chunk of concatStreaming({
  inputs,
  layout: { width: 2048 }
})) {
  await writeChunkSomewhere(chunk);
}

concatToStream(options) (Node.js Readable)

import { concatToStream } from "image-stitch";
import { pipeline } from "node:stream/promises";
import { createWriteStream } from "node:fs";

await pipeline(
  concatToStream({
    inputs,
    layout: { columns: 4 },
    onProgress(current, total) {
      console.info(`Completed ${current}/${total}`);
    }
  }),
  createWriteStream("spritesheet.png")
);

The async generator works everywhere (Node, Deno, browsers). The Node.js helper wraps it in a Readable instance for easy piping.

API reference

concatToBuffer(options)

Concatenate input images and return a Promise<Uint8Array>. A deprecated concat alias remains for backwards compatibility.

type IterableInput =
  | T[]
  | Iterable
  | AsyncIterable;

interface ConcatOptions {
  inputs: IterableInput<string | Uint8Array | ArrayBuffer | ImageDecoder>;
  layout: {
    columns?: number;
    rows?: number;
    width?: number;
    height?: number;
    wrapBehavior?: "wrap" | "truncate";
  };
  decoderOptions?: DecoderOptions;
  decoders?: DecoderPlugin[];
  outputFormat?: "png";
  onProgress?: (completed: number, total: number) => void;
}

The supporting typings (ImageDecoder, DecoderOptions, DecoderPlugin, and BrowserConcatOptions) are exported from the package for projects that want full TypeScript coverage.

concatStreaming(options)

Returns an async generator of Uint8Array chunks. Works in both Node.js and browsers.

concatToStream(options)

Node.js convenience wrapper that exposes the streaming concatenator as a Readable stream.

concatCanvases(options) (browser bundle)

interface ConcatCanvasesOptions extends Omit<BrowserConcatOptions, "inputs"> {
  canvases: IterableInput<HTMLCanvasElement>;
  output?: "blob" | "canvas";
  mimeType?: string; // Blob mode only
  targetCanvas?: HTMLCanvasElement; // Canvas mode only
}

Returns a Promise<Blob | HTMLCanvasElement> depending on output. When rendering to a canvas, you can provide targetCanvas to reuse an existing element.

Best practices