mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-09-14 21:46:35 +00:00
feat: add tool registry, icons
This commit is contained in:
+129
-1
@@ -28,23 +28,29 @@ import {
|
|||||||
} from './core/morphology';
|
} from './core/morphology';
|
||||||
import { gaussianBlur, sharpen as sharpenImage } from './core/convolution';
|
import { gaussianBlur, sharpen as sharpenImage } from './core/convolution';
|
||||||
import { gradientImage, noiseImage, solidImage } from './core/generate';
|
import { gradientImage, noiseImage, solidImage } from './core/generate';
|
||||||
|
import { rotateFreeImage, skewImage, transformImage, zoomImage } from './core/affine';
|
||||||
|
import { vignette } from './core/effects';
|
||||||
import {
|
import {
|
||||||
|
autoContrast,
|
||||||
brightnessContrast,
|
brightnessContrast,
|
||||||
changeHue,
|
changeHue,
|
||||||
extractChannel,
|
extractChannel,
|
||||||
|
gammaCorrection,
|
||||||
grayscale,
|
grayscale,
|
||||||
invert,
|
invert,
|
||||||
posterize,
|
posterize,
|
||||||
sepia,
|
sepia,
|
||||||
setOpacity,
|
setOpacity,
|
||||||
swapChannels,
|
swapChannels,
|
||||||
|
temperature,
|
||||||
|
tint,
|
||||||
thresholdBlackWhite,
|
thresholdBlackWhite,
|
||||||
twoColors,
|
twoColors,
|
||||||
type ChannelSwapPair,
|
type ChannelSwapPair,
|
||||||
type RgbChannel
|
type RgbChannel
|
||||||
} from './core/color';
|
} from './core/color';
|
||||||
import { centerByAlpha, crop, expandCanvas, flip, resize, rotate90, tile } from './core/geometry';
|
import { centerByAlpha, crop, expandCanvas, flip, resize, rotate90, tile } from './core/geometry';
|
||||||
import { decodeTextImage, toBase64, toDataUrl, type OutputMime } from './core/io';
|
import { decodeSvgText, decodeTextImage, jpegRoundtrip, toBase64, toDataUrl, type OutputMime } from './core/io';
|
||||||
import { hexToPixels, pixelsToHex } from './core/text';
|
import { hexToPixels, pixelsToHex } from './core/text';
|
||||||
import { clonePixelImage, type PixelImage } from './core/types';
|
import { clonePixelImage, type PixelImage } from './core/types';
|
||||||
|
|
||||||
@@ -860,6 +866,128 @@ export const TOOLS: ToolEntry[] = [
|
|||||||
? 'Да — все пиксели являются оттенками серого.'
|
? 'Да — все пиксели являются оттенками серого.'
|
||||||
: 'Нет — найдены цветные пиксели.'
|
: 'Нет — найдены цветные пиксели.'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'skew-png',
|
||||||
|
title: 'Наклонить PNG',
|
||||||
|
description: 'Сдвигает содержимое по горизонтали и вертикали — эффект перспективы.',
|
||||||
|
category: 'geometry',
|
||||||
|
params: [
|
||||||
|
{ id: 'degX', label: 'Наклон по X, °', type: 'slider', min: -80, max: 80, step: 1, default: 0 },
|
||||||
|
{ id: 'degY', label: 'Наклон по Y, °', type: 'slider', min: -80, max: 80, step: 1, default: 0 }
|
||||||
|
],
|
||||||
|
run: (img, p) => skewImage(img, num(p, 'degX'), num(p, 'degY'))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'rotate-free-png',
|
||||||
|
title: 'Повернуть на произвольный угол',
|
||||||
|
description:
|
||||||
|
'Поворот на любой угол. Холст расширяется под новые габариты, углы остаются прозрачными.',
|
||||||
|
category: 'geometry',
|
||||||
|
params: [
|
||||||
|
{ id: 'angle', label: 'Угол, °', type: 'slider', min: -180, max: 180, step: 1, default: 15 }
|
||||||
|
],
|
||||||
|
run: (img, p) => rotateFreeImage(img, num(p, 'angle'))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'zoom-png',
|
||||||
|
title: 'Приблизить PNG',
|
||||||
|
description:
|
||||||
|
'Увеличивает содержимое к центру. Холст прежнего размера — края обрезаются.',
|
||||||
|
category: 'geometry',
|
||||||
|
params: [
|
||||||
|
{ id: 'scale', label: 'Масштаб, %', type: 'slider', min: 100, max: 500, step: 10, default: 200 }
|
||||||
|
],
|
||||||
|
run: (img, p) => zoomImage(img, num(p, 'scale'))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'shift-png',
|
||||||
|
title: 'Сдвинуть PNG',
|
||||||
|
description: 'Перемещает содержимое на заданное смещение по X и Y.',
|
||||||
|
category: 'geometry',
|
||||||
|
params: [
|
||||||
|
{ id: 'offsetX', label: 'Смещение X, px', type: 'number', min: -5000, max: 5000, step: 1, default: 0 },
|
||||||
|
{ id: 'offsetY', label: 'Смещение Y, px', type: 'number', min: -5000, max: 5000, step: 1, default: 0 },
|
||||||
|
{ id: 'color', label: 'Цвет фона', type: 'color', default: '#ffffff' }
|
||||||
|
],
|
||||||
|
run: (img, p) =>
|
||||||
|
transformImage(
|
||||||
|
img,
|
||||||
|
[1, 0, 0, 1, -Math.trunc(num(p, 'offsetX')), -Math.trunc(num(p, 'offsetY'))],
|
||||||
|
img.width,
|
||||||
|
img.height
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'vignette-png',
|
||||||
|
title: 'Виньетка PNG',
|
||||||
|
description: 'Плавно затемняет края изображения, центр не затрагивает.',
|
||||||
|
category: 'filters',
|
||||||
|
params: [
|
||||||
|
{ id: 'strength', label: 'Сила затемнения, %', type: 'slider', min: 0, max: 100, step: 5, default: 50 }
|
||||||
|
],
|
||||||
|
run: (img, p) => vignette(img, num(p, 'strength'))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'jpeg-artifacts-png',
|
||||||
|
title: 'Артефакты JPEG',
|
||||||
|
description:
|
||||||
|
'Имитирует пережатие в JPEG с низким качеством — видимые квадраты и размытие цветов.',
|
||||||
|
category: 'filters',
|
||||||
|
params: [
|
||||||
|
{ id: 'quality', label: 'Качество JPEG', type: 'slider', min: 1, max: 50, step: 1, default: 10 }
|
||||||
|
],
|
||||||
|
run: (img, p) => jpegRoundtrip(img, num(p, 'quality'))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'gamma-png',
|
||||||
|
title: 'Гамма-коррекция PNG',
|
||||||
|
description: 'Корректирует яркость средних тонов. <1 темнее, >1 светлее, 1 — без изменений.',
|
||||||
|
category: 'color',
|
||||||
|
params: [
|
||||||
|
{ id: 'value', label: 'Гамма', type: 'slider', min: 0.1, max: 3, step: 0.05, default: 1 }
|
||||||
|
],
|
||||||
|
run: (img, p) => gammaCorrection(img, num(p, 'value'))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'auto-contrast-png',
|
||||||
|
title: 'Автоконтраст PNG',
|
||||||
|
description: 'Растягивает диапазон каждого канала на весь доступный диапазон яркости.',
|
||||||
|
category: 'color',
|
||||||
|
params: [],
|
||||||
|
run: (img) => autoContrast(img)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'temperature-png',
|
||||||
|
title: 'Температура PNG',
|
||||||
|
description: 'Отрицательные значения делают изображение теплее (оранжевее), положительные — холоднее (синеватее).',
|
||||||
|
category: 'color',
|
||||||
|
params: [
|
||||||
|
{ id: 'percent', label: 'Температура', type: 'slider', min: -100, max: 100, step: 1, default: 0 }
|
||||||
|
],
|
||||||
|
run: (img, p) => temperature(img, num(p, 'percent'))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'tint-png',
|
||||||
|
title: 'Тонировать PNG',
|
||||||
|
description: 'Умножает цветовые каналы на выбранный оттенок с заданной силой.',
|
||||||
|
category: 'color',
|
||||||
|
params: [
|
||||||
|
{ id: 'color', label: 'Цвет тонирования', type: 'color', default: '#ffb060' },
|
||||||
|
{ id: 'strength', label: 'Сила, %', type: 'slider', min: 0, max: 100, step: 1, default: 30 }
|
||||||
|
],
|
||||||
|
run: (img, p) => tint(img, str(p, 'color'), num(p, 'strength'))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'svg-to-png',
|
||||||
|
title: 'SVG в PNG',
|
||||||
|
description:
|
||||||
|
'Dекодирует SVG-разметку в растровое изображение. Вставьте SVG-код слева.',
|
||||||
|
category: 'convert',
|
||||||
|
sourceMode: 'text',
|
||||||
|
params: [{ id: 'width', label: 'Ширина результата, px', type: 'number', min: 1, max: 10000, step: 1, default: 512 }],
|
||||||
|
runFromText: (text, p) => decodeSvgText(text, Math.trunc(num(p, 'width'))),
|
||||||
|
run: (img) => clonePixelImage(img)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'png-is-transparent',
|
id: 'png-is-transparent',
|
||||||
title: 'Проверить: PNG прозрачный?',
|
title: 'Проверить: PNG прозрачный?',
|
||||||
|
|||||||
@@ -99,5 +99,16 @@ export const TOOL_ICONS: Record<string, typeof AppWindow> = {
|
|||||||
'make-thinner-png': ZoomOut,
|
'make-thinner-png': ZoomOut,
|
||||||
'harden-alpha-png': Sun,
|
'harden-alpha-png': Sun,
|
||||||
'despeckle-alpha-png': SearchCheck,
|
'despeckle-alpha-png': SearchCheck,
|
||||||
'close-holes-png': Hammer
|
'close-holes-png': Hammer,
|
||||||
|
'skew-png': Repeat2,
|
||||||
|
'rotate-free-png': RotateCw,
|
||||||
|
'zoom-png': ZoomIn,
|
||||||
|
'shift-png': Crosshair,
|
||||||
|
'vignette-png': Sun,
|
||||||
|
'jpeg-artifacts-png': Layers,
|
||||||
|
'gamma-png': Contrast,
|
||||||
|
'auto-contrast-png': Contrast,
|
||||||
|
'temperature-png': Sun,
|
||||||
|
'tint-png': Droplet,
|
||||||
|
'svg-to-png': FileImage
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user