87 lines
2.4 KiB
TypeScript
87 lines
2.4 KiB
TypeScript
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,
|
|
};
|