mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-09-14 13:36:36 +00:00
feat: add split to parts to geometry registry
This commit is contained in:
@@ -30,10 +30,10 @@ ZIP-архивом.
|
|||||||
через `crop`.
|
через `crop`.
|
||||||
4. **`web/src/lib/zip.ts` (новый):** `downloadZip(files, zipName)` через
|
4. **`web/src/lib/zip.ts` (новый):** `downloadZip(files, zipName)` через
|
||||||
`zipSync`.
|
`zipSync`.
|
||||||
5. **`core/errors.ts`:** ключ `errors.tooManyParts` (лимит cols·rows ≤ 1000).
|
5. **`core/errors.ts`:** ключ `errors.tooManyParts` (страховочный лимит
|
||||||
|
cols·rows ≤ 1000; при максимуме 6×6 недостижим).
|
||||||
6. **`registry/geometry.ts`:** схема (`columns`, `rows`, дефолт 2×2, min 1,
|
6. **`registry/geometry.ts`:** схема (`columns`, `rows`, дефолт 2×2, min 1,
|
||||||
max 50)
|
max 6 — максимум 36 частей) + entry `split-into-parts-png` в `geometryEntries`.
|
||||||
- entry `split-into-parts-png` в `geometryEntries`.
|
|
||||||
7. **Executor:** сериализация/десериализация `FileResult` в `executor.worker.ts`
|
7. **Executor:** сериализация/десериализация `FileResult` в `executor.worker.ts`
|
||||||
и тип ветки в `executor.ts`.
|
и тип ветки в `executor.ts`.
|
||||||
8. **UI:** `SchemaToolView.svelte` (`fileResult`, Download → zip),
|
8. **UI:** `SchemaToolView.svelte` (`fileResult`, Download → zip),
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
padToRatio,
|
padToRatio,
|
||||||
resize,
|
resize,
|
||||||
rotate90,
|
rotate90,
|
||||||
|
splitToParts,
|
||||||
symmetricCopy,
|
symmetricCopy,
|
||||||
tile,
|
tile,
|
||||||
trimToContent,
|
trimToContent,
|
||||||
@@ -23,7 +24,12 @@ import {
|
|||||||
type FlipAxis,
|
type FlipAxis,
|
||||||
} from "../core/geometry";
|
} from "../core/geometry";
|
||||||
import { field, toolSchema, type Dimension } from "../registry-schema";
|
import { field, toolSchema, type Dimension } from "../registry-schema";
|
||||||
import { imgTool, type ToolEntry } from "./types";
|
import {
|
||||||
|
imgTool,
|
||||||
|
requireSource,
|
||||||
|
type ToolEntry,
|
||||||
|
type ToolImageFile,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
interface AddBorderParams {
|
interface AddBorderParams {
|
||||||
thickness: number;
|
thickness: number;
|
||||||
@@ -356,6 +362,51 @@ const tileTool: ToolEntry<TileParams> = {
|
|||||||
run: imgTool((img, p) => tile(img, p.columns, p.rows)),
|
run: imgTool((img, p) => tile(img, p.columns, p.rows)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const MAX_SPLIT_PARTS = 1000;
|
||||||
|
|
||||||
|
interface SplitPartsParams {
|
||||||
|
columns: number;
|
||||||
|
rows: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const splitPartsSchema = toolSchema<SplitPartsParams>({
|
||||||
|
columns: field.number({ min: 1, max: 6, step: 1, default: 2 }),
|
||||||
|
rows: field.number({ min: 1, max: 6, step: 1, default: 2 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const splitPartsTool: ToolEntry<SplitPartsParams> = {
|
||||||
|
id: "split-into-parts-png",
|
||||||
|
title: "Split PNG into parts",
|
||||||
|
description:
|
||||||
|
"Divides the image into a grid of equal-sized parts. The canvas is padded with transparency to keep every part the same size.",
|
||||||
|
category: "geometry",
|
||||||
|
schema: splitPartsSchema,
|
||||||
|
input: "image",
|
||||||
|
result: "files",
|
||||||
|
run: (ctx) => {
|
||||||
|
const img = requireSource(ctx);
|
||||||
|
const params = ctx.params as SplitPartsParams;
|
||||||
|
const cols = Math.max(1, Math.trunc(params.columns));
|
||||||
|
const rowsCount = Math.max(1, Math.trunc(params.rows));
|
||||||
|
const count = cols * rowsCount;
|
||||||
|
if (count > MAX_SPLIT_PARTS) {
|
||||||
|
throw new ToolError("errors.tooManyParts", { count });
|
||||||
|
}
|
||||||
|
const parts = splitToParts(img, cols, rowsCount);
|
||||||
|
const rowLen = String(rowsCount).length;
|
||||||
|
const colLen = String(cols).length;
|
||||||
|
const files: ToolImageFile[] = parts.map((image, index) => {
|
||||||
|
const col = (index % cols) + 1;
|
||||||
|
const row = Math.floor(index / cols) + 1;
|
||||||
|
return {
|
||||||
|
name: `part-${String(row).padStart(rowLen, "0")}-${String(col).padStart(colLen, "0")}.png`,
|
||||||
|
image,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return { files };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
interface EmptyParams {}
|
interface EmptyParams {}
|
||||||
|
|
||||||
export const centerByAlphaSchema = toolSchema<EmptyParams>({});
|
export const centerByAlphaSchema = toolSchema<EmptyParams>({});
|
||||||
@@ -605,4 +656,5 @@ export const geometryEntries = [
|
|||||||
swapOrientationTool,
|
swapOrientationTool,
|
||||||
symmetricCopyTool,
|
symmetricCopyTool,
|
||||||
shiftTool,
|
shiftTool,
|
||||||
|
splitPartsTool,
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user