Skip to content
File

Blob: docs/deferred/background-removal.md

Markdown64 lines

Deferred: background removal / replacement

Goal

Let users cut out the subject and either make the background transparent or replace it with a solid color. Primary use cases: passport photos (plain white or light-blue background, which several countries require) and clean avatars / product shots.

Recommended approach

Use @imgly/background-removal (runs onnxruntime-web in the browser, no server). Run it in a Web Worker so the UI stays responsive. Steps:

  1. Add a "Remove background" action (a toggle in a new panel, or a button in the Adjust/Effects area). When enabled:
    • Send the source bitmap (or the cropped region) to a background-removal worker.
    • Get back an RGBA mask or a cutout image.
  2. In the export pipeline, composite the cutout over the chosen background (transparent for PNG/WebP; a solid color for JPEG and for passport mode).
  3. Cache the result keyed by source so toggling it on/off is instant.

A lighter alternative for fully manual control is a brush-based mask editor, but that needs a drawing surface (see free-form-crop.md / Konva).

The hard part: cross-origin isolation vs the model download

The app is cross-origin isolated (COEP require-corp) so wasm-vips threads work. Under require-corp, @imgly's default behavior of fetching its model and wasm from a CDN will be blocked. Two options:

  • Self-host the assets (recommended). Install @imgly/background-removal-data, copy its assets into the app (public/ or an emitted asset dir), and set the library's publicPath (or config.publicPath) to that same-origin location. Same-origin subresources are allowed under require-corp.
  • Or drop cross-origin isolation on the route that does removal. This disables the vips fast path and SharedArrayBuffer, so it is the worse trade.

Either way, verify the model actually loads with the COEP header present, not just without it.

Cost / risk

  • Model + runtime are large (tens of MB). Load lazily and show progress; do not block initial page load.
  • onnxruntime-web has its own threading and wasm; confirm it coexists with the existing COEP setup and with the vips worker.
  • This is genuinely heavy and was deliberately left for phase 2.

Effort

Medium-to-large. A day or two to a robust, self-hosted, worker-based integration with progress UI and JPEG/PNG background handling.

Acceptance checks

  • With COEP require-corp on, the model loads from a same-origin path.
  • Toggling removal updates the preview; export composites correctly (transparent for PNG/WebP, solid color for JPEG).
  • Passport mode can force a white (or specified) background.
  • Verify in a real browser (Playwright) that a known photo yields a cutout and a valid exported file.