PixelFit Open the image tool

Inside the browser · source walkthrough

How PixelFit processes an image in a Web Worker

Follow one selected image from the page to a worker, through an offscreen canvas and a measured encode, then back to the preview. This guide describes the current PixelFit source; it does not promise that every browser takes the same route.

Try PixelFit with a sample

One request · four stages

The image makes a round trip

  1. 01

    Collect settings

    File, output dimensions, format, quality, and optional byte ceiling.

  2. 02

    Draw offscreen

    The worker creates an image bitmap and draws it onto an OffscreenCanvas.

  3. 03

    Encode and measure

    Each candidate becomes a Blob; its actual byte size guides the next quality step.

  4. 04

    Show the result

    The page receives the Blob and displays its preview and measured size.

The browser API supports running OffscreenCanvas work in a worker. PixelFit checks for that capability before choosing this path. OffscreenCanvas documentation

01 · The page creates the worker

Use a worker when the required APIs exist

PixelFit checks for Worker, OffscreenCanvas, and createImageBitmap. It then starts image-worker.js and sends the selected file and settings as a message.

if (
  !("Worker" in window) ||
  !("OffscreenCanvas" in window) ||
  !("createImageBitmap" in window)
) {
  return null;
}

imageWorker = new Worker(
  new URL("image-worker.js", document.baseURI)
);
imageWorker.postMessage({ ...options, id });

This excerpt is from backgroundProcess() in app.js. The message uses the browser's worker messaging API; supported values are handled through structured cloning. Worker.postMessage()

02 · The worker draws and encodes

OffscreenCanvas keeps the worker's drawing separate

The worker turns the file into an ImageBitmap, creates an OffscreenCanvas at the requested output dimensions, draws the bitmap, and asks the canvas to create an encoded Blob.

bitmap = await createImageBitmap(file);
const canvas = new OffscreenCanvas(width, height);
const context = canvas.getContext("2d", { alpha: true });

context.drawImage(bitmap, 0, 0, width, height);
const result = await encode(canvas, mime, targetBytes, quality);

self.postMessage({
  id,
  blob: result.blob,
  width,
  height,
  quality: result.quality,
});

The context can be unavailable, so the worker reports that case to the page. PixelFit also closes the bitmap in a finally block after processing. OffscreenCanvas.convertToBlob()

03 · Measure the encoded output

A quality value is not a file-size guarantee

For JPEG or WebP with a target, PixelFit tries the midpoint between its quality floor and the upper bound. It measures each resulting Blob. A candidate at or below the ceiling becomes the current best; an oversized candidate narrows the upper bound.

The search stops after ten passes. If none of those candidates meet the ceiling, PixelFit tries once at the quality floor. That fallback may still exceed the target, so the interface can report that the limit was not reached. PNG follows a different path: it is encoded without this lossy quality search.

The implementation compares the actual Blob.size, not an estimate. See the 100 KB guide for what a target miss means when you use the tool.

What this design helps with

Move eligible encoding work off the page thread

A worker has a separate execution context from the document. OffscreenCanvas can run canvas work there, which helps avoid doing that work on the main thread when the browser and operation support the path. This is an implementation choice, not a benchmark or a guarantee that the page can never pause.

What the source shows

The image is processed in this browser

The selected file is passed to the local worker in the page. This processing path does not upload it to a PixelFit image-processing server. The page still loads normal site resources, so this statement is about the image-processing code, not every network request the site makes.

Common questions

Worker processing, explained

Does a worker always make image compression faster?

Not necessarily. A worker can keep supported work off the page's main thread, but total time still depends on the image, browser, device, format, and number of encodes. PixelFit does not publish a speed benchmark here.

What happens if the browser does not support this worker path?

The app falls back to its page-thread canvas encoder if the worker path is unavailable. The image can still be processed, although the page may do more of the work directly.

Can the size target always be reached?

No. The search is bounded, and the quality-floor fallback may still be over the requested limit. PixelFit reports the actual result. Read the 200 KB guide for a practical example of checking a destination limit.

Inspect the code, then try a sample

Choose a generated image, check the measured output, and inspect the preview before downloading.

Open PixelFit