feat: add registry - background, blur, sharpen
This commit is contained in:
@@ -1,4 +1,11 @@
|
|||||||
export type CategoryId = 'convert' | 'alpha' | 'color' | 'geometry' | 'analyze' | 'generate';
|
export type CategoryId =
|
||||||
|
| 'convert'
|
||||||
|
| 'alpha'
|
||||||
|
| 'color'
|
||||||
|
| 'geometry'
|
||||||
|
| 'analyze'
|
||||||
|
| 'generate'
|
||||||
|
| 'filters';
|
||||||
|
|
||||||
export type Category = { id: CategoryId; label: string };
|
export type Category = { id: CategoryId; label: string };
|
||||||
|
|
||||||
@@ -7,6 +14,7 @@ export const CATEGORIES: Category[] = [
|
|||||||
{ id: 'alpha', label: 'Прозрачность' },
|
{ id: 'alpha', label: 'Прозрачность' },
|
||||||
{ id: 'color', label: 'Цвет' },
|
{ id: 'color', label: 'Цвет' },
|
||||||
{ id: 'geometry', label: 'Геометрия' },
|
{ id: 'geometry', label: 'Геометрия' },
|
||||||
|
{ id: 'filters', label: 'Фильтры' },
|
||||||
{ id: 'analyze', label: 'Анализ' },
|
{ id: 'analyze', label: 'Анализ' },
|
||||||
{ id: 'generate', label: 'Генерация' }
|
{ id: 'generate', label: 'Генерация' }
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -58,11 +58,14 @@ const PLAN_TOOL_IDS = [
|
|||||||
'linear-gradient-png',
|
'linear-gradient-png',
|
||||||
'png-is-grayscale',
|
'png-is-grayscale',
|
||||||
'png-is-transparent',
|
'png-is-transparent',
|
||||||
'png-orientation'
|
'png-orientation',
|
||||||
|
'remove-background-png',
|
||||||
|
'blur-png',
|
||||||
|
'sharpen-png'
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('реестр инструментов', () => {
|
describe('реестр инструментов', () => {
|
||||||
it('содержит ровно 48 инструментов из плана', () => {
|
it('содержит ровно 51 инструмент из плана', () => {
|
||||||
expect(TOOLS.map((t) => t.id).sort()).toEqual([...PLAN_TOOL_IDS].sort());
|
expect(TOOLS.map((t) => t.id).sort()).toEqual([...PLAN_TOOL_IDS].sort());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import {
|
|||||||
isGrayscale,
|
isGrayscale,
|
||||||
orientationOf
|
orientationOf
|
||||||
} from './core/analyze';
|
} from './core/analyze';
|
||||||
|
import { backgroundMaskPreview, removeBackground } from './core/background';
|
||||||
|
import { gaussianBlur, sharpen as sharpenImage } from './core/convolution';
|
||||||
import { gradientImage, noiseImage, solidImage } from './core/generate';
|
import { gradientImage, noiseImage, solidImage } from './core/generate';
|
||||||
import {
|
import {
|
||||||
brightnessContrast,
|
brightnessContrast,
|
||||||
@@ -406,6 +408,28 @@ export const TOOLS: ToolEntry[] = [
|
|||||||
params: [],
|
params: [],
|
||||||
run: (img) => centerByAlpha(img)
|
run: (img) => centerByAlpha(img)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'blur-png',
|
||||||
|
title: 'Размытие PNG',
|
||||||
|
description:
|
||||||
|
'Гауссово размытие: три прохода разделяемого бокса — быстро при любом радиусе. Прозрачные края не темнеют.',
|
||||||
|
category: 'filters',
|
||||||
|
params: [
|
||||||
|
{ id: 'radius', label: 'Радиус, px', type: 'slider', min: 1, max: 32, step: 1, default: 4 }
|
||||||
|
],
|
||||||
|
run: (img, p) => gaussianBlur(img, num(p, 'radius'))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sharpen-png',
|
||||||
|
title: 'Резкость PNG',
|
||||||
|
description:
|
||||||
|
'Подчёркивает края ядром резкости; сила задаёт смесь с оригиналом. 0% — без изменений.',
|
||||||
|
category: 'filters',
|
||||||
|
params: [
|
||||||
|
{ id: 'strength', label: 'Сила, %', type: 'slider', min: 0, max: 100, step: 1, default: 50 }
|
||||||
|
],
|
||||||
|
run: (img, p) => sharpenImage(img, num(p, 'strength'))
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'grayscale-png',
|
id: 'grayscale-png',
|
||||||
title: 'Чёрно-белый PNG',
|
title: 'Чёрно-белый PNG',
|
||||||
@@ -601,6 +625,33 @@ export const TOOLS: ToolEntry[] = [
|
|||||||
params: [],
|
params: [],
|
||||||
run: (img) => invertAlpha(img)
|
run: (img) => invertAlpha(img)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'remove-background-png',
|
||||||
|
title: 'Удалить фон PNG (умно)',
|
||||||
|
description:
|
||||||
|
'Убирает однотонный фон: по цвету с допуском, только внешние области от краёв или весь совпадающий цвет. Умеет сглаживать границу.',
|
||||||
|
category: 'alpha',
|
||||||
|
params: [
|
||||||
|
{ id: 'color', label: 'Цвет фона', type: 'color', default: '#ffffff' },
|
||||||
|
{ id: 'tolerance', label: 'Допуск похожести, %', type: 'slider', min: 0, max: 100, step: 1, default: 10 },
|
||||||
|
{ id: 'outerOnly', label: 'Только внешние области', type: 'checkbox', default: true },
|
||||||
|
{ id: 'smooth', label: 'Сглаживание границы, проходы', type: 'slider', min: 0, max: 8, step: 1, default: 1 }
|
||||||
|
],
|
||||||
|
run: (img, p) =>
|
||||||
|
removeBackground(img, {
|
||||||
|
color: str(p, 'color'),
|
||||||
|
tolerancePercent: num(p, 'tolerance'),
|
||||||
|
outerOnly: p['outerOnly'] === true,
|
||||||
|
smoothPasses: num(p, 'smooth')
|
||||||
|
}),
|
||||||
|
preview: (img, p) =>
|
||||||
|
backgroundMaskPreview(img, {
|
||||||
|
color: str(p, 'color'),
|
||||||
|
tolerancePercent: num(p, 'tolerance'),
|
||||||
|
outerOnly: p['outerOnly'] === true,
|
||||||
|
smoothPasses: num(p, 'smooth')
|
||||||
|
})
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'remove-color-from-png',
|
id: 'remove-color-from-png',
|
||||||
title: 'Удалить цвет из PNG (прозрачность)',
|
title: 'Удалить цвет из PNG (прозрачность)',
|
||||||
|
|||||||
Reference in New Issue
Block a user