@pixerate/editor 0.207.0 → 0.209.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/animation-editor/index.cjs +60 -59
  2. package/dist/animation-editor/index.js +6 -5
  3. package/dist/{brushstrokeRender-7LXCU7PD.js → brushstrokeRender-C3UU6GVC.js} +5 -4
  4. package/dist/{brushstrokeRender-VO4ZTWVA.cjs → brushstrokeRender-EAJNE6WP.cjs} +12 -11
  5. package/dist/canvas/index.cjs +8 -8
  6. package/dist/canvas/index.js +1 -1
  7. package/dist/{chunk-2N2QPO3H.js → chunk-2PBZBRP5.js} +9 -7
  8. package/dist/{chunk-7NW46N7I.cjs → chunk-3EHPLDFQ.cjs} +54 -52
  9. package/dist/{chunk-H367YTXI.js → chunk-42TWUPNJ.js} +13 -387
  10. package/dist/chunk-474IQG74.cjs +384 -0
  11. package/dist/{chunk-MLC7HUHO.js → chunk-BGOCAUXH.js} +1 -1
  12. package/dist/chunk-DWYQPL2A.js +2010 -0
  13. package/dist/{chunk-YXKLVD56.js → chunk-F7YA3MMC.js} +2 -2
  14. package/dist/{chunk-ZZGPYNS2.js → chunk-G4E6RUPC.js} +1 -1
  15. package/dist/chunk-HVVR5PZW.js +384 -0
  16. package/dist/{chunk-FR2Q2LVF.cjs → chunk-I7G3RSUJ.cjs} +35 -35
  17. package/dist/chunk-K6PXS6DO.cjs +102 -0
  18. package/dist/{chunk-ZIDUPSP4.js → chunk-KFIOEOCQ.js} +24 -761
  19. package/dist/{chunk-V7GWZIZK.cjs → chunk-KWNMBMKG.cjs} +23 -21
  20. package/dist/chunk-L3G23N5Y.js +763 -0
  21. package/dist/{chunk-GHCXLQ47.js → chunk-NDMXB4PR.js} +2 -2
  22. package/dist/{chunk-CWM3CUUX.cjs → chunk-OLNIPTB3.cjs} +39 -413
  23. package/dist/{chunk-EBDCRTZI.cjs → chunk-PQ3H2AAN.cjs} +92 -90
  24. package/dist/{chunk-BRKVNXDZ.cjs → chunk-QAUIZPYI.cjs} +7 -7
  25. package/dist/{chunk-UYXL6ZWQ.cjs → chunk-QE7D7TZR.cjs} +494 -1231
  26. package/dist/chunk-QYLWG22N.cjs +763 -0
  27. package/dist/{chunk-YQ5C5BVK.cjs → chunk-ROVK6AXX.cjs} +60 -60
  28. package/dist/{chunk-HGTDMKNE.cjs → chunk-UOGKSVRQ.cjs} +126 -221
  29. package/dist/{chunk-EL5PAHNP.js → chunk-USQCKRZG.js} +6 -4
  30. package/dist/{chunk-36OKQDCF.js → chunk-WJ2RBZMM.js} +5 -3
  31. package/dist/chunk-X4LUGTQX.cjs +2010 -0
  32. package/dist/{chunk-NQMP3CWF.js → chunk-YBJXCQTR.js} +15 -110
  33. package/dist/chunk-ZIF4UJJ6.js +102 -0
  34. package/dist/{chunk-WTW7QRTS.cjs → chunk-ZMHPQ6HP.cjs} +1 -1
  35. package/dist/image-editor/controller.d.cts +53 -5
  36. package/dist/image-editor/controller.d.ts +53 -5
  37. package/dist/image-editor/index.cjs +1806 -3356
  38. package/dist/image-editor/index.js +462 -2012
  39. package/dist/image-editor/selection/index.d.cts +1 -0
  40. package/dist/image-editor/selection/index.d.ts +1 -0
  41. package/dist/image-editor/selection/segment/focus.d.cts +2 -0
  42. package/dist/image-editor/selection/segment/focus.d.ts +2 -0
  43. package/dist/image-editor/selection/segment/grabcut.d.cts +4 -2
  44. package/dist/image-editor/selection/segment/grabcut.d.ts +4 -2
  45. package/dist/image-editor/selection/segment/sky.d.cts +2 -0
  46. package/dist/image-editor/selection/segment/sky.d.ts +2 -0
  47. package/dist/image-editor/selection/segment/subject.d.cts +2 -1
  48. package/dist/image-editor/selection/segment/subject.d.ts +2 -1
  49. package/dist/image-editor/selection/segment/work.d.cts +5 -0
  50. package/dist/image-editor/selection/segment/work.d.ts +5 -0
  51. package/dist/image-editor/selection/select-and-mask.d.cts +12 -2
  52. package/dist/image-editor/selection/select-and-mask.d.ts +12 -2
  53. package/dist/image-editor/selection/tool-options.d.cts +3 -1
  54. package/dist/image-editor/selection/tool-options.d.ts +3 -1
  55. package/dist/image-editor/selection/worker.d.cts +126 -0
  56. package/dist/image-editor/selection/worker.d.ts +126 -0
  57. package/dist/image-editor/selection-worker.cjs +14 -0
  58. package/dist/image-editor/selection-worker.d.cts +12 -0
  59. package/dist/image-editor/selection-worker.d.ts +12 -0
  60. package/dist/image-editor/selection-worker.js +14 -0
  61. package/dist/image-editor/types.d.cts +22 -0
  62. package/dist/image-editor/types.d.ts +22 -0
  63. package/dist/paint/index.cjs +6 -5
  64. package/dist/paint/index.js +5 -4
  65. package/dist/paint-editor/index.cjs +394 -390
  66. package/dist/paint-editor/index.js +18 -14
  67. package/dist/raster/index.cjs +22 -18
  68. package/dist/raster/index.js +29 -25
  69. package/dist/vector/index.cjs +986 -985
  70. package/dist/vector/index.js +6 -5
  71. package/package.json +11 -1
  72. package/skills/pixerate-image-editor/SKILL.md +1 -1
@@ -9,32 +9,37 @@ import {
9
9
  multiplyHomographies
10
10
  } from "./chunk-OHKOFKBY.js";
11
11
  import {
12
- TILE,
13
- TiledSurface,
12
+ gaussianBlur
13
+ } from "./chunk-ZIF4UJJ6.js";
14
+ import {
14
15
  blendChannel,
15
16
  blendRgb,
16
- contentBounds,
17
17
  deepTile,
18
- emptySurface,
19
- finishTile,
20
18
  isBlendMode,
21
19
  isSeparableBlendMode,
22
20
  mixPigment8,
23
21
  mixPigmentRgb,
24
22
  readDeepRegion,
25
- readRegion,
26
23
  srgbDecode,
27
24
  srgbEncode,
28
25
  surfaceDepth,
26
+ tileSamples,
27
+ to32From8,
28
+ writeDeepRegion
29
+ } from "./chunk-42TWUPNJ.js";
30
+ import {
31
+ TILE,
32
+ TiledSurface,
33
+ contentBounds,
34
+ emptySurface,
35
+ finishTile,
36
+ readRegion,
29
37
  surfaceFromPixels,
30
38
  tileKey,
31
- tileSamples,
32
39
  tilesInRect,
33
- to32From8,
34
40
  translateSurface,
35
- writeDeepRegion,
36
41
  writeRegion
37
- } from "./chunk-H367YTXI.js";
42
+ } from "./chunk-HVVR5PZW.js";
38
43
 
39
44
  // src/raster/effects/model.ts
40
45
  var DEFAULT_GLOBAL_LIGHT = { angle: 120, altitude: 30 };
@@ -2263,104 +2268,6 @@ function decodeInPlace(d) {
2263
2268
  }
2264
2269
  }
2265
2270
 
2266
- // src/raster/blur.ts
2267
- function gaussianKernel(sigma) {
2268
- const r = Math.ceil(sigma * 3);
2269
- const k = new Float32Array(2 * r + 1);
2270
- let s = 0;
2271
- for (let i = -r; i <= r; i++) {
2272
- const v = Math.exp(-(i * i) / (2 * sigma * sigma));
2273
- k[i + r] = v;
2274
- s += v;
2275
- }
2276
- for (let i = 0; i < k.length; i++) k[i] /= s;
2277
- return k;
2278
- }
2279
- var DIRECT_GAUSSIAN_MAX_SIGMA = 8;
2280
- function boxRadii(sigma) {
2281
- const n = 3;
2282
- const wIdeal = Math.sqrt(12 * sigma * sigma / n + 1);
2283
- let wl = Math.floor(wIdeal);
2284
- if (wl % 2 === 0) wl--;
2285
- const wu = wl + 2;
2286
- const mIdeal = (12 * sigma * sigma - n * wl * wl - 4 * n * wl - 3 * n) / (-4 * wl - 4);
2287
- const m = Math.round(mIdeal);
2288
- const sizes = [0, 1, 2].map((i) => i < m ? wl : wu);
2289
- return sizes.map((s) => (s - 1) / 2);
2290
- }
2291
- function convolveLine(src, off, stride, len, k, edge, dst) {
2292
- const r = (k.length - 1) / 2;
2293
- for (let i = 0; i < len; i++) {
2294
- let a = 0;
2295
- const lo = i - r;
2296
- for (let j = 0; j < k.length; j++) {
2297
- let x = lo + j;
2298
- if (x < 0 || x >= len) {
2299
- if (edge === "zero") continue;
2300
- x = x < 0 ? 0 : len - 1;
2301
- }
2302
- a += src[off + x * stride] * k[j];
2303
- }
2304
- dst[i] = a;
2305
- }
2306
- }
2307
- function boxesLine(src, off, stride, len, radii, edge, a, b, dst) {
2308
- const pad = radii.reduce((s, r) => s + r, 0);
2309
- const plen = len + 2 * pad;
2310
- for (let i = 0; i < plen; i++) {
2311
- const j = i - pad;
2312
- a[i] = j < 0 ? edge === "zero" ? 0 : src[off] : j >= len ? edge === "zero" ? 0 : src[off + (len - 1) * stride] : src[off + j * stride];
2313
- }
2314
- let from = a;
2315
- let to = b;
2316
- for (const r of radii) {
2317
- let sum = 0;
2318
- for (let i = 0; i <= Math.min(r, plen - 1); i++) sum += from[i];
2319
- const k = 2 * r + 1;
2320
- for (let i = 0; i < plen; i++) {
2321
- to[i] = sum / k;
2322
- const add = i + r + 1;
2323
- const drop = i - r;
2324
- if (add < plen) sum += from[add];
2325
- if (drop >= 0) sum -= from[drop];
2326
- }
2327
- const t = from;
2328
- from = to;
2329
- to = t;
2330
- }
2331
- for (let i = 0; i < len; i++) dst[i] = from[i + pad];
2332
- }
2333
- function gaussianBlur(src, w, h, sigma, edge = "zero") {
2334
- const out = Float32Array.from(src);
2335
- if (!(sigma >= 0.1) || w <= 0 || h <= 0) return out;
2336
- const s = Math.min(sigma, 4 * Math.max(w, h));
2337
- const line = new Float32Array(Math.max(w, h));
2338
- const passes = [];
2339
- if (s <= DIRECT_GAUSSIAN_MAX_SIGMA) {
2340
- const k = gaussianKernel(s);
2341
- passes.push((buf, off, stride, len) => convolveLine(buf, off, stride, len, k, edge, line));
2342
- } else {
2343
- const radii = boxRadii(s);
2344
- const plen = Math.max(w, h) + 2 * radii.reduce((a2, r) => a2 + r, 0);
2345
- const a = new Float32Array(plen);
2346
- const b = new Float32Array(plen);
2347
- passes.push((buf, off, stride, len) => boxesLine(buf, off, stride, len, radii, edge, a, b, line));
2348
- }
2349
- for (const pass of passes) {
2350
- for (let y = 0; y < h; y++) {
2351
- pass(out, y * w, 1, w);
2352
- out.set(line.subarray(0, w), y * w);
2353
- }
2354
- }
2355
- for (const pass of passes) {
2356
- for (let x = 0; x < w; x++) {
2357
- pass(out, x, w, h);
2358
- for (let y = 0; y < h; y++) out[y * w + x] = line[y];
2359
- }
2360
- }
2361
- return out;
2362
- }
2363
-
2364
2271
  // src/raster/layers.ts
2365
2272
  var childrenOf = (l) => l.type === "group" ? l.children ?? null : null;
2366
2273
  function flattenLayers(layers) {
@@ -4293,8 +4200,6 @@ export {
4293
4200
  renderLayerEffects,
4294
4201
  DeepCompositor,
4295
4202
  workingToSamples,
4296
- DIRECT_GAUSSIAN_MAX_SIGMA,
4297
- gaussianBlur,
4298
4203
  flattenLayers,
4299
4204
  findLayer,
4300
4205
  mapLayer,
@@ -0,0 +1,102 @@
1
+ // src/raster/blur.ts
2
+ function gaussianKernel(sigma) {
3
+ const r = Math.ceil(sigma * 3);
4
+ const k = new Float32Array(2 * r + 1);
5
+ let s = 0;
6
+ for (let i = -r; i <= r; i++) {
7
+ const v = Math.exp(-(i * i) / (2 * sigma * sigma));
8
+ k[i + r] = v;
9
+ s += v;
10
+ }
11
+ for (let i = 0; i < k.length; i++) k[i] /= s;
12
+ return k;
13
+ }
14
+ var DIRECT_GAUSSIAN_MAX_SIGMA = 8;
15
+ function boxRadii(sigma) {
16
+ const n = 3;
17
+ const wIdeal = Math.sqrt(12 * sigma * sigma / n + 1);
18
+ let wl = Math.floor(wIdeal);
19
+ if (wl % 2 === 0) wl--;
20
+ const wu = wl + 2;
21
+ const mIdeal = (12 * sigma * sigma - n * wl * wl - 4 * n * wl - 3 * n) / (-4 * wl - 4);
22
+ const m = Math.round(mIdeal);
23
+ const sizes = [0, 1, 2].map((i) => i < m ? wl : wu);
24
+ return sizes.map((s) => (s - 1) / 2);
25
+ }
26
+ function convolveLine(src, off, stride, len, k, edge, dst) {
27
+ const r = (k.length - 1) / 2;
28
+ for (let i = 0; i < len; i++) {
29
+ let a = 0;
30
+ const lo = i - r;
31
+ for (let j = 0; j < k.length; j++) {
32
+ let x = lo + j;
33
+ if (x < 0 || x >= len) {
34
+ if (edge === "zero") continue;
35
+ x = x < 0 ? 0 : len - 1;
36
+ }
37
+ a += src[off + x * stride] * k[j];
38
+ }
39
+ dst[i] = a;
40
+ }
41
+ }
42
+ function boxesLine(src, off, stride, len, radii, edge, a, b, dst) {
43
+ const pad = radii.reduce((s, r) => s + r, 0);
44
+ const plen = len + 2 * pad;
45
+ for (let i = 0; i < plen; i++) {
46
+ const j = i - pad;
47
+ a[i] = j < 0 ? edge === "zero" ? 0 : src[off] : j >= len ? edge === "zero" ? 0 : src[off + (len - 1) * stride] : src[off + j * stride];
48
+ }
49
+ let from = a;
50
+ let to = b;
51
+ for (const r of radii) {
52
+ let sum = 0;
53
+ for (let i = 0; i <= Math.min(r, plen - 1); i++) sum += from[i];
54
+ const k = 2 * r + 1;
55
+ for (let i = 0; i < plen; i++) {
56
+ to[i] = sum / k;
57
+ const add = i + r + 1;
58
+ const drop = i - r;
59
+ if (add < plen) sum += from[add];
60
+ if (drop >= 0) sum -= from[drop];
61
+ }
62
+ const t = from;
63
+ from = to;
64
+ to = t;
65
+ }
66
+ for (let i = 0; i < len; i++) dst[i] = from[i + pad];
67
+ }
68
+ function gaussianBlur(src, w, h, sigma, edge = "zero") {
69
+ const out = Float32Array.from(src);
70
+ if (!(sigma >= 0.1) || w <= 0 || h <= 0) return out;
71
+ const s = Math.min(sigma, 4 * Math.max(w, h));
72
+ const line = new Float32Array(Math.max(w, h));
73
+ const passes = [];
74
+ if (s <= DIRECT_GAUSSIAN_MAX_SIGMA) {
75
+ const k = gaussianKernel(s);
76
+ passes.push((buf, off, stride, len) => convolveLine(buf, off, stride, len, k, edge, line));
77
+ } else {
78
+ const radii = boxRadii(s);
79
+ const plen = Math.max(w, h) + 2 * radii.reduce((a2, r) => a2 + r, 0);
80
+ const a = new Float32Array(plen);
81
+ const b = new Float32Array(plen);
82
+ passes.push((buf, off, stride, len) => boxesLine(buf, off, stride, len, radii, edge, a, b, line));
83
+ }
84
+ for (const pass of passes) {
85
+ for (let y = 0; y < h; y++) {
86
+ pass(out, y * w, 1, w);
87
+ out.set(line.subarray(0, w), y * w);
88
+ }
89
+ }
90
+ for (const pass of passes) {
91
+ for (let x = 0; x < w; x++) {
92
+ pass(out, x, w, h);
93
+ for (let y = 0; y < h; y++) out[y * w + x] = line[y];
94
+ }
95
+ }
96
+ return out;
97
+ }
98
+
99
+ export {
100
+ DIRECT_GAUSSIAN_MAX_SIGMA,
101
+ gaussianBlur
102
+ };
@@ -74,7 +74,7 @@ function profileAlongPolyline(points, values, count = 32) {
74
74
  var round3 = (v) => Math.round(v * 1e3) / 1e3;
75
75
  var loading = null;
76
76
  function loadCanvasBrushstrokeRenderer() {
77
- loading ??= Promise.resolve().then(() => _interopRequireWildcard(require("./brushstrokeRender-VO4ZTWVA.cjs"))).catch((error) => {
77
+ loading ??= Promise.resolve().then(() => _interopRequireWildcard(require("./brushstrokeRender-EAJNE6WP.cjs"))).catch((error) => {
78
78
  loading = null;
79
79
  throw error;
80
80
  });
@@ -1,9 +1,11 @@
1
- import { AdjustmentKind, AdjustmentLayer, AdjustmentParamsMap, Annotation, CreateAnnotationPayload, AspectRatio, CropBox, DepthMaskOptions, ExportOptions, ImageAdjustments, ImageDimensions, ImageEditorFit, ImageEditorOptions, ImageEditorState, ImageEditorTool, ImageTransform, ImagePoint, SerializedImageEditorState } from './types.cjs';
1
+ import { AdjustmentKind, AdjustmentLayer, AdjustmentParamsMap, Annotation, CreateAnnotationPayload, AspectRatio, CropBox, DepthMaskOptions, ExportOptions, ImageAdjustments, ImageDimensions, ImageEditorFit, ImageEditorOptions, ImageEditorState, ImageEditorTool, ImageTransform, ImagePoint, SerializedImageEditorState, DocumentOpener } from './types.cjs';
2
2
  import { type PathToSelectionOptions, type SelectionToPathOptions } from './selection/path.cjs';
3
3
  import { type MagneticEdgeOptions } from './selection/magnetic.cjs';
4
- import { type ObjectTarget } from './selection/segment/grabcut.cjs';
5
- import { type FocusAreaOptions } from './selection/segment/focus.cjs';
6
- import { type SkyOptions } from './selection/segment/sky.cjs';
4
+ import type { ObjectTarget } from './selection/segment/grabcut.cjs';
5
+ import { type SelectionJob, type SelectionJobResult, type SelectionWorkerFactory } from './selection/worker.cjs';
6
+ import type { SelectionProgress } from './selection/segment/work.cjs';
7
+ import type { FocusAreaOptions } from './selection/segment/focus.cjs';
8
+ import type { SkyOptions } from './selection/segment/sky.cjs';
7
9
  import { RenderOptions } from './renderer.cjs';
8
10
  import { type BlendMode } from './blend.cjs';
9
11
  import type { ImageHistogram } from './histogram.cjs';
@@ -146,6 +148,8 @@ export interface SampleOptions {
146
148
  }
147
149
  /** Options of {@link ImageEditorController.quickSelect}. */
148
150
  export interface QuickSelectCommandOptions {
151
+ signal?: AbortSignal;
152
+ onProgress?: SelectionProgress;
149
153
  /** Brush diameter in natural pixels (default 30). */
150
154
  size?: number;
151
155
  /** How the strokes combine with the selection (default `replace`: the first replaces, the rest add). */
@@ -157,13 +161,14 @@ export interface QuickSelectCommandOptions {
157
161
  }
158
162
  /** Options of {@link ImageEditorController.selectFocusArea}. */
159
163
  export interface FocusAreaCommandOptions extends FocusAreaOptions {
164
+ signal?: AbortSignal;
160
165
  /** How the area combines with the selection (default `replace`). */
161
166
  mode?: SelectionMode;
162
167
  /** Sample every layer (default true) or only the active pixel layer. */
163
168
  sampleAllLayers?: boolean;
164
169
  }
165
170
  /** Where Select and Mask puts its result (Photoshop's Output To). */
166
- export type RefineOutput = 'selection' | 'layer-mask' | 'new-layer' | 'new-layer-with-mask';
171
+ export type RefineOutput = 'selection' | 'layer-mask' | 'new-layer' | 'new-layer-with-mask' | 'new-document' | 'new-document-with-mask';
167
172
  /** What {@link ImageEditorController.refineSelectionTo} made. */
168
173
  export interface RefineOutputResult {
169
174
  output: RefineOutput;
@@ -171,6 +176,8 @@ export interface RefineOutputResult {
171
176
  layerId?: string;
172
177
  /** The layer it made (`new-layer`, `new-layer-with-mask`). */
173
178
  newLayerId?: string;
179
+ /** The id the host's document opener returned (`new-document`, `new-document-with-mask`). */
180
+ documentId?: string;
174
181
  /** How the edge was refined: by colour, or with the segmentation model (object aware). */
175
182
  refineMode: 'color' | 'object';
176
183
  }
@@ -186,6 +193,7 @@ export interface SkyCommandOptions extends SkyOptions {
186
193
  }
187
194
  /** Options of {@link ImageEditorController.selectObject}. */
188
195
  export interface SelectObjectCommandOptions {
196
+ onProgress?: SelectionProgress;
189
197
  /**
190
198
  * With a segmentation provider set, ask it for the object in the box or under the point (default
191
199
  * true), falling back to GrabCut when nothing it returns fits; false always uses GrabCut.
@@ -684,6 +692,8 @@ export declare class ImageEditorController {
684
692
  private compositor;
685
693
  /** The segmentation provider behind `selectSubject` (see `setSegmentationProvider`). */
686
694
  private segmentation;
695
+ private selectionWorker;
696
+ private documentOpener;
687
697
  /** The effects provider slot (see `setEffectsProvider`). */
688
698
  readonly effects: EffectsSlot;
689
699
  /** Renders provider effects: effect smart filter results and effect layers. */
@@ -714,6 +724,40 @@ export declare class ImageEditorController {
714
724
  private refreshEffectSurfaces;
715
725
  /** The registered segmentation provider, or `null` (then `selectSubject` finds the most salient subject without a model). */
716
726
  get segmentationProvider(): SegmentationProvider | null;
727
+ /**
728
+ * Runs the long selections in a Web Worker made by `factory` (or with `null`, on the page again).
729
+ * A worker that is cancelled or fails is replaced by a fresh one on the next job.
730
+ */
731
+ setSelectionWorker(factory: SelectionWorkerFactory | null): void;
732
+ /** Sets (or with `null` removes) how new documents are opened (see `DocumentOpener`). Not an edit. */
733
+ setDocumentOpener(opener: DocumentOpener | null): void;
734
+ /** Whether the host can open new documents (the New Document outputs are available). */
735
+ get canOpenDocuments(): boolean;
736
+ /**
737
+ * A new one-layer document from the selection (or `options.selection`) on a pixel layer
738
+ * (`layerId`, default the active one), the size of this image: the selected pixels on
739
+ * transparency, or with `withMask` the whole layer masked by the selection. This document is
740
+ * not changed. `decontaminate` (0..100) cleans the soft edge's colours as the new-layer
741
+ * outputs do.
742
+ */
743
+ documentFromSelection(options?: {
744
+ layerId?: string;
745
+ withMask?: boolean;
746
+ selection?: SelectionMask | null;
747
+ decontaminate?: number;
748
+ radius?: number;
749
+ }): SerializedLayeredImageEditorState;
750
+ /** Whether the long selections run in a worker. */
751
+ get hasSelectionWorker(): boolean;
752
+ /**
753
+ * Runs a long selection job on `pixels`: in the worker when there is one, else here (which
754
+ * blocks the page until it is done). `signal` cancels it (rejecting with an `AbortError`);
755
+ * `onProgress` hears its stages. The document is not changed.
756
+ */
757
+ runSelectionJob(job: SelectionJob, pixels: PixelBuffer, options?: {
758
+ signal?: AbortSignal;
759
+ onProgress?: SelectionProgress;
760
+ }): Promise<SelectionJobResult>;
717
761
  /** Registers (or with `null` removes) the segmentation provider. Not an edit: no undo step. */
718
762
  setSegmentationProvider(provider: SegmentationProvider | null): void;
719
763
  /** The registered effects provider, or `null`. */
@@ -1673,6 +1717,8 @@ export declare class ImageEditorController {
1673
1717
  * its alpha.
1674
1718
  */
1675
1719
  private decontaminateLayer;
1720
+ /** `layer`'s surface with Decontaminate Colors applied along `coverage`'s soft edge, colours read from `source`. */
1721
+ private decontaminatedSurface;
1676
1722
  /**
1677
1723
  * Loads a selection from a mask image (an AI segmentation, a saved mask): a data URL / URL or
1678
1724
  * RGBA pixels, by luminance (white = selected) or a channel. Any size; it is resampled.
@@ -1723,6 +1769,8 @@ export declare class ImageEditorController {
1723
1769
  beforeApply?: (outlines: ImagePoint[][]) => void | Promise<void>;
1724
1770
  /** Without a model: smoother, less blocky edges (Auto-Enhance). */
1725
1771
  enhanceEdge?: boolean;
1772
+ /** Without a model: hears the stages of finding the subject. */
1773
+ onProgress?: SelectionProgress;
1726
1774
  }): Promise<{
1727
1775
  segments: {
1728
1776
  label: string;
@@ -1,9 +1,11 @@
1
- import { AdjustmentKind, AdjustmentLayer, AdjustmentParamsMap, Annotation, CreateAnnotationPayload, AspectRatio, CropBox, DepthMaskOptions, ExportOptions, ImageAdjustments, ImageDimensions, ImageEditorFit, ImageEditorOptions, ImageEditorState, ImageEditorTool, ImageTransform, ImagePoint, SerializedImageEditorState } from './types.js';
1
+ import { AdjustmentKind, AdjustmentLayer, AdjustmentParamsMap, Annotation, CreateAnnotationPayload, AspectRatio, CropBox, DepthMaskOptions, ExportOptions, ImageAdjustments, ImageDimensions, ImageEditorFit, ImageEditorOptions, ImageEditorState, ImageEditorTool, ImageTransform, ImagePoint, SerializedImageEditorState, DocumentOpener } from './types.js';
2
2
  import { type PathToSelectionOptions, type SelectionToPathOptions } from './selection/path.js';
3
3
  import { type MagneticEdgeOptions } from './selection/magnetic.js';
4
- import { type ObjectTarget } from './selection/segment/grabcut.js';
5
- import { type FocusAreaOptions } from './selection/segment/focus.js';
6
- import { type SkyOptions } from './selection/segment/sky.js';
4
+ import type { ObjectTarget } from './selection/segment/grabcut.js';
5
+ import { type SelectionJob, type SelectionJobResult, type SelectionWorkerFactory } from './selection/worker.js';
6
+ import type { SelectionProgress } from './selection/segment/work.js';
7
+ import type { FocusAreaOptions } from './selection/segment/focus.js';
8
+ import type { SkyOptions } from './selection/segment/sky.js';
7
9
  import { RenderOptions } from './renderer.js';
8
10
  import { type BlendMode } from './blend.js';
9
11
  import type { ImageHistogram } from './histogram.js';
@@ -146,6 +148,8 @@ export interface SampleOptions {
146
148
  }
147
149
  /** Options of {@link ImageEditorController.quickSelect}. */
148
150
  export interface QuickSelectCommandOptions {
151
+ signal?: AbortSignal;
152
+ onProgress?: SelectionProgress;
149
153
  /** Brush diameter in natural pixels (default 30). */
150
154
  size?: number;
151
155
  /** How the strokes combine with the selection (default `replace`: the first replaces, the rest add). */
@@ -157,13 +161,14 @@ export interface QuickSelectCommandOptions {
157
161
  }
158
162
  /** Options of {@link ImageEditorController.selectFocusArea}. */
159
163
  export interface FocusAreaCommandOptions extends FocusAreaOptions {
164
+ signal?: AbortSignal;
160
165
  /** How the area combines with the selection (default `replace`). */
161
166
  mode?: SelectionMode;
162
167
  /** Sample every layer (default true) or only the active pixel layer. */
163
168
  sampleAllLayers?: boolean;
164
169
  }
165
170
  /** Where Select and Mask puts its result (Photoshop's Output To). */
166
- export type RefineOutput = 'selection' | 'layer-mask' | 'new-layer' | 'new-layer-with-mask';
171
+ export type RefineOutput = 'selection' | 'layer-mask' | 'new-layer' | 'new-layer-with-mask' | 'new-document' | 'new-document-with-mask';
167
172
  /** What {@link ImageEditorController.refineSelectionTo} made. */
168
173
  export interface RefineOutputResult {
169
174
  output: RefineOutput;
@@ -171,6 +176,8 @@ export interface RefineOutputResult {
171
176
  layerId?: string;
172
177
  /** The layer it made (`new-layer`, `new-layer-with-mask`). */
173
178
  newLayerId?: string;
179
+ /** The id the host's document opener returned (`new-document`, `new-document-with-mask`). */
180
+ documentId?: string;
174
181
  /** How the edge was refined: by colour, or with the segmentation model (object aware). */
175
182
  refineMode: 'color' | 'object';
176
183
  }
@@ -186,6 +193,7 @@ export interface SkyCommandOptions extends SkyOptions {
186
193
  }
187
194
  /** Options of {@link ImageEditorController.selectObject}. */
188
195
  export interface SelectObjectCommandOptions {
196
+ onProgress?: SelectionProgress;
189
197
  /**
190
198
  * With a segmentation provider set, ask it for the object in the box or under the point (default
191
199
  * true), falling back to GrabCut when nothing it returns fits; false always uses GrabCut.
@@ -684,6 +692,8 @@ export declare class ImageEditorController {
684
692
  private compositor;
685
693
  /** The segmentation provider behind `selectSubject` (see `setSegmentationProvider`). */
686
694
  private segmentation;
695
+ private selectionWorker;
696
+ private documentOpener;
687
697
  /** The effects provider slot (see `setEffectsProvider`). */
688
698
  readonly effects: EffectsSlot;
689
699
  /** Renders provider effects: effect smart filter results and effect layers. */
@@ -714,6 +724,40 @@ export declare class ImageEditorController {
714
724
  private refreshEffectSurfaces;
715
725
  /** The registered segmentation provider, or `null` (then `selectSubject` finds the most salient subject without a model). */
716
726
  get segmentationProvider(): SegmentationProvider | null;
727
+ /**
728
+ * Runs the long selections in a Web Worker made by `factory` (or with `null`, on the page again).
729
+ * A worker that is cancelled or fails is replaced by a fresh one on the next job.
730
+ */
731
+ setSelectionWorker(factory: SelectionWorkerFactory | null): void;
732
+ /** Sets (or with `null` removes) how new documents are opened (see `DocumentOpener`). Not an edit. */
733
+ setDocumentOpener(opener: DocumentOpener | null): void;
734
+ /** Whether the host can open new documents (the New Document outputs are available). */
735
+ get canOpenDocuments(): boolean;
736
+ /**
737
+ * A new one-layer document from the selection (or `options.selection`) on a pixel layer
738
+ * (`layerId`, default the active one), the size of this image: the selected pixels on
739
+ * transparency, or with `withMask` the whole layer masked by the selection. This document is
740
+ * not changed. `decontaminate` (0..100) cleans the soft edge's colours as the new-layer
741
+ * outputs do.
742
+ */
743
+ documentFromSelection(options?: {
744
+ layerId?: string;
745
+ withMask?: boolean;
746
+ selection?: SelectionMask | null;
747
+ decontaminate?: number;
748
+ radius?: number;
749
+ }): SerializedLayeredImageEditorState;
750
+ /** Whether the long selections run in a worker. */
751
+ get hasSelectionWorker(): boolean;
752
+ /**
753
+ * Runs a long selection job on `pixels`: in the worker when there is one, else here (which
754
+ * blocks the page until it is done). `signal` cancels it (rejecting with an `AbortError`);
755
+ * `onProgress` hears its stages. The document is not changed.
756
+ */
757
+ runSelectionJob(job: SelectionJob, pixels: PixelBuffer, options?: {
758
+ signal?: AbortSignal;
759
+ onProgress?: SelectionProgress;
760
+ }): Promise<SelectionJobResult>;
717
761
  /** Registers (or with `null` removes) the segmentation provider. Not an edit: no undo step. */
718
762
  setSegmentationProvider(provider: SegmentationProvider | null): void;
719
763
  /** The registered effects provider, or `null`. */
@@ -1673,6 +1717,8 @@ export declare class ImageEditorController {
1673
1717
  * its alpha.
1674
1718
  */
1675
1719
  private decontaminateLayer;
1720
+ /** `layer`'s surface with Decontaminate Colors applied along `coverage`'s soft edge, colours read from `source`. */
1721
+ private decontaminatedSurface;
1676
1722
  /**
1677
1723
  * Loads a selection from a mask image (an AI segmentation, a saved mask): a data URL / URL or
1678
1724
  * RGBA pixels, by luminance (white = selected) or a channel. Any size; it is resampled.
@@ -1723,6 +1769,8 @@ export declare class ImageEditorController {
1723
1769
  beforeApply?: (outlines: ImagePoint[][]) => void | Promise<void>;
1724
1770
  /** Without a model: smoother, less blocky edges (Auto-Enhance). */
1725
1771
  enhanceEdge?: boolean;
1772
+ /** Without a model: hears the stages of finding the subject. */
1773
+ onProgress?: SelectionProgress;
1726
1774
  }): Promise<{
1727
1775
  segments: {
1728
1776
  label: string;