@crispcut/background-removal
v1.1.2
Published
AI background removal for clip art, t-shirt designs, and POD assets. Both models trained at 1024×1024. Runs in the browser via ONNX Runtime.
Maintainers
Readme
✂ CrispCut
Background removal that just works. Built for designs, not photos.
Clip art · T-shirt graphics · Print-on-demand assets
Runs in the browser. Nothing uploaded. Two models trained at 1024×1024.
Install
npm i @crispcut/background-removalUse
import { cut } from '@crispcut/background-removal';
const result = await cut(image);
img.src = result.url;That's it. One function, one result.
GPU
const result = await cut(image, { gpu: true });Auto-picks the best backend (WebGPU → WebGL). Falls back to CPU silently if GPU isn't available.
Quality model
const result = await cut(image, { model: 'quality', gpu: true });Trim
Auto-crop transparent padding — perfect for clip art and POD assets:
const result = await cut(image, { trim: true });
// Keep 10px padding around the subject
const result = await cut(image, { trim: 10 });Smooth edges
Edges are feathered by default for clean alpha transitions. Adjust or disable:
await cut(image); // smooth: true (default — 2px feather)
await cut(image, { smooth: 5 }); // heavier feather
await cut(image, { smooth: false }); // hard edgesProgress
await cut(image, {
onProgress: p => {
bar.style.width = `${Math.round(p * 100)}%`;
},
});Download
const result = await cut(image);
result.download(); // → crispcut-result.png
result.download('my-file.png'); // custom filenameClean up
result.revoke(); // free the object URL when doneBatch
import { cutAll } from '@crispcut/background-removal';
const results = await cutAll([file1, file2, file3], { gpu: true });
// With per-image callback
await cutAll(files, { trim: true }, (i, total, result) => {
console.log(`${i + 1}/${total} done`);
});Two models
| | 'fast' (default) | 'quality' |
|---|---|---|
| Size | 6.5 MB | 30.8 MB |
| CPU | ~5–10 s | ~25–45 s |
| GPU | ~1–2 s | ~5–10 s |
| Architecture | MobileNetV2 UNet | EfficientNet-b5 UNet++ SCSE |
Both trained at 1024×1024 on design-specific content. INT8 quantized.
All options
await cut(image, {
model: 'fast', // 'fast' | 'quality'
gpu: false, // use GPU — auto-picks best, falls back gracefully
edge: 0.5, // 0–1, higher = tighter crop
smooth: true, // true | false | number (feather px)
trim: false, // true | false | number (padding px)
format: 'image/png', // 'image/png' | 'image/webp'
quality: 0.92, // webp quality
modelUrl: undefined, // override for self-hosting
onProgress: undefined, // (progress: number) => void — 0 to 1
});Result
const result = await cut(image);
result.url // object URL for <img src>
result.blob // PNG Blob
result.width // output width (trimmed if trim was used)
result.height // output height
result.model // 'fast' | 'quality'
result.time // ms
result.download() // trigger browser download
result.revoke() // release object URLPreload
import { preload } from '@crispcut/background-removal';
preload(); // warm up fast model
preload({ model: 'quality', gpu: true }); // warm up quality + GPUClear cache
import { clearCache } from '@crispcut/background-removal';
clearCache(); // free both
clearCache('quality'); // free oneReact
import { cut } from '@crispcut/background-removal';
import { useState } from 'react';
export function BgRemover() {
const [src, setSrc] = useState(null);
async function handle(e) {
const file = e.target.files[0];
if (!file) return;
const { url } = await cut(file, { gpu: true, trim: true });
setSrc(url);
}
return (
<>
<input type="file" accept="image/*" onChange={handle} />
{src && <img src={src} />}
</>
);
}Vite
export default {
optimizeDeps: { exclude: ['onnxruntime-web'] },
};Self-hosting
cut(image, { modelUrl: '/models/crispcut-fast.onnx' });Models: huggingface.co/bowespublishing/crisp-cut
License
Package — MIT
Model weights — AGPL-3.0 / Commercial
