
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
image-stitch
Advanced tools
Stitch images together efficiently with multi-format support (PNG, JPEG, HEIC), streaming, for node.js and web
image-stitch combines images into a single output without relying on Canvas APIs. It works in Node.js and modern browsers, including streaming scenarios for large images.
Features:
npm install image-stitch
import { concatToBuffer } from 'image-stitch' resolves to dist/esm/index.js with rich type definitions.require load dist/cjs/index.cjs automatically.import 'image-stitch/bundle' for a single-file ESM artifact that keeps dependencies external. The
browser bundle ships with PNG support out of the box; add JPEG/HEIC decoders only when you need them.<script src="https://cdn.jsdelivr.net/npm/image-stitch/dist/browser/image-stitch.min.js"></script> into any page and use window.ImageStitch.import ... from 'image-stitch/node' ensures you get the full Node.js build (useful for JSDOM testing).import { concatToBuffer } from 'npm:image-stitch/deno/mod.ts' targets the ESM build with Node compatibility.All bundles ship with source maps and .d.ts files so editors stay fully typed.
import { concatToBuffer } from 'image-stitch';
import { readFileSync, writeFileSync } from 'fs';
const result = await concatToBuffer({
inputs: [
readFileSync('one.png'),
readFileSync('two.png')
],
layout: { columns: 2 }
});
writeFileSync('stitched.png', result);
By default, image-stitch outputs PNG (lossless). You can also output JPEG (lossy) with configurable quality:
import { concatToBuffer } from 'image-stitch';
// Output as JPEG with custom quality
const result = await concatToBuffer({
inputs: ['photo1.jpg', 'photo2.jpg', 'image.png'],
layout: { columns: 3 },
outputFormat: 'jpeg', // 'png' (default) or 'jpeg'
jpegQuality: 90 // 1-100, default: 85
});
writeFileSync('stitched.jpg', result);
JPEG output features:
concatToStream() and concatStreaming()Place images at arbitrary x,y coordinates with support for overlapping and alpha blending:
import { concatToBuffer, type PositionedImage } from 'image-stitch';
const inputs: PositionedImage[] = [
{ x: 0, y: 0, source: 'background.png' },
{ x: 50, y: 50, zIndex: 10, source: 'overlay.png' }, // Overlaps background with explicit zIndex
{ x: 200, y: 100, source: imageBuffer }
];
const result = await concatToBuffer({
inputs,
layout: {
width: 500, // Optional: canvas width (auto-calculated if omitted)
height: 400 // Optional: canvas height (auto-calculated if omitted)
},
enableAlphaBlending: true // Default: true (blend overlapping images)
});
Positioned image features:
zIndex)// Example: Create a composite with watermark
const composite = await concatToBuffer({
inputs: [
{ x: 0, y: 0, source: 'photo.jpg' },
{ x: 420, y: 380, source: 'watermark.png' } // Bottom-right corner
],
layout: {}, // Canvas auto-sized to fit all images
outputFormat: 'jpeg',
jpegQuality: 90
});
Pass an onProgress callback to receive a counter whenever an input tile finishes streaming. The callback receives the number of
completed inputs and the total inputs in the operation, making it easy to update loading indicators while large grids process.
await concatToBuffer({
inputs: tiles,
layout: { rows: 4, columns: 4 },
onProgress(current, total) {
console.log(`Stitched ${current}/${total}`);
}
});
👉 Read the full guides, API docs, and interactive demos at image-stitch GitHub Pages.
Modern browsers provide native HEIC/JPEG decoding primitives, so the browser-focused bundle keeps only the PNG decoder by default. Opt in to extra formats with lightweight plugins:
import { concatToBuffer } from 'image-stitch/bundle';
import { jpegDecoder } from 'image-stitch/decoders/jpeg';
import { heicDecoder } from 'image-stitch/decoders/heic';
await concatToBuffer({
inputs: [jpegBytes, heicBytes],
layout: { columns: 2 },
decoders: [jpegDecoder, heicDecoder]
});
Node.js imports (import { concatToBuffer } from 'image-stitch') continue to register PNG, JPEG, and HEIC decoders automatically.
image-stitch supports Node.js, modern browsers, and hybrid environments like JSDOM.
Standard usage works out of the box with npm install image-stitch.
Node environments automatically use efficient native libraries (like sharp if installed) or pure JS fallbacks (jpeg-js, pako).
For JSDOM environments (e.g. Jest/Vitest tests), you can ensure robust behavior by using the Node-specific export or configuring custom constructors.
Option 1: Force Node Logic (Recommended)
Import from image-stitch/node to bypass browser bundles and use Node.js capabilities (file system, streams, buffers) even if JSDOM mocks browser globals.
import { concatToBuffer } from 'image-stitch/node';
// Uses Node.js logic and dependencies (pako, jpeg-js, etc.)
Option 2: Dependency Injection
If you prefer to use browser-like APIs (Canvas) in your tests, you can inject compatible constructors (like napi-rs/canvas or canvas).
import { concatToBuffer } from 'image-stitch';
import { Image, Canvas } from '@napi-rs/canvas';
await concatToBuffer({
inputs: [...],
layout: { columns: 2 },
decoderOptions: {
customConstructors: { Image, Canvas } // injected constructors
}
});
FAQs
Stitch images together efficiently with multi-format support (PNG, JPEG, HEIC), streaming, for node.js and web
The npm package image-stitch receives a total of 4 weekly downloads. As such, image-stitch popularity was classified as not popular.
We found that image-stitch demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.