import { describe, expect, it } from "vitest"; import { backgroundMaskPreview, backgroundRemovalMask, removeBackground, } from "./background"; import { makeImage } from "./test-helpers"; const GREEN = [0, 255, 0, 255]; const RED = [255, 0, 0, 255]; describe("backgroundRemovalMask", () => { it("глобальный режим удаляет все совпадающие пиксели", () => { const mask = backgroundRemovalMask(makeImage(2, 1, [GREEN, RED]), { color: "#00ff00", tolerancePercent: 0, outerOnly: false, smoothPasses: 0, }); expect([...mask]).toEqual([1, 0]); }); describe("режим внешних областей", () => { const ringRedCenterGreen = [RED, RED, RED, RED, GREEN, RED, RED, RED, RED]; it("заливка от краёв не достаёт до изолированного совпадающего острова", () => { const mask = backgroundRemovalMask(makeImage(3, 3, ringRedCenterGreen), { color: "#00ff00", tolerancePercent: 0, outerOnly: true, smoothPasses: 0, }); expect(mask[4]).toBe(0); }); it("глобальный режим удаляет и изолированный остров", () => { const mask = backgroundRemovalMask(makeImage(3, 3, ringRedCenterGreen), { color: "#00ff00", tolerancePercent: 0, outerOnly: false, smoothPasses: 0, }); expect(mask[4]).toBe(1); expect(mask[0]).toBe(0); }); }); it("допуск расширяет захват по цветовому расстоянию", () => { const img = makeImage(2, 1, [ [10, 10, 10, 255], [128, 128, 128, 255], ]); const tight = backgroundRemovalMask(img, { color: "#000000", tolerancePercent: 40, outerOnly: false, smoothPasses: 0, }); const wide = backgroundRemovalMask(img, { color: "#000000", tolerancePercent: 60, outerOnly: false, smoothPasses: 0, }); expect(tight[1]).toBe(0); expect(wide[1]).toBe(1); }); }); describe("smoothMask-поведение через backgroundRemovalMask", () => { const ringRedCenterGreen = [RED, RED, RED, RED, GREEN, RED, RED, RED, RED]; const opts = { color: "#00ff00", tolerancePercent: 0, outerOnly: false }; const alphaAtCenter = (img: { data: Uint8ClampedArray }) => img.data[19]; it("без сглаживания центр удалён", () => { const img = removeBackground(makeImage(3, 3, ringRedCenterGreen), { ...opts, smoothPasses: 0, }); expect(alphaAtCenter(img)).toBe(0); }); it("два прохода мажоритарного фильтра возвращают изолированный пиксель", () => { const img = removeBackground(makeImage(3, 3, ringRedCenterGreen), { ...opts, smoothPasses: 2, }); expect(alphaAtCenter(img)).toBe(255); }); }); describe("removeBackground", () => { it("обнуляет альфу удалённых, сохраняет RGB остальных", () => { const out = removeBackground(makeImage(2, 1, [GREEN, [5, 6, 7, 200]]), { color: "#00ff00", tolerancePercent: 0, outerOnly: false, smoothPasses: 0, }); expect(out.data[3]).toBe(0); expect([...out.data.slice(4, 8)]).toEqual([5, 6, 7, 200]); }); }); describe("backgroundMaskPreview", () => { it("белое там, где удаление, чёрное — где остаёмся, всё непрозрачно", () => { const preview = backgroundMaskPreview( makeImage(2, 1, [GREEN, [9, 9, 9, 60]]), { color: "#00ff00", tolerancePercent: 0, outerOnly: false, smoothPasses: 0, }, ); expect([...preview.data]).toEqual([255, 255, 255, 255, 0, 0, 0, 255]); }); });