How the Instatic Image-Variant Worker Generates Sharp Resizes and BlurHash

The Instatic image-variant worker is a CPU-isolated Bun.Worker that uses Sharp to probe image dimensions, encodes BlurHash placeholders from tiny RGBA samples, and generates responsive WebP ladders up to 16,383 pixels wide, returning all data via transferable ArrayBuffers to prevent memory duplication.

The image-variant worker in the CoreBunch/Instatic repository manages the heavy lifting of the image-upload pipeline. Located in server/handlers/cms/imageVariantWorker.ts, this dedicated worker processes raw image bytes outside the main thread to keep the application responsive. According to the Instatic source code, the worker performs three distinct operations: metadata probing, BlurHash placeholder generation, and optional responsive-variant creation, all orchestrated through type-safe messages defined in imageVariantProtocol.ts.

Probing Intrinsic Dimensions with Sharp

Before any transformation, the worker validates the input by reading the image header. It calls sharp(bytes).metadata() to extract the original width and height from the file headers without decoding the full pixel data.

If the metadata lacks dimensions, the worker immediately returns an error response to the host. When dimensions are present, they are stored as originalWidth and originalHeight to guide downstream resize calculations and constrain the variant ladder.

Generating BlurHash Placeholders

To create an instant visual placeholder, the worker encodes a BlurHash string representing the image’s approximate colors and gradients. The process funnels the full-resolution image through a tight pipeline:

  1. Downsample the image to a tiny sampling size configured by blurhashConfig.sampleWidth and blurhashConfig.sampleHeight using fit: 'fill' to ensure exact dimensions.
  2. Force an alpha channel with .ensureAlpha() so the raw pixel buffer always has four channels.
  3. Extract raw RGBA bytes via .raw().toBuffer({resolveWithObject:true}).
  4. Encode the bytes using the blurhash library’s encode function, passing the component counts (blurhashConfig.x and blurhashConfig.y) to control hash complexity.

The resulting compact string can be decoded client-side to render a blurry preview while the full image loads.

Building the Responsive WebP Ladder

When the host sets generateLadder to true, the worker constructs a series of responsive WebP variants. It selects target widths that are smaller than the intrinsic width, appends the intrinsic width as the final rung, and clamps any width that would exceed WebP’s hard limit of 16,383 pixels.

For each target width in the ladder, the worker executes:

const variant = await sharp(bytes)
  .resize({ width, withoutEnlargement: true })
  .webp({ quality: req.webpQuality })
  .toBuffer({ resolveWithObject: true });

The withoutEnlargement: true option prevents Sharp from upscaling small images. The worker then converts the Node.js Buffer into a clean ArrayBuffer using the internal toArrayBuffer helper so the memory can be transferred rather than copied back to the host.

Zero-Copy Communication with the Host

The host-side façade in server/handlers/cms/imageVariantWorkerHost.ts manages a pool of workers and exposes runImageVariantJob for queuing tasks. When the worker finishes, it packages the metadata, BlurHash string, and variant payloads into a response object.

Crucially, the worker includes the ArrayBuffer instances in a transfer list passed to postMessage. This transfers ownership of the underlying memory to the host thread instantly, eliminating the duplication that occurs with structured cloning.

Practical Implementation Examples

Running an Image-Variant Job from the Host

import { runImageVariantJob, isImageVariantOk } from '@/server/handlers/cms/imageVariantWorkerHost';

const imgBytes = await fetch('/example.png').then(r => r.arrayBuffer());

const response = await runImageVariantJob({
  bytes: imgBytes,
  generateLadder: true,
  targetWidths: [64, 320, 640],
  webpQuality: 80,
  blurhashConfig: { x: 4, y: 3, sampleWidth: 32, sampleHeight: 32 },
});

if (isImageVariantOk(response)) {
  console.log('Original size:', response.width, 'x', response.height);
  console.log('BlurHash:', response.blurHash);
  console.log('Variants produced:', response.variants.length);
}

Decoding BlurHash Client-Side

import { decode as decodeBlurHash } from 'blurhash';

function blurHashToDataUrl(hash: string) {
  const { x, y, w, h } = { x: 4, y: 3, w: 32, h: 32 };
  const pixels = decodeBlurHash(hash, w, h, { x, y });
  const canvas = document.createElement('canvas');
  canvas.width = w;
  canvas.height = h;
  const ctx = canvas.getContext('2d')!;
  const imgData = ctx.createImageData(w, h);
  imgData.data.set(pixels);
  ctx.putImageData(imgData, 0, 0);
  return canvas.toDataURL();
}

Applying BlurHash via CSS

import { blurHashToCssBackground } from '@/src/modules/base/image';

const cssBg = blurHashToCssBackground(response.blurHash);
element.style.backgroundImage = cssBg;

Summary

  • The image-variant worker is implemented as a Bun.Worker in imageVariantWorker.ts to isolate CPU-intensive tasks from the main event loop.
  • Sharp probes metadata via .metadata() and generates WebP variants with .resize({width, withoutEnlargement:true}).
  • BlurHash encodings are produced by resizing to a tiny sample with fit:'fill', ensuring alpha with .ensureAlpha(), and passing raw RGBA bytes to the blurhash library’s encode function.
  • WebP ladders respect a 16,383-pixel maximum dimension and include the intrinsic width as the largest rung.
  • The toArrayBuffer helper converts Node.js Buffers into transferable ArrayBuffers, enabling zero-copy message passing via imageVariantWorkerHost.ts.

Frequently Asked Questions

Why does the worker use fit: 'fill' when sampling for BlurHash?

The Sharp resize operation uses fit: 'fill' to force the image to exactly match sampleWidth and sampleHeight without preserving aspect ratio. This guarantees that the raw pixel buffer passed to the BlurHash encoder has predictable dimensions, simplifying the encoding math and ensuring consistent hash output regardless of the original image’s aspect ratio.

What is the maximum image size the image-variant worker can process?

The worker can process images of any file size that fits in memory, but the WebP output is clamped to a maximum dimension of 16,383 pixels per side (the WebP format limit). The worker calculates maxSafeWidth to ensure no variant exceeds this boundary, preserving the aspect ratio when necessary.

How does the host application receive results without memory duplication?

The worker uses a transferable ArrayBuffer array in its postMessage call. By including the buffers in the transfer list, ownership moves directly to the host thread without cloning, which is critical for performance when handling large image payloads across the worker boundary.

What happens if an uploaded image lacks dimension metadata?

If sharp(bytes).metadata() returns undefined for width or height, the worker catches this condition and returns a failure response containing an error message. The host can then handle the malformed image appropriately without attempting to generate variants or a BlurHash.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →