mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-09-14 21:46:35 +00:00
feat: add alpha tools
This commit is contained in:
@@ -1,8 +1,26 @@
|
|||||||
import type { ToolEntry } from "./types";
|
import type { ToolEntry } from "./types";
|
||||||
import { field, toolSchema } from "../registry-schema";
|
import { field, toolSchema } from "../registry-schema";
|
||||||
import type { Offset } from "../registry-schema";
|
import type { Offset } from "../registry-schema";
|
||||||
import { colorMask, removeColorToAlpha } from "../core/alpha";
|
import {
|
||||||
import { contourImage, strokeImage } from "../core/morphology";
|
colorMask,
|
||||||
|
extractAlphaMask,
|
||||||
|
flattenOntoColor,
|
||||||
|
hardenAlpha,
|
||||||
|
invertAlpha,
|
||||||
|
removeColorToAlpha,
|
||||||
|
roundCorners,
|
||||||
|
setAlphaChannel,
|
||||||
|
} from "../core/alpha";
|
||||||
|
import { backgroundMaskPreview, removeBackground } from "../core/background";
|
||||||
|
import {
|
||||||
|
closingImage,
|
||||||
|
contourImage,
|
||||||
|
dilateImage,
|
||||||
|
erodeImage,
|
||||||
|
openingImage,
|
||||||
|
strokeImage,
|
||||||
|
} from "../core/morphology";
|
||||||
|
import { defringe, featherAlpha } from "../core/pixel-fx";
|
||||||
import {
|
import {
|
||||||
boxTest,
|
boxTest,
|
||||||
circleTest,
|
circleTest,
|
||||||
@@ -242,6 +260,251 @@ const wavyMask: ToolEntry<WavyMaskParams> = {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface EmptyParams {}
|
||||||
|
|
||||||
|
export const removeAlphaChannelSchema = toolSchema<EmptyParams>({});
|
||||||
|
|
||||||
|
const removeAlphaChannel: ToolEntry<EmptyParams> = {
|
||||||
|
id: "remove-alpha-channel-png",
|
||||||
|
title: "Remove alpha channel PNG",
|
||||||
|
description:
|
||||||
|
"Composites the image over a white background and saves without transparency.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: removeAlphaChannelSchema,
|
||||||
|
run: (img) => flattenOntoColor(img, "#ffffff"),
|
||||||
|
};
|
||||||
|
|
||||||
|
interface SetAlphaChannelParams {
|
||||||
|
percent: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const setAlphaChannelSchema = toolSchema<SetAlphaChannelParams>({
|
||||||
|
percent: field.slider({ min: 0, max: 100, step: 1, default: 100 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const setAlphaChannelTool: ToolEntry<SetAlphaChannelParams> = {
|
||||||
|
id: "set-alpha-channel-png",
|
||||||
|
title: "Set alpha channel PNG",
|
||||||
|
description: "Assigns the same opacity to all pixels; colors stay unchanged.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: setAlphaChannelSchema,
|
||||||
|
run: (img, p) => setAlphaChannel(img, p.percent),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const extractAlphaMaskSchema = toolSchema<EmptyParams>({});
|
||||||
|
|
||||||
|
const extractAlphaMaskTool: ToolEntry<EmptyParams> = {
|
||||||
|
id: "extract-alpha-mask-png",
|
||||||
|
title: "Extract alpha mask PNG",
|
||||||
|
description: "Turns transparency into a black-and-white opaque mask.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: extractAlphaMaskSchema,
|
||||||
|
run: (img) => extractAlphaMask(img),
|
||||||
|
};
|
||||||
|
|
||||||
|
interface RoundCornersParams {
|
||||||
|
radius: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const roundCornersSchema = toolSchema<RoundCornersParams>({
|
||||||
|
radius: field.slider({ min: 0, max: 50, step: 1, default: 10 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const roundCornersTool: ToolEntry<RoundCornersParams> = {
|
||||||
|
id: "round-corners-png",
|
||||||
|
title: "Round corners PNG",
|
||||||
|
description:
|
||||||
|
"Clips corners by a radius set as a percentage of half the smaller side.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: roundCornersSchema,
|
||||||
|
run: (img, p) => roundCorners(img, p.radius),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const invertAlphaSchema = toolSchema<EmptyParams>({});
|
||||||
|
|
||||||
|
const invertAlphaTool: ToolEntry<EmptyParams> = {
|
||||||
|
id: "invert-alpha-png",
|
||||||
|
title: "Invert alpha PNG",
|
||||||
|
description: "Opaque areas become transparent and vice versa.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: invertAlphaSchema,
|
||||||
|
run: (img) => invertAlpha(img),
|
||||||
|
};
|
||||||
|
|
||||||
|
interface RemoveBackgroundParams {
|
||||||
|
color: string;
|
||||||
|
tolerance: number;
|
||||||
|
outerOnly: boolean;
|
||||||
|
smooth: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const removeBackgroundSchema = toolSchema<RemoveBackgroundParams>(
|
||||||
|
{
|
||||||
|
color: field.color({ default: "#ffffff" }),
|
||||||
|
tolerance: field.slider({ min: 0, max: 100, step: 1, default: 10 }),
|
||||||
|
outerOnly: field.checkbox({ default: true }),
|
||||||
|
smooth: field.slider({ min: 0, max: 8, step: 1, default: 1 }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
layout: {
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
title: "Background",
|
||||||
|
cols: 2,
|
||||||
|
fields: ["color", "tolerance"],
|
||||||
|
},
|
||||||
|
{ title: "Options", fields: ["outerOnly", "smooth"] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const removeBackgroundTool: ToolEntry<RemoveBackgroundParams> = {
|
||||||
|
id: "remove-background-png",
|
||||||
|
title: "Remove background PNG (smart)",
|
||||||
|
description:
|
||||||
|
"Removes a solid background: by color with tolerance, outer regions from the edges only, or every matching pixel. Can smooth the boundary.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: removeBackgroundSchema,
|
||||||
|
run: (img, p) =>
|
||||||
|
removeBackground(img, {
|
||||||
|
color: p.color,
|
||||||
|
tolerancePercent: p.tolerance,
|
||||||
|
outerOnly: p.outerOnly,
|
||||||
|
smoothPasses: p.smooth,
|
||||||
|
}),
|
||||||
|
preview: (img, p) =>
|
||||||
|
backgroundMaskPreview(img, {
|
||||||
|
color: p.color,
|
||||||
|
tolerancePercent: p.tolerance,
|
||||||
|
outerOnly: p.outerOnly,
|
||||||
|
smoothPasses: p.smooth,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
interface MakeThickerParams {
|
||||||
|
radius: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const makeThickerSchema = toolSchema<MakeThickerParams>({
|
||||||
|
radius: field.slider({ min: 1, max: 10, step: 1, default: 2 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const makeThickerTool: ToolEntry<MakeThickerParams> = {
|
||||||
|
id: "make-thicker-png",
|
||||||
|
title: "Thicken PNG",
|
||||||
|
description: "Expands opaque areas by the given number of pixels.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: makeThickerSchema,
|
||||||
|
run: (img, p) => dilateImage(img, p.radius),
|
||||||
|
};
|
||||||
|
|
||||||
|
interface MakeThinnerParams {
|
||||||
|
radius: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const makeThinnerSchema = toolSchema<MakeThinnerParams>({
|
||||||
|
radius: field.slider({ min: 1, max: 10, step: 1, default: 1 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const makeThinnerTool: ToolEntry<MakeThinnerParams> = {
|
||||||
|
id: "make-thinner-png",
|
||||||
|
title: "Thin PNG",
|
||||||
|
description: "Shrinks opaque areas — thins the strokes of text and details.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: makeThinnerSchema,
|
||||||
|
run: (img, p) => erodeImage(img, p.radius),
|
||||||
|
};
|
||||||
|
|
||||||
|
interface FeatherEdgesParams {
|
||||||
|
radius: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const featherEdgesSchema = toolSchema<FeatherEdgesParams>({
|
||||||
|
radius: field.slider({ min: 1, max: 20, step: 1, default: 3 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const featherEdgesTool: ToolEntry<FeatherEdgesParams> = {
|
||||||
|
id: "feather-edges-png",
|
||||||
|
title: "Feather Edges PNG",
|
||||||
|
description:
|
||||||
|
"Blurs only the alpha channel: hard cutout edges become soft and gradual, colors stay untouched.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: featherEdgesSchema,
|
||||||
|
run: (img, p) => featherAlpha(img, p.radius),
|
||||||
|
};
|
||||||
|
|
||||||
|
interface CleanEdgesParams {
|
||||||
|
radius: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const cleanEdgesSchema = toolSchema<CleanEdgesParams>({
|
||||||
|
radius: field.slider({ min: 1, max: 10, step: 1, default: 3 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const cleanEdgesTool: ToolEntry<CleanEdgesParams> = {
|
||||||
|
id: "clean-edges-png",
|
||||||
|
title: "Clean Edges PNG (defringe)",
|
||||||
|
description:
|
||||||
|
"Replaces edge-halo colors of semi-transparent pixels with the nearest fully opaque color. Alpha stays as is.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: cleanEdgesSchema,
|
||||||
|
run: (img, p) => defringe(img, p.radius),
|
||||||
|
};
|
||||||
|
|
||||||
|
interface HardenAlphaParams {
|
||||||
|
threshold: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const hardenAlphaSchema = toolSchema<HardenAlphaParams>({
|
||||||
|
threshold: field.slider({ min: 0, max: 100, step: 1, default: 50 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const hardenAlphaTool: ToolEntry<HardenAlphaParams> = {
|
||||||
|
id: "harden-alpha-png",
|
||||||
|
title: "Harden edges PNG",
|
||||||
|
description:
|
||||||
|
"Binarizes the alpha channel by threshold: semi-transparent pixels become either fully transparent or fully opaque.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: hardenAlphaSchema,
|
||||||
|
run: (img, p) => hardenAlpha(img, p.threshold),
|
||||||
|
};
|
||||||
|
|
||||||
|
interface DespeckleAlphaParams {
|
||||||
|
radius: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const despeckleAlphaSchema = toolSchema<DespeckleAlphaParams>({
|
||||||
|
radius: field.slider({ min: 1, max: 3, step: 1, default: 1 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const despeckleAlphaTool: ToolEntry<DespeckleAlphaParams> = {
|
||||||
|
id: "despeckle-alpha-png",
|
||||||
|
title: "Despeckle PNG",
|
||||||
|
description:
|
||||||
|
"Opening: removes lone semi-transparent pixels and small specks.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: despeckleAlphaSchema,
|
||||||
|
run: (img, p) => openingImage(img, p.radius),
|
||||||
|
};
|
||||||
|
|
||||||
|
interface CloseHolesParams {
|
||||||
|
radius: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const closeHolesSchema = toolSchema<CloseHolesParams>({
|
||||||
|
radius: field.slider({ min: 1, max: 3, step: 1, default: 1 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const closeHolesTool: ToolEntry<CloseHolesParams> = {
|
||||||
|
id: "close-holes-png",
|
||||||
|
title: "Close holes PNG",
|
||||||
|
description: "Closing: fills lone transparent dots inside the object.",
|
||||||
|
category: "alpha",
|
||||||
|
schema: closeHolesSchema,
|
||||||
|
run: (img, p) => closingImage(img, p.radius),
|
||||||
|
};
|
||||||
|
|
||||||
export const alphaEntries = [
|
export const alphaEntries = [
|
||||||
addStroke,
|
addStroke,
|
||||||
findContour,
|
findContour,
|
||||||
@@ -250,4 +513,17 @@ export const alphaEntries = [
|
|||||||
squareMask,
|
squareMask,
|
||||||
starMask,
|
starMask,
|
||||||
wavyMask,
|
wavyMask,
|
||||||
|
removeAlphaChannel,
|
||||||
|
setAlphaChannelTool,
|
||||||
|
extractAlphaMaskTool,
|
||||||
|
roundCornersTool,
|
||||||
|
invertAlphaTool,
|
||||||
|
removeBackgroundTool,
|
||||||
|
makeThickerTool,
|
||||||
|
makeThinnerTool,
|
||||||
|
featherEdgesTool,
|
||||||
|
cleanEdgesTool,
|
||||||
|
hardenAlphaTool,
|
||||||
|
despeckleAlphaTool,
|
||||||
|
closeHolesTool,
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user