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
+15
View File
@@ -203,3 +203,18 @@
тона (например поднять tone кнопок до ~55) и вернуть порог 4.5. Также тона (например поднять tone кнопок до ~55) и вернуть порог 4.5. Также
проверить `--color-danger` (dark, тон 55): текст на нём 4.93 — ок, но проверить `--color-danger` (dark, тон 55): текст на нём 4.93 — ок, но
light-danger тон 48 = 4.25 на границе. light-danger тон 48 = 4.25 на границе.
17. **Отображение маски для инструментов (runMask/preview-mask)** — придумать и
реализовать процесс показа маски результата. **Контекст:** в старом
контракте поле `preview` у `remove-color`/`remove-background` показывало
быстрый ч/б превью-маску (`colorMask`/`backgroundMaskPreview`) того, что
будет вырезано. При миграции на единый `run(ctx)` поле убрано (шаг 8,
`registry-new/alpha.ts`) — новый executor и schema-превью зовут `run()`
напрямую, маска пока не нужна. **Идея 1:** дать каждому `run` возможность
вернуть (или инструмент — объявить) `runMask` — ч/б изображение маски
изменений либо иной подход (отдельное поле `mask` + функция маски, второй
результат, overlay). Оценка — на усмотрение при проработке (S/M). Пока живём
без неё. **Идея 2:** каждый `run` возвращает два изображения - для
отображения (показывает маску или сам результат), и для передачи в следующий
инструмент (всегда результат. Оценка — на усмотрение при проработке (S/M).
Пока живём без неё.
+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 { field, toolSchema } from "../registry-schema";
import type { Offset } from "../registry-schema"; import type { Offset } from "../registry-schema";
import { import {
colorMask,
extractAlphaMask, extractAlphaMask,
flattenOntoColor, flattenOntoColor,
hardenAlpha, hardenAlpha,
@@ -11,7 +10,7 @@ import {
roundCorners, roundCorners,
setAlphaChannel, setAlphaChannel,
} from "../core/alpha"; } from "../core/alpha";
import { backgroundMaskPreview, removeBackground } from "../core/background"; import { removeBackground } from "../core/background";
import { import {
closingImage, closingImage,
contourImage, contourImage,
@@ -46,7 +45,8 @@ const addStroke: ToolEntry<AddStrokeParams> = {
"Adds a colored ring outline around the opaque content with the chosen thickness.", "Adds a colored ring outline around the opaque content with the chosen thickness.",
category: "alpha", category: "alpha",
schema: addStrokeSchema, 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 { 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.", "Leaves only a line along the boundary of opaque regions in the chosen color and thickness.",
category: "alpha", category: "alpha",
schema: findContourSchema, 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 { 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.", "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", category: "alpha",
schema: removeColorSchema, schema: removeColorSchema,
run: (img, p) => removeColorToAlpha(img, p.targetColor, p.tolerance), input: "image",
preview: (img, p) => colorMask(img, p.targetColor, p.tolerance), run: imgTool((img, p) => removeColorToAlpha(img, p.targetColor, p.tolerance)),
}; };
interface CircleMaskParams { 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.", "Cuts the image into a circle. Diameter is set as a share of the smaller side.",
category: "alpha", category: "alpha",
schema: circleMaskSchema, schema: circleMaskSchema,
run: (img, p) => input: "image",
run: imgTool((img, p) =>
renderShape( renderShape(
img, img,
circleTest(p.size / 200), circleTest(p.size / 200),
p.offset.x / 100, p.offset.x / 100,
p.offset.y / 100, p.offset.y / 100,
), ),
),
}; };
interface SquareMaskParams { 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.", "Cuts the image into a rectangle with sides as a share of the smaller side.",
category: "alpha", category: "alpha",
schema: squareMaskSchema, schema: squareMaskSchema,
run: (img, p) => input: "image",
run: imgTool((img, p) =>
renderShape( renderShape(
img, img,
boxTest(p.widthPct / 200, p.heightPct / 200), boxTest(p.widthPct / 200, p.heightPct / 200),
p.offset.x / 100, p.offset.x / 100,
p.offset.y / 100, p.offset.y / 100,
), ),
),
}; };
interface StarMaskParams { interface StarMaskParams {
@@ -205,13 +210,15 @@ const starMask: ToolEntry<StarMaskParams> = {
"Cuts the image into an n-pointed star with adjustable inner radius and rotation.", "Cuts the image into an n-pointed star with adjustable inner radius and rotation.",
category: "alpha", category: "alpha",
schema: starMaskSchema, schema: starMaskSchema,
run: (img, p) => input: "image",
run: imgTool((img, p) =>
renderShape( renderShape(
img, img,
starTest(p.points, p.innerRadius / 100, p.size / 200, p.rotation), starTest(p.points, p.innerRadius / 100, p.size / 200, p.rotation),
p.offset.x / 100, p.offset.x / 100,
p.offset.y / 100, p.offset.y / 100,
), ),
),
}; };
interface WavyMaskParams { 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.", "Cuts the image into a wavy-edged circle: radius is modulated by a sine with chosen amplitude and frequency.",
category: "alpha", category: "alpha",
schema: wavyMaskSchema, schema: wavyMaskSchema,
run: (img, p) => input: "image",
run: imgTool((img, p) =>
renderShape( renderShape(
img, img,
wavyTest(p.size / 200, p.amplitude / 200, p.waves, p.phase), wavyTest(p.size / 200, p.amplitude / 200, p.waves, p.phase),
p.offset.x / 100, p.offset.x / 100,
p.offset.y / 100, p.offset.y / 100,
), ),
),
}; };
interface EmptyParams {} interface EmptyParams {}
@@ -271,7 +280,8 @@ const removeAlphaChannel: ToolEntry<EmptyParams> = {
"Composites the image over a white background and saves without transparency.", "Composites the image over a white background and saves without transparency.",
category: "alpha", category: "alpha",
schema: removeAlphaChannelSchema, schema: removeAlphaChannelSchema,
run: (img) => flattenOntoColor(img, "#ffffff"), input: "image",
run: imgTool((img) => flattenOntoColor(img, "#ffffff")),
}; };
interface SetAlphaChannelParams { interface SetAlphaChannelParams {
@@ -288,7 +298,8 @@ const setAlphaChannelTool: ToolEntry<SetAlphaChannelParams> = {
description: "Assigns the same opacity to all pixels; colors stay unchanged.", description: "Assigns the same opacity to all pixels; colors stay unchanged.",
category: "alpha", category: "alpha",
schema: setAlphaChannelSchema, schema: setAlphaChannelSchema,
run: (img, p) => setAlphaChannel(img, p.percent), input: "image",
run: imgTool((img, p) => setAlphaChannel(img, p.percent)),
}; };
export const extractAlphaMaskSchema = toolSchema<EmptyParams>({}); export const extractAlphaMaskSchema = toolSchema<EmptyParams>({});
@@ -299,7 +310,8 @@ const extractAlphaMaskTool: ToolEntry<EmptyParams> = {
description: "Turns transparency into a black-and-white opaque mask.", description: "Turns transparency into a black-and-white opaque mask.",
category: "alpha", category: "alpha",
schema: extractAlphaMaskSchema, schema: extractAlphaMaskSchema,
run: (img) => extractAlphaMask(img), input: "image",
run: imgTool((img) => extractAlphaMask(img)),
}; };
interface RoundCornersParams { interface RoundCornersParams {
@@ -317,7 +329,8 @@ const roundCornersTool: ToolEntry<RoundCornersParams> = {
"Clips corners by a radius set as a percentage of half the smaller side.", "Clips corners by a radius set as a percentage of half the smaller side.",
category: "alpha", category: "alpha",
schema: roundCornersSchema, schema: roundCornersSchema,
run: (img, p) => roundCorners(img, p.radius), input: "image",
run: imgTool((img, p) => roundCorners(img, p.radius)),
}; };
export const invertAlphaSchema = toolSchema<EmptyParams>({}); export const invertAlphaSchema = toolSchema<EmptyParams>({});
@@ -328,7 +341,8 @@ const invertAlphaTool: ToolEntry<EmptyParams> = {
description: "Opaque areas become transparent and vice versa.", description: "Opaque areas become transparent and vice versa.",
category: "alpha", category: "alpha",
schema: invertAlphaSchema, schema: invertAlphaSchema,
run: (img) => invertAlpha(img), input: "image",
run: imgTool((img) => invertAlpha(img)),
}; };
interface RemoveBackgroundParams { 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.", "Removes a solid background: by color with tolerance, outer regions from the edges only, or every matching pixel. Can smooth the boundary.",
category: "alpha", category: "alpha",
schema: removeBackgroundSchema, schema: removeBackgroundSchema,
run: (img, p) => input: "image",
run: imgTool((img, p) =>
removeBackground(img, { removeBackground(img, {
color: p.color, color: p.color,
tolerancePercent: p.tolerance, tolerancePercent: p.tolerance,
outerOnly: p.outerOnly, outerOnly: p.outerOnly,
smoothPasses: p.smooth, smoothPasses: p.smooth,
}), }),
preview: (img, p) => ),
backgroundMaskPreview(img, {
color: p.color,
tolerancePercent: p.tolerance,
outerOnly: p.outerOnly,
smoothPasses: p.smooth,
}),
}; };
interface MakeThickerParams { interface MakeThickerParams {
@@ -396,7 +405,8 @@ const makeThickerTool: ToolEntry<MakeThickerParams> = {
description: "Expands opaque areas by the given number of pixels.", description: "Expands opaque areas by the given number of pixels.",
category: "alpha", category: "alpha",
schema: makeThickerSchema, schema: makeThickerSchema,
run: (img, p) => dilateImage(img, p.radius), input: "image",
run: imgTool((img, p) => dilateImage(img, p.radius)),
}; };
interface MakeThinnerParams { interface MakeThinnerParams {
@@ -413,7 +423,8 @@ const makeThinnerTool: ToolEntry<MakeThinnerParams> = {
description: "Shrinks opaque areas — thins the strokes of text and details.", description: "Shrinks opaque areas — thins the strokes of text and details.",
category: "alpha", category: "alpha",
schema: makeThinnerSchema, schema: makeThinnerSchema,
run: (img, p) => erodeImage(img, p.radius), input: "image",
run: imgTool((img, p) => erodeImage(img, p.radius)),
}; };
interface FeatherEdgesParams { 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.", "Blurs only the alpha channel: hard cutout edges become soft and gradual, colors stay untouched.",
category: "alpha", category: "alpha",
schema: featherEdgesSchema, schema: featherEdgesSchema,
run: (img, p) => featherAlpha(img, p.radius), input: "image",
run: imgTool((img, p) => featherAlpha(img, p.radius)),
}; };
interface CleanEdgesParams { 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.", "Replaces edge-halo colors of semi-transparent pixels with the nearest fully opaque color. Alpha stays as is.",
category: "alpha", category: "alpha",
schema: cleanEdgesSchema, schema: cleanEdgesSchema,
run: (img, p) => defringe(img, p.radius), input: "image",
run: imgTool((img, p) => defringe(img, p.radius)),
}; };
interface HardenAlphaParams { 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.", "Binarizes the alpha channel by threshold: semi-transparent pixels become either fully transparent or fully opaque.",
category: "alpha", category: "alpha",
schema: hardenAlphaSchema, schema: hardenAlphaSchema,
run: (img, p) => hardenAlpha(img, p.threshold), input: "image",
run: imgTool((img, p) => hardenAlpha(img, p.threshold)),
}; };
interface DespeckleAlphaParams { interface DespeckleAlphaParams {
@@ -485,7 +499,8 @@ const despeckleAlphaTool: ToolEntry<DespeckleAlphaParams> = {
"Opening: removes lone semi-transparent pixels and small specks.", "Opening: removes lone semi-transparent pixels and small specks.",
category: "alpha", category: "alpha",
schema: despeckleAlphaSchema, schema: despeckleAlphaSchema,
run: (img, p) => openingImage(img, p.radius), input: "image",
run: imgTool((img, p) => openingImage(img, p.radius)),
}; };
interface CloseHolesParams { interface CloseHolesParams {
@@ -502,7 +517,8 @@ const closeHolesTool: ToolEntry<CloseHolesParams> = {
description: "Closing: fills lone transparent dots inside the object.", description: "Closing: fills lone transparent dots inside the object.",
category: "alpha", category: "alpha",
schema: closeHolesSchema, schema: closeHolesSchema,
run: (img, p) => closingImage(img, p.radius), input: "image",
run: imgTool((img, p) => closingImage(img, p.radius)),
}; };
export const alphaEntries = [ 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 { parseHexList } from "../core/palette";
import { ditherImage, mapToNearest, quantizeImage } from "../core/quantize"; import { ditherImage, mapToNearest, quantizeImage } from "../core/quantize";
import { field, toolSchema, type ColorPair } from "../registry-schema"; import { field, toolSchema, type ColorPair } from "../registry-schema";
import type { ToolEntry } from "./types"; import { imgTool, type ToolEntry } from "./types";
interface TwoColorsParams { interface TwoColorsParams {
pair: ColorPair; pair: ColorPair;
@@ -40,7 +40,8 @@ const twoColorsTool: ToolEntry<TwoColorsParams> = {
"Recolors the image into two chosen colors by luminance threshold.", "Recolors the image into two chosen colors by luminance threshold.",
category: "color", category: "color",
schema: twoColorsSchema, 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 { interface GammaParams {
@@ -58,7 +59,8 @@ const gammaTool: ToolEntry<GammaParams> = {
"Corrects midtone brightness. <1 darker, >1 lighter, 1 — unchanged.", "Corrects midtone brightness. <1 darker, >1 lighter, 1 — unchanged.",
category: "color", category: "color",
schema: gammaSchema, schema: gammaSchema,
run: (img, p) => gammaCorrection(img, p.value), input: "image",
run: imgTool((img, p) => gammaCorrection(img, p.value)),
}; };
interface TemperatureParams { interface TemperatureParams {
@@ -76,7 +78,8 @@ const temperatureTool: ToolEntry<TemperatureParams> = {
"Positive values make the image warmer (more orange), negative ones cooler (more blue).", "Positive values make the image warmer (more orange), negative ones cooler (more blue).",
category: "color", category: "color",
schema: temperatureSchema, schema: temperatureSchema,
run: (img, p) => temperature(img, p.percent), input: "image",
run: imgTool((img, p) => temperature(img, p.percent)),
}; };
interface TintParams { interface TintParams {
@@ -96,7 +99,8 @@ const tintTool: ToolEntry<TintParams> = {
"Multiplies color channels by the chosen tint with the given strength.", "Multiplies color channels by the chosen tint with the given strength.",
category: "color", category: "color",
schema: tintSchema, 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 { interface QuantizeParams {
@@ -114,7 +118,8 @@ const quantizeTool: ToolEntry<QuantizeParams> = {
"Reduces the image to k colors via median-cut palette. Transparent pixels are preserved.", "Reduces the image to k colors via median-cut palette. Transparent pixels are preserved.",
category: "color", category: "color",
schema: quantizeSchema, schema: quantizeSchema,
run: (img, p) => quantizeImage(img, p.colors).image, input: "image",
run: imgTool((img, p) => quantizeImage(img, p.colors).image),
}; };
interface CustomPaletteParams { interface CustomPaletteParams {
@@ -132,7 +137,8 @@ const customPalette: ToolEntry<CustomPaletteParams> = {
"Maps every pixel to the nearest color from your comma-separated hex list.", "Maps every pixel to the nearest color from your comma-separated hex list.",
category: "color", category: "color",
schema: customPaletteSchema, schema: customPaletteSchema,
run: (img, p) => mapToNearest(img, parseHexList(p.colors)), input: "image",
run: imgTool((img, p) => mapToNearest(img, parseHexList(p.colors))),
}; };
interface DitheringParams { interface DitheringParams {
@@ -158,7 +164,8 @@ const ditheringTool: ToolEntry<DitheringParams> = {
"Applies FloydSteinberg error diffusion or ordered Bayer dithering while reducing to k colors.", "Applies FloydSteinberg error diffusion or ordered Bayer dithering while reducing to k colors.",
category: "color", category: "color",
schema: ditheringSchema, 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 {} 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.", "Converts the image to shades of gray using the BT.601 luminance formula. Alpha is preserved.",
category: "color", category: "color",
schema: grayscaleSchema, schema: grayscaleSchema,
run: (img) => grayscale(img), input: "image",
run: imgTool((img) => grayscale(img)),
}; };
export const invertColorsSchema = toolSchema<EmptyParams>({}); export const invertColorsSchema = toolSchema<EmptyParams>({});
@@ -183,7 +191,8 @@ const invertColorsTool: ToolEntry<EmptyParams> = {
description: "Inverts each color channel (255 value). Alpha is unchanged.", description: "Inverts each color channel (255 value). Alpha is unchanged.",
category: "color", category: "color",
schema: invertColorsSchema, schema: invertColorsSchema,
run: (img) => invert(img), input: "image",
run: imgTool((img) => invert(img)),
}; };
interface BrightnessContrastParams { 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.", "Adjusts brightness and contrast in the range from 100 to +100. Zero means no change.",
category: "color", category: "color",
schema: brightnessContrastSchema, 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 { interface OpacityParams {
@@ -230,7 +240,8 @@ const opacityTool: ToolEntry<OpacityParams> = {
"Multiplies the alpha channel by a percentage: 0% — fully transparent, 100% — unchanged.", "Multiplies the alpha channel by a percentage: 0% — fully transparent, 100% — unchanged.",
category: "color", category: "color",
schema: opacitySchema, schema: opacitySchema,
run: (img, p) => setOpacity(img, p.percent), input: "image",
run: imgTool((img, p) => setOpacity(img, p.percent)),
}; };
export const sepiaSchema = toolSchema<EmptyParams>({}); 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.", description: "Tints the image into the warm brown tones of classic sepia.",
category: "color", category: "color",
schema: sepiaSchema, schema: sepiaSchema,
run: (img) => sepia(img), input: "image",
run: imgTool((img) => sepia(img)),
}; };
interface HueShiftParams { interface HueShiftParams {
@@ -259,7 +271,8 @@ const hueShiftTool: ToolEntry<HueShiftParams> = {
"Shifts the hue around the circle. Saturation and lightness are preserved.", "Shifts the hue around the circle. Saturation and lightness are preserved.",
category: "color", category: "color",
schema: hueShiftSchema, schema: hueShiftSchema,
run: (img, p) => changeHue(img, p.degrees), input: "image",
run: imgTool((img, p) => changeHue(img, p.degrees)),
}; };
interface ExtractChannelParams { interface ExtractChannelParams {
@@ -284,7 +297,8 @@ const extractChannelTool: ToolEntry<ExtractChannelParams> = {
"Keeps only the chosen channel — red, green or blue — as shades of gray.", "Keeps only the chosen channel — red, green or blue — as shades of gray.",
category: "color", category: "color",
schema: extractChannelSchema, schema: extractChannelSchema,
run: (img, p) => extractChannel(img, p.channel), input: "image",
run: imgTool((img, p) => extractChannel(img, p.channel)),
}; };
interface SwapChannelsParams { interface SwapChannelsParams {
@@ -309,7 +323,8 @@ const swapChannelsTool: ToolEntry<SwapChannelsParams> = {
"Swaps two color channels — a quick way to get unusual coloring.", "Swaps two color channels — a quick way to get unusual coloring.",
category: "color", category: "color",
schema: swapChannelsSchema, schema: swapChannelsSchema,
run: (img, p) => swapChannels(img, p.pair), input: "image",
run: imgTool((img, p) => swapChannels(img, p.pair)),
}; };
interface BlackAndWhiteParams { interface BlackAndWhiteParams {
@@ -327,7 +342,8 @@ const blackAndWhiteTool: ToolEntry<BlackAndWhiteParams> = {
"Hard binarization by luminance: every pixel becomes black or white.", "Hard binarization by luminance: every pixel becomes black or white.",
category: "color", category: "color",
schema: blackAndWhiteSchema, schema: blackAndWhiteSchema,
run: (img, p) => thresholdBlackWhite(img, p.threshold), input: "image",
run: imgTool((img, p) => thresholdBlackWhite(img, p.threshold)),
}; };
interface PosterizeParams { interface PosterizeParams {
@@ -344,7 +360,8 @@ const posterizeTool: ToolEntry<PosterizeParams> = {
description: "Reduces the number of levels per channel — a poster effect.", description: "Reduces the number of levels per channel — a poster effect.",
category: "color", category: "color",
schema: posterizeSchema, schema: posterizeSchema,
run: (img, p) => posterize(img, p.levels), input: "image",
run: imgTool((img, p) => posterize(img, p.levels)),
}; };
export const autoContrastSchema = toolSchema<EmptyParams>({}); export const autoContrastSchema = toolSchema<EmptyParams>({});
@@ -356,7 +373,8 @@ const autoContrastTool: ToolEntry<EmptyParams> = {
"Stretches each channel's range across the full available brightness range.", "Stretches each channel's range across the full available brightness range.",
category: "color", category: "color",
schema: autoContrastSchema, schema: autoContrastSchema,
run: (img) => autoContrast(img), input: "image",
run: imgTool((img) => autoContrast(img)),
}; };
interface DecreaseColorCountParams { 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.", "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", category: "color",
schema: decreaseColorCountSchema, 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 { 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>; } satisfies ToolEntry<ChannelParams>;
}); });
} }