image-grid-combine
v1.0.0
Published
Combine multiple images into a single grid image with the Canvas API. Dependency-free, works in any modern browser.
Maintainers
Readme
image-grid-combine
Combine several images into one grid image using the Canvas API.
No dependencies, no build step, no server round-trip — the images are composited
in the browser and you get back a Blob or a data URL.
npm install image-grid-combineUsage
import { combineToBlob } from 'image-grid-combine';
const blob = await combineToBlob({
sources: [fileA, fileB, fileC, fileD], // File, Blob, URL, <img>, canvas, ImageBitmap
columns: 2,
gap: 12,
padding: 24,
background: '#0b0b0f',
fit: 'cover',
});
preview.src = URL.createObjectURL(blob);Every source is accepted in whatever shape you already have it: a File from an
<input type="file">, a Blob from fetch, a URL string, an HTMLImageElement,
a canvas, or an ImageBitmap. They are loaded in parallel and drawn in the order
you pass them.
API
combineToBlob(options) => Promise<Blob>
Composites the images and resolves with an encoded Blob. This is the usual
entry point — hand the blob to URL.createObjectURL, a FormData, or a
download link.
combineToDataURL(options) => Promise<string>
Same thing, but resolves with a data: URL.
combineToCanvas(options) => Promise<HTMLCanvasElement | OffscreenCanvas>
Returns the raw canvas if you want to keep drawing on it. Uses OffscreenCanvas
when the browser has it, so it also runs inside a worker.
Options
| Option | Type | Default | Notes |
| --- | --- | --- | --- |
| sources | ImageSource[] | — | Required, at least one image. |
| columns | number | square-ish | Columns per row. Left unset, the grid stays as square as the image count allows. |
| gap | number | 0 | Pixels between cells. |
| padding | number | 0 | Pixels around the outside of the grid. |
| background | string \| null | '#ffffff' | Any CSS colour. null leaves the gaps transparent (PNG only). |
| cellSize | number \| {width, height} | auto | Pin the cell size. Left unset, cells take the size of the largest source so nothing is upscaled. |
| fit | 'cover' \| 'contain' \| 'stretch' | 'cover' | How each image fills its cell. |
| maxWidth | number | 2048 | Upper bound used when the cell size is auto. |
| format | string | 'image/png' | Blob/data URL output only. |
| quality | number | 0.92 | Blob/data URL output only; ignored for PNG. |
fit modes
cover(default) fills the cell and crops the overflow — no letterboxing, no distortion. Good for photo grids where cells must line up.containfits the whole image inside the cell and letterboxes the rest, so nothing is ever cropped.stretchfills the cell exactly, aspect ratio be damned.
Layout helpers
The geometry is separated from the drawing, so you can compute a layout without touching a canvas — useful for previews, drag-and-drop targets, or running the same maths in a worker or on the server.
import { autoCellSize, computeGridLayout, fitRect } from 'image-grid-combine/layout';
const { cellWidth, cellHeight, columns } = autoCellSize(
[{ width: 1600, height: 900 }, { width: 900, height: 1600 }],
{ gap: 8, maxWidth: 1200 },
);
const layout = computeGridLayout({ count: 2, columns, cellWidth, cellHeight, gap: 8 });
// layout.cells -> [{ index, x, y, width, height }, ...]
const rect = fitRect({ sourceWidth: 1600, sourceHeight: 900, boxWidth: 600, boxHeight: 600 });
// rect -> { sx, sy, sw, sh, dx, dy, dw, dh } ready for ctx.drawImagecomputeGridLayout and fitRect are pure functions with no DOM access, and they
are covered by the test suite:
npm testNotes and limits
- Everything happens client-side. Images loaded from another origin need CORS
headers, otherwise the canvas is tainted and encoding throws — the library sets
crossOrigin="anonymous"for you on URL sources, but the server still has to agree. - Very large grids are bounded by
maxWidth(2048px by default) because browsers cap canvas dimensions, and Safari's cap is the lowest of the mainstream engines. - SVG sources rasterise at their intrinsic size.
Related
- Lumfuse — a browser-based AI image combiner for when you would rather not write code: drop in two or more photos and merge them with AI blending, no install and no signup.
License
MIT
