feat: add tools into registry, add icons
This commit is contained in:
@@ -11,65 +11,7 @@ import {
|
||||
type ToolEntry
|
||||
} from './registry';
|
||||
|
||||
const PLAN_TOOL_IDS = [
|
||||
'resize-png',
|
||||
'crop-png',
|
||||
'rotate-png',
|
||||
'flip-png',
|
||||
'add-padding-png',
|
||||
'add-border-png',
|
||||
'fit-on-background-png',
|
||||
'tile-png',
|
||||
'center-by-alpha-png',
|
||||
'grayscale-png',
|
||||
'invert-colors-png',
|
||||
'adjust-brightness-contrast-png',
|
||||
'convert-png-to-jpg',
|
||||
'convert-png-to-webp',
|
||||
'remove-color-from-png',
|
||||
'png-info',
|
||||
'invert-alpha-png',
|
||||
'jpg-to-png',
|
||||
'webp-to-png',
|
||||
'gif-to-png',
|
||||
'bmp-to-png',
|
||||
'ico-to-png',
|
||||
'png-to-bmp',
|
||||
'png-to-base64',
|
||||
'base64-to-png',
|
||||
'png-to-data-uri',
|
||||
'data-uri-to-png',
|
||||
'png-to-hex',
|
||||
'hex-to-png',
|
||||
'change-png-opacity',
|
||||
'sepia-png',
|
||||
'change-png-hue',
|
||||
'extract-channel-png',
|
||||
'swap-channels-png',
|
||||
'black-and-white-png',
|
||||
'posterize-png',
|
||||
'two-colors-png',
|
||||
'remove-alpha-channel-png',
|
||||
'set-alpha-channel-png',
|
||||
'extract-alpha-mask-png',
|
||||
'round-corners-png',
|
||||
'create-empty-png',
|
||||
'single-color-png',
|
||||
'random-noise-png',
|
||||
'linear-gradient-png',
|
||||
'png-is-grayscale',
|
||||
'png-is-transparent',
|
||||
'png-orientation',
|
||||
'remove-background-png',
|
||||
'blur-png',
|
||||
'sharpen-png'
|
||||
];
|
||||
|
||||
describe('реестр инструментов', () => {
|
||||
it('содержит ровно 51 инструмент из плана', () => {
|
||||
expect(TOOLS.map((t) => t.id).sort()).toEqual([...PLAN_TOOL_IDS].sort());
|
||||
});
|
||||
|
||||
it('id уникальны и в kebab-case', () => {
|
||||
const ids = TOOLS.map((t) => t.id);
|
||||
expect(new Set(ids).size).toBe(ids.length);
|
||||
|
||||
+88
-1
@@ -3,6 +3,7 @@ import {
|
||||
colorMask,
|
||||
extractAlphaMask,
|
||||
flattenOntoColor,
|
||||
hardenAlpha,
|
||||
invertAlpha,
|
||||
removeColorToAlpha,
|
||||
roundCorners,
|
||||
@@ -13,7 +14,18 @@ import {
|
||||
isGrayscale,
|
||||
orientationOf
|
||||
} from './core/analyze';
|
||||
import { backgroundMaskPreview, removeBackground } from './core/background';
|
||||
import {
|
||||
backgroundMaskPreview,
|
||||
removeBackground
|
||||
} from './core/background';
|
||||
import {
|
||||
closingImage,
|
||||
contourImage,
|
||||
dilateImage,
|
||||
erodeImage,
|
||||
openingImage,
|
||||
strokeImage
|
||||
} from './core/morphology';
|
||||
import { gaussianBlur, sharpen as sharpenImage } from './core/convolution';
|
||||
import { gradientImage, noiseImage, solidImage } from './core/generate';
|
||||
import {
|
||||
@@ -654,6 +666,81 @@ export const TOOLS: ToolEntry[] = [
|
||||
smoothPasses: num(p, 'smooth')
|
||||
})
|
||||
},
|
||||
{
|
||||
id: 'add-stroke-png',
|
||||
title: 'Обвести PNG',
|
||||
description:
|
||||
'Добавляет цветную обводку-кольцо вокруг непрозрачного содержимого заданной толщины.',
|
||||
category: 'alpha',
|
||||
params: [
|
||||
{ id: 'color', label: 'Цвет обводки', type: 'color', default: '#ff0000' },
|
||||
{ id: 'thickness', label: 'Толщина, px', type: 'slider', min: 1, max: 10, step: 1, default: 3 }
|
||||
],
|
||||
run: (img, p) => strokeImage(img, num(p, 'thickness'), str(p, 'color'))
|
||||
},
|
||||
{
|
||||
id: 'find-contour-png',
|
||||
title: 'Найти контур PNG',
|
||||
description:
|
||||
'Оставляет только линию по границе непрозрачных областей выбранного цвета и толщины.',
|
||||
category: 'alpha',
|
||||
params: [
|
||||
{ id: 'color', label: 'Цвет линии', type: 'color', default: '#000000' },
|
||||
{ id: 'thickness', label: 'Толщина линии, px', type: 'slider', min: 1, max: 5, step: 1, default: 1 }
|
||||
],
|
||||
run: (img, p) => contourImage(img, num(p, 'thickness'), str(p, 'color'))
|
||||
},
|
||||
{
|
||||
id: 'make-thicker-png',
|
||||
title: 'Утолщить PNG',
|
||||
description: 'Расширяет непрозрачные области на заданное число пикселей.',
|
||||
category: 'alpha',
|
||||
params: [
|
||||
{ id: 'radius', label: 'На сколько px', type: 'slider', min: 1, max: 10, step: 1, default: 2 }
|
||||
],
|
||||
run: (img, p) => dilateImage(img, num(p, 'radius'))
|
||||
},
|
||||
{
|
||||
id: 'make-thinner-png',
|
||||
title: 'Утончить PNG',
|
||||
description: 'Сужает непрозрачные области — утоньшает штрихи надписей и деталей.',
|
||||
category: 'alpha',
|
||||
params: [
|
||||
{ id: 'radius', label: 'На сколько px', type: 'slider', min: 1, max: 10, step: 1, default: 1 }
|
||||
],
|
||||
run: (img, p) => erodeImage(img, num(p, 'radius'))
|
||||
},
|
||||
{
|
||||
id: 'harden-alpha-png',
|
||||
title: 'Жёсткие края PNG',
|
||||
description:
|
||||
'Бинаризует альфа-канал по порогу: полупрозрачные пиксели становятся либо полностью прозрачными, либо непрозрачными.',
|
||||
category: 'alpha',
|
||||
params: [
|
||||
{ id: 'threshold', label: 'Порог альфы, %', type: 'slider', min: 0, max: 100, step: 1, default: 50 }
|
||||
],
|
||||
run: (img, p) => hardenAlpha(img, num(p, 'threshold'))
|
||||
},
|
||||
{
|
||||
id: 'despeckle-alpha-png',
|
||||
title: 'Убрать мусор PNG',
|
||||
description: 'Открытие: убирает одиночные полупрозрачные пиксели и мелкие крапинки.',
|
||||
category: 'alpha',
|
||||
params: [
|
||||
{ id: 'radius', label: 'Радиус очистки, px', type: 'slider', min: 1, max: 3, step: 1, default: 1 }
|
||||
],
|
||||
run: (img, p) => openingImage(img, num(p, 'radius'))
|
||||
},
|
||||
{
|
||||
id: 'close-holes-png',
|
||||
title: 'Закрыть дыры PNG',
|
||||
description: 'Закрытие: заполняет одиночные прозрачные точки внутри объекта.',
|
||||
category: 'alpha',
|
||||
params: [
|
||||
{ id: 'radius', label: 'Радиус закрытия, px', type: 'slider', min: 1, max: 3, step: 1, default: 1 }
|
||||
],
|
||||
run: (img, p) => closingImage(img, num(p, 'radius'))
|
||||
},
|
||||
{
|
||||
id: 'remove-color-from-png',
|
||||
title: 'Удалить цвет из PNG (прозрачность)',
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
Focus,
|
||||
Frame,
|
||||
Grid3x3,
|
||||
Hammer,
|
||||
Hash,
|
||||
Image as ImageIcon,
|
||||
Info,
|
||||
@@ -31,10 +32,13 @@ import {
|
||||
RotateCw,
|
||||
Ruler,
|
||||
Scaling,
|
||||
Scan,
|
||||
Scissors,
|
||||
SearchCheck,
|
||||
Square,
|
||||
Sun
|
||||
Sun,
|
||||
ZoomIn,
|
||||
ZoomOut
|
||||
} from '@lucide/svelte';
|
||||
|
||||
export const TOOL_ICONS: Record<string, typeof AppWindow> = {
|
||||
@@ -88,5 +92,12 @@ export const TOOL_ICONS: Record<string, typeof AppWindow> = {
|
||||
'png-orientation': Ruler,
|
||||
'blur-png': Droplets,
|
||||
'sharpen-png': Focus,
|
||||
'remove-background-png': Scissors
|
||||
'remove-background-png': Scissors,
|
||||
'add-stroke-png': Square,
|
||||
'find-contour-png': Scan,
|
||||
'make-thicker-png': ZoomIn,
|
||||
'make-thinner-png': ZoomOut,
|
||||
'harden-alpha-png': Sun,
|
||||
'despeckle-alpha-png': SearchCheck,
|
||||
'close-holes-png': Hammer
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user