@pixerate/editor 0.96.0 → 0.98.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/THIRD_PARTY_NOTICES.md +4 -2
  2. package/dist/animation-editor/index.cjs +55 -53
  3. package/dist/animation-editor/index.cjs.map +1 -1
  4. package/dist/animation-editor/index.d.cts +3 -2
  5. package/dist/animation-editor/index.d.ts +3 -2
  6. package/dist/animation-editor/index.js +11 -9
  7. package/dist/animation-editor/index.js.map +1 -1
  8. package/dist/chunk-DWGZUSES.cjs +694 -0
  9. package/dist/chunk-DWGZUSES.cjs.map +1 -0
  10. package/dist/chunk-GX332W2C.js +181 -0
  11. package/dist/chunk-GX332W2C.js.map +1 -0
  12. package/dist/{chunk-7MD7C6XQ.cjs → chunk-JF5PXN7W.cjs} +96 -744
  13. package/dist/chunk-JF5PXN7W.cjs.map +1 -0
  14. package/dist/chunk-KKREERP2.js +694 -0
  15. package/dist/chunk-KKREERP2.js.map +1 -0
  16. package/dist/chunk-MUUXNRU4.cjs +181 -0
  17. package/dist/chunk-MUUXNRU4.cjs.map +1 -0
  18. package/dist/{chunk-KFTQ2PKP.js → chunk-WIR377F6.js} +1001 -61
  19. package/dist/chunk-WIR377F6.js.map +1 -0
  20. package/dist/{chunk-T422YCHR.cjs → chunk-WT6ZAWJP.cjs} +1023 -83
  21. package/dist/chunk-WT6ZAWJP.cjs.map +1 -0
  22. package/dist/{chunk-4JLB2USO.js → chunk-YGZNGDIT.js} +45 -693
  23. package/dist/chunk-YGZNGDIT.js.map +1 -0
  24. package/dist/image-editor/index.cjs +1519 -360
  25. package/dist/image-editor/index.cjs.map +1 -1
  26. package/dist/image-editor/index.d.cts +378 -5
  27. package/dist/image-editor/index.d.ts +378 -5
  28. package/dist/image-editor/index.js +1244 -85
  29. package/dist/image-editor/index.js.map +1 -1
  30. package/dist/raster/index.cjs +25 -2
  31. package/dist/raster/index.cjs.map +1 -1
  32. package/dist/raster/index.d.cts +143 -4
  33. package/dist/raster/index.d.ts +143 -4
  34. package/dist/raster/index.js +25 -2
  35. package/dist/{svg-ymShkNtu.d.cts → svg-C9r284x8.d.cts} +6 -9
  36. package/dist/{svg-Dh17jCyA.d.ts → svg-MVKBqwD4.d.ts} +6 -9
  37. package/dist/types-CwMPoRMU.d.cts +40 -0
  38. package/dist/types-CwMPoRMU.d.ts +40 -0
  39. package/dist/vector/index.cjs +490 -554
  40. package/dist/vector/index.cjs.map +1 -1
  41. package/dist/vector/index.d.cts +154 -292
  42. package/dist/vector/index.d.ts +154 -292
  43. package/dist/vector/index.js +91 -155
  44. package/dist/vector/index.js.map +1 -1
  45. package/dist/warp-B8rAguzs.d.ts +165 -0
  46. package/dist/warp-nYs2DPrx.d.cts +165 -0
  47. package/package.json +1 -1
  48. package/skills/pixerate-image-editor/SKILL.md +49 -3
  49. package/dist/chunk-4JLB2USO.js.map +0 -1
  50. package/dist/chunk-7MD7C6XQ.cjs.map +0 -1
  51. package/dist/chunk-KFTQ2PKP.js.map +0 -1
  52. package/dist/chunk-T422YCHR.cjs.map +0 -1
@@ -0,0 +1,165 @@
1
+ import { H as Homography, V as Vec2, B as Box, Q as Quad, A as AffineMatrix, W as WarpStyle, a as WarpMesh } from './types-CwMPoRMU.js';
2
+
3
+ /**
4
+ * Perspective (projective) maps between quadrilaterals: Free Distort and Perspective in both the
5
+ * vector and the image editor. Pure maths; degenerate or non-finite input gives `null` instead of
6
+ * NaNs.
7
+ *
8
+ * Ported from ArtCraft (MIT OR Apache-2.0, © ArtCraft Team and contributors; see
9
+ * THIRD_PARTY_NOTICES.md): pdfcraft `crates/geom/src/perspective.rs` (`Homography::from_points`,
10
+ * `Homography::apply`, `solve8`, `order_quad`) and photocraft `crates/algo/src/transform.rs`
11
+ * (`Homography::square_to_quad`, `rect_to_quad`, `inverse`, `mul`, `local_scale`, `front_side`,
12
+ * `warp_output_bounds`, `convex_quad`).
13
+ */
14
+
15
+ /**
16
+ * Gaussian elimination with partial pivoting on an 8×8 system (the 9th column of each row is the
17
+ * right-hand side). Null when the system is singular.
18
+ */
19
+ declare function solve8(rows: readonly (readonly number[])[]): number[] | null;
20
+ /** The image of `p`, or null where the map sends it to infinity. */
21
+ declare function applyHomography(h: Homography, p: Vec2): Vec2 | null;
22
+ /**
23
+ * The projective map that takes each of `from` to the point at the same index of `to`. Null when
24
+ * three of either set are collinear or a coordinate is not finite.
25
+ */
26
+ declare function homographyFromPoints(from: readonly Vec2[], to: readonly Vec2[]): Homography | null;
27
+ /**
28
+ * Whether `h` maps the whole convex quad `quad` without sending any of it through infinity (the
29
+ * denominator keeps one sign over it): what a usable distortion needs.
30
+ */
31
+ declare function homographyKeepsQuad(h: Homography, quad: readonly Vec2[]): boolean;
32
+ /**
33
+ * The four corners in reading order for a y-down space: top-left, top-right, bottom-right,
34
+ * bottom-left, whatever order they come in. Null unless they form a convex quadrilateral with a
35
+ * non-negligible area.
36
+ */
37
+ declare function orderQuad(points: readonly Vec2[]): Vec2[] | null;
38
+ /** The inverse map, or null for a singular one. */
39
+ declare function invertHomography(m: Homography): Homography | null;
40
+ /** An affine matrix (SVG order) as a homography. */
41
+ declare function homographyFromAffine(m: AffineMatrix): Homography;
42
+ /**
43
+ * The map taking box `r`'s corners onto `quad` (TL, TR, BR, BL), exact for parallelograms (then
44
+ * affine). Null for an empty box, a non-finite or degenerate quad, or a singular result.
45
+ */
46
+ declare function rectToQuad(r: Box, quad: readonly Vec2[]): Homography | null;
47
+ /** Box `r`'s corners as a quad (TL, TR, BR, BL). */
48
+ declare function boxQuad(r: Box): Quad;
49
+
50
+ /**
51
+ * Warp geometry shared by the vector editor's envelopes and the image editor's Free Transform
52
+ * warp: preset warp styles and editable Bézier meshes, both forward maps from a source box onto
53
+ * the plane.
54
+ *
55
+ * - **Presets** (`WarpStyle`, Photoshop's fifteen with bend and horizontal / vertical distortion
56
+ * in percent): each is one bicubic Bézier patch whose 4 × 4 control grid follows the bend
57
+ * (`warpPresetGrid`). Every preset is the identity at bend 0 and continuous in it.
58
+ * - **Meshes** (`WarpMesh`): a grid of bicubic patches. Splitting a mesh (`splitWarpMeshU` / `V`)
59
+ * is an exact de Casteljau subdivision, so it never changes the shape, and a preset turns into
60
+ * an editable mesh of any size exactly.
61
+ *
62
+ * Ported from ArtCraft (MIT OR Apache-2.0, © ArtCraft Team and contributors; see
63
+ * THIRD_PARTY_NOTICES.md): photocraft `crates/geom/src/warp.rs` (`WarpStyle`, `StyleWarp`,
64
+ * `rest_grid`, `edge_arc`, `arc_grid`, `blend_rows`, `preset_grid`, `bernstein`, `split_cubic`,
65
+ * `BERN_INV`, and `BezierMesh`: `identity`, `fit`, `eval`, `split_u`, `split_v`, `remove_split_u`,
66
+ * `transpose`, `map_points`, `param_at`, `pull`, `smooth_lines`, `drag_point`, `control_bounds`;
67
+ * `Warp::map` and `Warp::to_mesh`).
68
+ */
69
+
70
+ /** The fifteen presets in Photoshop's menu order. */
71
+ declare const WARP_STYLES: readonly WarpStyle[];
72
+ declare const WARP_STYLE_LABELS: Readonly<Record<WarpStyle, string>>;
73
+ /**
74
+ * A preset as a Bézier control grid (rows of `[x, y]` in box units, y down). `b`, `hd`, `vd` are
75
+ * the bend and the horizontal / vertical distortion as fractions (−1…1); `aspect` is the box's
76
+ * height over its width. The arc family stays circular in pixels, the other offsets scale with the
77
+ * box, and a vertical warp is the horizontal one with the axes (and distortions) swapped.
78
+ */
79
+ declare function warpPresetGrid(style: WarpStyle, b: number, hd: number, vd: number, vertical: boolean, aspect: number): [number, number][][];
80
+ /** A preset warp's settings (bend and distortions in percent, −100…100). */
81
+ interface WarpPreset {
82
+ style: WarpStyle;
83
+ bend: number;
84
+ horizontal?: number;
85
+ vertical?: number;
86
+ /** Bend along the vertical axis. */
87
+ orientation?: 'horizontal' | 'vertical';
88
+ }
89
+ /**
90
+ * A preset as one Bézier patch over `bounds` (points in the bounds' space), or null when it
91
+ * changes nothing (an unknown style, all-zero amounts, or an empty box).
92
+ */
93
+ declare function warpPresetMesh(preset: WarpPreset, bounds: Box): WarpMesh | null;
94
+ /** Control points per row. */
95
+ declare const warpMeshColumns: (m: WarpMesh) => number;
96
+ /** Control point rows. */
97
+ declare const warpMeshRows: (m: WarpMesh) => number;
98
+ /** Whether a mesh is well formed: knots from 0 to 1 increasing, the right number of finite points. */
99
+ declare function isValidWarpMesh(m: unknown): m is WarpMesh;
100
+ /** Fits a mesh with patch boundaries `us` / `vs` to the map `f` (box fractions → output) by interpolating it at each patch's thirds. Exact for bicubic maps (affine maps included). */
101
+ declare function fitWarpMesh(f: (s: number, t: number) => Vec2, us: readonly number[], vs: readonly number[]): WarpMesh;
102
+ /** The identity mesh over `bounds` with `columns × rows` patches. */
103
+ declare function identityWarpMesh(bounds: Box, columns?: number, rows?: number): WarpMesh;
104
+ /** The surface at box fractions `(s, t)`. */
105
+ declare function evalWarpMesh(m: WarpMesh, s: number, t: number): Vec2;
106
+ /** The mesh with the patch column holding `s` split at `s` (exact). Null when `s` is on or too close to a boundary. */
107
+ declare function splitWarpMeshU(m: WarpMesh, s: number): WarpMesh | null;
108
+ /** The mesh with the patch row holding `t` split at `t` (exact). */
109
+ declare function splitWarpMeshV(m: WarpMesh, t: number): WarpMesh | null;
110
+ /**
111
+ * The mesh without interior vertical boundary `k` (1 … us.length − 2), its two patch columns
112
+ * merged: exact when they came from an unedited split; otherwise the outer control points stay and
113
+ * the inner handles are extrapolated.
114
+ */
115
+ declare function removeWarpMeshSplitU(m: WarpMesh, k: number): WarpMesh | null;
116
+ /** Removes interior horizontal boundary `k`. */
117
+ declare function removeWarpMeshSplitV(m: WarpMesh, k: number): WarpMesh | null;
118
+ /** Every control point through `f` (exact for affine maps). */
119
+ declare function mapWarpMeshPoints(m: WarpMesh, f: (p: Vec2) => Vec2): WarpMesh;
120
+ /**
121
+ * The mesh with `columns × rows` patches over the same surface: split exactly when its knots are
122
+ * a subset of the new even ones (a one-patch mesh always is), otherwise refitted.
123
+ */
124
+ declare function resizeWarpMesh(m: WarpMesh, columns: number, rows: number): WarpMesh;
125
+ /** Bounding box of the control points (the surface lies inside it). */
126
+ declare function warpMeshControlBounds(m: WarpMesh): Box;
127
+ /** Box fractions `(s, t)` whose surface point is nearest `p` (a coarse search, then Newton steps). */
128
+ declare function warpMeshParamAt(m: WarpMesh, p: Vec2): {
129
+ s: number;
130
+ t: number;
131
+ distance: number;
132
+ };
133
+ /**
134
+ * `base` with control point `index` dragged by `d`, keeping the surface smooth across the grid
135
+ * lines: an anchor moves with the eight points around it as one block; a handle moves with the two
136
+ * points beside it across its line, and the handle opposite it on the same anchor turns the other
137
+ * way (with its two neighbours), so the line keeps passing straight through the anchor. An inner
138
+ * point of a patch moves alone.
139
+ */
140
+ declare function dragWarpMeshPoint(base: WarpMesh, index: number, d: Vec2): WarpMesh;
141
+ /**
142
+ * `base` with its surface point at box fractions `(s, t)` pulled by `d`, the way dragging inside a
143
+ * patch works: interior anchors within about two cells follow by a share of `d` that fades with
144
+ * distance (each with its block of handles, so grid lines stay smooth); the outer border stays
145
+ * pinned unless the grab is near it, and then it bows; the four corners never move. The grabbed
146
+ * patch's inner points (and, near the border, the border's handles) make up the rest, so the
147
+ * grabbed point lands exactly at its start + `d`.
148
+ */
149
+ declare function pullWarpMesh(base: WarpMesh, s: number, t: number, d: Vec2): WarpMesh;
150
+ /**
151
+ * The control points an editor shows: the anchors (where grid lines cross) and the handles along
152
+ * the grid lines, each with the anchor it belongs to. Points inside a patch are left out (drag
153
+ * inside a patch to pull the surface instead).
154
+ */
155
+ declare function warpMeshEditPoints(m: WarpMesh): {
156
+ anchors: number[];
157
+ handles: {
158
+ index: number;
159
+ anchor: number;
160
+ }[];
161
+ };
162
+ /** The mesh's grid lines (patch borders) as cubics `[p0, p1, p2, p3]`. */
163
+ declare function warpMeshGridCurves(m: WarpMesh): Vec2[][];
164
+
165
+ export { warpPresetMesh as A, boxQuad as B, homographyFromAffine as C, invertHomography as D, rectToQuad as E, WARP_STYLES as W, WARP_STYLE_LABELS as a, type WarpPreset as b, applyHomography as c, dragWarpMeshPoint as d, evalWarpMesh as e, fitWarpMesh as f, removeWarpMeshSplitV as g, resizeWarpMesh as h, isValidWarpMesh as i, splitWarpMeshU as j, splitWarpMeshV as k, homographyFromPoints as l, mapWarpMeshPoints as m, homographyKeepsQuad as n, orderQuad as o, pullWarpMesh as p, identityWarpMesh as q, removeWarpMeshSplitU as r, solve8 as s, warpMeshControlBounds as t, warpMeshEditPoints as u, warpMeshGridCurves as v, warpMeshColumns as w, warpMeshParamAt as x, warpMeshRows as y, warpPresetGrid as z };
@@ -0,0 +1,165 @@
1
+ import { H as Homography, V as Vec2, B as Box, Q as Quad, A as AffineMatrix, W as WarpStyle, a as WarpMesh } from './types-CwMPoRMU.cjs';
2
+
3
+ /**
4
+ * Perspective (projective) maps between quadrilaterals: Free Distort and Perspective in both the
5
+ * vector and the image editor. Pure maths; degenerate or non-finite input gives `null` instead of
6
+ * NaNs.
7
+ *
8
+ * Ported from ArtCraft (MIT OR Apache-2.0, © ArtCraft Team and contributors; see
9
+ * THIRD_PARTY_NOTICES.md): pdfcraft `crates/geom/src/perspective.rs` (`Homography::from_points`,
10
+ * `Homography::apply`, `solve8`, `order_quad`) and photocraft `crates/algo/src/transform.rs`
11
+ * (`Homography::square_to_quad`, `rect_to_quad`, `inverse`, `mul`, `local_scale`, `front_side`,
12
+ * `warp_output_bounds`, `convex_quad`).
13
+ */
14
+
15
+ /**
16
+ * Gaussian elimination with partial pivoting on an 8×8 system (the 9th column of each row is the
17
+ * right-hand side). Null when the system is singular.
18
+ */
19
+ declare function solve8(rows: readonly (readonly number[])[]): number[] | null;
20
+ /** The image of `p`, or null where the map sends it to infinity. */
21
+ declare function applyHomography(h: Homography, p: Vec2): Vec2 | null;
22
+ /**
23
+ * The projective map that takes each of `from` to the point at the same index of `to`. Null when
24
+ * three of either set are collinear or a coordinate is not finite.
25
+ */
26
+ declare function homographyFromPoints(from: readonly Vec2[], to: readonly Vec2[]): Homography | null;
27
+ /**
28
+ * Whether `h` maps the whole convex quad `quad` without sending any of it through infinity (the
29
+ * denominator keeps one sign over it): what a usable distortion needs.
30
+ */
31
+ declare function homographyKeepsQuad(h: Homography, quad: readonly Vec2[]): boolean;
32
+ /**
33
+ * The four corners in reading order for a y-down space: top-left, top-right, bottom-right,
34
+ * bottom-left, whatever order they come in. Null unless they form a convex quadrilateral with a
35
+ * non-negligible area.
36
+ */
37
+ declare function orderQuad(points: readonly Vec2[]): Vec2[] | null;
38
+ /** The inverse map, or null for a singular one. */
39
+ declare function invertHomography(m: Homography): Homography | null;
40
+ /** An affine matrix (SVG order) as a homography. */
41
+ declare function homographyFromAffine(m: AffineMatrix): Homography;
42
+ /**
43
+ * The map taking box `r`'s corners onto `quad` (TL, TR, BR, BL), exact for parallelograms (then
44
+ * affine). Null for an empty box, a non-finite or degenerate quad, or a singular result.
45
+ */
46
+ declare function rectToQuad(r: Box, quad: readonly Vec2[]): Homography | null;
47
+ /** Box `r`'s corners as a quad (TL, TR, BR, BL). */
48
+ declare function boxQuad(r: Box): Quad;
49
+
50
+ /**
51
+ * Warp geometry shared by the vector editor's envelopes and the image editor's Free Transform
52
+ * warp: preset warp styles and editable Bézier meshes, both forward maps from a source box onto
53
+ * the plane.
54
+ *
55
+ * - **Presets** (`WarpStyle`, Photoshop's fifteen with bend and horizontal / vertical distortion
56
+ * in percent): each is one bicubic Bézier patch whose 4 × 4 control grid follows the bend
57
+ * (`warpPresetGrid`). Every preset is the identity at bend 0 and continuous in it.
58
+ * - **Meshes** (`WarpMesh`): a grid of bicubic patches. Splitting a mesh (`splitWarpMeshU` / `V`)
59
+ * is an exact de Casteljau subdivision, so it never changes the shape, and a preset turns into
60
+ * an editable mesh of any size exactly.
61
+ *
62
+ * Ported from ArtCraft (MIT OR Apache-2.0, © ArtCraft Team and contributors; see
63
+ * THIRD_PARTY_NOTICES.md): photocraft `crates/geom/src/warp.rs` (`WarpStyle`, `StyleWarp`,
64
+ * `rest_grid`, `edge_arc`, `arc_grid`, `blend_rows`, `preset_grid`, `bernstein`, `split_cubic`,
65
+ * `BERN_INV`, and `BezierMesh`: `identity`, `fit`, `eval`, `split_u`, `split_v`, `remove_split_u`,
66
+ * `transpose`, `map_points`, `param_at`, `pull`, `smooth_lines`, `drag_point`, `control_bounds`;
67
+ * `Warp::map` and `Warp::to_mesh`).
68
+ */
69
+
70
+ /** The fifteen presets in Photoshop's menu order. */
71
+ declare const WARP_STYLES: readonly WarpStyle[];
72
+ declare const WARP_STYLE_LABELS: Readonly<Record<WarpStyle, string>>;
73
+ /**
74
+ * A preset as a Bézier control grid (rows of `[x, y]` in box units, y down). `b`, `hd`, `vd` are
75
+ * the bend and the horizontal / vertical distortion as fractions (−1…1); `aspect` is the box's
76
+ * height over its width. The arc family stays circular in pixels, the other offsets scale with the
77
+ * box, and a vertical warp is the horizontal one with the axes (and distortions) swapped.
78
+ */
79
+ declare function warpPresetGrid(style: WarpStyle, b: number, hd: number, vd: number, vertical: boolean, aspect: number): [number, number][][];
80
+ /** A preset warp's settings (bend and distortions in percent, −100…100). */
81
+ interface WarpPreset {
82
+ style: WarpStyle;
83
+ bend: number;
84
+ horizontal?: number;
85
+ vertical?: number;
86
+ /** Bend along the vertical axis. */
87
+ orientation?: 'horizontal' | 'vertical';
88
+ }
89
+ /**
90
+ * A preset as one Bézier patch over `bounds` (points in the bounds' space), or null when it
91
+ * changes nothing (an unknown style, all-zero amounts, or an empty box).
92
+ */
93
+ declare function warpPresetMesh(preset: WarpPreset, bounds: Box): WarpMesh | null;
94
+ /** Control points per row. */
95
+ declare const warpMeshColumns: (m: WarpMesh) => number;
96
+ /** Control point rows. */
97
+ declare const warpMeshRows: (m: WarpMesh) => number;
98
+ /** Whether a mesh is well formed: knots from 0 to 1 increasing, the right number of finite points. */
99
+ declare function isValidWarpMesh(m: unknown): m is WarpMesh;
100
+ /** Fits a mesh with patch boundaries `us` / `vs` to the map `f` (box fractions → output) by interpolating it at each patch's thirds. Exact for bicubic maps (affine maps included). */
101
+ declare function fitWarpMesh(f: (s: number, t: number) => Vec2, us: readonly number[], vs: readonly number[]): WarpMesh;
102
+ /** The identity mesh over `bounds` with `columns × rows` patches. */
103
+ declare function identityWarpMesh(bounds: Box, columns?: number, rows?: number): WarpMesh;
104
+ /** The surface at box fractions `(s, t)`. */
105
+ declare function evalWarpMesh(m: WarpMesh, s: number, t: number): Vec2;
106
+ /** The mesh with the patch column holding `s` split at `s` (exact). Null when `s` is on or too close to a boundary. */
107
+ declare function splitWarpMeshU(m: WarpMesh, s: number): WarpMesh | null;
108
+ /** The mesh with the patch row holding `t` split at `t` (exact). */
109
+ declare function splitWarpMeshV(m: WarpMesh, t: number): WarpMesh | null;
110
+ /**
111
+ * The mesh without interior vertical boundary `k` (1 … us.length − 2), its two patch columns
112
+ * merged: exact when they came from an unedited split; otherwise the outer control points stay and
113
+ * the inner handles are extrapolated.
114
+ */
115
+ declare function removeWarpMeshSplitU(m: WarpMesh, k: number): WarpMesh | null;
116
+ /** Removes interior horizontal boundary `k`. */
117
+ declare function removeWarpMeshSplitV(m: WarpMesh, k: number): WarpMesh | null;
118
+ /** Every control point through `f` (exact for affine maps). */
119
+ declare function mapWarpMeshPoints(m: WarpMesh, f: (p: Vec2) => Vec2): WarpMesh;
120
+ /**
121
+ * The mesh with `columns × rows` patches over the same surface: split exactly when its knots are
122
+ * a subset of the new even ones (a one-patch mesh always is), otherwise refitted.
123
+ */
124
+ declare function resizeWarpMesh(m: WarpMesh, columns: number, rows: number): WarpMesh;
125
+ /** Bounding box of the control points (the surface lies inside it). */
126
+ declare function warpMeshControlBounds(m: WarpMesh): Box;
127
+ /** Box fractions `(s, t)` whose surface point is nearest `p` (a coarse search, then Newton steps). */
128
+ declare function warpMeshParamAt(m: WarpMesh, p: Vec2): {
129
+ s: number;
130
+ t: number;
131
+ distance: number;
132
+ };
133
+ /**
134
+ * `base` with control point `index` dragged by `d`, keeping the surface smooth across the grid
135
+ * lines: an anchor moves with the eight points around it as one block; a handle moves with the two
136
+ * points beside it across its line, and the handle opposite it on the same anchor turns the other
137
+ * way (with its two neighbours), so the line keeps passing straight through the anchor. An inner
138
+ * point of a patch moves alone.
139
+ */
140
+ declare function dragWarpMeshPoint(base: WarpMesh, index: number, d: Vec2): WarpMesh;
141
+ /**
142
+ * `base` with its surface point at box fractions `(s, t)` pulled by `d`, the way dragging inside a
143
+ * patch works: interior anchors within about two cells follow by a share of `d` that fades with
144
+ * distance (each with its block of handles, so grid lines stay smooth); the outer border stays
145
+ * pinned unless the grab is near it, and then it bows; the four corners never move. The grabbed
146
+ * patch's inner points (and, near the border, the border's handles) make up the rest, so the
147
+ * grabbed point lands exactly at its start + `d`.
148
+ */
149
+ declare function pullWarpMesh(base: WarpMesh, s: number, t: number, d: Vec2): WarpMesh;
150
+ /**
151
+ * The control points an editor shows: the anchors (where grid lines cross) and the handles along
152
+ * the grid lines, each with the anchor it belongs to. Points inside a patch are left out (drag
153
+ * inside a patch to pull the surface instead).
154
+ */
155
+ declare function warpMeshEditPoints(m: WarpMesh): {
156
+ anchors: number[];
157
+ handles: {
158
+ index: number;
159
+ anchor: number;
160
+ }[];
161
+ };
162
+ /** The mesh's grid lines (patch borders) as cubics `[p0, p1, p2, p3]`. */
163
+ declare function warpMeshGridCurves(m: WarpMesh): Vec2[][];
164
+
165
+ export { warpPresetMesh as A, boxQuad as B, homographyFromAffine as C, invertHomography as D, rectToQuad as E, WARP_STYLES as W, WARP_STYLE_LABELS as a, type WarpPreset as b, applyHomography as c, dragWarpMeshPoint as d, evalWarpMesh as e, fitWarpMesh as f, removeWarpMeshSplitV as g, resizeWarpMesh as h, isValidWarpMesh as i, splitWarpMeshU as j, splitWarpMeshV as k, homographyFromPoints as l, mapWarpMeshPoints as m, homographyKeepsQuad as n, orderQuad as o, pullWarpMesh as p, identityWarpMesh as q, removeWarpMeshSplitU as r, solve8 as s, warpMeshControlBounds as t, warpMeshEditPoints as u, warpMeshGridCurves as v, warpMeshColumns as w, warpMeshParamAt as x, warpMeshRows as y, warpPresetGrid as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor",
3
- "version": "0.96.0",
3
+ "version": "0.98.0",
4
4
  "description": "UI-agnostic rich text and media editing core library",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: pixerate-image-editor
3
- description: How to colour-correct, composite and retouch a photo in the Pixerate image editor through its agent tools - layers (pixel, adjustment, group and annotation layers with masks, clipping, blend modes, opacity and fill; merge, flatten, layer via copy, filters), live layer effects (shadows, glows, bevel and emboss, satin, overlays, strokes), base adjustments (exposure, contrast, white balance, saturation, blur), adjustment layers (curves, levels, hue/saturation, vibrance, color balance, black and white, photo filter, invert, posterize, threshold), selections (wand, color range, grow, shrink, feather, refine edge) and layer masks, crop, rotate, flip, Mixer Brush, undo, PSD, histogram and PNG previews. Use when asked to edit, grade, correct, brighten, warm up, crop, straighten or mask an image, add a shadow, glow or outline, or open or save a PSD, or when get_adjustments, set_adjustments, add_adjustment_layer, list_layers, add_layer_effect, paint_stroke, select_by_color, import_psd or render_preview are available.
3
+ description: How to colour-correct, composite and retouch a photo in the Pixerate image editor through its agent tools - layers (pixel, adjustment, group and annotation layers with masks, clipping, blend modes, opacity and fill; merge, flatten, layer via copy, filters), live layer effects (shadows, glows, bevels, satin, overlays, strokes), base adjustments (exposure, contrast, white balance, saturation, blur), adjustment layers (curves, levels, hue/saturation, vibrance, color balance, black and white and more), selections (wand, color range, modify, refine edge) and masks, Free Transform (scale, rotate, skew, distort, warp), crop, rotate, flip, Mixer Brush, undo, PSD, histogram and previews. Use when asked to edit, grade, correct, brighten, crop, straighten or mask an image, add a shadow, glow or outline, transform or warp a layer, or open or save a PSD, or when get_adjustments, set_adjustments, list_layers, add_layer_effect, transform_layer, paint_stroke, select_by_color, import_psd or render_preview are available.
4
4
  ---
5
5
 
6
6
  # Image editor
@@ -67,6 +67,27 @@ batching.
67
67
  5. **Bake only when asked** (`merge_down`, `merge_visible`, `flatten_image`, `apply_layer_mask`):
68
68
  they are destructive. `render_preview` with `layerId` shows one layer alone.
69
69
 
70
+ ### Free Transform
71
+
72
+ 1. **Read the frame first**: `get_transform_frame` says what a transform would move (`content`,
73
+ `moved`) and its `frame` (document bounds of the content) with its corners. Every transform
74
+ works on that frame: the numeric fields are percent of it and turn about one of its anchors.
75
+ 2. **Pick what moves** with `content`: `layer` (all its pixels and a linked mask), `selection`
76
+ (only the selected pixels, committed back into the same layer; the hole they leave is
77
+ transparent and the outline moves with them), `selection-copy` (Layer via Copy, then the copy
78
+ is transformed on a new layer; the original stays) or `auto` (selection when something is
79
+ selected). `channel: "mask"` moves an unlinked mask alone; `transform_selection` moves only
80
+ the outline.
81
+ 3. **Choose the tool by the change**: `transform_layer` with `scaleX` / `scaleY` (percent),
82
+ `rotate`, `skewX` / `skewY` (degrees), `dx` / `dy` and a `reference` anchor for scale, rotate
83
+ and skew; `corners` for Distort (each corner free) and Perspective (move two corners
84
+ symmetrically: the top pair in by the same amount narrows the top); `matrix` when you have one;
85
+ `warp_layer` for a preset bend (`style`, `bend`, `horizontal`, `vertical`) or a custom `mesh`;
86
+ `flip_layer` and `rotate_layer_90` for exact flips and quarter turns.
87
+ 4. **Transform once.** Every call resamples the pixels, so chained calls soften them: put scale,
88
+ rotation and move into one `transform_layer` call (or one matrix) instead of several.
89
+ 5. **Look**: `render_preview`, or `capture_view` at the edges; each call is one undo step.
90
+
70
91
  ### Layer effects
71
92
 
72
93
  1. **Effects are live and per layer**: drop and inner shadows, outer and inner glows,
@@ -193,6 +214,16 @@ batching.
193
214
  layer `opacity` fades the effects too.
194
215
  - **Prefer an effect over painted pixels** for shadows, glows, outlines and colour fills of a
195
216
  shape: it follows later edits and stays adjustable.
217
+ - **Transforms: one resample, bicubic, whole pixels when you can.** Combine a scale, rotation and
218
+ move into one `transform_layer` call; use `rotate_layer_90` / `flip_layer` (exact) instead of
219
+ `rotate: 90` or `scaleX: -100`. `interpolation: "nearest"` keeps hard pixel art crisp; bicubic
220
+ (default) is right for photos, bilinear is a little softer. Enlarging past about 200 % shows
221
+ softness: prefer a larger source.
222
+ - **Scale proportionally** unless asked to stretch: give `scaleX` and `scaleY` the same value.
223
+ Keep the subject in frame: after a scale about `center` the layer can run past the canvas,
224
+ which `bounds` in the result shows.
225
+ - **Unlink a mask** (`set_layer_mask_properties` `linked: false`) when the pixels should move
226
+ under a fixed mask (a picture inside a frame); link it again afterwards.
196
227
  - **Merge Down only onto an opaque, 100 % lower layer** when the result must look the same:
197
228
  the merged layer keeps the lower layer's opacity and blend, so a faded lower layer fades the
198
229
  merged content too, and a blend mode on the upper layer stops seeing what was below the lower
@@ -214,6 +245,7 @@ batching.
214
245
  | `render_preview` | See the edited image (crop, adjustments, layers, annotations) as a PNG, or with `layerId` one layer alone. `maxSide` 16..2048 px, default 512. Images cost tokens: render after a group of edits, use 512 for overall look and 1024+ to judge clipping, edges and masks. Fails in environments without rendering. |
215
246
  | `inspect_psd` | Read a PSD / PSB (`data` base64) without opening it: size, `depth`, `colorMode`, `resolution`, every layer bottom first with `psdKind`, the `type` it would become and `status` (`mapped`, `approximated`, `dropped`) with `notes`, and the import `warnings`. Call before `import_psd`. |
216
247
  | `export_psd` | Save the document as an 8-bit RGB PSD (PSB above 30000 px) with layers, groups, adjustment layers and masks. Returns `data` (base64), `size` in bytes, `psb` and `warnings` (crop or rotation not applied, filters and depth masks baked, annotations rasterized or left out, Pigment blends written as Normal). Changes nothing. |
248
+ | `get_transform_frame` | Before a transform: what it would move (`content`, `moved`: pixels, mask, selection), its `frame` (document bounds of the content), `corners` (top-left, top-right, bottom-right, bottom-left) and `center`. `meshColumns` / `meshRows` also return an identity warp `mesh` over the frame to edit for `warp_layer`. Changes nothing. |
217
249
  | `capture_view` | Inspect detail in natural image pixels (the space of `get_selection` and `select_region`, before crop and rotation): `region` `content` (whole image, default), `selection` or `rect`; small regions are enlarged up to 8× with hard pixel edges, so a 64 px rect shows real pixels. `includeOverlays: true` shades unselected pixels and outlines the crop: use it to check a mask's edge before `apply_selection_as_mask`. Returns the `rect` and `scale`. Use `render_preview` for the final framed result. |
218
250
 
219
251
  ### Write
@@ -247,9 +279,14 @@ batching.
247
279
  | `merge_down` | Composite a layer onto the pixel layer below it (masks, fill and filters baked). Destructive; see Best practices. Returns the merged layer. |
248
280
  | `merge_visible` | Composite all visible top-level layers into one layer; hidden ones stay. Destructive. |
249
281
  | `flatten_image` | Composite everything visible into one Background; hidden layers are discarded. Destructive; do it only when asked. |
250
- | `offset_layer` | Move a pixel layer and its mask to `x`, `y` or by `dx`, `dy` (integers, document px). Refused when its position is locked. Returns the offset and bounds. |
282
+ | `offset_layer` | Move a pixel layer and its linked mask to `x`, `y` or by `dx`, `dy` (integers, document px; an unlinked mask stays put). Refused when its position is locked. Returns the offset and bounds. |
283
+ | `transform_layer` | Free Transform a pixel layer (with its linked mask), the selected pixels (`content` `selection`), a copy of them on a new layer (`selection-copy`) or an unlinked mask (`channel` `mask`). Give the transform one way: `scaleX` / `scaleY` (percent), `rotate`, `skewX` / `skewY` (degrees), `dx` / `dy` (px) about `reference` (an anchor or `{x, y}`, default `center`); or `matrix` `[a, b, c, d, e, f]`; or `corners` (the frame's new corners: distort / perspective, kept convex). `interpolation` nearest, bilinear or bicubic (default). One undo step. Returns `layerId` (the new layer for a copy), `moved`, `frame`, `corners` and the new `bounds`. |
284
+ | `warp_layer` | Warp the same targets as `transform_layer` through a preset (`style` arc … twist, `bend` −100..100 default 50, `horizontal` / `vertical` distortion, `orientation`) or a `mesh` (`columns`, `rows`, (3·columns + 1) × (3·rows + 1) `points` in document px; start from `get_transform_frame`'s identity mesh). One undo step. Returns the new `bounds`. |
285
+ | `transform_selection` | Transform only the selection outline (Transform Selection): the same numeric fields, `matrix` or `corners` as `transform_layer`, over the selection's bounds. Pixels do not change. Needs a selection. Returns the new selection `bounds`. |
286
+ | `flip_layer` | Mirror a pixel layer, its selected pixels or a copy (`content`) `horizontal` or `vertical` about the frame's centre, exactly. For the whole image use `flip_image`. Returns the new `bounds`. |
287
+ | `rotate_layer_90` | Turn a pixel layer, its selected pixels or a copy by `turn` 90 (clockwise), -90 or 180 about the frame's centre, landing on whole pixels (no resampling). For the whole image use `set_rotation`. Returns the new `bounds`. |
251
288
  | `add_layer_mask` | Mask any layer `from` `reveal-all`, `hide-all` or `selection`, with optional `density` / `feather`. Replaces an existing mask. Returns the mask summary. |
252
- | `set_layer_mask_properties` | Change any layer mask's `density`, `feather` or `enabled` without touching its pixels. |
289
+ | `set_layer_mask_properties` | Change any layer mask's `density`, `feather`, `enabled` or `linked` (false: the mask stays put when the layer moves or transforms) without touching its pixels. |
253
290
  | `apply_layer_mask` | Bake a pixel layer's mask into its alpha and remove it. Destructive. |
254
291
  | `remove_layer_mask` | Delete a mask without applying it; disable it instead to keep it. |
255
292
  | `layer_via_copy` | Copy the selected pixels of a pixel layer (default the active one) to a new layer above it; `cut: true` removes them from the source. Needs a selection. Returns the new layer. |
@@ -328,5 +365,14 @@ batching.
328
365
  selection: start low (wand 20..40, range 30..60), check `percent`, and add with `mode: add`.
329
366
  - `modify_selection`, `refine_selection` and `apply_selection_as_mask` fail with "Nothing is
330
367
  selected." when the selection is empty; select first.
368
+ - Transforms refuse hidden layers, layers with `locks.position` or `locks.pixels`, and adjustment,
369
+ annotation and group layers (transform a layer's mask with `channel: "mask"` after unlinking
370
+ it). A result larger than about 11 600 × 11 600 px is refused.
371
+ - `transform_layer` scale fields are percent (100 = unchanged), not factors; `rotate` is degrees
372
+ clockwise. `corners` that cross or fold through the horizon are refused: keep the quad convex.
373
+ - With a selection, `content: "auto"` (the default) moves only the selected pixels, not the
374
+ whole layer. Pass `content: "layer"` to move everything regardless of the selection.
375
+ - A Background transformed smaller leaves transparent canvas around it; fill it with a layer
376
+ below or crop afterwards.
331
377
  - Opacity values are 0..1, not percent. Curves and levels points are 0..255 levels; levels
332
378
  `gamma` is 0.1..9.99 (1 = neutral); hue is degrees -180..180.