@pixerate/editor 0.185.0 → 0.186.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-GYYSPMVU.js → chunk-FW7N64XK.js} +295 -188
- package/dist/{chunk-C6TRAAG4.cjs → chunk-X2KQQZBT.cjs} +355 -248
- package/dist/image-editor/controller.d.cts +56 -0
- package/dist/image-editor/controller.d.ts +56 -0
- package/dist/image-editor/index.cjs +1461 -1030
- package/dist/image-editor/index.js +447 -16
- package/dist/image-editor/layers/model.d.cts +5 -1
- package/dist/image-editor/layers/model.d.ts +5 -1
- 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/serialize.d.cts +3 -0
- package/dist/image-editor/layers/serialize.d.ts +3 -0
- package/dist/image-editor/psd/channels.d.cts +24 -0
- package/dist/image-editor/psd/channels.d.ts +24 -0
- package/dist/image-editor/psd/export.d.cts +3 -0
- package/dist/image-editor/psd/export.d.ts +3 -0
- package/dist/image-editor/psd/import.d.cts +10 -0
- package/dist/image-editor/psd/import.d.ts +10 -0
- package/dist/image-editor/renderer.d.cts +6 -0
- package/dist/image-editor/renderer.d.ts +6 -0
- package/dist/image-editor/selection/channels.d.cts +52 -0
- package/dist/image-editor/selection/channels.d.ts +52 -0
- package/dist/image-editor/selection/gesture.d.cts +7 -0
- package/dist/image-editor/selection/gesture.d.ts +7 -0
- package/dist/image-editor/selection/index.d.cts +1 -0
- package/dist/image-editor/selection/index.d.ts +1 -0
- package/dist/image-editor/selection/overlay.d.cts +2 -0
- package/dist/image-editor/selection/overlay.d.ts +2 -0
- package/dist/image-editor/tools.d.cts +3 -1
- package/dist/image-editor/tools.d.ts +3 -1
- package/dist/image-editor/types.d.cts +10 -0
- package/dist/image-editor/types.d.ts +10 -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 +7 -0
- package/skills/pixerate-image-selection-masking/SKILL.md +13 -1
|
@@ -474,7 +474,11 @@ export interface SmartObjectLayer extends LayerBase {
|
|
|
474
474
|
export type ImageLayer = PixelLayer | AdjustmentLayerNode | GroupLayer | AnnotationLayer | SmartObjectLayer | ShapeLayer | TypeLayer;
|
|
475
475
|
export type ImageLayerType = ImageLayer['type'];
|
|
476
476
|
/** Which part of the active layer painting targets (`filter-mask`: a smart object's filter mask). */
|
|
477
|
-
|
|
477
|
+
/**
|
|
478
|
+
* What a paint, fill or retouch writes: a layer's pixels, its mask, a smart object's filter mask,
|
|
479
|
+
* or (in Quick Mask mode) the selection itself (`quick-mask`, not a layer).
|
|
480
|
+
*/
|
|
481
|
+
export type LayerTarget = 'pixels' | 'mask' | 'filter-mask' | 'quick-mask';
|
|
478
482
|
/** A fresh id with `prefix` (`layer`, `flt`, …). */
|
|
479
483
|
export declare function newLayerId(prefix?: string): string;
|
|
480
484
|
export type LayerLocation = RasterLayerLocation<ImageLayer>;
|
|
@@ -474,7 +474,11 @@ export interface SmartObjectLayer extends LayerBase {
|
|
|
474
474
|
export type ImageLayer = PixelLayer | AdjustmentLayerNode | GroupLayer | AnnotationLayer | SmartObjectLayer | ShapeLayer | TypeLayer;
|
|
475
475
|
export type ImageLayerType = ImageLayer['type'];
|
|
476
476
|
/** Which part of the active layer painting targets (`filter-mask`: a smart object's filter mask). */
|
|
477
|
-
|
|
477
|
+
/**
|
|
478
|
+
* What a paint, fill or retouch writes: a layer's pixels, its mask, a smart object's filter mask,
|
|
479
|
+
* or (in Quick Mask mode) the selection itself (`quick-mask`, not a layer).
|
|
480
|
+
*/
|
|
481
|
+
export type LayerTarget = 'pixels' | 'mask' | 'filter-mask' | 'quick-mask';
|
|
478
482
|
/** A fresh id with `prefix` (`layer`, `flt`, …). */
|
|
479
483
|
export declare function newLayerId(prefix?: string): string;
|
|
480
484
|
export type LayerLocation = RasterLayerLocation<ImageLayer>;
|
|
@@ -139,7 +139,8 @@ export interface ShortcutEvent {
|
|
|
139
139
|
/**
|
|
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
|
-
* opacity to 10..90 % and 0 to 100 %; D resets the colours to black and white; X swaps them
|
|
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
144
|
*/
|
|
144
145
|
export declare function handlePaintShortcut(controller: ImageEditorController, e: ShortcutEvent): boolean;
|
|
145
146
|
/** One pointer sample in document pixels. */
|
|
@@ -139,7 +139,8 @@ export interface ShortcutEvent {
|
|
|
139
139
|
/**
|
|
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
|
-
* opacity to 10..90 % and 0 to 100 %; D resets the colours to black and white; X swaps them
|
|
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
144
|
*/
|
|
144
145
|
export declare function handlePaintShortcut(controller: ImageEditorController, e: ShortcutEvent): boolean;
|
|
145
146
|
/** One pointer sample in document pixels. */
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { Annotation, CropBox, DepthMaskOptions, ImageTransform } from '../types.cjs';
|
|
10
10
|
import type { SerializedSelection } from '../selection/mask.cjs';
|
|
11
|
+
import type { SerializedAlphaChannel } from '../selection/channels.cjs';
|
|
11
12
|
import type { SerializedColorMode, SerializedColorProfile } from '../color-management.cjs';
|
|
12
13
|
import { type PsdSmartFilter, type EffectSmartFilter, type ImageEffectGenerator, type SmartContents, type ImageLayer, type LayerFilter, type LayerLocks, type ShapeComponent, type ShapePaint, type ShapeStroke, type ParagraphRun, type TextRun, type TypeLayer } from './model.cjs';
|
|
13
14
|
import { type GlobalLight, type LayerEffect, type LayerEffects } from '../../raster/effects/model.cjs';
|
|
@@ -222,6 +223,8 @@ export interface SerializedLayeredImageEditorState {
|
|
|
222
223
|
/** Blur migrated from a v1 / v2 document with adjustment layers (runs after the layers). */
|
|
223
224
|
legacyOutputBlur?: number;
|
|
224
225
|
selection?: SerializedSelection;
|
|
226
|
+
/** Alpha channels (saved selections), run-length encoded. */
|
|
227
|
+
channels?: SerializedAlphaChannel[];
|
|
225
228
|
/** Global light for layer effects (missing = 120°, 30°). */
|
|
226
229
|
globalLight?: GlobalLight;
|
|
227
230
|
/** The document's patterns for pattern effects, each an RGBA PNG data URL. */
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { Annotation, CropBox, DepthMaskOptions, ImageTransform } from '../types.js';
|
|
10
10
|
import type { SerializedSelection } from '../selection/mask.js';
|
|
11
|
+
import type { SerializedAlphaChannel } from '../selection/channels.js';
|
|
11
12
|
import type { SerializedColorMode, SerializedColorProfile } from '../color-management.js';
|
|
12
13
|
import { type PsdSmartFilter, type EffectSmartFilter, type ImageEffectGenerator, type SmartContents, type ImageLayer, type LayerFilter, type LayerLocks, type ShapeComponent, type ShapePaint, type ShapeStroke, type ParagraphRun, type TextRun, type TypeLayer } from './model.js';
|
|
13
14
|
import { type GlobalLight, type LayerEffect, type LayerEffects } from '../../raster/effects/model.js';
|
|
@@ -222,6 +223,8 @@ export interface SerializedLayeredImageEditorState {
|
|
|
222
223
|
/** Blur migrated from a v1 / v2 document with adjustment layers (runs after the layers). */
|
|
223
224
|
legacyOutputBlur?: number;
|
|
224
225
|
selection?: SerializedSelection;
|
|
226
|
+
/** Alpha channels (saved selections), run-length encoded. */
|
|
227
|
+
channels?: SerializedAlphaChannel[];
|
|
225
228
|
/** Global light for layer effects (missing = 120°, 30°). */
|
|
226
229
|
globalLight?: GlobalLight;
|
|
227
230
|
/** The document's patterns for pattern effects, each an RGBA PNG data URL. */
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PsdResource } from './file.cjs';
|
|
2
|
+
/** An alpha channel as the PSD code reads and writes it: an 8-bit plane over the canvas. */
|
|
3
|
+
export interface PsdAlphaChannel {
|
|
4
|
+
name: string;
|
|
5
|
+
/** `width × height` coverage, 255 = selected. */
|
|
6
|
+
data: Uint8Array;
|
|
7
|
+
/** `#rrggbb` overlay colour. */
|
|
8
|
+
color: string;
|
|
9
|
+
/** 0..1. */
|
|
10
|
+
opacity: number;
|
|
11
|
+
indicates: 'masked' | 'selected';
|
|
12
|
+
}
|
|
13
|
+
/** The image resources that name and describe `channels`. */
|
|
14
|
+
export declare function alphaChannelResources(channels: readonly PsdAlphaChannel[]): PsdResource[];
|
|
15
|
+
/**
|
|
16
|
+
* The alpha channels of a file: merged planes `first … channels − 1`, named from 1045 (or
|
|
17
|
+
* 1006), described by 1077. Spot colour channels (kind 2) are left out and reported.
|
|
18
|
+
*/
|
|
19
|
+
export declare function readAlphaChannels(planes: Uint8Array, header: {
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
depth: number;
|
|
23
|
+
channels: number;
|
|
24
|
+
}, first: number, resource: (id: number) => Uint8Array | undefined, warn: (message: string) => void): PsdAlphaChannel[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PsdResource } from './file.js';
|
|
2
|
+
/** An alpha channel as the PSD code reads and writes it: an 8-bit plane over the canvas. */
|
|
3
|
+
export interface PsdAlphaChannel {
|
|
4
|
+
name: string;
|
|
5
|
+
/** `width × height` coverage, 255 = selected. */
|
|
6
|
+
data: Uint8Array;
|
|
7
|
+
/** `#rrggbb` overlay colour. */
|
|
8
|
+
color: string;
|
|
9
|
+
/** 0..1. */
|
|
10
|
+
opacity: number;
|
|
11
|
+
indicates: 'masked' | 'selected';
|
|
12
|
+
}
|
|
13
|
+
/** The image resources that name and describe `channels`. */
|
|
14
|
+
export declare function alphaChannelResources(channels: readonly PsdAlphaChannel[]): PsdResource[];
|
|
15
|
+
/**
|
|
16
|
+
* The alpha channels of a file: merged planes `first … channels − 1`, named from 1045 (or
|
|
17
|
+
* 1006), described by 1077. Spot colour channels (kind 2) are left out and reported.
|
|
18
|
+
*/
|
|
19
|
+
export declare function readAlphaChannels(planes: Uint8Array, header: {
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
depth: number;
|
|
23
|
+
channels: number;
|
|
24
|
+
}, first: number, resource: (id: number) => Uint8Array | undefined, warn: (message: string) => void): PsdAlphaChannel[];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ImageLayer, type SmartContents } from '../layers/model.cjs';
|
|
2
|
+
import { type PsdAlphaChannel } from './channels.cjs';
|
|
2
3
|
import { type GlobalLight } from '../../raster/effects/model.cjs';
|
|
3
4
|
import { type EffectPattern } from '../../raster/effects/patterns.cjs';
|
|
4
5
|
export interface PsdExportInput {
|
|
@@ -8,6 +9,8 @@ export interface PsdExportInput {
|
|
|
8
9
|
layers: readonly ImageLayer[];
|
|
9
10
|
/** The composite, `width × height` RGBA, written as the merged image. */
|
|
10
11
|
merged: ArrayLike<number>;
|
|
12
|
+
/** Alpha channels, written as extra merged planes with their names and display info. */
|
|
13
|
+
alphaChannels?: readonly PsdAlphaChannel[];
|
|
11
14
|
/** Pixels per inch (default 72). */
|
|
12
15
|
resolution?: number;
|
|
13
16
|
/** The document's patterns; those the effects use are embedded (built-in ones too). */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ImageLayer, type SmartContents } from '../layers/model.js';
|
|
2
|
+
import { type PsdAlphaChannel } from './channels.js';
|
|
2
3
|
import { type GlobalLight } from '../../raster/effects/model.js';
|
|
3
4
|
import { type EffectPattern } from '../../raster/effects/patterns.js';
|
|
4
5
|
export interface PsdExportInput {
|
|
@@ -8,6 +9,8 @@ export interface PsdExportInput {
|
|
|
8
9
|
layers: readonly ImageLayer[];
|
|
9
10
|
/** The composite, `width × height` RGBA, written as the merged image. */
|
|
10
11
|
merged: ArrayLike<number>;
|
|
12
|
+
/** Alpha channels, written as extra merged planes with their names and display info. */
|
|
13
|
+
alphaChannels?: readonly PsdAlphaChannel[];
|
|
11
14
|
/** Pixels per inch (default 72). */
|
|
12
15
|
resolution?: number;
|
|
13
16
|
/** The document's patterns; those the effects use are embedded (built-in ones too). */
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PSD / PSB → our layer tree. Everything the model holds maps directly (smart objects with their
|
|
3
|
+
* embedded contents, placement, warp, smart filters and filter mask; shape layers with their
|
|
4
|
+
* paths, fill, stroke and live shapes; type layers with their text, styles and Photoshop's pixels
|
|
5
|
+
* until edited); everything else comes in as close as it can (fill layers as their stored pixels)
|
|
6
|
+
* with a warning naming the layers.
|
|
7
|
+
*/
|
|
8
|
+
import { type PsdAlphaChannel } from './channels.cjs';
|
|
1
9
|
import type { ImageLayer, LayerBlendMode } from '../layers/model.cjs';
|
|
2
10
|
import { type PsdFile } from './file.cjs';
|
|
3
11
|
import type { DocumentColorProfile } from '../color-management.cjs';
|
|
@@ -54,6 +62,8 @@ export interface PsdImportResult {
|
|
|
54
62
|
};
|
|
55
63
|
/** The bits per channel the layers keep: 16 or 32 for such files (not indexed or bitmap), else 8. */
|
|
56
64
|
bitDepth: 8 | 16 | 32;
|
|
65
|
+
/** The file's alpha channels (saved selections), as 8-bit planes. */
|
|
66
|
+
alphaChannels?: PsdAlphaChannel[];
|
|
57
67
|
}
|
|
58
68
|
export interface PsdImportOptions {
|
|
59
69
|
/** Makes layer ids (defaults to `psd-<n>`). */
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PSD / PSB → our layer tree. Everything the model holds maps directly (smart objects with their
|
|
3
|
+
* embedded contents, placement, warp, smart filters and filter mask; shape layers with their
|
|
4
|
+
* paths, fill, stroke and live shapes; type layers with their text, styles and Photoshop's pixels
|
|
5
|
+
* until edited); everything else comes in as close as it can (fill layers as their stored pixels)
|
|
6
|
+
* with a warning naming the layers.
|
|
7
|
+
*/
|
|
8
|
+
import { type PsdAlphaChannel } from './channels.js';
|
|
1
9
|
import type { ImageLayer, LayerBlendMode } from '../layers/model.js';
|
|
2
10
|
import { type PsdFile } from './file.js';
|
|
3
11
|
import type { DocumentColorProfile } from '../color-management.js';
|
|
@@ -54,6 +62,8 @@ export interface PsdImportResult {
|
|
|
54
62
|
};
|
|
55
63
|
/** The bits per channel the layers keep: 16 or 32 for such files (not indexed or bitmap), else 8. */
|
|
56
64
|
bitDepth: 8 | 16 | 32;
|
|
65
|
+
/** The file's alpha channels (saved selections), as 8-bit planes. */
|
|
66
|
+
alphaChannels?: PsdAlphaChannel[];
|
|
57
67
|
}
|
|
58
68
|
export interface PsdImportOptions {
|
|
59
69
|
/** Makes layer ids (defaults to `psd-<n>`). */
|
|
@@ -174,6 +174,12 @@ export declare class ImageEditorRenderer {
|
|
|
174
174
|
private publishHistogram;
|
|
175
175
|
private quickMaskCache;
|
|
176
176
|
private outlineCache;
|
|
177
|
+
private emptyMaskCache;
|
|
178
|
+
/** An empty selection of the image's size (Quick Mask mode with nothing selected). */
|
|
179
|
+
private emptyMask;
|
|
180
|
+
private overlayCache;
|
|
181
|
+
/** A channel's tint (colour, opacity, masked or selected area), drawn in natural image space. */
|
|
182
|
+
private drawMaskOverlay;
|
|
177
183
|
/** Rubylith over the unselected area, drawn in natural image space. */
|
|
178
184
|
private drawQuickMask;
|
|
179
185
|
/**
|
|
@@ -174,6 +174,12 @@ export declare class ImageEditorRenderer {
|
|
|
174
174
|
private publishHistogram;
|
|
175
175
|
private quickMaskCache;
|
|
176
176
|
private outlineCache;
|
|
177
|
+
private emptyMaskCache;
|
|
178
|
+
/** An empty selection of the image's size (Quick Mask mode with nothing selected). */
|
|
179
|
+
private emptyMask;
|
|
180
|
+
private overlayCache;
|
|
181
|
+
/** A channel's tint (colour, opacity, masked or selected area), drawn in natural image space. */
|
|
182
|
+
private drawMaskOverlay;
|
|
177
183
|
/** Rubylith over the unselected area, drawn in natural image space. */
|
|
178
184
|
private drawQuickMask;
|
|
179
185
|
/**
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type SelectionMask, type SerializedSelection } from './mask.cjs';
|
|
2
|
+
/**
|
|
3
|
+
* An alpha channel: a saved selection kept with the document (Select › Save Selection), shown
|
|
4
|
+
* as a tinted overlay when visible. Its mask is the selection's 8-bit coverage over the canvas
|
|
5
|
+
* (immutable, so undo steps share it).
|
|
6
|
+
*/
|
|
7
|
+
export interface AlphaChannel {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
/** Coverage (255 = selected). An empty channel has a mask with `bounds: null`. */
|
|
11
|
+
mask: SelectionMask;
|
|
12
|
+
/** Overlay tint, `#rrggbb` (default red, the Quick Mask's). */
|
|
13
|
+
color: string;
|
|
14
|
+
/** Overlay opacity 0..1 (default 0.5). */
|
|
15
|
+
opacity: number;
|
|
16
|
+
/** Whether the tint covers the `masked` (unselected, default) or the `selected` area. */
|
|
17
|
+
indicates: 'masked' | 'selected';
|
|
18
|
+
/** Shown as an overlay on the canvas (default false). */
|
|
19
|
+
visible: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** An alpha channel as stored in a document. */
|
|
22
|
+
export interface SerializedAlphaChannel extends Omit<AlphaChannel, 'mask'> {
|
|
23
|
+
mask: SerializedSelection;
|
|
24
|
+
}
|
|
25
|
+
export declare const DEFAULT_CHANNEL_COLOR = "#ff0000";
|
|
26
|
+
/** A summary of a channel for agents and panels (no pixels). */
|
|
27
|
+
export declare function describeChannel(channel: AlphaChannel): {
|
|
28
|
+
bounds: import("../index.cjs").CropBox | null;
|
|
29
|
+
percent: number;
|
|
30
|
+
id: string;
|
|
31
|
+
name: string;
|
|
32
|
+
/** Overlay tint, `#rrggbb` (default red, the Quick Mask's). */
|
|
33
|
+
color: string;
|
|
34
|
+
/** Overlay opacity 0..1 (default 0.5). */
|
|
35
|
+
opacity: number;
|
|
36
|
+
/** Whether the tint covers the `masked` (unselected, default) or the `selected` area. */
|
|
37
|
+
indicates: "masked" | "selected";
|
|
38
|
+
/** Shown as an overlay on the canvas (default false). */
|
|
39
|
+
visible: boolean;
|
|
40
|
+
};
|
|
41
|
+
export declare function serializeChannels(channels: readonly AlphaChannel[]): SerializedAlphaChannel[];
|
|
42
|
+
/** Restores stored channels, skipping (and reporting) damaged ones or ones of another size. */
|
|
43
|
+
export declare function deserializeChannels(value: unknown, size: {
|
|
44
|
+
width: number;
|
|
45
|
+
height: number;
|
|
46
|
+
}, problems?: string[]): AlphaChannel[];
|
|
47
|
+
/** A channel's grey thumbnail (white = selected) as RGBA pixels, at most `maxSide` px. */
|
|
48
|
+
export declare function channelThumbnail(channel: AlphaChannel, maxSide?: number): {
|
|
49
|
+
width: number;
|
|
50
|
+
height: number;
|
|
51
|
+
data: Uint8ClampedArray;
|
|
52
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type SelectionMask, type SerializedSelection } from './mask.js';
|
|
2
|
+
/**
|
|
3
|
+
* An alpha channel: a saved selection kept with the document (Select › Save Selection), shown
|
|
4
|
+
* as a tinted overlay when visible. Its mask is the selection's 8-bit coverage over the canvas
|
|
5
|
+
* (immutable, so undo steps share it).
|
|
6
|
+
*/
|
|
7
|
+
export interface AlphaChannel {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
/** Coverage (255 = selected). An empty channel has a mask with `bounds: null`. */
|
|
11
|
+
mask: SelectionMask;
|
|
12
|
+
/** Overlay tint, `#rrggbb` (default red, the Quick Mask's). */
|
|
13
|
+
color: string;
|
|
14
|
+
/** Overlay opacity 0..1 (default 0.5). */
|
|
15
|
+
opacity: number;
|
|
16
|
+
/** Whether the tint covers the `masked` (unselected, default) or the `selected` area. */
|
|
17
|
+
indicates: 'masked' | 'selected';
|
|
18
|
+
/** Shown as an overlay on the canvas (default false). */
|
|
19
|
+
visible: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** An alpha channel as stored in a document. */
|
|
22
|
+
export interface SerializedAlphaChannel extends Omit<AlphaChannel, 'mask'> {
|
|
23
|
+
mask: SerializedSelection;
|
|
24
|
+
}
|
|
25
|
+
export declare const DEFAULT_CHANNEL_COLOR = "#ff0000";
|
|
26
|
+
/** A summary of a channel for agents and panels (no pixels). */
|
|
27
|
+
export declare function describeChannel(channel: AlphaChannel): {
|
|
28
|
+
bounds: import("../index.js").CropBox | null;
|
|
29
|
+
percent: number;
|
|
30
|
+
id: string;
|
|
31
|
+
name: string;
|
|
32
|
+
/** Overlay tint, `#rrggbb` (default red, the Quick Mask's). */
|
|
33
|
+
color: string;
|
|
34
|
+
/** Overlay opacity 0..1 (default 0.5). */
|
|
35
|
+
opacity: number;
|
|
36
|
+
/** Whether the tint covers the `masked` (unselected, default) or the `selected` area. */
|
|
37
|
+
indicates: "masked" | "selected";
|
|
38
|
+
/** Shown as an overlay on the canvas (default false). */
|
|
39
|
+
visible: boolean;
|
|
40
|
+
};
|
|
41
|
+
export declare function serializeChannels(channels: readonly AlphaChannel[]): SerializedAlphaChannel[];
|
|
42
|
+
/** Restores stored channels, skipping (and reporting) damaged ones or ones of another size. */
|
|
43
|
+
export declare function deserializeChannels(value: unknown, size: {
|
|
44
|
+
width: number;
|
|
45
|
+
height: number;
|
|
46
|
+
}, problems?: string[]): AlphaChannel[];
|
|
47
|
+
/** A channel's grey thumbnail (white = selected) as RGBA pixels, at most `maxSide` px. */
|
|
48
|
+
export declare function channelThumbnail(channel: AlphaChannel, maxSide?: number): {
|
|
49
|
+
width: number;
|
|
50
|
+
height: number;
|
|
51
|
+
data: Uint8ClampedArray;
|
|
52
|
+
};
|
|
@@ -76,3 +76,10 @@ export declare function handleSelectionShortcut(controller: ImageEditorControlle
|
|
|
76
76
|
shiftKey?: boolean;
|
|
77
77
|
altKey?: boolean;
|
|
78
78
|
}, onError?: (message: string) => void): boolean;
|
|
79
|
+
/** Q (no modifiers) toggles Quick Mask mode. Returns true when the key was used. */
|
|
80
|
+
export declare function handleQuickMaskKey(controller: ImageEditorController, e: {
|
|
81
|
+
key: string;
|
|
82
|
+
ctrlKey?: boolean;
|
|
83
|
+
metaKey?: boolean;
|
|
84
|
+
altKey?: boolean;
|
|
85
|
+
}): boolean;
|
|
@@ -76,3 +76,10 @@ export declare function handleSelectionShortcut(controller: ImageEditorControlle
|
|
|
76
76
|
shiftKey?: boolean;
|
|
77
77
|
altKey?: boolean;
|
|
78
78
|
}, onError?: (message: string) => void): boolean;
|
|
79
|
+
/** Q (no modifiers) toggles Quick Mask mode. Returns true when the key was used. */
|
|
80
|
+
export declare function handleQuickMaskKey(controller: ImageEditorController, e: {
|
|
81
|
+
key: string;
|
|
82
|
+
ctrlKey?: boolean;
|
|
83
|
+
metaKey?: boolean;
|
|
84
|
+
altKey?: boolean;
|
|
85
|
+
}): boolean;
|
|
@@ -10,6 +10,8 @@ export interface QuickMaskStyle {
|
|
|
10
10
|
color?: readonly [number, number, number];
|
|
11
11
|
/** 0..1 (default 0.5): opacity over fully unselected pixels. */
|
|
12
12
|
opacity?: number;
|
|
13
|
+
/** Tint the unselected area (`masked`, default) or the selected area (`selected`). */
|
|
14
|
+
indicates?: 'masked' | 'selected';
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* Quick Mask view: RGBA pixels (natural image size) tinting the *unselected* area, so the
|
|
@@ -10,6 +10,8 @@ export interface QuickMaskStyle {
|
|
|
10
10
|
color?: readonly [number, number, number];
|
|
11
11
|
/** 0..1 (default 0.5): opacity over fully unselected pixels. */
|
|
12
12
|
opacity?: number;
|
|
13
|
+
/** Tint the unselected area (`masked`, default) or the selected area (`selected`). */
|
|
14
|
+
indicates?: 'masked' | 'selected';
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* Quick Mask view: RGBA pixels (natural image size) tinting the *unselected* area, so the
|
|
@@ -27,7 +27,9 @@ export interface ImageEditorToolProviderOptions {
|
|
|
27
27
|
* `select_rect`, `select_ellipse`, `select_polygon`, `select_line`, `magic_wand`,
|
|
28
28
|
* `select_color_range`, `grow_selection`, `select_similar`, `reselect`,
|
|
29
29
|
* `select_layer_transparency`, `stroke_selection`, `crop_to_selection`, `content_aware_fill`,
|
|
30
|
-
* `copy_pixels`, `cut_pixels`, `paste_pixels`,
|
|
30
|
+
* `copy_pixels`, `cut_pixels`, `paste_pixels`, alpha channels (`list_channels`, `save_selection`,
|
|
31
|
+
* `load_selection_from_channel`, `set_channel_properties`, `duplicate_channel`,
|
|
32
|
+
* `delete_channel`), `set_quick_mask`,
|
|
31
33
|
* `load_selection_from_image`, `load_selection_from_mask`, `set_selection_display`,
|
|
32
34
|
* `modify_selection`, `refine_selection`, `apply_selection_as_mask` and the deprecated
|
|
33
35
|
* `select_region` / `select_by_color` (see `createImageSelectionTools`).
|
|
@@ -27,7 +27,9 @@ export interface ImageEditorToolProviderOptions {
|
|
|
27
27
|
* `select_rect`, `select_ellipse`, `select_polygon`, `select_line`, `magic_wand`,
|
|
28
28
|
* `select_color_range`, `grow_selection`, `select_similar`, `reselect`,
|
|
29
29
|
* `select_layer_transparency`, `stroke_selection`, `crop_to_selection`, `content_aware_fill`,
|
|
30
|
-
* `copy_pixels`, `cut_pixels`, `paste_pixels`,
|
|
30
|
+
* `copy_pixels`, `cut_pixels`, `paste_pixels`, alpha channels (`list_channels`, `save_selection`,
|
|
31
|
+
* `load_selection_from_channel`, `set_channel_properties`, `duplicate_channel`,
|
|
32
|
+
* `delete_channel`), `set_quick_mask`,
|
|
31
33
|
* `load_selection_from_image`, `load_selection_from_mask`, `set_selection_display`,
|
|
32
34
|
* `modify_selection`, `refine_selection`, `apply_selection_as_mask` and the deprecated
|
|
33
35
|
* `select_region` / `select_by_color` (see `createImageSelectionTools`).
|
|
@@ -2,6 +2,7 @@ import type { GlobalLight } from '../raster/effects/model.cjs';
|
|
|
2
2
|
import type { EffectPattern } from '../raster/effects/patterns.cjs';
|
|
3
3
|
import type { BlendMode } from './blend.cjs';
|
|
4
4
|
import type { SelectionMask, SerializedSelection } from './selection/mask.cjs';
|
|
5
|
+
import type { AlphaChannel, SerializedAlphaChannel } from './selection/channels.cjs';
|
|
5
6
|
import type { ImageLayer, LayerTarget } from './layers/model.cjs';
|
|
6
7
|
import type { SerializedLayeredImageEditorState } from './layers/serialize.cjs';
|
|
7
8
|
import type { PaintOptions } from './controller.cjs';
|
|
@@ -313,6 +314,13 @@ export interface ImageEditorState {
|
|
|
313
314
|
quickMask?: boolean;
|
|
314
315
|
/** How the canvas shows the selection (view state; `quickMask` mirrors `'quickMask'`). */
|
|
315
316
|
selectionDisplay?: 'ants' | 'quickMask' | 'none';
|
|
317
|
+
/**
|
|
318
|
+
* Quick Mask mode: painting and fills without a layer edit the selection itself (white
|
|
319
|
+
* selects, black deselects), shown as a tint. View state; the edits are undo steps.
|
|
320
|
+
*/
|
|
321
|
+
quickMaskEditing?: boolean;
|
|
322
|
+
/** Alpha channels: saved selections kept with the document, recorded in undo history. */
|
|
323
|
+
channels?: AlphaChannel[];
|
|
316
324
|
/**
|
|
317
325
|
* The layer stack, bottom to top. Opening an image gives one pixel layer, "Background", whose
|
|
318
326
|
* pixels are the source image. Layers are immutable: compare them by identity.
|
|
@@ -380,6 +388,8 @@ export interface LegacySerializedImageEditorState {
|
|
|
380
388
|
annotations: Annotation[];
|
|
381
389
|
/** The active selection, run-length encoded. Missing when nothing is selected. */
|
|
382
390
|
selection?: SerializedSelection;
|
|
391
|
+
/** Alpha channels (saved selections), run-length encoded. */
|
|
392
|
+
channels?: SerializedAlphaChannel[];
|
|
383
393
|
}
|
|
384
394
|
/**
|
|
385
395
|
* A stored editor state: the document-level schema (v1 / v2) or the layered schema (v3, see
|
|
@@ -2,6 +2,7 @@ import type { GlobalLight } from '../raster/effects/model.js';
|
|
|
2
2
|
import type { EffectPattern } from '../raster/effects/patterns.js';
|
|
3
3
|
import type { BlendMode } from './blend.js';
|
|
4
4
|
import type { SelectionMask, SerializedSelection } from './selection/mask.js';
|
|
5
|
+
import type { AlphaChannel, SerializedAlphaChannel } from './selection/channels.js';
|
|
5
6
|
import type { ImageLayer, LayerTarget } from './layers/model.js';
|
|
6
7
|
import type { SerializedLayeredImageEditorState } from './layers/serialize.js';
|
|
7
8
|
import type { PaintOptions } from './controller.js';
|
|
@@ -313,6 +314,13 @@ export interface ImageEditorState {
|
|
|
313
314
|
quickMask?: boolean;
|
|
314
315
|
/** How the canvas shows the selection (view state; `quickMask` mirrors `'quickMask'`). */
|
|
315
316
|
selectionDisplay?: 'ants' | 'quickMask' | 'none';
|
|
317
|
+
/**
|
|
318
|
+
* Quick Mask mode: painting and fills without a layer edit the selection itself (white
|
|
319
|
+
* selects, black deselects), shown as a tint. View state; the edits are undo steps.
|
|
320
|
+
*/
|
|
321
|
+
quickMaskEditing?: boolean;
|
|
322
|
+
/** Alpha channels: saved selections kept with the document, recorded in undo history. */
|
|
323
|
+
channels?: AlphaChannel[];
|
|
316
324
|
/**
|
|
317
325
|
* The layer stack, bottom to top. Opening an image gives one pixel layer, "Background", whose
|
|
318
326
|
* pixels are the source image. Layers are immutable: compare them by identity.
|
|
@@ -380,6 +388,8 @@ export interface LegacySerializedImageEditorState {
|
|
|
380
388
|
annotations: Annotation[];
|
|
381
389
|
/** The active selection, run-length encoded. Missing when nothing is selected. */
|
|
382
390
|
selection?: SerializedSelection;
|
|
391
|
+
/** Alpha channels (saved selections), run-length encoded. */
|
|
392
|
+
channels?: SerializedAlphaChannel[];
|
|
383
393
|
}
|
|
384
394
|
/**
|
|
385
395
|
* A stored editor state: the document-level schema (v1 / v2) or the layered schema (v3, see
|
|
@@ -7,7 +7,7 @@ var _chunkZ64NRDEHcjs = require('../chunk-Z64NRDEH.cjs');
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _chunkX2KQQZBTcjs = require('../chunk-X2KQQZBT.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 } = _chunkX2KQQZBTcjs.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 _chunkX2KQQZBTcjs.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(_chunkX2KQQZBTcjs.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 _chunkX2KQQZBTcjs.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 = _chunkX2KQQZBTcjs.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
|
@@ -241,6 +241,7 @@ in the source frame at the document's bit depth, colour mode and profile. Read
|
|
|
241
241
|
| `get_adjustments` | Read the current state: `values` by control id, `process` version (1 or 2), and `layers` bottom to top with id, kind, params, opacity, blend, enabled and mask. Call first, and to find layer ids. |
|
|
242
242
|
| `list_controls` | Get every base control (id, label, section, min, max, step, default, `requiresProcess`), each layer kind's settable controls (plus `opacity`), the blend mode ids and the `layers.<layerId>.<controlId>` path format. Call once per session before writing. |
|
|
243
243
|
| `get_selection` | Read the active selection: `empty`, `bounds` (natural pixels), `area` in pixels, `percent` of the image and a description. Check it after every select or modify step and before masking: a wand that covered 90% of the image is the wrong selection. |
|
|
244
|
+
| `list_channels` | Read the alpha channels (saved selections): id, name, bounds, percent, overlay and visibility, and whether Quick Mask mode is on. |
|
|
244
245
|
| `select_subject` | Select › Subject (only when the host has a segmentation model): `target` describes what to select ("the dog", "the sky"); an AI model finds the matching objects and selects their outlines, combined by `mode`. `maxSegments` 1 for a single subject. Returns the selection and `found` (label, bounds per object); nothing found leaves the selection unchanged. |
|
|
245
246
|
| `list_layers` | Read the layer stack bottom to top as a tree: id, type (`pixel`, `adjustment`, `group`, `shape`, `annotation`, `smart`; smart objects add their `contents`, `smartFilters` and `filterMask`; shapes a `shape` summary of component ops and kinds and paint types, and `annotation` when migrated from one), name, document `bounds` of pixel layers, visibility, opacity, `fillOpacity`, blend, `clipped`, locks, a `mask` summary, an `effects` summary (master switch, scale, effect ids and kinds), pixel-layer `filters` (the Background's `develop` filter is the base adjustments), adjustment `kind` and `params`, group `children`, and which layer is `active`. Call it to understand a document with more than the Background before changing it; adjustment layer ids work with every adjustment-layer tool. |
|
|
246
247
|
| `list_layer_effects` | Read one layer's effects: `enabled` (master switch), `scale` (Scale Effects), `margin` (px they reach beyond the shape), `fromPsd`, and every effect with `id`, `kind`, `label` and all its settings. Also returns the `globalLight`, the `patterns` pattern effects can use and the effect `kinds`. Call before changing effects you did not add. |
|
|
@@ -395,6 +396,12 @@ in the source frame at the document's bit depth, colour mode and profile. Read
|
|
|
395
396
|
| `copy_pixels` | Copy the selected pixels of a layer (or with `merged` the visible image) to the editor clipboard, cropped to the selection with its soft edge. No undo step. Returns `width`, `height`, `x`, `y`. |
|
|
396
397
|
| `cut_pixels` | Copy, then clear the selected pixels (one undo step). Returns the size and position. |
|
|
397
398
|
| `paste_pixels` | Paste the clipboard as a new layer: `mode` `new-layer` (centred on the selection or canvas), `in-place`, `into` (masked by the selection) or `outside` (masked by its inverse). One undo step. Returns `layerId`, `bounds`, `masked`. |
|
|
399
|
+
| `save_selection` | Save the selection to a new alpha channel (`name`), or into `channelId` by `mode`. Saved with the document and in PSD. Returns the `channel`. |
|
|
400
|
+
| `load_selection_from_channel` | Load an alpha channel as the selection (`channelId`, `invert`, `mode`). Returns the summary. |
|
|
401
|
+
| `set_channel_properties` | Rename a channel or change its overlay `color`, `opacity`, `indicates` (`masked` / `selected`) and `visible`. Returns the `channel`. |
|
|
402
|
+
| `duplicate_channel` | Copy a channel (`name`, default "<name> copy"). Returns the copy. |
|
|
403
|
+
| `delete_channel` | Delete a channel (undoable). Returns the remaining channels. |
|
|
404
|
+
| `set_quick_mask` | Quick Mask mode (`enabled`): paint, fill and retouch tools without `layerId` edit the selection (white selects, black deselects); turn it off before painting layers. Returns the mode. |
|
|
398
405
|
|
|
399
406
|
### Save and open
|
|
400
407
|
|
|
@@ -53,6 +53,9 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
|
|
|
53
53
|
- `grow_selection` (tolerance 10–30) picks up the shades a wand click missed;
|
|
54
54
|
`select_similar` adds the same colours elsewhere in the image.
|
|
55
55
|
- `contract` 1–2 px pulls the edge off a halo.
|
|
56
|
+
- Paint it directly: `set_quick_mask` `enabled: true`, then `paint_stroke` without
|
|
57
|
+
`layerId` (white adds, black removes, a soft brush feathers; `blur_stroke` softens a part
|
|
58
|
+
of the edge), then `set_quick_mask` `enabled: false`.
|
|
56
59
|
- `refine_selection` snaps to real edges: radius 2–4 for hard edges, 8–20 for hair and fur;
|
|
57
60
|
`smartRadius: true` for mixed edges.
|
|
58
61
|
- `shiftEdge` −10..−30 % tightens a refined edge that picked up background.
|
|
@@ -70,7 +73,10 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
|
|
|
70
73
|
- A copy elsewhere: `copy_pixels`, then `paste_pixels` (`into` masks it by a selection).
|
|
71
74
|
Soften with the mask's own `feather` / `density` rather than `modify_selection` `feather`, so
|
|
72
75
|
it stays adjustable.
|
|
73
|
-
6. **
|
|
76
|
+
6. **Store.** `save_selection` with a clear name before you change a selection that took
|
|
77
|
+
work, and whenever it will be needed again (a second adjustment, a later refinement). Load
|
|
78
|
+
it with `load_selection_from_channel`; channels are saved with the document and in PSDs.
|
|
79
|
+
7. **Verify.** `render_preview` at 1024 px or more, and `capture_view` on the edge at 2–8×.
|
|
74
80
|
**Check:** no fringe of the old background colour, no stair-steps, no visible line where an
|
|
75
81
|
adjustment ends. Fix by loading the mask back (`load_selection_from_mask`), refining, and
|
|
76
82
|
masking again.
|
|
@@ -151,6 +157,8 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
|
|
|
151
157
|
- **A forgotten selection limits new layers and filters:** `add_adjustment_layer`,
|
|
152
158
|
`apply_effect` and `add_smart_filter` mask themselves by it. `deselect` first for a global
|
|
153
159
|
change, or pass `useSelection: false`.
|
|
160
|
+
- **Quick Mask left on:** while it is on, `paint_stroke` and `fill_pixels` without `layerId`
|
|
161
|
+
edit the selection, not the image. Turn it off when the selection is done.
|
|
154
162
|
- **Hidden selection still applies:** with `set_selection_display` `none`, paint and fills are
|
|
155
163
|
still limited to it. `deselect` before a whole-layer edit.
|
|
156
164
|
- **Wrong coordinates:** use natural image pixels, not preview pixels. On a cropped or rotated
|
|
@@ -168,6 +176,10 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
|
|
|
168
176
|
- `select_layer_transparency`: a layer's own pixels
|
|
169
177
|
- `grow_selection`, `select_similar`: add similar colour, connected or anywhere
|
|
170
178
|
- `reselect`: undo a deselect
|
|
179
|
+
- `save_selection`, `load_selection_from_channel`, `list_channels`: keep selections as alpha channels
|
|
180
|
+
- `set_channel_properties`, `duplicate_channel`, `delete_channel`: manage channels
|
|
181
|
+
- `set_quick_mask`: paint the selection
|
|
182
|
+
- `fill_pixels`, `blur_stroke`: fill or soften the selection in Quick Mask mode
|
|
171
183
|
- `magic_wand`: similar colour from a seed
|
|
172
184
|
- `select_color_range`: colour samples, hue, tone and skin presets
|
|
173
185
|
- `select_subject`: a subject by description (needs a host model)
|