Add local background removal and mask tools

This commit is contained in:
achraf
2026-06-07 23:32:26 +02:00
parent f5364bf7a8
commit e29dc6fd6d
23 changed files with 2508 additions and 21 deletions

View File

@@ -0,0 +1,86 @@
import { lazy } from "react";
import type { PlimiPlugin } from "../../core/plugins/plugin-types";
import { runBackgroundRemover } from "./run";
import {
estimateUncachedDownloadBytes,
type BackgroundRemoverOptions,
} from "./remove";
import BgWorker from "./worker?worker";
export type { BackgroundRemoverOptions } from "./remove";
const BackgroundRemoverUi = lazy(() => import("./BackgroundRemoverUi"));
function formatMb(bytes: number): string {
return `${(bytes / 1024 / 1024).toFixed(0)} MB`;
}
export const backgroundRemoverPlugin: PlimiPlugin<BackgroundRemoverOptions> = {
manifest: {
id: "background-remover",
name: "Background Remover",
description:
"Remove the background from any image with AI, entirely in your browser. Your photo is never uploaded.",
category: "image",
version: "1.0.0",
tags: ["image", "background", "remove", "ai", "transparent", "cutout"],
input: {
type: "files",
accept: ["image/png", "image/jpeg", "image/webp"],
multiple: false,
},
output: { type: "files" },
offlineReady: true,
},
optionsSchema: {
fields: [
{
type: "select",
key: "quality",
label: "Quality",
defaultValue: "small",
options: [
{ label: "Smallest download (quantized)", value: "small" },
{ label: "Balanced (FP16)", value: "medium" },
{ label: "Best quality (FP32)", value: "large" },
],
},
{
type: "boolean",
key: "useGpu",
label: "Use GPU (WebGPU) when available",
defaultValue: true,
},
],
},
capabilities: {
cancelable: false,
worker: true,
persistentWorker: true,
wasm: true,
customUi: true,
preview: true,
},
getRunWarning: async (_input, options) => {
const bytes = await estimateUncachedDownloadBytes(options, self.location.origin);
if (bytes <= 0) return null;
const label =
options.quality === "small"
? "Smallest download"
: options.quality === "medium"
? "Balanced"
: "Best quality";
return (
`Running the “${label}” model needs a one-time download of about ` +
`${formatMb(bytes)} to your device. It is cached afterwards, so future ` +
`runs are instant and fully offline. Continue?`
);
},
run: runBackgroundRemover,
worker: () => new BgWorker(),
customUi: BackgroundRemoverUi,
};