@pixerate/editor 0.187.0 → 0.189.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.
- package/dist/{chunk-X2KQQZBT.cjs → chunk-ED4L4UD6.cjs} +389 -180
- package/dist/{chunk-FW7N64XK.js → chunk-ZEHTUR7Z.js} +229 -20
- package/dist/image-editor/controller.d.cts +20 -3
- package/dist/image-editor/controller.d.ts +20 -3
- package/dist/image-editor/index.cjs +1618 -1467
- package/dist/image-editor/index.js +623 -472
- package/dist/image-editor/layers/paint-ui.d.cts +2 -1
- package/dist/image-editor/layers/paint-ui.d.ts +2 -1
- package/dist/image-editor/layers/panel.d.cts +3 -2
- package/dist/image-editor/layers/panel.d.ts +3 -2
- package/dist/image-editor/renderer.d.cts +6 -0
- package/dist/image-editor/renderer.d.ts +6 -0
- package/dist/image-editor/selection/gesture.d.cts +10 -0
- package/dist/image-editor/selection/gesture.d.ts +10 -0
- package/dist/image-editor/selection/layer-mask.d.cts +6 -0
- package/dist/image-editor/selection/layer-mask.d.ts +6 -0
- package/dist/image-editor/selection/mask.d.cts +20 -1
- package/dist/image-editor/selection/mask.d.ts +20 -1
- package/dist/image-editor/selection/shapes.d.cts +8 -0
- package/dist/image-editor/selection/shapes.d.ts +8 -0
- package/dist/image-editor/selection/tool-options.d.cts +1 -1
- package/dist/image-editor/selection/tool-options.d.ts +1 -1
- package/dist/image-editor/types.d.cts +8 -0
- package/dist/image-editor/types.d.ts +8 -0
- package/dist/paint-editor/index.cjs +6 -6
- package/dist/paint-editor/index.js +1 -1
- package/package.json +1 -1
- package/skills/pixerate-image-editor/SKILL.md +1 -0
- package/skills/pixerate-image-selection-masking/SKILL.md +4 -1
|
@@ -140,7 +140,8 @@ export interface ShortcutEvent {
|
|
|
140
140
|
* Applies a paint shortcut. Returns true when it was one (the caller then prevents the default).
|
|
141
141
|
* B / Shift+B (Mixer Brush) / E / V choose the tool; [ and ] change the size, with Shift the hardness by 25 %; 1..9 set the
|
|
142
142
|
* opacity to 10..90 % and 0 to 100 %; D resets the colours to black and white; X swaps them; Q
|
|
143
|
-
* toggles Quick Mask mode (painting then edits the selection)
|
|
143
|
+
* toggles Quick Mask mode (painting then edits the selection); the backslash key shows the active
|
|
144
|
+
* layer's mask as a red overlay.
|
|
144
145
|
*/
|
|
145
146
|
export declare function handlePaintShortcut(controller: ImageEditorController, e: ShortcutEvent): boolean;
|
|
146
147
|
/** One pointer sample in document pixels. */
|
|
@@ -140,7 +140,8 @@ export interface ShortcutEvent {
|
|
|
140
140
|
* Applies a paint shortcut. Returns true when it was one (the caller then prevents the default).
|
|
141
141
|
* B / Shift+B (Mixer Brush) / E / V choose the tool; [ and ] change the size, with Shift the hardness by 25 %; 1..9 set the
|
|
142
142
|
* opacity to 10..90 % and 0 to 100 %; D resets the colours to black and white; X swaps them; Q
|
|
143
|
-
* toggles Quick Mask mode (painting then edits the selection)
|
|
143
|
+
* toggles Quick Mask mode (painting then edits the selection); the backslash key shows the active
|
|
144
|
+
* layer's mask as a red overlay.
|
|
144
145
|
*/
|
|
145
146
|
export declare function handlePaintShortcut(controller: ImageEditorController, e: ShortcutEvent): boolean;
|
|
146
147
|
/** One pointer sample in document pixels. */
|
|
@@ -8,8 +8,9 @@ import { type ImageLayer, type SmartFilter } from './model.cjs';
|
|
|
8
8
|
import type { LayerPlacement } from './ops.cjs';
|
|
9
9
|
/**
|
|
10
10
|
* A click on a layer's mask thumbnail, as in Photoshop: Ctrl/⌘-click loads the mask as the
|
|
11
|
-
* selection (with Shift adding, Alt subtracting, both intersecting),
|
|
12
|
-
*
|
|
11
|
+
* selection (with Shift adding, Alt subtracting, both intersecting), Alt-click shows the mask
|
|
12
|
+
* alone in grey (Alt+Shift-click as a red overlay; again to go back to the image), Shift-click
|
|
13
|
+
* turns the mask on or off, and a plain click makes the mask the paint target.
|
|
13
14
|
*/
|
|
14
15
|
export declare function maskThumbnailClick(controller: ImageEditorController, layer: ImageLayer, e: {
|
|
15
16
|
ctrlKey?: boolean;
|
|
@@ -8,8 +8,9 @@ import { type ImageLayer, type SmartFilter } from './model.js';
|
|
|
8
8
|
import type { LayerPlacement } from './ops.js';
|
|
9
9
|
/**
|
|
10
10
|
* A click on a layer's mask thumbnail, as in Photoshop: Ctrl/⌘-click loads the mask as the
|
|
11
|
-
* selection (with Shift adding, Alt subtracting, both intersecting),
|
|
12
|
-
*
|
|
11
|
+
* selection (with Shift adding, Alt subtracting, both intersecting), Alt-click shows the mask
|
|
12
|
+
* alone in grey (Alt+Shift-click as a red overlay; again to go back to the image), Shift-click
|
|
13
|
+
* turns the mask on or off, and a plain click makes the mask the paint target.
|
|
13
14
|
*/
|
|
14
15
|
export declare function maskThumbnailClick(controller: ImageEditorController, layer: ImageLayer, e: {
|
|
15
16
|
ctrlKey?: boolean;
|
|
@@ -178,6 +178,12 @@ export declare class ImageEditorRenderer {
|
|
|
178
178
|
/** An empty selection of the image's size (Quick Mask mode with nothing selected). */
|
|
179
179
|
private emptyMask;
|
|
180
180
|
private overlayCache;
|
|
181
|
+
private maskViewCache;
|
|
182
|
+
private grayCache;
|
|
183
|
+
/** A layer's mask as canvas-sized coverage for its mask view, kept while the mask is unchanged. */
|
|
184
|
+
private maskViewSelection;
|
|
185
|
+
/** A mask alone in grey (white = revealed), opaque, drawn in natural image space. */
|
|
186
|
+
private drawMaskGray;
|
|
181
187
|
/** A channel's tint (colour, opacity, masked or selected area), drawn in natural image space. */
|
|
182
188
|
private drawMaskOverlay;
|
|
183
189
|
/** Rubylith over the unselected area, drawn in natural image space. */
|
|
@@ -178,6 +178,12 @@ export declare class ImageEditorRenderer {
|
|
|
178
178
|
/** An empty selection of the image's size (Quick Mask mode with nothing selected). */
|
|
179
179
|
private emptyMask;
|
|
180
180
|
private overlayCache;
|
|
181
|
+
private maskViewCache;
|
|
182
|
+
private grayCache;
|
|
183
|
+
/** A layer's mask as canvas-sized coverage for its mask view, kept while the mask is unchanged. */
|
|
184
|
+
private maskViewSelection;
|
|
185
|
+
/** A mask alone in grey (white = revealed), opaque, drawn in natural image space. */
|
|
186
|
+
private drawMaskGray;
|
|
181
187
|
/** A channel's tint (colour, opacity, masked or selected area), drawn in natural image space. */
|
|
182
188
|
private drawMaskOverlay;
|
|
183
189
|
/** Rubylith over the unselected area, drawn in natural image space. */
|
|
@@ -76,6 +76,16 @@ export declare function handleSelectionShortcut(controller: ImageEditorControlle
|
|
|
76
76
|
shiftKey?: boolean;
|
|
77
77
|
altKey?: boolean;
|
|
78
78
|
}, onError?: (message: string) => void): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* The backslash key (no modifiers) shows or hides the active layer's mask as a red overlay; it
|
|
81
|
+
* does nothing when the layer has no painted mask. Returns true when the key was used.
|
|
82
|
+
*/
|
|
83
|
+
export declare function handleMaskViewKey(controller: ImageEditorController, e: {
|
|
84
|
+
key: string;
|
|
85
|
+
ctrlKey?: boolean;
|
|
86
|
+
metaKey?: boolean;
|
|
87
|
+
altKey?: boolean;
|
|
88
|
+
}): boolean;
|
|
79
89
|
/** Q (no modifiers) toggles Quick Mask mode. Returns true when the key was used. */
|
|
80
90
|
export declare function handleQuickMaskKey(controller: ImageEditorController, e: {
|
|
81
91
|
key: string;
|
|
@@ -76,6 +76,16 @@ export declare function handleSelectionShortcut(controller: ImageEditorControlle
|
|
|
76
76
|
shiftKey?: boolean;
|
|
77
77
|
altKey?: boolean;
|
|
78
78
|
}, onError?: (message: string) => void): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* The backslash key (no modifiers) shows or hides the active layer's mask as a red overlay; it
|
|
81
|
+
* does nothing when the layer has no painted mask. Returns true when the key was used.
|
|
82
|
+
*/
|
|
83
|
+
export declare function handleMaskViewKey(controller: ImageEditorController, e: {
|
|
84
|
+
key: string;
|
|
85
|
+
ctrlKey?: boolean;
|
|
86
|
+
metaKey?: boolean;
|
|
87
|
+
altKey?: boolean;
|
|
88
|
+
}): boolean;
|
|
79
89
|
/** Q (no modifiers) toggles Quick Mask mode. Returns true when the key was used. */
|
|
80
90
|
export declare function handleQuickMaskKey(controller: ImageEditorController, e: {
|
|
81
91
|
key: string;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { AdjustmentLayer, AdjustmentLayerMask } from '../types.cjs';
|
|
2
2
|
import { type ImageProjection } from '../geometry.cjs';
|
|
3
3
|
import { type SelectionMask } from './mask.cjs';
|
|
4
|
+
import type { ImageLayer } from '../layers/model.cjs';
|
|
5
|
+
/**
|
|
6
|
+
* A layer's painted mask over the `width × height` canvas as coverage (white = revealed), its
|
|
7
|
+
* pixels before density and feather; `null` without one (a depth mask is computed, not painted).
|
|
8
|
+
*/
|
|
9
|
+
export declare function layerMaskSelection(layer: ImageLayer, width: number, height: number): SelectionMask | null;
|
|
4
10
|
/** Properties of a layer mask that leave its pixels intact (Photoshop's Properties › Masks). */
|
|
5
11
|
export interface LayerMaskProps {
|
|
6
12
|
/** 0..1 (default 1): at 0.5 the masked-out areas still get half of the adjustment. */
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { AdjustmentLayer, AdjustmentLayerMask } from '../types.js';
|
|
2
2
|
import { type ImageProjection } from '../geometry.js';
|
|
3
3
|
import { type SelectionMask } from './mask.js';
|
|
4
|
+
import type { ImageLayer } from '../layers/model.js';
|
|
5
|
+
/**
|
|
6
|
+
* A layer's painted mask over the `width × height` canvas as coverage (white = revealed), its
|
|
7
|
+
* pixels before density and feather; `null` without one (a depth mask is computed, not painted).
|
|
8
|
+
*/
|
|
9
|
+
export declare function layerMaskSelection(layer: ImageLayer, width: number, height: number): SelectionMask | null;
|
|
4
10
|
/** Properties of a layer mask that leave its pixels intact (Photoshop's Properties › Masks). */
|
|
5
11
|
export interface LayerMaskProps {
|
|
6
12
|
/** 0..1 (default 1): at 0.5 the masked-out areas still get half of the adjustment. */
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import type { CropBox } from '../types.cjs';
|
|
2
|
+
import { TiledSurface } from '../../raster/surface.cjs';
|
|
2
3
|
/**
|
|
3
4
|
* A selection: one 8-bit coverage value per image pixel (0 = not selected, 255 = fully
|
|
4
5
|
* selected), row-major over the whole source image in natural pixels — the same space as the
|
|
5
6
|
* crop box and annotations. Soft values are partial selection (feathered or anti-aliased edges).
|
|
6
7
|
*
|
|
8
|
+
* The coverage is stored as 256 × 256 tiles (`surface`, one byte per pixel, missing tiles are 0
|
|
9
|
+
* and every pixel outside the image is 0), so an empty or fully selected area costs nothing and
|
|
10
|
+
* masks share the tiles an operation did not change. `data` is the same coverage as one array,
|
|
11
|
+
* built on first read and cached for the few masks read most recently.
|
|
12
|
+
*
|
|
7
13
|
* Treat a mask as immutable: every operation returns a new one, so history entries can share
|
|
8
|
-
* them without copying.
|
|
14
|
+
* them without copying. Never write to `data`.
|
|
9
15
|
*/
|
|
10
16
|
export interface SelectionMask {
|
|
11
17
|
readonly width: number;
|
|
@@ -13,6 +19,8 @@ export interface SelectionMask {
|
|
|
13
19
|
readonly data: Uint8Array;
|
|
14
20
|
/** Bounding box of the non-zero coverage, or `null` when nothing is selected. */
|
|
15
21
|
readonly bounds: CropBox | null;
|
|
22
|
+
/** The coverage as tiles (1 channel, default 0), shared with other masks where equal. */
|
|
23
|
+
readonly surface: TiledSurface;
|
|
16
24
|
}
|
|
17
25
|
/** How a new selection combines with the current one. */
|
|
18
26
|
export type SelectionMode = 'replace' | 'add' | 'subtract' | 'intersect';
|
|
@@ -35,8 +43,19 @@ export interface SerializedSelection {
|
|
|
35
43
|
}
|
|
36
44
|
/** Bounding box of non-zero bytes. */
|
|
37
45
|
export declare function computeSelectionBounds(width: number, height: number, data: ArrayLike<number>): CropBox | null;
|
|
46
|
+
/**
|
|
47
|
+
* A selection over `width × height` from a 1-channel tiled surface in image space (Quick Mask
|
|
48
|
+
* paint, a mask): its tiles are shared, and coverage outside the image is dropped. A surface
|
|
49
|
+
* whose default is not 0 is read out instead.
|
|
50
|
+
*/
|
|
51
|
+
export declare function selectionFromTiles(width: number, height: number, surface: TiledSurface): SelectionMask;
|
|
38
52
|
/** Wraps coverage bytes (taken over, not copied) as a selection, computing its bounds. */
|
|
39
53
|
export declare function createSelectionMask(width: number, height: number, data?: Uint8Array): SelectionMask;
|
|
54
|
+
/**
|
|
55
|
+
* A selection that is `data` (`rect.width × rect.height` coverage bytes) inside `rect` and
|
|
56
|
+
* nothing elsewhere, without allocating the whole image. `rect` must lie inside the image.
|
|
57
|
+
*/
|
|
58
|
+
export declare function selectionFromRegion(width: number, height: number, rect: CropBox, data: ArrayLike<number>): SelectionMask;
|
|
40
59
|
/** Select › All. */
|
|
41
60
|
export declare function fullSelection(width: number, height: number): SelectionMask;
|
|
42
61
|
export declare function isSelectionEmpty(mask: SelectionMask | null | undefined): boolean;
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import type { CropBox } from '../types.js';
|
|
2
|
+
import { TiledSurface } from '../../raster/surface.js';
|
|
2
3
|
/**
|
|
3
4
|
* A selection: one 8-bit coverage value per image pixel (0 = not selected, 255 = fully
|
|
4
5
|
* selected), row-major over the whole source image in natural pixels — the same space as the
|
|
5
6
|
* crop box and annotations. Soft values are partial selection (feathered or anti-aliased edges).
|
|
6
7
|
*
|
|
8
|
+
* The coverage is stored as 256 × 256 tiles (`surface`, one byte per pixel, missing tiles are 0
|
|
9
|
+
* and every pixel outside the image is 0), so an empty or fully selected area costs nothing and
|
|
10
|
+
* masks share the tiles an operation did not change. `data` is the same coverage as one array,
|
|
11
|
+
* built on first read and cached for the few masks read most recently.
|
|
12
|
+
*
|
|
7
13
|
* Treat a mask as immutable: every operation returns a new one, so history entries can share
|
|
8
|
-
* them without copying.
|
|
14
|
+
* them without copying. Never write to `data`.
|
|
9
15
|
*/
|
|
10
16
|
export interface SelectionMask {
|
|
11
17
|
readonly width: number;
|
|
@@ -13,6 +19,8 @@ export interface SelectionMask {
|
|
|
13
19
|
readonly data: Uint8Array;
|
|
14
20
|
/** Bounding box of the non-zero coverage, or `null` when nothing is selected. */
|
|
15
21
|
readonly bounds: CropBox | null;
|
|
22
|
+
/** The coverage as tiles (1 channel, default 0), shared with other masks where equal. */
|
|
23
|
+
readonly surface: TiledSurface;
|
|
16
24
|
}
|
|
17
25
|
/** How a new selection combines with the current one. */
|
|
18
26
|
export type SelectionMode = 'replace' | 'add' | 'subtract' | 'intersect';
|
|
@@ -35,8 +43,19 @@ export interface SerializedSelection {
|
|
|
35
43
|
}
|
|
36
44
|
/** Bounding box of non-zero bytes. */
|
|
37
45
|
export declare function computeSelectionBounds(width: number, height: number, data: ArrayLike<number>): CropBox | null;
|
|
46
|
+
/**
|
|
47
|
+
* A selection over `width × height` from a 1-channel tiled surface in image space (Quick Mask
|
|
48
|
+
* paint, a mask): its tiles are shared, and coverage outside the image is dropped. A surface
|
|
49
|
+
* whose default is not 0 is read out instead.
|
|
50
|
+
*/
|
|
51
|
+
export declare function selectionFromTiles(width: number, height: number, surface: TiledSurface): SelectionMask;
|
|
38
52
|
/** Wraps coverage bytes (taken over, not copied) as a selection, computing its bounds. */
|
|
39
53
|
export declare function createSelectionMask(width: number, height: number, data?: Uint8Array): SelectionMask;
|
|
54
|
+
/**
|
|
55
|
+
* A selection that is `data` (`rect.width × rect.height` coverage bytes) inside `rect` and
|
|
56
|
+
* nothing elsewhere, without allocating the whole image. `rect` must lie inside the image.
|
|
57
|
+
*/
|
|
58
|
+
export declare function selectionFromRegion(width: number, height: number, rect: CropBox, data: ArrayLike<number>): SelectionMask;
|
|
40
59
|
/** Select › All. */
|
|
41
60
|
export declare function fullSelection(width: number, height: number): SelectionMask;
|
|
42
61
|
export declare function isSelectionEmpty(mask: SelectionMask | null | undefined): boolean;
|
|
@@ -11,6 +11,14 @@ export interface ShapeSelectionOptions {
|
|
|
11
11
|
* their top), so the cost is about pixels + edges × rows they span.
|
|
12
12
|
*/
|
|
13
13
|
export declare function polygonCoverage(points: readonly ImagePoint[], width: number, height: number, antiAlias?: boolean): Float32Array;
|
|
14
|
+
/**
|
|
15
|
+
* {@link polygonCoverage} over just the polygon's bounding box (clipped to the image): `coverage`
|
|
16
|
+
* is `box.width × box.height`; `box` is `null` when the polygon covers no pixel row or column.
|
|
17
|
+
*/
|
|
18
|
+
export declare function polygonCoverageBox(points: readonly ImagePoint[], width: number, height: number, antiAlias?: boolean): {
|
|
19
|
+
box: CropBox | null;
|
|
20
|
+
coverage: Float32Array;
|
|
21
|
+
};
|
|
14
22
|
/** Lasso / polygonal lasso: an even-odd polygon in natural image pixels. */
|
|
15
23
|
export declare function polygonSelection(width: number, height: number, points: readonly ImagePoint[], options?: ShapeSelectionOptions): SelectionMask;
|
|
16
24
|
/** Normalises a rectangle with a negative width or height. */
|
|
@@ -11,6 +11,14 @@ export interface ShapeSelectionOptions {
|
|
|
11
11
|
* their top), so the cost is about pixels + edges × rows they span.
|
|
12
12
|
*/
|
|
13
13
|
export declare function polygonCoverage(points: readonly ImagePoint[], width: number, height: number, antiAlias?: boolean): Float32Array;
|
|
14
|
+
/**
|
|
15
|
+
* {@link polygonCoverage} over just the polygon's bounding box (clipped to the image): `coverage`
|
|
16
|
+
* is `box.width × box.height`; `box` is `null` when the polygon covers no pixel row or column.
|
|
17
|
+
*/
|
|
18
|
+
export declare function polygonCoverageBox(points: readonly ImagePoint[], width: number, height: number, antiAlias?: boolean): {
|
|
19
|
+
box: CropBox | null;
|
|
20
|
+
coverage: Float32Array;
|
|
21
|
+
};
|
|
14
22
|
/** Lasso / polygonal lasso: an even-odd polygon in natural image pixels. */
|
|
15
23
|
export declare function polygonSelection(width: number, height: number, points: readonly ImagePoint[], options?: ShapeSelectionOptions): SelectionMask;
|
|
16
24
|
/** Normalises a rectangle with a negative width or height. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type SelectionMask, type SelectionMode } from './mask.cjs';
|
|
2
2
|
import type { ColorDistance, ColorRangePreset } from './wand.cjs';
|
|
3
3
|
import type { RefineEdgeParams } from './refine.cjs';
|
|
4
4
|
/** Selection tools of the image editor UI. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type SelectionMask, type SelectionMode } from './mask.js';
|
|
2
2
|
import type { ColorDistance, ColorRangePreset } from './wand.js';
|
|
3
3
|
import type { RefineEdgeParams } from './refine.js';
|
|
4
4
|
/** Selection tools of the image editor UI. */
|
|
@@ -314,6 +314,14 @@ export interface ImageEditorState {
|
|
|
314
314
|
quickMask?: boolean;
|
|
315
315
|
/** How the canvas shows the selection (view state; `quickMask` mirrors `'quickMask'`). */
|
|
316
316
|
selectionDisplay?: 'ants' | 'quickMask' | 'none';
|
|
317
|
+
/**
|
|
318
|
+
* A layer mask shown on the canvas (view state, not saved): `gray` shows the mask alone in
|
|
319
|
+
* grey (Alt-click its thumbnail), `overlay` tints what it hides in red over the image (the \ key).
|
|
320
|
+
*/
|
|
321
|
+
maskView?: {
|
|
322
|
+
layerId: string;
|
|
323
|
+
mode: 'gray' | 'overlay';
|
|
324
|
+
} | null;
|
|
317
325
|
/**
|
|
318
326
|
* Quick Mask mode: painting and fills without a layer edit the selection itself (white
|
|
319
327
|
* selects, black deselects), shown as a tint. View state; the edits are undo steps.
|
|
@@ -314,6 +314,14 @@ export interface ImageEditorState {
|
|
|
314
314
|
quickMask?: boolean;
|
|
315
315
|
/** How the canvas shows the selection (view state; `quickMask` mirrors `'quickMask'`). */
|
|
316
316
|
selectionDisplay?: 'ants' | 'quickMask' | 'none';
|
|
317
|
+
/**
|
|
318
|
+
* A layer mask shown on the canvas (view state, not saved): `gray` shows the mask alone in
|
|
319
|
+
* grey (Alt-click its thumbnail), `overlay` tints what it hides in red over the image (the \ key).
|
|
320
|
+
*/
|
|
321
|
+
maskView?: {
|
|
322
|
+
layerId: string;
|
|
323
|
+
mode: 'gray' | 'overlay';
|
|
324
|
+
} | null;
|
|
317
325
|
/**
|
|
318
326
|
* Quick Mask mode: painting and fills without a layer edit the selection itself (white
|
|
319
327
|
* selects, black deselects), shown as a tint. View state; the edits are undo steps.
|
|
@@ -7,7 +7,7 @@ var _chunkZ64NRDEHcjs = require('../chunk-Z64NRDEH.cjs');
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _chunkED4L4UD6cjs = require('../chunk-ED4L4UD6.cjs');
|
|
11
11
|
require('../chunk-A2IS7EHE.cjs');
|
|
12
12
|
|
|
13
13
|
|
|
@@ -1653,11 +1653,11 @@ function header(state, options) {
|
|
|
1653
1653
|
return out;
|
|
1654
1654
|
}
|
|
1655
1655
|
function serializePaintDocument(state, options = {}) {
|
|
1656
|
-
const { layers, assets } =
|
|
1656
|
+
const { layers, assets } = _chunkED4L4UD6cjs.serializeLayers.call(void 0, state.layers);
|
|
1657
1657
|
return { ...header(state, options), layers, assets };
|
|
1658
1658
|
}
|
|
1659
1659
|
async function serializePaintDocumentExternal(state, store, options = {}) {
|
|
1660
|
-
const { layers, assets } = await
|
|
1660
|
+
const { layers, assets } = await _chunkED4L4UD6cjs.serializeLayersExternal.call(void 0, state.layers, store);
|
|
1661
1661
|
return { ...header(state, options), layers, assets };
|
|
1662
1662
|
}
|
|
1663
1663
|
function paintLayersOnly(layers, problems) {
|
|
@@ -1694,7 +1694,7 @@ function deserializePaintDocument(raw) {
|
|
|
1694
1694
|
const canvas = normalizeCanvas({ width: r.width, height: r.height, dpi: _nullishCoalesce(r.dpi, () => ( void 0)) });
|
|
1695
1695
|
const paper = _chunkYQ5C5BVKcjs.normalizePaper.call(void 0, _nullishCoalesce(r.paper, () => ( {})));
|
|
1696
1696
|
const assets = r.assets && typeof r.assets === "object" ? r.assets : {};
|
|
1697
|
-
const layers = paintLayersOnly(
|
|
1697
|
+
const layers = paintLayersOnly(_chunkED4L4UD6cjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
|
|
1698
1698
|
const wanted = typeof r.activeLayerId === "string" ? r.activeLayerId : null;
|
|
1699
1699
|
const activeLayerId = wanted && _chunkHGTDMKNEcjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.flattenLayers.call(void 0, layers), 'access', _70 => _70.filter, 'call', _71 => _71((l) => l.type === "pixel"), 'access', _72 => _72.pop, 'call', _73 => _73(), 'optionalAccess', _74 => _74.id]), () => ( null));
|
|
1700
1700
|
const wetEvents = Array.isArray(r.wetEvents) ? r.wetEvents.filter((e) => e && typeof e === "object" && Number.isInteger(e.clock) && typeof e.kind === "string") : [];
|
|
@@ -1710,7 +1710,7 @@ async function deserializePaintDocumentAsync(raw, store) {
|
|
|
1710
1710
|
if (!raw || typeof raw !== "object") throw new Error("Not a paint document: expected a JSON object.");
|
|
1711
1711
|
const r = raw;
|
|
1712
1712
|
const problems = [];
|
|
1713
|
-
const assets = await
|
|
1713
|
+
const assets = await _chunkED4L4UD6cjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
|
|
1714
1714
|
const loaded = deserializePaintDocument({ ...r, assets });
|
|
1715
1715
|
return { ...loaded, problems: [...problems, ...loaded.problems] };
|
|
1716
1716
|
}
|
|
@@ -5409,7 +5409,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
|
|
|
5409
5409
|
return next.type === "group" ? { ...next, children: toStandard(next.children) } : next;
|
|
5410
5410
|
});
|
|
5411
5411
|
const layers = toStandard(dried);
|
|
5412
|
-
const result =
|
|
5412
|
+
const result = _chunkED4L4UD6cjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
|
|
5413
5413
|
for (const [mode, names] of changed) {
|
|
5414
5414
|
const label = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _271 => _271.find, 'call', _272 => _272((m) => m.id === mode), 'optionalAccess', _273 => _273.label]), () => ( mode));
|
|
5415
5415
|
const std = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _274 => _274.find, 'call', _275 => _275((m) => m.id === _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _276 => _276.label]), () => ( _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)));
|
package/package.json
CHANGED
|
@@ -297,6 +297,7 @@ in the source frame at the document's bit depth, colour mode and profile. Read
|
|
|
297
297
|
| `add_layer_mask` | Mask any layer `from` `reveal-all`, `hide-all`, `selection`, `hide-selection` (its inverse) or `transparency` (the layer's own alpha), with optional `density` / `feather`. Replaces an existing mask. Returns the mask summary. |
|
|
298
298
|
| `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. |
|
|
299
299
|
| `apply_layer_mask` | Bake a pixel layer's mask into its alpha and remove it. Destructive. |
|
|
300
|
+
| `set_mask_view` | Show a layer's mask to check it (`view` `gray` alone, `overlay` red tint over what it hides, `off`; `layerId`, default active). View state only; look with `capture_view` `includeOverlays: true`, then `off`. Returns `{view, layerId}`. |
|
|
300
301
|
| `remove_layer_mask` | Delete a mask without applying it; disable it instead to keep it. |
|
|
301
302
|
| `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. |
|
|
302
303
|
| `rasterize_layer` | Turn a shape layer into a pixel layer showing the same pixels (same id, mask, effects, opacity, blend; the paths are gone), an annotation layer into pixels (browser only), a smart object into a pixel layer (as `rasterize_smart_object`), or bake a pixel layer's develop / blur filters into its pixels. Do it before painting over a shape or annotation, or when the user wants the filters fixed. Destructive. |
|
|
@@ -82,7 +82,9 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
|
|
|
82
82
|
`load_selection_from_image`).
|
|
83
83
|
7. **Verify.** `render_preview` at 1024 px or more, and `capture_view` on the edge at 2–8×.
|
|
84
84
|
**Check:** no fringe of the old background colour, no stair-steps, no visible line where an
|
|
85
|
-
adjustment ends.
|
|
85
|
+
adjustment ends. To judge a layer mask itself, `set_mask_view` `gray` (or `overlay`) and
|
|
86
|
+
`capture_view` with `includeOverlays: true`; holes and stray grey show plainly there. Set it
|
|
87
|
+
back to `off` afterwards. Fix by loading the mask back (`load_selection_from_mask`), refining, and
|
|
86
88
|
masking again.
|
|
87
89
|
|
|
88
90
|
## Decision table
|
|
@@ -192,6 +194,7 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
|
|
|
192
194
|
- `load_selection_from_image`: AI or saved mattes
|
|
193
195
|
- `load_selection_from_mask`: a layer mask back to a selection
|
|
194
196
|
- `set_selection_display`: ants, Quick Mask tint or hidden
|
|
197
|
+
- `set_mask_view`: a layer mask alone in grey or as a red overlay, to check it
|
|
195
198
|
- `modify_selection`: expand, contract, feather, border, smooth
|
|
196
199
|
- `refine_selection`: snap the edge to the image
|
|
197
200
|
- `transform_selection`: move or scale the outline only
|