@pixerate/editor 0.197.0 → 0.199.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.
@@ -30,6 +30,8 @@ export declare function snapTo45(from: ImagePoint, point: ImagePoint): ImagePoin
30
30
  * - Quick Selection: drag (or click) a brush stroke; on `end` it grows into the region painted on,
31
31
  * out to its edges (async: await {@link settled}). With the New mode and a selection already
32
32
  * there, strokes add, as in Photoshop; Alt subtracts.
33
+ * - Object Selection: drag a box around an object, or click on it; on `end` the object is
34
+ * selected (async: await {@link settled}).
33
35
  * - Single row / column: a click selects a 1 px line across the image.
34
36
  *
35
37
  * Shift adds, Alt subtracts, both intersect (overriding the options bar mode). While dragging,
@@ -54,7 +56,7 @@ export declare class SelectionGesture {
54
56
  private pending;
55
57
  constructor(controller: ImageEditorController, getOptions: () => SelectionToolOptions);
56
58
  get active(): boolean;
57
- /** Resolves once a Quick Selection stroke has been applied. */
59
+ /** Resolves once a Quick Selection stroke or an Object Selection has been applied. */
58
60
  get settled(): Promise<void>;
59
61
  /** The anchors of a Magnetic Lasso being drawn (empty otherwise). */
60
62
  get magneticAnchors(): ImagePoint[];
@@ -30,6 +30,8 @@ export declare function snapTo45(from: ImagePoint, point: ImagePoint): ImagePoin
30
30
  * - Quick Selection: drag (or click) a brush stroke; on `end` it grows into the region painted on,
31
31
  * out to its edges (async: await {@link settled}). With the New mode and a selection already
32
32
  * there, strokes add, as in Photoshop; Alt subtracts.
33
+ * - Object Selection: drag a box around an object, or click on it; on `end` the object is
34
+ * selected (async: await {@link settled}).
33
35
  * - Single row / column: a click selects a 1 px line across the image.
34
36
  *
35
37
  * Shift adds, Alt subtracts, both intersect (overriding the options bar mode). While dragging,
@@ -54,7 +56,7 @@ export declare class SelectionGesture {
54
56
  private pending;
55
57
  constructor(controller: ImageEditorController, getOptions: () => SelectionToolOptions);
56
58
  get active(): boolean;
57
- /** Resolves once a Quick Selection stroke has been applied. */
59
+ /** Resolves once a Quick Selection stroke or an Object Selection has been applied. */
58
60
  get settled(): Promise<void>;
59
61
  /** The anchors of a Magnetic Lasso being drawn (empty otherwise). */
60
62
  get magneticAnchors(): ImagePoint[];
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Object Selection: GrabCut (Rother, Kolmogorov & Blake, 2004) from a box drawn around an object
3
+ * or a click on it. Two colour models, mixtures of five Gaussians each, are fitted to what is
4
+ * currently inside and outside the object; a graph cut relabels every pixel by them and by the
5
+ * edges between neighbours; the two steps repeat until the labels settle. It runs on the reduced
6
+ * copy of the image and is scaled back up with an anti-aliased edge, as Quick Selection is.
7
+ */
8
+ import type { CropBox, ImagePoint } from '../../types.cjs';
9
+ import { type PixelBuffer, type SelectionMask } from '../mask.cjs';
10
+ import { type Rect, type WorkImage } from './work.cjs';
11
+ /** A mixture of {@link K} full-covariance Gaussians over RGB. */
12
+ export declare class ColorGmm {
13
+ private readonly logWeight;
14
+ private readonly mean;
15
+ /** Inverse covariances, row-major 3 × 3. */
16
+ private readonly inv;
17
+ /** ln(weight) − ½ ln((2π)³ |Σ|) per component; −∞ for an empty one. */
18
+ private readonly logNorm;
19
+ /** Fits the components to the pixels `ids` of `rgb`, each in component `comp[id]`. */
20
+ fit(rgb: Float32Array, ids: ArrayLike<number>, comp: Uint8Array): void;
21
+ /** ln p(colour | component k), up to the shared constant. */
22
+ private componentLog;
23
+ /** −ln p(colour) under the mixture (large for colours the model hasn't seen). */
24
+ cost(r: number, g: number, b: number): number;
25
+ /** The component most likely to have produced the colour. */
26
+ nearest(r: number, g: number, b: number): number;
27
+ }
28
+ /** Pixels fixed to one side, and a starting guess, over a window of the work image. */
29
+ export interface GrabCutSetup {
30
+ roi: Rect;
31
+ /** Per window pixel: 1 = starts inside the object. */
32
+ initial: Uint8Array;
33
+ /** Per window pixel: 1 = fixed outside. */
34
+ hardBg: Uint8Array;
35
+ /** Per window pixel: 1 = fixed inside. */
36
+ hardFg: Uint8Array | null;
37
+ }
38
+ /** GrabCut over the setup's window; returns 1 for the object per window pixel. */
39
+ export declare function grabCutLabels(work: WorkImage, setup: GrabCutSetup, iterations: number): Uint8Array;
40
+ /**
41
+ * Keeps the object's main parts: the pieces (4-connected) holding `seed` (window index), or
42
+ * without one, every piece at least a fifth the size of the largest.
43
+ */
44
+ export declare function keepMainPieces(label: Uint8Array, rw: number, rh: number, seed: number | null): void;
45
+ export interface ObjectSelectionOptions {
46
+ /** Smoother, less blocky edges (Auto-Enhance). Default false. */
47
+ enhanceEdge?: boolean;
48
+ /** Most rounds of fitting and cutting (default 5; it stops early once the labels settle). */
49
+ iterations?: number;
50
+ }
51
+ /** What to select: a box around the object, or a point on it (natural pixels). */
52
+ export type ObjectTarget = {
53
+ rect: CropBox;
54
+ } | {
55
+ point: ImagePoint;
56
+ };
57
+ /**
58
+ * Object Selection over `pixels`: the object in `target.rect` (everything outside the box is
59
+ * background), or the object under `target.point` (searched for in a window around it that grows
60
+ * while the object reaches its border). Returns a selection of the whole image, empty when
61
+ * nothing stands out.
62
+ */
63
+ export declare function selectObjectIn(pixels: PixelBuffer, target: ObjectTarget, options?: ObjectSelectionOptions): SelectionMask;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Object Selection: GrabCut (Rother, Kolmogorov & Blake, 2004) from a box drawn around an object
3
+ * or a click on it. Two colour models, mixtures of five Gaussians each, are fitted to what is
4
+ * currently inside and outside the object; a graph cut relabels every pixel by them and by the
5
+ * edges between neighbours; the two steps repeat until the labels settle. It runs on the reduced
6
+ * copy of the image and is scaled back up with an anti-aliased edge, as Quick Selection is.
7
+ */
8
+ import type { CropBox, ImagePoint } from '../../types.js';
9
+ import { type PixelBuffer, type SelectionMask } from '../mask.js';
10
+ import { type Rect, type WorkImage } from './work.js';
11
+ /** A mixture of {@link K} full-covariance Gaussians over RGB. */
12
+ export declare class ColorGmm {
13
+ private readonly logWeight;
14
+ private readonly mean;
15
+ /** Inverse covariances, row-major 3 × 3. */
16
+ private readonly inv;
17
+ /** ln(weight) − ½ ln((2π)³ |Σ|) per component; −∞ for an empty one. */
18
+ private readonly logNorm;
19
+ /** Fits the components to the pixels `ids` of `rgb`, each in component `comp[id]`. */
20
+ fit(rgb: Float32Array, ids: ArrayLike<number>, comp: Uint8Array): void;
21
+ /** ln p(colour | component k), up to the shared constant. */
22
+ private componentLog;
23
+ /** −ln p(colour) under the mixture (large for colours the model hasn't seen). */
24
+ cost(r: number, g: number, b: number): number;
25
+ /** The component most likely to have produced the colour. */
26
+ nearest(r: number, g: number, b: number): number;
27
+ }
28
+ /** Pixels fixed to one side, and a starting guess, over a window of the work image. */
29
+ export interface GrabCutSetup {
30
+ roi: Rect;
31
+ /** Per window pixel: 1 = starts inside the object. */
32
+ initial: Uint8Array;
33
+ /** Per window pixel: 1 = fixed outside. */
34
+ hardBg: Uint8Array;
35
+ /** Per window pixel: 1 = fixed inside. */
36
+ hardFg: Uint8Array | null;
37
+ }
38
+ /** GrabCut over the setup's window; returns 1 for the object per window pixel. */
39
+ export declare function grabCutLabels(work: WorkImage, setup: GrabCutSetup, iterations: number): Uint8Array;
40
+ /**
41
+ * Keeps the object's main parts: the pieces (4-connected) holding `seed` (window index), or
42
+ * without one, every piece at least a fifth the size of the largest.
43
+ */
44
+ export declare function keepMainPieces(label: Uint8Array, rw: number, rh: number, seed: number | null): void;
45
+ export interface ObjectSelectionOptions {
46
+ /** Smoother, less blocky edges (Auto-Enhance). Default false. */
47
+ enhanceEdge?: boolean;
48
+ /** Most rounds of fitting and cutting (default 5; it stops early once the labels settle). */
49
+ iterations?: number;
50
+ }
51
+ /** What to select: a box around the object, or a point on it (natural pixels). */
52
+ export type ObjectTarget = {
53
+ rect: CropBox;
54
+ } | {
55
+ point: ImagePoint;
56
+ };
57
+ /**
58
+ * Object Selection over `pixels`: the object in `target.rect` (everything outside the box is
59
+ * background), or the object under `target.point` (searched for in a window around it that grows
60
+ * while the object reaches its border). Returns a selection of the whole image, empty when
61
+ * nothing stands out.
62
+ */
63
+ export declare function selectObjectIn(pixels: PixelBuffer, target: ObjectTarget, options?: ObjectSelectionOptions): SelectionMask;
@@ -1,2 +1,5 @@
1
1
  export * from './maxflow.cjs';
2
+ export * from './work.cjs';
2
3
  export * from './quick.cjs';
4
+ export * from './grabcut.cjs';
5
+ export * from './subject.cjs';
@@ -1,2 +1,5 @@
1
1
  export * from './maxflow.js';
2
+ export * from './work.js';
2
3
  export * from './quick.js';
4
+ export * from './grabcut.js';
5
+ export * from './subject.js';
@@ -9,25 +9,6 @@
9
9
  */
10
10
  import type { ImagePoint } from '../../types.cjs';
11
11
  import { type PixelBuffer, type SelectionMask } from '../mask.cjs';
12
- /** The reduced image the segmentations work on (sRGB, 0..255 per channel). */
13
- export interface WorkImage {
14
- /** Natural size of the image it was made from. */
15
- sourceWidth: number;
16
- sourceHeight: number;
17
- width: number;
18
- height: number;
19
- /** Reduced pixels per natural pixel (≤ 1). */
20
- scale: number;
21
- /** RGB, 3 values per pixel. */
22
- rgb: Float32Array;
23
- }
24
- /** Long side of the work image (the issue's 512²). */
25
- export declare const WORK_SIZE = 512;
26
- /**
27
- * `pixels` reduced to at most {@link WORK_SIZE} px on the long side by area averaging (alpha
28
- * composited over white). Cached per pixel buffer.
29
- */
30
- export declare function workImage(pixels: PixelBuffer, maxSide?: number): WorkImage;
31
12
  export interface QuickSelectOptions {
32
13
  /** Brush diameter in natural pixels (default 30). */
33
14
  size?: number;
@@ -9,25 +9,6 @@
9
9
  */
10
10
  import type { ImagePoint } from '../../types.js';
11
11
  import { type PixelBuffer, type SelectionMask } from '../mask.js';
12
- /** The reduced image the segmentations work on (sRGB, 0..255 per channel). */
13
- export interface WorkImage {
14
- /** Natural size of the image it was made from. */
15
- sourceWidth: number;
16
- sourceHeight: number;
17
- width: number;
18
- height: number;
19
- /** Reduced pixels per natural pixel (≤ 1). */
20
- scale: number;
21
- /** RGB, 3 values per pixel. */
22
- rgb: Float32Array;
23
- }
24
- /** Long side of the work image (the issue's 512²). */
25
- export declare const WORK_SIZE = 512;
26
- /**
27
- * `pixels` reduced to at most {@link WORK_SIZE} px on the long side by area averaging (alpha
28
- * composited over white). Cached per pixel buffer.
29
- */
30
- export declare function workImage(pixels: PixelBuffer, maxSide?: number): WorkImage;
31
12
  export interface QuickSelectOptions {
32
13
  /** Brush diameter in natural pixels (default 30). */
33
14
  size?: number;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Select Subject without a segmentation model: the most salient subject, found classically.
3
+ *
4
+ * 1. SLIC superpixels (Achanta et al., 2012) group the reduced image into a few hundred patches of
5
+ * similar colour.
6
+ * 2. Each patch's saliency is how unlike the image's border it is (the border is mostly
7
+ * background), times how much it contrasts with the patches around it (region contrast, Cheng
8
+ * et al., 2015), times a mild preference for the centre.
9
+ * 3. Otsu's threshold splits the patches into a first guess at the subject.
10
+ * 4. GrabCut refines that guess along the image's edges, with the clearly-background border fixed.
11
+ *
12
+ * It cannot tell which object a description names: it selects what stands out.
13
+ */
14
+ import type { PixelBuffer, SelectionMask } from '../mask.cjs';
15
+ import { type WorkImage } from './work.cjs';
16
+ export interface Superpixels {
17
+ /** Superpixel of each work pixel. */
18
+ label: Int32Array;
19
+ count: number;
20
+ /** Mean L*a*b* per superpixel, 3 values each. */
21
+ lab: Float64Array;
22
+ /** Mean position per superpixel, in work pixels, 2 values each. */
23
+ centre: Float64Array;
24
+ size: Int32Array;
25
+ }
26
+ /** SLIC superpixels of the work image: about `target` of them, `compactness` 10 (L*a*b* units). */
27
+ export declare function slicSuperpixels(work: WorkImage, target?: number, compactness?: number, rounds?: number): Superpixels;
28
+ /** Saliency 0..1 of each superpixel (see the module comment). */
29
+ export declare function superpixelSaliency(sp: Superpixels, width: number, height: number): Float64Array;
30
+ /** Otsu's threshold of `values` (0..1) weighted by `weights`. */
31
+ export declare function otsuThreshold(values: ArrayLike<number>, weights: ArrayLike<number>): number;
32
+ /** What {@link findSubject} found. */
33
+ export interface FoundSubject {
34
+ selection: SelectionMask;
35
+ /** Why nothing was selected, when nothing was. */
36
+ reason?: string;
37
+ }
38
+ /**
39
+ * The most salient subject of `pixels` as a selection of the whole image (empty, with a reason,
40
+ * when nothing stands out from the background).
41
+ */
42
+ export declare function findSubject(pixels: PixelBuffer, options?: {
43
+ enhanceEdge?: boolean;
44
+ }): FoundSubject;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Select Subject without a segmentation model: the most salient subject, found classically.
3
+ *
4
+ * 1. SLIC superpixels (Achanta et al., 2012) group the reduced image into a few hundred patches of
5
+ * similar colour.
6
+ * 2. Each patch's saliency is how unlike the image's border it is (the border is mostly
7
+ * background), times how much it contrasts with the patches around it (region contrast, Cheng
8
+ * et al., 2015), times a mild preference for the centre.
9
+ * 3. Otsu's threshold splits the patches into a first guess at the subject.
10
+ * 4. GrabCut refines that guess along the image's edges, with the clearly-background border fixed.
11
+ *
12
+ * It cannot tell which object a description names: it selects what stands out.
13
+ */
14
+ import type { PixelBuffer, SelectionMask } from '../mask.js';
15
+ import { type WorkImage } from './work.js';
16
+ export interface Superpixels {
17
+ /** Superpixel of each work pixel. */
18
+ label: Int32Array;
19
+ count: number;
20
+ /** Mean L*a*b* per superpixel, 3 values each. */
21
+ lab: Float64Array;
22
+ /** Mean position per superpixel, in work pixels, 2 values each. */
23
+ centre: Float64Array;
24
+ size: Int32Array;
25
+ }
26
+ /** SLIC superpixels of the work image: about `target` of them, `compactness` 10 (L*a*b* units). */
27
+ export declare function slicSuperpixels(work: WorkImage, target?: number, compactness?: number, rounds?: number): Superpixels;
28
+ /** Saliency 0..1 of each superpixel (see the module comment). */
29
+ export declare function superpixelSaliency(sp: Superpixels, width: number, height: number): Float64Array;
30
+ /** Otsu's threshold of `values` (0..1) weighted by `weights`. */
31
+ export declare function otsuThreshold(values: ArrayLike<number>, weights: ArrayLike<number>): number;
32
+ /** What {@link findSubject} found. */
33
+ export interface FoundSubject {
34
+ selection: SelectionMask;
35
+ /** Why nothing was selected, when nothing was. */
36
+ reason?: string;
37
+ }
38
+ /**
39
+ * The most salient subject of `pixels` as a selection of the whole image (empty, with a reason,
40
+ * when nothing stands out from the background).
41
+ */
42
+ export declare function findSubject(pixels: PixelBuffer, options?: {
43
+ enhanceEdge?: boolean;
44
+ }): FoundSubject;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The reduced copy of the image the graph segmentations (Quick Selection, Object Selection) work
3
+ * on, and scaling their result back up to the image with an anti-aliased edge.
4
+ */
5
+ import { type PixelBuffer, type SelectionMask } from '../mask.cjs';
6
+ /** The reduced image the segmentations work on (sRGB, 0..255 per channel). */
7
+ export interface WorkImage {
8
+ /** Natural size of the image it was made from. */
9
+ sourceWidth: number;
10
+ sourceHeight: number;
11
+ width: number;
12
+ height: number;
13
+ /** Reduced pixels per natural pixel (≤ 1). */
14
+ scale: number;
15
+ /** RGB, 3 values per pixel. */
16
+ rgb: Float32Array;
17
+ }
18
+ /** Long side of the work image (the issue's 512²). */
19
+ export declare const WORK_SIZE = 512;
20
+ /**
21
+ * `pixels` reduced to at most {@link WORK_SIZE} px on the long side by area averaging (alpha
22
+ * composited over white). Cached per pixel buffer.
23
+ */
24
+ export declare function workImage(pixels: PixelBuffer, maxSide?: number): WorkImage;
25
+ /** Edge weight between neighbours: high for similar colours, low across an edge (GrabCut's γ, β). */
26
+ export declare const GAMMA = 50;
27
+ /**
28
+ * Capacities are whole multiples of 1 / UNITS: in floating point, residuals that should reach
29
+ * zero are left a hair above it and max-flow then pushes thousands of near-empty paths.
30
+ */
31
+ export declare const UNITS = 64;
32
+ export interface Rect {
33
+ x: number;
34
+ y: number;
35
+ width: number;
36
+ height: number;
37
+ }
38
+ /**
39
+ * Capacities of the edges between neighbours in `roi` (to the right and below, indexed by the
40
+ * pixel in the window): high between similar colours, low across an edge, GrabCut's
41
+ * γ·exp(−β‖Δc‖²) with β from the window's mean squared difference, in whole {@link UNITS}.
42
+ */
43
+ export declare function smoothnessWeights(work: WorkImage, roi: Rect): {
44
+ right: Float64Array;
45
+ down: Float64Array;
46
+ };
47
+ /** A 3 × 3 box blur of `src` (w × h), `passes` times. */
48
+ export declare function boxBlur(src: Float32Array, w: number, h: number, passes: number): Float32Array;
49
+ /**
50
+ * The region of the work-image `label` over `roi` at natural size: inside and outside as they
51
+ * are, and the pixels along the edge anti-aliased by where their colour lies between the region's
52
+ * colour and the surroundings' just either side.
53
+ */
54
+ export declare function upscaleRegion(work: WorkImage, pixels: PixelBuffer, roi: Rect, label: Uint8Array, enhance: boolean): SelectionMask;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The reduced copy of the image the graph segmentations (Quick Selection, Object Selection) work
3
+ * on, and scaling their result back up to the image with an anti-aliased edge.
4
+ */
5
+ import { type PixelBuffer, type SelectionMask } from '../mask.js';
6
+ /** The reduced image the segmentations work on (sRGB, 0..255 per channel). */
7
+ export interface WorkImage {
8
+ /** Natural size of the image it was made from. */
9
+ sourceWidth: number;
10
+ sourceHeight: number;
11
+ width: number;
12
+ height: number;
13
+ /** Reduced pixels per natural pixel (≤ 1). */
14
+ scale: number;
15
+ /** RGB, 3 values per pixel. */
16
+ rgb: Float32Array;
17
+ }
18
+ /** Long side of the work image (the issue's 512²). */
19
+ export declare const WORK_SIZE = 512;
20
+ /**
21
+ * `pixels` reduced to at most {@link WORK_SIZE} px on the long side by area averaging (alpha
22
+ * composited over white). Cached per pixel buffer.
23
+ */
24
+ export declare function workImage(pixels: PixelBuffer, maxSide?: number): WorkImage;
25
+ /** Edge weight between neighbours: high for similar colours, low across an edge (GrabCut's γ, β). */
26
+ export declare const GAMMA = 50;
27
+ /**
28
+ * Capacities are whole multiples of 1 / UNITS: in floating point, residuals that should reach
29
+ * zero are left a hair above it and max-flow then pushes thousands of near-empty paths.
30
+ */
31
+ export declare const UNITS = 64;
32
+ export interface Rect {
33
+ x: number;
34
+ y: number;
35
+ width: number;
36
+ height: number;
37
+ }
38
+ /**
39
+ * Capacities of the edges between neighbours in `roi` (to the right and below, indexed by the
40
+ * pixel in the window): high between similar colours, low across an edge, GrabCut's
41
+ * γ·exp(−β‖Δc‖²) with β from the window's mean squared difference, in whole {@link UNITS}.
42
+ */
43
+ export declare function smoothnessWeights(work: WorkImage, roi: Rect): {
44
+ right: Float64Array;
45
+ down: Float64Array;
46
+ };
47
+ /** A 3 × 3 box blur of `src` (w × h), `passes` times. */
48
+ export declare function boxBlur(src: Float32Array, w: number, h: number, passes: number): Float32Array;
49
+ /**
50
+ * The region of the work-image `label` over `roi` at natural size: inside and outside as they
51
+ * are, and the pixels along the edge anti-aliased by where their colour lies between the region's
52
+ * colour and the surroundings' just either side.
53
+ */
54
+ export declare function upscaleRegion(work: WorkImage, pixels: PixelBuffer, roi: Rect, label: Uint8Array, enhance: boolean): SelectionMask;
@@ -2,7 +2,7 @@ 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. */
5
- export type SelectionToolKind = 'wand' | 'rect' | 'ellipse' | 'row' | 'column' | 'lasso' | 'polygon' | 'magnetic' | 'quick' | 'range' | 'type' | 'type-vertical';
5
+ export type SelectionToolKind = 'wand' | 'rect' | 'ellipse' | 'row' | 'column' | 'lasso' | 'polygon' | 'magnetic' | 'quick' | 'object' | 'range' | 'type' | 'type-vertical';
6
6
  export declare const SELECTION_TOOLS: readonly {
7
7
  id: SelectionToolKind;
8
8
  label: string;
@@ -43,6 +43,10 @@ export interface SelectionToolOptions {
43
43
  quickSampleAll?: boolean;
44
44
  /** Quick Selection: smoother, less blocky edges (Auto-Enhance; default false). */
45
45
  quickEnhance?: boolean;
46
+ /** Object Selection: read every layer (default true) or only the active pixel layer. */
47
+ objectSampleAll?: boolean;
48
+ /** Object Selection: smoother, less blocky edges (Auto-Enhance; default false). */
49
+ objectEnhance?: boolean;
46
50
  /** Type Mask: the text to select (default "Type"). A click places its first baseline. */
47
51
  typeText?: string;
48
52
  /** Type Mask: font size in px (default 72). */
@@ -2,7 +2,7 @@ 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. */
5
- export type SelectionToolKind = 'wand' | 'rect' | 'ellipse' | 'row' | 'column' | 'lasso' | 'polygon' | 'magnetic' | 'quick' | 'range' | 'type' | 'type-vertical';
5
+ export type SelectionToolKind = 'wand' | 'rect' | 'ellipse' | 'row' | 'column' | 'lasso' | 'polygon' | 'magnetic' | 'quick' | 'object' | 'range' | 'type' | 'type-vertical';
6
6
  export declare const SELECTION_TOOLS: readonly {
7
7
  id: SelectionToolKind;
8
8
  label: string;
@@ -43,6 +43,10 @@ export interface SelectionToolOptions {
43
43
  quickSampleAll?: boolean;
44
44
  /** Quick Selection: smoother, less blocky edges (Auto-Enhance; default false). */
45
45
  quickEnhance?: boolean;
46
+ /** Object Selection: read every layer (default true) or only the active pixel layer. */
47
+ objectSampleAll?: boolean;
48
+ /** Object Selection: smoother, less blocky edges (Auto-Enhance; default false). */
49
+ objectEnhance?: boolean;
46
50
  /** Type Mask: the text to select (default "Type"). A click places its first baseline. */
47
51
  typeText?: string;
48
52
  /** Type Mask: font size in px (default 72). */
@@ -23,8 +23,8 @@ export interface ImageSegmentationToolProviderOptions {
23
23
  /** The `select_subject` tool: Select › Subject through the controller's segmentation provider. */
24
24
  export declare function createImageSubjectSelectionTool(controller: ImageEditorController): AgentTool;
25
25
  /**
26
- * Agent tools that need the controller's segmentation provider (`select_subject`). The list is
27
- * empty while no provider is set, so a host can register this once and the tool appears when a
28
- * model is available.
26
+ * @deprecated `select_subject` is now one of the selection tools of `createImageEditorToolProvider`
27
+ * (it works without a model too), so this provider lists no tools; it stays so hosts that register
28
+ * it keep working. Remove it from your registry.
29
29
  */
30
30
  export declare function createImageSegmentationToolProvider(controller: ImageEditorController, options?: ImageSegmentationToolProviderOptions): AgentToolProvider;
@@ -23,8 +23,8 @@ export interface ImageSegmentationToolProviderOptions {
23
23
  /** The `select_subject` tool: Select › Subject through the controller's segmentation provider. */
24
24
  export declare function createImageSubjectSelectionTool(controller: ImageEditorController): AgentTool;
25
25
  /**
26
- * Agent tools that need the controller's segmentation provider (`select_subject`). The list is
27
- * empty while no provider is set, so a host can register this once and the tool appears when a
28
- * model is available.
26
+ * @deprecated `select_subject` is now one of the selection tools of `createImageEditorToolProvider`
27
+ * (it works without a model too), so this provider lists no tools; it stays so hosts that register
28
+ * it keep working. Remove it from your registry.
29
29
  */
30
30
  export declare function createImageSegmentationToolProvider(controller: ImageEditorController, options?: ImageSegmentationToolProviderOptions): AgentToolProvider;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor",
3
- "version": "0.197.0",
3
+ "version": "0.199.0",
4
4
  "description": "UI-agnostic rich text and media editing core library",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -221,7 +221,7 @@ in the source frame at the document's bit depth, colour mode and profile. Read
221
221
  | `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. |
222
222
  | `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. |
223
223
  | `list_channels` | Read the alpha channels (saved selections): id, name, bounds, percent, overlay and visibility, and whether Quick Mask mode is on. |
224
- | `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. |
224
+ | `select_subject` | Select › Subject. With a host segmentation model, `target` describes what to select ("the dog", "the sky") and the model's outlines are selected (`maxSegments` 1 for one). Without one, the subject that stands out most is found classically; `target` can't choose it (`method: "saliency"`, `note`). Combined by `mode`. Returns the selection, `found` (label, bounds) and `method`; nothing found leaves the selection unchanged. |
225
225
  | `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. |
226
226
  | `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. |
227
227
  | `get_image_info` | Read the geometry: source `image` size, `crop` box (source pixels, or null), `rotation` degrees, `flipH` / `flipV`, the `output` size after crop and rotation, `bitDepth` (8, 16 or 32), the layer count and `canUndo` / `canRedo`. Call before cropping or selecting so coordinates are right. |
@@ -253,6 +253,7 @@ in the source frame at the document's bit depth, colour mode and profile. Read
253
253
  | `select_ellipse` | Elliptical marquee inscribed in `x`, `y`, `width`, `height`; same options. A feathered ellipse makes a vignette. Returns the summary. |
254
254
  | `select_line` | Single row or column marquee: `orientation` `row` (at y) or `column` (at x), `position` in natural px, `mode`. A 1 px line across the image. Returns the summary. |
255
255
  | `quick_select` | Quick Selection: `strokes` (brush paths of `{x, y}`), `size` (diameter, default 30), `mode`, `sampleAllLayers`, `enhanceEdge`. Each stroke grows out to its region's edges; with `replace` the first replaces and the rest add. Paint inside the area, then check and fix with `add` / `subtract` strokes. Returns the summary. |
256
+ | `select_object` | Object Selection (GrabCut): `rect` (a box around the object) or `point` (on it), `mode`, `sampleAllLayers`, `enhanceEdge`. Outside the box is background. Make the box a little larger than the object. Returns the summary. |
256
257
  | `select_polygon` | The lasso: `points` (at least 3 `{x, y}` along the outline, closed automatically), `mode`, `feather`, `antiAlias`; `snapToEdges: {width, contrast}` makes it the Magnetic Lasso (points snap to edges, the outline follows them). Trace a subject's contour, not its box. Returns the summary (plus `outlinePoints` when snapped). |
257
258
  | `magic_wand` | Select similar colour from `x`, `y`: `tolerance` 0..255 (default 32), `contiguous` (default true), `distance` `rgb` or `perceptual`, `sampleMerged`, `sample` (`composite` or `active-layer`), `mode`, `feather`. For flat backdrops and solid colours. Returns the summary. |
258
259
  | `select_color_range` | Color Range, soft: `samples` (`[{color, x?, y?}]`) or a `preset` (reds … magentas, highlights, midtones, shadows, skinTones); `fuzziness` (samples 0..200, default 40; tone presets' falloff, default 20), `localized` px radius around positioned samples, `invert`, `sample`, `mode`, `feather`. Returns the summary. |
@@ -96,7 +96,8 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
96
96
  | Subject | Method |
97
97
  | --- | --- |
98
98
  | Geometric areas: a frame, a screen, a band | `select_rect` / `select_ellipse`, with `feather` for soft transitions |
99
- | A subject with a clear outline (product, person, animal) | `select_subject` if the host has a model; else `select_polygon` with `snapToEdges` (12–30 points within `width` of the edge), then `refine_selection` |
99
+ | One object among others, where you can box it (a product on a table, a person in a group) | `select_object` with a `rect` a little larger than the object on every side; then `quick_select` add / subtract strokes for what it missed |
100
+ | A subject with a clear outline (product, person, animal) | `select_subject` (with a host model, by description; without one it takes whatever stands out most, so check `method` and the result); else `select_object` around it, or `select_polygon` with `snapToEdges` (12–30 points within `width` of the edge), then `refine_selection` |
100
101
  | An area or subject that differs from its surroundings (a shirt, a sky, a car) | `quick_select` with strokes painted inside it, away from the edge (`size` a fraction of its width); `add` / `subtract` strokes where it fell short or leaked |
101
102
  | A low-contrast or busy outline the edges don't follow | `select_polygon` without `snapToEdges`, along the contour (20–60 points) |
102
103
  | Flat backdrop or solid colour (studio white, green screen, sky without clouds) | `magic_wand` on the backdrop (`tolerance` 20–40; `distance: "perceptual"` for gradients), then `invert_selection` |
@@ -157,6 +158,13 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
157
158
  30–60), check `percent`, and grow with `mode: "add"`.
158
159
  - **Box instead of outline:** `select_rect` around a subject masks its background too. Trace
159
160
  the contour.
161
+ - **Select Subject without a model picks the wrong thing:** it selects what stands out most from
162
+ the image's border, which may be a bright sign rather than the person. When `method` is
163
+ `saliency`, check with `capture_view`; if it's wrong, use `select_object` with a box.
164
+ - **Object Selection takes part of the background:** inside the box, anything that looks
165
+ unlike the background around the box counts as the object. Tighten the box, or `subtract` a
166
+ `quick_select` stroke on the extra. With `point`, it may stop at an inner edge of a
167
+ multicoloured object: use a box instead.
160
168
  - **Quick Selection spills over a weak edge:** a stroke grows into neighbouring areas of a
161
169
  similar colour. Paint smaller strokes further from the edge, then a `subtract` stroke on the
162
170
  spill. Strokes near an edge also pull in the other side.
@@ -194,6 +202,7 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
194
202
  - `select_rect`, `select_ellipse`: marquees
195
203
  - `select_polygon`: the lasso, along a contour; with `snapToEdges`, the Magnetic Lasso
196
204
  - `quick_select`: brush strokes that grow out to the region's edges
205
+ - `select_object`: the object in a box or under a point
197
206
  - `select_line`: a single row or column
198
207
  - `select_layer_transparency`: a layer's own pixels
199
208
  - `grow_selection`, `select_similar`: add similar colour, connected or anywhere
@@ -206,7 +215,7 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
206
215
  - `fill_pixels`, `blur_stroke`: fill or soften the selection in Quick Mask mode
207
216
  - `magic_wand`: similar colour from a seed
208
217
  - `select_color_range`: colour samples, hue, tone and skin presets
209
- - `select_subject`: a subject by description (needs a host model)
218
+ - `select_subject`: a subject by description with a host model; without one, the most salient subject
210
219
  - `load_selection_from_image`: AI or saved mattes
211
220
  - `load_selection_from_mask`: a layer mask back to a selection
212
221
  - `set_selection_display`: ants, Quick Mask tint or hidden