@pixerate/editor 0.197.0 → 0.198.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,45 @@
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
+ /** A mixture of {@link K} full-covariance Gaussians over RGB. */
11
+ export declare class ColorGmm {
12
+ private readonly logWeight;
13
+ private readonly mean;
14
+ /** Inverse covariances, row-major 3 × 3. */
15
+ private readonly inv;
16
+ /** ln(weight) − ½ ln((2π)³ |Σ|) per component; −∞ for an empty one. */
17
+ private readonly logNorm;
18
+ /** Fits the components to the pixels `ids` of `rgb`, each in component `comp[id]`. */
19
+ fit(rgb: Float32Array, ids: ArrayLike<number>, comp: Uint8Array): void;
20
+ /** ln p(colour | component k), up to the shared constant. */
21
+ private componentLog;
22
+ /** −ln p(colour) under the mixture (large for colours the model hasn't seen). */
23
+ cost(r: number, g: number, b: number): number;
24
+ /** The component most likely to have produced the colour. */
25
+ nearest(r: number, g: number, b: number): number;
26
+ }
27
+ export interface ObjectSelectionOptions {
28
+ /** Smoother, less blocky edges (Auto-Enhance). Default false. */
29
+ enhanceEdge?: boolean;
30
+ /** Most rounds of fitting and cutting (default 5; it stops early once the labels settle). */
31
+ iterations?: number;
32
+ }
33
+ /** What to select: a box around the object, or a point on it (natural pixels). */
34
+ export type ObjectTarget = {
35
+ rect: CropBox;
36
+ } | {
37
+ point: ImagePoint;
38
+ };
39
+ /**
40
+ * Object Selection over `pixels`: the object in `target.rect` (everything outside the box is
41
+ * background), or the object under `target.point` (searched for in a window around it that grows
42
+ * while the object reaches its border). Returns a selection of the whole image, empty when
43
+ * nothing stands out.
44
+ */
45
+ export declare function selectObjectIn(pixels: PixelBuffer, target: ObjectTarget, options?: ObjectSelectionOptions): SelectionMask;
@@ -0,0 +1,45 @@
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
+ /** A mixture of {@link K} full-covariance Gaussians over RGB. */
11
+ export declare class ColorGmm {
12
+ private readonly logWeight;
13
+ private readonly mean;
14
+ /** Inverse covariances, row-major 3 × 3. */
15
+ private readonly inv;
16
+ /** ln(weight) − ½ ln((2π)³ |Σ|) per component; −∞ for an empty one. */
17
+ private readonly logNorm;
18
+ /** Fits the components to the pixels `ids` of `rgb`, each in component `comp[id]`. */
19
+ fit(rgb: Float32Array, ids: ArrayLike<number>, comp: Uint8Array): void;
20
+ /** ln p(colour | component k), up to the shared constant. */
21
+ private componentLog;
22
+ /** −ln p(colour) under the mixture (large for colours the model hasn't seen). */
23
+ cost(r: number, g: number, b: number): number;
24
+ /** The component most likely to have produced the colour. */
25
+ nearest(r: number, g: number, b: number): number;
26
+ }
27
+ export interface ObjectSelectionOptions {
28
+ /** Smoother, less blocky edges (Auto-Enhance). Default false. */
29
+ enhanceEdge?: boolean;
30
+ /** Most rounds of fitting and cutting (default 5; it stops early once the labels settle). */
31
+ iterations?: number;
32
+ }
33
+ /** What to select: a box around the object, or a point on it (natural pixels). */
34
+ export type ObjectTarget = {
35
+ rect: CropBox;
36
+ } | {
37
+ point: ImagePoint;
38
+ };
39
+ /**
40
+ * Object Selection over `pixels`: the object in `target.rect` (everything outside the box is
41
+ * background), or the object under `target.point` (searched for in a window around it that grows
42
+ * while the object reaches its border). Returns a selection of the whole image, empty when
43
+ * nothing stands out.
44
+ */
45
+ export declare function selectObjectIn(pixels: PixelBuffer, target: ObjectTarget, options?: ObjectSelectionOptions): SelectionMask;
@@ -1,2 +1,4 @@
1
1
  export * from './maxflow.cjs';
2
+ export * from './work.cjs';
2
3
  export * from './quick.cjs';
4
+ export * from './grabcut.cjs';
@@ -1,2 +1,4 @@
1
1
  export * from './maxflow.js';
2
+ export * from './work.js';
2
3
  export * from './quick.js';
4
+ export * from './grabcut.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,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). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor",
3
- "version": "0.197.0",
3
+ "version": "0.198.0",
4
4
  "description": "UI-agnostic rich text and media editing core library",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -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` if the host has a model; 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,10 @@ 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
+ - **Object Selection takes part of the background:** inside the box, anything that looks
162
+ unlike the background around the box counts as the object. Tighten the box, or `subtract` a
163
+ `quick_select` stroke on the extra. With `point`, it may stop at an inner edge of a
164
+ multicoloured object: use a box instead.
160
165
  - **Quick Selection spills over a weak edge:** a stroke grows into neighbouring areas of a
161
166
  similar colour. Paint smaller strokes further from the edge, then a `subtract` stroke on the
162
167
  spill. Strokes near an edge also pull in the other side.
@@ -194,6 +199,7 @@ This skill is the method. `pixerate-image-editor` has the full tool reference.
194
199
  - `select_rect`, `select_ellipse`: marquees
195
200
  - `select_polygon`: the lasso, along a contour; with `snapToEdges`, the Magnetic Lasso
196
201
  - `quick_select`: brush strokes that grow out to the region's edges
202
+ - `select_object`: the object in a box or under a point
197
203
  - `select_line`: a single row or column
198
204
  - `select_layer_transparency`: a layer's own pixels
199
205
  - `grow_selection`, `select_similar`: add similar colour, connected or anywhere