feat: update alpha and colors tools to new types

This commit is contained in:
2026-09-10 12:01:54 +05:00
parent 2937974fe7
commit bea010dd90
3 changed files with 105 additions and 52 deletions
+47 -31
View File
@@ -1,8 +1,7 @@
import type { ToolEntry } from "./types";
import { imgTool, type ToolEntry } from "./types";
import { field, toolSchema } from "../registry-schema";
import type { Offset } from "../registry-schema";
import {
colorMask,
extractAlphaMask,
flattenOntoColor,
hardenAlpha,
@@ -11,7 +10,7 @@ import {
roundCorners,
setAlphaChannel,
} from "../core/alpha";
import { backgroundMaskPreview, removeBackground } from "../core/background";
import { removeBackground } from "../core/background";
import {
closingImage,
contourImage,
@@ -46,7 +45,8 @@ const addStroke: ToolEntry<AddStrokeParams> = {
"Adds a colored ring outline around the opaque content with the chosen thickness.",
category: "alpha",
schema: addStrokeSchema,
run: (img, p) => strokeImage(img, p.thickness, p.color),
input: "image",
run: imgTool((img, p) => strokeImage(img, p.thickness, p.color)),
};
interface FindContourParams {
@@ -66,7 +66,8 @@ const findContour: ToolEntry<FindContourParams> = {
"Leaves only a line along the boundary of opaque regions in the chosen color and thickness.",
category: "alpha",
schema: findContourSchema,
run: (img, p) => contourImage(img, p.thickness, p.color),
input: "image",
run: imgTool((img, p) => contourImage(img, p.thickness, p.color)),
};
interface RemoveColorParams {
@@ -86,8 +87,8 @@ const removeColor: ToolEntry<RemoveColorParams> = {
"Makes all pixels close to the chosen color transparent. The tolerance sets the allowed deviation as a percentage of the maximum color distance.",
category: "alpha",
schema: removeColorSchema,
run: (img, p) => removeColorToAlpha(img, p.targetColor, p.tolerance),
preview: (img, p) => colorMask(img, p.targetColor, p.tolerance),
input: "image",
run: imgTool((img, p) => removeColorToAlpha(img, p.targetColor, p.tolerance)),
};
interface CircleMaskParams {
@@ -117,13 +118,15 @@ const circleMask: ToolEntry<CircleMaskParams> = {
"Cuts the image into a circle. Diameter is set as a share of the smaller side.",
category: "alpha",
schema: circleMaskSchema,
run: (img, p) =>
input: "image",
run: imgTool((img, p) =>
renderShape(
img,
circleTest(p.size / 200),
p.offset.x / 100,
p.offset.y / 100,
),
),
};
interface SquareMaskParams {
@@ -159,13 +162,15 @@ const squareMask: ToolEntry<SquareMaskParams> = {
"Cuts the image into a rectangle with sides as a share of the smaller side.",
category: "alpha",
schema: squareMaskSchema,
run: (img, p) =>
input: "image",
run: imgTool((img, p) =>
renderShape(
img,
boxTest(p.widthPct / 200, p.heightPct / 200),
p.offset.x / 100,
p.offset.y / 100,
),
),
};
interface StarMaskParams {
@@ -205,13 +210,15 @@ const starMask: ToolEntry<StarMaskParams> = {
"Cuts the image into an n-pointed star with adjustable inner radius and rotation.",
category: "alpha",
schema: starMaskSchema,
run: (img, p) =>
input: "image",
run: imgTool((img, p) =>
renderShape(
img,
starTest(p.points, p.innerRadius / 100, p.size / 200, p.rotation),
p.offset.x / 100,
p.offset.y / 100,
),
),
};
interface WavyMaskParams {
@@ -251,13 +258,15 @@ const wavyMask: ToolEntry<WavyMaskParams> = {
"Cuts the image into a wavy-edged circle: radius is modulated by a sine with chosen amplitude and frequency.",
category: "alpha",
schema: wavyMaskSchema,
run: (img, p) =>
input: "image",
run: imgTool((img, p) =>
renderShape(
img,
wavyTest(p.size / 200, p.amplitude / 200, p.waves, p.phase),
p.offset.x / 100,
p.offset.y / 100,
),
),
};
interface EmptyParams {}
@@ -271,7 +280,8 @@ const removeAlphaChannel: ToolEntry<EmptyParams> = {
"Composites the image over a white background and saves without transparency.",
category: "alpha",
schema: removeAlphaChannelSchema,
run: (img) => flattenOntoColor(img, "#ffffff"),
input: "image",
run: imgTool((img) => flattenOntoColor(img, "#ffffff")),
};
interface SetAlphaChannelParams {
@@ -288,7 +298,8 @@ const setAlphaChannelTool: ToolEntry<SetAlphaChannelParams> = {
description: "Assigns the same opacity to all pixels; colors stay unchanged.",
category: "alpha",
schema: setAlphaChannelSchema,
run: (img, p) => setAlphaChannel(img, p.percent),
input: "image",
run: imgTool((img, p) => setAlphaChannel(img, p.percent)),
};
export const extractAlphaMaskSchema = toolSchema<EmptyParams>({});
@@ -299,7 +310,8 @@ const extractAlphaMaskTool: ToolEntry<EmptyParams> = {
description: "Turns transparency into a black-and-white opaque mask.",
category: "alpha",
schema: extractAlphaMaskSchema,
run: (img) => extractAlphaMask(img),
input: "image",
run: imgTool((img) => extractAlphaMask(img)),
};
interface RoundCornersParams {
@@ -317,7 +329,8 @@ const roundCornersTool: ToolEntry<RoundCornersParams> = {
"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),
input: "image",
run: imgTool((img, p) => roundCorners(img, p.radius)),
};
export const invertAlphaSchema = toolSchema<EmptyParams>({});
@@ -328,7 +341,8 @@ const invertAlphaTool: ToolEntry<EmptyParams> = {
description: "Opaque areas become transparent and vice versa.",
category: "alpha",
schema: invertAlphaSchema,
run: (img) => invertAlpha(img),
input: "image",
run: imgTool((img) => invertAlpha(img)),
};
interface RemoveBackgroundParams {
@@ -366,20 +380,15 @@ const removeBackgroundTool: ToolEntry<RemoveBackgroundParams> = {
"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) =>
input: "image",
run: imgTool((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 {
@@ -396,7 +405,8 @@ const makeThickerTool: ToolEntry<MakeThickerParams> = {
description: "Expands opaque areas by the given number of pixels.",
category: "alpha",
schema: makeThickerSchema,
run: (img, p) => dilateImage(img, p.radius),
input: "image",
run: imgTool((img, p) => dilateImage(img, p.radius)),
};
interface MakeThinnerParams {
@@ -413,7 +423,8 @@ const makeThinnerTool: ToolEntry<MakeThinnerParams> = {
description: "Shrinks opaque areas — thins the strokes of text and details.",
category: "alpha",
schema: makeThinnerSchema,
run: (img, p) => erodeImage(img, p.radius),
input: "image",
run: imgTool((img, p) => erodeImage(img, p.radius)),
};
interface FeatherEdgesParams {
@@ -431,7 +442,8 @@ const featherEdgesTool: ToolEntry<FeatherEdgesParams> = {
"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),
input: "image",
run: imgTool((img, p) => featherAlpha(img, p.radius)),
};
interface CleanEdgesParams {
@@ -449,7 +461,8 @@ const cleanEdgesTool: ToolEntry<CleanEdgesParams> = {
"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),
input: "image",
run: imgTool((img, p) => defringe(img, p.radius)),
};
interface HardenAlphaParams {
@@ -467,7 +480,8 @@ const hardenAlphaTool: ToolEntry<HardenAlphaParams> = {
"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),
input: "image",
run: imgTool((img, p) => hardenAlpha(img, p.threshold)),
};
interface DespeckleAlphaParams {
@@ -485,7 +499,8 @@ const despeckleAlphaTool: ToolEntry<DespeckleAlphaParams> = {
"Opening: removes lone semi-transparent pixels and small specks.",
category: "alpha",
schema: despeckleAlphaSchema,
run: (img, p) => openingImage(img, p.radius),
input: "image",
run: imgTool((img, p) => openingImage(img, p.radius)),
};
interface CloseHolesParams {
@@ -502,7 +517,8 @@ const closeHolesTool: ToolEntry<CloseHolesParams> = {
description: "Closing: fills lone transparent dots inside the object.",
category: "alpha",
schema: closeHolesSchema,
run: (img, p) => closingImage(img, p.radius),
input: "image",
run: imgTool((img, p) => closingImage(img, p.radius)),
};
export const alphaEntries = [
+43 -21
View File
@@ -21,7 +21,7 @@ import { renderSpace, SPACES, type SpaceId } from "../core/channels";
import { parseHexList } from "../core/palette";
import { ditherImage, mapToNearest, quantizeImage } from "../core/quantize";
import { field, toolSchema, type ColorPair } from "../registry-schema";
import type { ToolEntry } from "./types";
import { imgTool, type ToolEntry } from "./types";
interface TwoColorsParams {
pair: ColorPair;
@@ -40,7 +40,8 @@ const twoColorsTool: ToolEntry<TwoColorsParams> = {
"Recolors the image into two chosen colors by luminance threshold.",
category: "color",
schema: twoColorsSchema,
run: (img, p) => twoColors(img, p.pair.from, p.pair.to, p.threshold),
input: "image",
run: imgTool((img, p) => twoColors(img, p.pair.from, p.pair.to, p.threshold)),
};
interface GammaParams {
@@ -58,7 +59,8 @@ const gammaTool: ToolEntry<GammaParams> = {
"Corrects midtone brightness. <1 darker, >1 lighter, 1 — unchanged.",
category: "color",
schema: gammaSchema,
run: (img, p) => gammaCorrection(img, p.value),
input: "image",
run: imgTool((img, p) => gammaCorrection(img, p.value)),
};
interface TemperatureParams {
@@ -76,7 +78,8 @@ const temperatureTool: ToolEntry<TemperatureParams> = {
"Positive values make the image warmer (more orange), negative ones cooler (more blue).",
category: "color",
schema: temperatureSchema,
run: (img, p) => temperature(img, p.percent),
input: "image",
run: imgTool((img, p) => temperature(img, p.percent)),
};
interface TintParams {
@@ -96,7 +99,8 @@ const tintTool: ToolEntry<TintParams> = {
"Multiplies color channels by the chosen tint with the given strength.",
category: "color",
schema: tintSchema,
run: (img, p) => tint(img, p.color, p.strength),
input: "image",
run: imgTool((img, p) => tint(img, p.color, p.strength)),
};
interface QuantizeParams {
@@ -114,7 +118,8 @@ const quantizeTool: ToolEntry<QuantizeParams> = {
"Reduces the image to k colors via median-cut palette. Transparent pixels are preserved.",
category: "color",
schema: quantizeSchema,
run: (img, p) => quantizeImage(img, p.colors).image,
input: "image",
run: imgTool((img, p) => quantizeImage(img, p.colors).image),
};
interface CustomPaletteParams {
@@ -132,7 +137,8 @@ const customPalette: ToolEntry<CustomPaletteParams> = {
"Maps every pixel to the nearest color from your comma-separated hex list.",
category: "color",
schema: customPaletteSchema,
run: (img, p) => mapToNearest(img, parseHexList(p.colors)),
input: "image",
run: imgTool((img, p) => mapToNearest(img, parseHexList(p.colors))),
};
interface DitheringParams {
@@ -158,7 +164,8 @@ const ditheringTool: ToolEntry<DitheringParams> = {
"Applies FloydSteinberg error diffusion or ordered Bayer dithering while reducing to k colors.",
category: "color",
schema: ditheringSchema,
run: (img, p) => ditherImage(img, p.colors, p.pattern),
input: "image",
run: imgTool((img, p) => ditherImage(img, p.colors, p.pattern)),
};
interface EmptyParams {}
@@ -172,7 +179,8 @@ const grayscaleTool: ToolEntry<EmptyParams> = {
"Converts the image to shades of gray using the BT.601 luminance formula. Alpha is preserved.",
category: "color",
schema: grayscaleSchema,
run: (img) => grayscale(img),
input: "image",
run: imgTool((img) => grayscale(img)),
};
export const invertColorsSchema = toolSchema<EmptyParams>({});
@@ -183,7 +191,8 @@ const invertColorsTool: ToolEntry<EmptyParams> = {
description: "Inverts each color channel (255 value). Alpha is unchanged.",
category: "color",
schema: invertColorsSchema,
run: (img) => invert(img),
input: "image",
run: imgTool((img) => invert(img)),
};
interface BrightnessContrastParams {
@@ -212,7 +221,8 @@ const brightnessContrastTool: ToolEntry<BrightnessContrastParams> = {
"Adjusts brightness and contrast in the range from 100 to +100. Zero means no change.",
category: "color",
schema: brightnessContrastSchema,
run: (img, p) => brightnessContrast(img, p.brightness, p.contrast),
input: "image",
run: imgTool((img, p) => brightnessContrast(img, p.brightness, p.contrast)),
};
interface OpacityParams {
@@ -230,7 +240,8 @@ const opacityTool: ToolEntry<OpacityParams> = {
"Multiplies the alpha channel by a percentage: 0% — fully transparent, 100% — unchanged.",
category: "color",
schema: opacitySchema,
run: (img, p) => setOpacity(img, p.percent),
input: "image",
run: imgTool((img, p) => setOpacity(img, p.percent)),
};
export const sepiaSchema = toolSchema<EmptyParams>({});
@@ -241,7 +252,8 @@ const sepiaTool: ToolEntry<EmptyParams> = {
description: "Tints the image into the warm brown tones of classic sepia.",
category: "color",
schema: sepiaSchema,
run: (img) => sepia(img),
input: "image",
run: imgTool((img) => sepia(img)),
};
interface HueShiftParams {
@@ -259,7 +271,8 @@ const hueShiftTool: ToolEntry<HueShiftParams> = {
"Shifts the hue around the circle. Saturation and lightness are preserved.",
category: "color",
schema: hueShiftSchema,
run: (img, p) => changeHue(img, p.degrees),
input: "image",
run: imgTool((img, p) => changeHue(img, p.degrees)),
};
interface ExtractChannelParams {
@@ -284,7 +297,8 @@ const extractChannelTool: ToolEntry<ExtractChannelParams> = {
"Keeps only the chosen channel — red, green or blue — as shades of gray.",
category: "color",
schema: extractChannelSchema,
run: (img, p) => extractChannel(img, p.channel),
input: "image",
run: imgTool((img, p) => extractChannel(img, p.channel)),
};
interface SwapChannelsParams {
@@ -309,7 +323,8 @@ const swapChannelsTool: ToolEntry<SwapChannelsParams> = {
"Swaps two color channels — a quick way to get unusual coloring.",
category: "color",
schema: swapChannelsSchema,
run: (img, p) => swapChannels(img, p.pair),
input: "image",
run: imgTool((img, p) => swapChannels(img, p.pair)),
};
interface BlackAndWhiteParams {
@@ -327,7 +342,8 @@ const blackAndWhiteTool: ToolEntry<BlackAndWhiteParams> = {
"Hard binarization by luminance: every pixel becomes black or white.",
category: "color",
schema: blackAndWhiteSchema,
run: (img, p) => thresholdBlackWhite(img, p.threshold),
input: "image",
run: imgTool((img, p) => thresholdBlackWhite(img, p.threshold)),
};
interface PosterizeParams {
@@ -344,7 +360,8 @@ const posterizeTool: ToolEntry<PosterizeParams> = {
description: "Reduces the number of levels per channel — a poster effect.",
category: "color",
schema: posterizeSchema,
run: (img, p) => posterize(img, p.levels),
input: "image",
run: imgTool((img, p) => posterize(img, p.levels)),
};
export const autoContrastSchema = toolSchema<EmptyParams>({});
@@ -356,7 +373,8 @@ const autoContrastTool: ToolEntry<EmptyParams> = {
"Stretches each channel's range across the full available brightness range.",
category: "color",
schema: autoContrastSchema,
run: (img) => autoContrast(img),
input: "image",
run: imgTool((img) => autoContrast(img)),
};
interface DecreaseColorCountParams {
@@ -390,7 +408,8 @@ const decreaseColorCountTool: ToolEntry<DecreaseColorCountParams> = {
"Median-cut engine as a quick way to drop to 2256 colors. Presets marked (extreme/strong/balanced/light) match the classic compression levels.",
category: "color",
schema: decreaseColorCountSchema,
run: (img, p) => quantizeImage(img, Number(p.maxColors)).image,
input: "image",
run: imgTool((img, p) => quantizeImage(img, Number(p.maxColors)).image),
};
interface ChannelParams {
@@ -474,7 +493,10 @@ function channelEntries(): ToolEntry<ChannelParams>[] {
],
}),
}),
run: (img, p) => renderSpace(img, space.id, p.component, p.display),
input: "image",
run: imgTool((img, p) =>
renderSpace(img, space.id, p.component, p.display),
),
} satisfies ToolEntry<ChannelParams>;
});
}