@pixerate/editor 0.24.0 → 0.25.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/README.md +71 -1
- package/THIRD_PARTY_NOTICES.md +29 -0
- package/dist/agent/index.cjs +10 -9
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +1 -1
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.js +4 -3
- package/dist/agent/index.js.map +1 -1
- package/dist/canvas/index.cjs +3173 -340
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +617 -4
- package/dist/canvas/index.d.ts +617 -4
- package/dist/canvas/index.js +3105 -272
- package/dist/canvas/index.js.map +1 -1
- package/dist/chunk-4BVP64JJ.cjs +1406 -0
- package/dist/chunk-4BVP64JJ.cjs.map +1 -0
- package/dist/{chunk-XNORY7M6.cjs → chunk-7WISYZFO.cjs} +105 -50
- package/dist/chunk-7WISYZFO.cjs.map +1 -0
- package/dist/{chunk-OLZJXL4R.cjs → chunk-AL6JMGWW.cjs} +59 -25
- package/dist/chunk-AL6JMGWW.cjs.map +1 -0
- package/dist/chunk-BVP3TSLH.cjs +69 -0
- package/dist/chunk-BVP3TSLH.cjs.map +1 -0
- package/dist/{chunk-MCSJFWAO.cjs → chunk-C7P22VIP.cjs} +670 -96
- package/dist/chunk-C7P22VIP.cjs.map +1 -0
- package/dist/{chunk-PGNZKFQS.js → chunk-ECCCYKGL.js} +76 -21
- package/dist/chunk-ECCCYKGL.js.map +1 -0
- package/dist/{chunk-3CN2WD3X.js → chunk-FH6F67DN.js} +646 -72
- package/dist/chunk-FH6F67DN.js.map +1 -0
- package/dist/chunk-HRMEDT2L.js +1406 -0
- package/dist/chunk-HRMEDT2L.js.map +1 -0
- package/dist/{chunk-ITBSKI26.js → chunk-IXHSYOVY.js} +941 -9
- package/dist/chunk-IXHSYOVY.js.map +1 -0
- package/dist/{chunk-FODNLX5N.js → chunk-NAXVVS5I.js} +38 -4
- package/dist/chunk-NAXVVS5I.js.map +1 -0
- package/dist/chunk-O5RYH2PG.js +69 -0
- package/dist/chunk-O5RYH2PG.js.map +1 -0
- package/dist/{chunk-SBCZ6RN5.cjs → chunk-PO6A6QQH.cjs} +1039 -107
- package/dist/chunk-PO6A6QQH.cjs.map +1 -0
- package/dist/{chunk-3LV6RRPH.js → chunk-QGYDWPRM.js} +2 -2
- package/dist/{chunk-U5KWZU4X.js → chunk-RR7F5GUM.js} +2632 -129
- package/dist/chunk-RR7F5GUM.js.map +1 -0
- package/dist/{chunk-5S3Z4PPF.js → chunk-UAKDG62Z.js} +232 -25
- package/dist/chunk-UAKDG62Z.js.map +1 -0
- package/dist/{chunk-SML64VJG.cjs → chunk-V3CHHWOE.cjs} +4 -4
- package/dist/{chunk-SML64VJG.cjs.map → chunk-V3CHHWOE.cjs.map} +1 -1
- package/dist/chunk-WSQKHXW7.cjs +5726 -0
- package/dist/chunk-WSQKHXW7.cjs.map +1 -0
- package/dist/{chunk-D27YFC46.cjs → chunk-X4N4WUKB.cjs} +267 -60
- package/dist/chunk-X4N4WUKB.cjs.map +1 -0
- package/dist/commands/index.cjs +74 -1
- package/dist/commands/index.cjs.map +1 -1
- package/dist/commands/index.d.cts +34 -1
- package/dist/commands/index.d.ts +34 -1
- package/dist/commands/index.js +73 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/compare/index.cjs +3 -3
- package/dist/compare/index.d.cts +1 -1
- package/dist/compare/index.d.ts +1 -1
- package/dist/compare/index.js +2 -2
- package/dist/controller-BIJiNoVs.d.cts +1842 -0
- package/dist/controller-BIJiNoVs.d.ts +1842 -0
- package/dist/{documents-BQjzJNe2.d.ts → documents-CHT1U5Vs.d.ts} +10 -0
- package/dist/{documents-KRTPhvst.d.cts → documents-Gp7wb0Me.d.cts} +10 -0
- package/dist/extensions/index.cjs +53 -6
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +12 -4
- package/dist/extensions/index.d.ts +12 -4
- package/dist/extensions/index.js +53 -6
- package/dist/generation/index.cjs +1013 -69
- package/dist/generation/index.cjs.map +1 -1
- package/dist/generation/index.d.cts +474 -13
- package/dist/generation/index.d.ts +474 -13
- package/dist/generation/index.js +976 -32
- package/dist/generation/index.js.map +1 -1
- package/dist/image-editor/index.cjs +3385 -1275
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +693 -128
- package/dist/image-editor/index.d.ts +693 -128
- package/dist/image-editor/index.js +3325 -1215
- package/dist/image-editor/index.js.map +1 -1
- package/dist/{index-fJrlkJCd.d.ts → index-7a6bHTLy.d.ts} +494 -5
- package/dist/{index-BhJBSm2d.d.cts → index-Csd5qI8u.d.cts} +494 -5
- package/dist/index.cjs +1491 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -19
- package/dist/index.d.ts +110 -19
- package/dist/index.js +1464 -18
- package/dist/index.js.map +1 -1
- package/dist/mention-text-CDnCFd3c.d.cts +53 -0
- package/dist/mention-text-CDnCFd3c.d.ts +53 -0
- package/dist/model-C1zApQM8.d.cts +219 -0
- package/dist/model-C1zApQM8.d.ts +219 -0
- package/dist/persistence/index.d.cts +3 -120
- package/dist/persistence/index.d.ts +3 -120
- package/dist/{registry-GJI4gToU.d.cts → registry-CEgwXED1.d.cts} +12 -1
- package/dist/{registry-GJI4gToU.d.ts → registry-CEgwXED1.d.ts} +12 -1
- package/dist/serializers/index.cjs +12 -4
- package/dist/serializers/index.cjs.map +1 -1
- package/dist/serializers/index.d.cts +39 -12
- package/dist/serializers/index.d.ts +39 -12
- package/dist/serializers/index.js +12 -4
- package/dist/spreadsheet/index.cjs +127 -3
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +431 -11
- package/dist/spreadsheet/index.d.ts +431 -11
- package/dist/spreadsheet/index.js +127 -3
- package/dist/storage-BpFfspHm.d.cts +120 -0
- package/dist/storage-BpFfspHm.d.ts +120 -0
- package/dist/tokens/index.cjs +115 -0
- package/dist/tokens/index.cjs.map +1 -0
- package/dist/tokens/index.d.cts +212 -0
- package/dist/tokens/index.d.ts +212 -0
- package/dist/tokens/index.js +115 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/{track-changes-BK5sVf4_.d.cts → track-changes-D_VAPELi.d.cts} +95 -11
- package/dist/{track-changes-CDjCrwKe.d.ts → track-changes-Db_fGEvx.d.ts} +95 -11
- package/package.json +6 -1
- package/dist/chunk-3CN2WD3X.js.map +0 -1
- package/dist/chunk-5S3Z4PPF.js.map +0 -1
- package/dist/chunk-D27YFC46.cjs.map +0 -1
- package/dist/chunk-FODNLX5N.js.map +0 -1
- package/dist/chunk-ITBSKI26.js.map +0 -1
- package/dist/chunk-MA2F5KHF.cjs +0 -3223
- package/dist/chunk-MA2F5KHF.cjs.map +0 -1
- package/dist/chunk-MCSJFWAO.cjs.map +0 -1
- package/dist/chunk-OLZJXL4R.cjs.map +0 -1
- package/dist/chunk-PGNZKFQS.js.map +0 -1
- package/dist/chunk-SBCZ6RN5.cjs.map +0 -1
- package/dist/chunk-U5KWZU4X.js.map +0 -1
- package/dist/chunk-XNORY7M6.cjs.map +0 -1
- package/dist/controller-BhLLAoi8.d.cts +0 -1000
- package/dist/controller-BhLLAoi8.d.ts +0 -1000
- /package/dist/{chunk-3LV6RRPH.js.map → chunk-QGYDWPRM.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { b as LoadReport, J as JsonObject, f as MigrationStep } from '../migrate-iTlm3a8h.cjs';
|
|
2
|
-
import { A as AgentToolProvider } from '../registry-DnzpgY27.cjs';
|
|
2
|
+
import { A as AgentToolProvider, a as AgentTool } from '../registry-DnzpgY27.cjs';
|
|
3
3
|
import '../schema-DYDGdYL9.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -50,6 +50,94 @@ declare function blendPixel(mode: BlendMode, backdrop: readonly number[], source
|
|
|
50
50
|
*/
|
|
51
51
|
declare function blendImageData(backdrop: ImageData, source: ImageData, mode: BlendMode, alpha?: number): void;
|
|
52
52
|
|
|
53
|
+
/**
|
|
54
|
+
* A selection: one 8-bit coverage value per image pixel (0 = not selected, 255 = fully
|
|
55
|
+
* selected), row-major over the whole source image in natural pixels — the same space as the
|
|
56
|
+
* crop box and annotations. Soft values are partial selection (feathered or anti-aliased edges).
|
|
57
|
+
*
|
|
58
|
+
* Treat a mask as immutable: every operation returns a new one, so history entries can share
|
|
59
|
+
* them without copying.
|
|
60
|
+
*/
|
|
61
|
+
interface SelectionMask {
|
|
62
|
+
readonly width: number;
|
|
63
|
+
readonly height: number;
|
|
64
|
+
readonly data: Uint8Array;
|
|
65
|
+
/** Bounding box of the non-zero coverage, or `null` when nothing is selected. */
|
|
66
|
+
readonly bounds: CropBox | null;
|
|
67
|
+
}
|
|
68
|
+
/** How a new selection combines with the current one. */
|
|
69
|
+
type SelectionMode = 'replace' | 'add' | 'subtract' | 'intersect';
|
|
70
|
+
declare const SELECTION_MODES: readonly SelectionMode[];
|
|
71
|
+
declare function isSelectionMode(value: unknown): value is SelectionMode;
|
|
72
|
+
/** Parses `replace|add|subtract|intersect`; anything else is `replace`. */
|
|
73
|
+
declare function parseSelectionMode(value: unknown): SelectionMode;
|
|
74
|
+
/** RGBA pixels, 8 bits per channel, straight alpha (an `ImageData` qualifies). */
|
|
75
|
+
interface PixelBuffer {
|
|
76
|
+
width: number;
|
|
77
|
+
height: number;
|
|
78
|
+
data: ArrayLike<number>;
|
|
79
|
+
}
|
|
80
|
+
/** Serialized selection: a run-length encoding of the 8-bit coverage. */
|
|
81
|
+
interface SerializedSelection {
|
|
82
|
+
width: number;
|
|
83
|
+
height: number;
|
|
84
|
+
/** `r1:` + base64 of (value byte, LEB128 run length) pairs. */
|
|
85
|
+
rle: string;
|
|
86
|
+
}
|
|
87
|
+
/** Bounding box of non-zero bytes. */
|
|
88
|
+
declare function computeSelectionBounds(width: number, height: number, data: ArrayLike<number>): CropBox | null;
|
|
89
|
+
/** Wraps coverage bytes (taken over, not copied) as a selection, computing its bounds. */
|
|
90
|
+
declare function createSelectionMask(width: number, height: number, data?: Uint8Array): SelectionMask;
|
|
91
|
+
/** Select › All. */
|
|
92
|
+
declare function fullSelection(width: number, height: number): SelectionMask;
|
|
93
|
+
declare function isSelectionEmpty(mask: SelectionMask | null | undefined): boolean;
|
|
94
|
+
/** Coverage at a pixel, 0..1 (0 outside the image). */
|
|
95
|
+
declare function selectionValueAt(mask: SelectionMask, x: number, y: number): number;
|
|
96
|
+
/** 8-bit value of a coverage (clamped and rounded; NaN → 0). */
|
|
97
|
+
declare function coverageToByte(v: number): number;
|
|
98
|
+
/** A selection from 0..1 coverage. */
|
|
99
|
+
declare function selectionFromCoverage(width: number, height: number, coverage: ArrayLike<number>): SelectionMask;
|
|
100
|
+
/** The selection's coverage as 0..1 floats. */
|
|
101
|
+
declare function selectionToCoverage(mask: SelectionMask): Float32Array;
|
|
102
|
+
/** Number of fully-or-partly selected pixels, weighted by coverage (Σ coverage). */
|
|
103
|
+
declare function selectionArea(mask: SelectionMask | null | undefined): number;
|
|
104
|
+
/**
|
|
105
|
+
* Combines `next` with `prev` by `mode` (8-bit, exact: combining a mask with itself is a no-op).
|
|
106
|
+
* Add is the maximum, Subtract `max(prev − next, 0)`, Intersect the minimum. A missing `prev`
|
|
107
|
+
* reads as nothing selected. Returns `null` when nothing remains selected.
|
|
108
|
+
*/
|
|
109
|
+
declare function combineSelections(prev: SelectionMask | null | undefined, next: SelectionMask, mode: SelectionMode): SelectionMask | null;
|
|
110
|
+
/** Select › Inverse. */
|
|
111
|
+
declare function invertSelection(mask: SelectionMask): SelectionMask;
|
|
112
|
+
/** Bilinear resample to another size (e.g. an AI mask returned at a different resolution). */
|
|
113
|
+
declare function resizeSelection(mask: SelectionMask, width: number, height: number): SelectionMask;
|
|
114
|
+
type SelectionChannel = 'alpha' | 'luminance' | 'red' | 'green' | 'blue';
|
|
115
|
+
/**
|
|
116
|
+
* A selection from an image: by default its luminance (white = selected, the usual convention
|
|
117
|
+
* of segmentation masks), or one channel. Partly transparent pixels count as black for
|
|
118
|
+
* luminance, so a mask PNG with transparency works either way.
|
|
119
|
+
*/
|
|
120
|
+
declare function selectionFromPixels(pixels: PixelBuffer, options?: {
|
|
121
|
+
channel?: SelectionChannel;
|
|
122
|
+
invert?: boolean;
|
|
123
|
+
threshold?: number;
|
|
124
|
+
}): SelectionMask;
|
|
125
|
+
/** The selection as RGBA pixels: grey (white = selected, opaque) or white with coverage as alpha. */
|
|
126
|
+
declare function selectionToPixels(mask: SelectionMask, as?: 'gray' | 'alpha'): {
|
|
127
|
+
width: number;
|
|
128
|
+
height: number;
|
|
129
|
+
data: Uint8ClampedArray;
|
|
130
|
+
};
|
|
131
|
+
/** Run-length encodes coverage bytes: `r1:` + base64 of (value, LEB128 run length) pairs. */
|
|
132
|
+
declare function encodeSelectionRle(data: Uint8Array): string;
|
|
133
|
+
/** Decodes {@link encodeSelectionRle}; throws unless the runs cover exactly `length` bytes. */
|
|
134
|
+
declare function decodeSelectionRle(rle: string, length: number): Uint8Array;
|
|
135
|
+
declare function serializeSelection(mask: SelectionMask): SerializedSelection;
|
|
136
|
+
/** Restores a {@link SerializedSelection}; throws on damaged data. */
|
|
137
|
+
declare function deserializeSelection(value: unknown): SelectionMask;
|
|
138
|
+
/** A short, stable hash of a string or bytes (FNV-1a, 32-bit, hex) for cache keys. */
|
|
139
|
+
declare function hashMaskContent(content: string | Uint8Array): string;
|
|
140
|
+
|
|
53
141
|
interface ImageDimensions {
|
|
54
142
|
width: number;
|
|
55
143
|
height: number;
|
|
@@ -209,6 +297,27 @@ interface AdjustmentLayerBase {
|
|
|
209
297
|
opacity: number;
|
|
210
298
|
/** How the adjusted colour is blended over the layers below. */
|
|
211
299
|
blend: BlendMode;
|
|
300
|
+
/**
|
|
301
|
+
* Optional layer mask (natural image pixels): where it is 0 the layer has no effect. Missing:
|
|
302
|
+
* the layer applies everywhere (layers saved before masks existed are unchanged).
|
|
303
|
+
*/
|
|
304
|
+
mask?: AdjustmentLayerMask;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* A layer mask: 8-bit coverage of the source image, run-length encoded (see
|
|
308
|
+
* `encodeSelectionRle`), plus non-destructive density and feather.
|
|
309
|
+
*/
|
|
310
|
+
interface AdjustmentLayerMask {
|
|
311
|
+
width: number;
|
|
312
|
+
height: number;
|
|
313
|
+
/** `r1:` run-length encoding of the mask bytes. */
|
|
314
|
+
rle: string;
|
|
315
|
+
/** 0..1 (missing = 1). */
|
|
316
|
+
density?: number;
|
|
317
|
+
/** Gaussian σ in pixels (missing = 0). */
|
|
318
|
+
feather?: number;
|
|
319
|
+
/** `false` keeps the mask but ignores it. */
|
|
320
|
+
enabled?: boolean;
|
|
212
321
|
}
|
|
213
322
|
/** A non-destructive adjustment layer (Photoshop's Layer › New Adjustment Layer). */
|
|
214
323
|
type AdjustmentLayer = {
|
|
@@ -306,6 +415,13 @@ interface ImageEditorState {
|
|
|
306
415
|
zoom: number;
|
|
307
416
|
pan: ImagePoint;
|
|
308
417
|
isOriginalCompared: boolean;
|
|
418
|
+
/**
|
|
419
|
+
* The active selection (8-bit coverage over the source image), or null/missing when nothing is
|
|
420
|
+
* selected. Recorded in undo history and saved as `selection` in `toJSON()`.
|
|
421
|
+
*/
|
|
422
|
+
selection?: SelectionMask | null;
|
|
423
|
+
/** Quick Mask view: tint the unselected area instead of drawing marching ants (view state). */
|
|
424
|
+
quickMask?: boolean;
|
|
309
425
|
}
|
|
310
426
|
interface SerializedImageEditorState {
|
|
311
427
|
/**
|
|
@@ -318,6 +434,8 @@ interface SerializedImageEditorState {
|
|
|
318
434
|
adjustments: ImageAdjustments;
|
|
319
435
|
depthMask: DepthMaskOptions;
|
|
320
436
|
annotations: Annotation[];
|
|
437
|
+
/** The active selection, run-length encoded. Missing when nothing is selected. */
|
|
438
|
+
selection?: SerializedSelection;
|
|
321
439
|
}
|
|
322
440
|
interface ExportOptions {
|
|
323
441
|
format?: 'image/png' | 'image/jpeg' | 'image/webp';
|
|
@@ -356,7 +474,9 @@ interface ImageEditorAIHooks {
|
|
|
356
474
|
* ({@link applyProcess2Adjustments}); anything else (including a missing value, as in edits saved
|
|
357
475
|
* before process versions existed) is the frozen legacy rendering ({@link applyLegacyAdjustments}).
|
|
358
476
|
*/
|
|
359
|
-
declare function applyAdjustments(imageData: ImageData, adjustments: ImageAdjustments
|
|
477
|
+
declare function applyAdjustments(imageData: ImageData, adjustments: ImageAdjustments, options?: {
|
|
478
|
+
layerMasks?: ReadonlyMap<string, ArrayLike<number>>;
|
|
479
|
+
}): void;
|
|
360
480
|
/**
|
|
361
481
|
* Process 1: the original 8-bit gamma-space rendering, clamping after every step. Frozen so
|
|
362
482
|
* that edits saved without a `process` look exactly as they always have. `tint` is ignored.
|
|
@@ -540,6 +660,15 @@ interface RenderOptions {
|
|
|
540
660
|
interactive?: boolean;
|
|
541
661
|
draftAnnotation?: Annotation | null;
|
|
542
662
|
draftCrop?: CropBox | null;
|
|
663
|
+
/**
|
|
664
|
+
* How the active selection is shown: marching ants (default when there is a selection),
|
|
665
|
+
* a Quick Mask tint over the unselected area (default when `state.quickMask`), or not at all.
|
|
666
|
+
*/
|
|
667
|
+
selectionDisplay?: 'ants' | 'quickMask' | 'none';
|
|
668
|
+
/** Dash offset of the marching ants in screen pixels (animate it to make them march). */
|
|
669
|
+
antsOffset?: number;
|
|
670
|
+
/** A selection being drawn (e.g. a lasso), shown as a dashed outline in natural pixels. */
|
|
671
|
+
draftSelectionPath?: ImagePoint[] | null;
|
|
543
672
|
}
|
|
544
673
|
/**
|
|
545
674
|
* Image Cache to avoid refetching HTMLImageElement objects repeatedly during re-renders.
|
|
@@ -581,6 +710,13 @@ declare class ImageEditorRenderer {
|
|
|
581
710
|
* and the depth mask (which receives the identical transform so it stays aligned).
|
|
582
711
|
*/
|
|
583
712
|
private renderBaseImage;
|
|
713
|
+
private quickMaskCache;
|
|
714
|
+
private outlineCache;
|
|
715
|
+
/** Rubylith over the unselected area, drawn in natural image space. */
|
|
716
|
+
private drawQuickMask;
|
|
717
|
+
/** Marching ants: a white line under a black dashed one, one screen pixel wide. */
|
|
718
|
+
private drawAnts;
|
|
719
|
+
private drawDraftPath;
|
|
584
720
|
private getSourceId;
|
|
585
721
|
/**
|
|
586
722
|
* Draws an individual annotation onto the canvas.
|
|
@@ -623,10 +759,355 @@ declare class ImageEditorRenderer {
|
|
|
623
759
|
renderMask(state: ImageEditorState, options?: {
|
|
624
760
|
useAnnotations?: boolean;
|
|
625
761
|
useCrop?: boolean;
|
|
762
|
+
useSelection?: boolean;
|
|
626
763
|
}): Promise<HTMLCanvasElement>;
|
|
627
764
|
private drawAnnotationMask;
|
|
628
765
|
}
|
|
629
766
|
|
|
767
|
+
interface ShapeSelectionOptions {
|
|
768
|
+
/** Partial coverage along the edge (default true). */
|
|
769
|
+
antiAlias?: boolean;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Even-odd polygon coverage over a `width × height` image: exact horizontal coverage on 4
|
|
773
|
+
* sub-rows per pixel row (1 without anti-aliasing, where a pixel is in when its centre is).
|
|
774
|
+
* Each sub-row only tests the edges that cross it (an active edge list over edges sorted by
|
|
775
|
+
* their top), so the cost is about pixels + edges × rows they span.
|
|
776
|
+
*/
|
|
777
|
+
declare function polygonCoverage(points: readonly ImagePoint[], width: number, height: number, antiAlias?: boolean): Float32Array;
|
|
778
|
+
/** Lasso / polygonal lasso: an even-odd polygon in natural image pixels. */
|
|
779
|
+
declare function polygonSelection(width: number, height: number, points: readonly ImagePoint[], options?: ShapeSelectionOptions): SelectionMask;
|
|
780
|
+
/** Normalises a rectangle with a negative width or height. */
|
|
781
|
+
declare function normalizeRect(rect: CropBox): CropBox;
|
|
782
|
+
/** Rectangular marquee. Fractional edges get partial coverage when anti-aliased. */
|
|
783
|
+
declare function rectSelection(width: number, height: number, rect: CropBox, options?: ShapeSelectionOptions): SelectionMask;
|
|
784
|
+
/** The ellipse inscribed in `rect` as a polygon fine enough that its chords stay within 0.05 px. */
|
|
785
|
+
declare function ellipsePoints(rect: CropBox): ImagePoint[];
|
|
786
|
+
/** Elliptical marquee inscribed in `rect`. */
|
|
787
|
+
declare function ellipseSelection(width: number, height: number, rect: CropBox, options?: ShapeSelectionOptions): SelectionMask;
|
|
788
|
+
|
|
789
|
+
/** How the magic wand measures colour difference. */
|
|
790
|
+
type ColorDistance = 'rgb' | 'perceptual';
|
|
791
|
+
interface MagicWandOptions {
|
|
792
|
+
/**
|
|
793
|
+
* 0..255. `rgb`: the largest per-channel difference in levels (alpha included), as
|
|
794
|
+
* Photoshop's wand. `perceptual`: CIE76 ΔE*ab, with 255 ≙ ΔE 100. Default 32.
|
|
795
|
+
*/
|
|
796
|
+
tolerance?: number;
|
|
797
|
+
/** Only the 4-connected region around the seed (default true); otherwise every similar pixel. */
|
|
798
|
+
contiguous?: boolean;
|
|
799
|
+
/** Soft one-pixel fringe on the edge (default true). */
|
|
800
|
+
antiAlias?: boolean;
|
|
801
|
+
/** Default `rgb`. */
|
|
802
|
+
distance?: ColorDistance;
|
|
803
|
+
}
|
|
804
|
+
/** CIE Lab (D65) of an 8-bit sRGB colour. */
|
|
805
|
+
declare function srgb8ToLab(r: number, g: number, b: number): [number, number, number];
|
|
806
|
+
/**
|
|
807
|
+
* Magic wand: pixels similar to the seed pixel. Contiguous mode is a scanline span fill with an
|
|
808
|
+
* explicit stack (fill a run, then scan the rows above and below it for new runs), so it is
|
|
809
|
+
* linear in the pixels visited and never recurses. An empty selection when the seed is outside.
|
|
810
|
+
*/
|
|
811
|
+
declare function magicWand(pixels: PixelBuffer, seed: ImagePoint, options?: MagicWandOptions): SelectionMask;
|
|
812
|
+
/** One Color Range sample: a colour (0..255 levels or `#rrggbb`) and, optionally, where it was picked. */
|
|
813
|
+
interface ColorRangeSample {
|
|
814
|
+
color: readonly [number, number, number] | string;
|
|
815
|
+
at?: ImagePoint;
|
|
816
|
+
}
|
|
817
|
+
interface ColorRangeOptions {
|
|
818
|
+
/** 0..200 levels (default 40): coverage falls off linearly to 0 at `fuzziness + 1` levels. */
|
|
819
|
+
fuzziness?: number;
|
|
820
|
+
/**
|
|
821
|
+
* Localized Color Clusters: a sample with a position also fades with distance from it,
|
|
822
|
+
* reaching 0 at this many pixels.
|
|
823
|
+
*/
|
|
824
|
+
localized?: number;
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Select › Color Range › Sampled Colors: each pixel takes its best match over the samples; a
|
|
828
|
+
* match falls off linearly with the largest per-channel difference, `1 − d / (fuzziness + 1)`.
|
|
829
|
+
* Transparent pixels are never selected.
|
|
830
|
+
*/
|
|
831
|
+
declare function colorRange(pixels: PixelBuffer, samples: readonly ColorRangeSample[], options?: ColorRangeOptions): SelectionMask;
|
|
832
|
+
type ToneRangePreset = 'shadows' | 'midtones' | 'highlights';
|
|
833
|
+
/** Luma bounds (0..255, Rec. 601) of the tonal presets. */
|
|
834
|
+
declare const TONE_RANGE_PRESETS: Record<ToneRangePreset, [number, number]>;
|
|
835
|
+
/**
|
|
836
|
+
* Select › Color Range › Shadows / Midtones / Highlights: pixels whose luma lies in `lo..hi` are
|
|
837
|
+
* selected; outside, selection falls off linearly to 0 over `falloff` levels.
|
|
838
|
+
*/
|
|
839
|
+
declare function toneRange(pixels: PixelBuffer, range: ToneRangePreset | readonly [number, number], falloff?: number): SelectionMask;
|
|
840
|
+
/**
|
|
841
|
+
* Select › Color Range › Reds … Magentas (`center` 0, 60, …, 300°): closeness of hue (full at
|
|
842
|
+
* the centre, none 60° away) × chroma × (2 − max), so neutrals are never selected.
|
|
843
|
+
*/
|
|
844
|
+
declare function hueRange(pixels: PixelBuffer, center: number): SelectionMask;
|
|
845
|
+
|
|
846
|
+
/** Distance reported for every pixel when there is no seed at all. */
|
|
847
|
+
declare const EMPTY_DISTANCE = 10000000000;
|
|
848
|
+
/**
|
|
849
|
+
* Exact Euclidean distance from every pixel centre to the nearest seed pixel centre (row-major
|
|
850
|
+
* `inside`, non-zero = seed): nearest seeds along columns, then the lower envelope of parabolas
|
|
851
|
+
* along rows (Felzenszwalb & Huttenlocher). Linear in the pixel count.
|
|
852
|
+
*/
|
|
853
|
+
declare function distanceTransform(inside: ArrayLike<number | boolean>, width: number, height: number): Float32Array;
|
|
854
|
+
/** Grows coverage (0..1) by `r` pixels: covered when the nearest selected centre is ≤ r away (fractional r → partial). */
|
|
855
|
+
declare function expandCoverage(m: ArrayLike<number>, w: number, h: number, r: number): Float32Array;
|
|
856
|
+
/** Shrinks coverage by `r` pixels (expands the inverse). */
|
|
857
|
+
declare function contractCoverage(m: ArrayLike<number>, w: number, h: number, r: number): Float32Array;
|
|
858
|
+
/**
|
|
859
|
+
* Select › Modify › Border: a soft band `2r` wide centred on the edge. A pixel `D` away (centre
|
|
860
|
+
* to centre) from the nearest pixel on the other side of the edge is selected `1 − (D − 1) / r`.
|
|
861
|
+
*/
|
|
862
|
+
declare function borderCoverage(m: ArrayLike<number>, w: number, h: number, r: number): Float32Array;
|
|
863
|
+
/**
|
|
864
|
+
* Select › Modify › Smooth: box average of radius `round(r)` with replicated edges, then
|
|
865
|
+
* re-thresholded at ½ — specks drop, corners round, straight edges stay hard.
|
|
866
|
+
*/
|
|
867
|
+
declare function smoothCoverage(m: ArrayLike<number>, w: number, h: number, r: number): Float32Array;
|
|
868
|
+
/** Above this σ a Gaussian is approximated by three box passes (cost independent of σ). */
|
|
869
|
+
declare const DIRECT_GAUSSIAN_MAX_SIGMA = 8;
|
|
870
|
+
type Edge = 'zero' | 'clamp';
|
|
871
|
+
/**
|
|
872
|
+
* Separable Gaussian blur of a single-channel float image. `edge` `zero` treats pixels beyond
|
|
873
|
+
* the image as 0 (selection feather), `clamp` replicates the border (mask refinement). σ up to
|
|
874
|
+
* {@link DIRECT_GAUSSIAN_MAX_SIGMA} is convolved directly; wider blurs use three box passes, so
|
|
875
|
+
* the cost per pixel never grows with σ.
|
|
876
|
+
*/
|
|
877
|
+
declare function gaussianBlur(src: ArrayLike<number>, w: number, h: number, sigma: number, edge?: Edge): Float32Array;
|
|
878
|
+
/** Select › Modify › Feather: Gaussian blur with σ = radius (as Photoshop), zero beyond the image. */
|
|
879
|
+
declare function featherCoverage(m: ArrayLike<number>, w: number, h: number, radius: number): Float32Array;
|
|
880
|
+
/** Grey dilation (`grow`) or erosion with a square of radius `r`, separable, O(1) per pixel. */
|
|
881
|
+
declare function greyMorphology(src: ArrayLike<number>, w: number, h: number, r: number, grow: boolean): Float32Array;
|
|
882
|
+
/**
|
|
883
|
+
* Grows (positive) or shrinks (negative) soft coverage by a fractional distance: whole pixels
|
|
884
|
+
* use one morphology, the remainder blends with the next pixel, so 0.3 px differs from 1 px.
|
|
885
|
+
*/
|
|
886
|
+
declare function shiftCoverage(src: ArrayLike<number>, w: number, h: number, amount: number): Float32Array;
|
|
887
|
+
type SelectionModifyOp = 'grow' | 'shrink' | 'feather' | 'border' | 'smooth';
|
|
888
|
+
declare const SELECTION_MODIFY_OPS: readonly SelectionModifyOp[];
|
|
889
|
+
/** Select › Modify (grow = Expand, shrink = Contract, feather, border, smooth) by `radius` pixels. */
|
|
890
|
+
declare function modifySelection(mask: SelectionMask, op: SelectionModifyOp, radius: number): SelectionMask;
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* Refine Edge / Select and Mask parameters (Photoshop's units). Refinement is edge-aware: within
|
|
894
|
+
* `radius` pixels of the mask's edge the coverage is re-estimated from the image with a colour
|
|
895
|
+
* guided filter (He et al.), so a coarse or misaligned mask (e.g. an AI segmentation) follows
|
|
896
|
+
* the real edges of the image.
|
|
897
|
+
*/
|
|
898
|
+
interface RefineEdgeParams {
|
|
899
|
+
/** Edge-detection band radius in pixels (0 = no edge detection). */
|
|
900
|
+
radius?: number;
|
|
901
|
+
/** Narrow the band where the image edge is sharp (hair stays soft, hard edges stay hard). */
|
|
902
|
+
smartRadius?: boolean;
|
|
903
|
+
/** 0..100: rounds jagged edges. */
|
|
904
|
+
smooth?: number;
|
|
905
|
+
/** Pixels of Gaussian softening. */
|
|
906
|
+
feather?: number;
|
|
907
|
+
/** 0..100: hardens soft edges. */
|
|
908
|
+
contrast?: number;
|
|
909
|
+
/** −100..100: moves the edge out (positive) or in; 100 % is `max(radius, 4)` pixels. */
|
|
910
|
+
shiftEdge?: number;
|
|
911
|
+
}
|
|
912
|
+
declare const DEFAULT_REFINE_EDGE_PARAMS: Required<RefineEdgeParams>;
|
|
913
|
+
/** Guided-filter regulariser (colour guide, samples in 0..1). */
|
|
914
|
+
declare const GUIDED_FILTER_EPS = 0.0001;
|
|
915
|
+
/** Clamped, complete parameters. */
|
|
916
|
+
declare function normalizeRefineEdgeParams(p?: RefineEdgeParams): Required<RefineEdgeParams>;
|
|
917
|
+
/** Pixels around the mask's content that refinement can read or write. */
|
|
918
|
+
declare function refineEdgeHalo(params?: RefineEdgeParams): number;
|
|
919
|
+
/** Box mean of radius `r` (window clipped to the image, divided by its pixel count). O(1) per pixel. */
|
|
920
|
+
declare function boxMean(src: ArrayLike<number>, w: number, h: number, r: number): Float32Array;
|
|
921
|
+
/**
|
|
922
|
+
* Guided filter with a colour guide (He et al., Eq. 19–21: `a_k = (Σ_k + εU)⁻¹ cov_k(I, p)`):
|
|
923
|
+
* filters `p` so that it is locally a linear function of the guide's colour, which makes the
|
|
924
|
+
* output's edges follow the guide's edges. `guide` is three planes of 0..1 values.
|
|
925
|
+
*/
|
|
926
|
+
declare function guidedFilterColor(guide: readonly [Float32Array, Float32Array, Float32Array], p: Float32Array, w: number, h: number, r: number, eps?: number): Float32Array;
|
|
927
|
+
/**
|
|
928
|
+
* Per-pixel transition width (pixels) of the guide's luminance: local range over local maximum
|
|
929
|
+
* gradient in a window of radius `r` (a sharp step gives about 2, a ramp of width L about L).
|
|
930
|
+
*/
|
|
931
|
+
declare function edgeWidth(guide: readonly [Float32Array, Float32Array, Float32Array], w: number, h: number, r: number): Float32Array;
|
|
932
|
+
/**
|
|
933
|
+
* Refines soft coverage `m` (`w × h`, 0..1) with `guide` (three 0..1 planes, required when
|
|
934
|
+
* `radius > 0`): edge-aware re-estimation in a band around the edge, then smooth, feather,
|
|
935
|
+
* contrast and shift edge, in that order.
|
|
936
|
+
*/
|
|
937
|
+
declare function refineCoverage(guide: readonly [Float32Array, Float32Array, Float32Array] | null, m: Float32Array, w: number, h: number, params?: RefineEdgeParams): Float32Array;
|
|
938
|
+
/** Three 0..1 planes of a window of an RGBA buffer. */
|
|
939
|
+
declare function guidePlanes(pixels: PixelBuffer, win?: CropBox): [Float32Array, Float32Array, Float32Array];
|
|
940
|
+
/**
|
|
941
|
+
* Refine Edge on a selection (or a coarse AI mask loaded as one) against `pixels` (the image,
|
|
942
|
+
* same size). Work is confined to the mask's bounds grown by {@link refineEdgeHalo}, so a small
|
|
943
|
+
* selection on a large image stays cheap.
|
|
944
|
+
*/
|
|
945
|
+
declare function refineSelection(pixels: PixelBuffer | null, mask: SelectionMask, params?: RefineEdgeParams): SelectionMask;
|
|
946
|
+
|
|
947
|
+
type CropHandle = 'nw' | 'ne' | 'se' | 'sw' | 'n' | 's' | 'e' | 'w' | 'inside' | null;
|
|
948
|
+
interface ViewportMetrics {
|
|
949
|
+
vpWidth: number;
|
|
950
|
+
vpHeight: number;
|
|
951
|
+
centerX: number;
|
|
952
|
+
centerY: number;
|
|
953
|
+
baseW: number;
|
|
954
|
+
baseH: number;
|
|
955
|
+
fitScale: number;
|
|
956
|
+
renderW: number;
|
|
957
|
+
renderH: number;
|
|
958
|
+
totalScale: number;
|
|
959
|
+
imageRect: {
|
|
960
|
+
x: number;
|
|
961
|
+
y: number;
|
|
962
|
+
width: number;
|
|
963
|
+
height: number;
|
|
964
|
+
};
|
|
965
|
+
cropRect: {
|
|
966
|
+
x: number;
|
|
967
|
+
y: number;
|
|
968
|
+
width: number;
|
|
969
|
+
height: number;
|
|
970
|
+
} | null;
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* A complete description of the natural-image -> target mapping (see module comment).
|
|
974
|
+
*/
|
|
975
|
+
interface ImageProjection {
|
|
976
|
+
/** Visible region in natural image pixels (crop box or full image). */
|
|
977
|
+
region: CropBox;
|
|
978
|
+
/** Rotation in degrees, normalised to [0, 360). */
|
|
979
|
+
angle: number;
|
|
980
|
+
flipH: boolean;
|
|
981
|
+
flipV: boolean;
|
|
982
|
+
/** Uniform scale from image pixels to target pixels. */
|
|
983
|
+
scale: number;
|
|
984
|
+
/** Target-space point that the centre of `region` maps to. */
|
|
985
|
+
originX: number;
|
|
986
|
+
originY: number;
|
|
987
|
+
}
|
|
988
|
+
/** Normalises any rotation in degrees to [0, 360). */
|
|
989
|
+
declare function normalizeAngle(degrees: number): number;
|
|
990
|
+
/** Whether the rotation swaps the displayed width and height. */
|
|
991
|
+
declare function isQuarterTurnSwapped(transform: Pick<ImageTransform, 'rotate'>): boolean;
|
|
992
|
+
/** Size of a region once rotated (bounding box for arbitrary angles). */
|
|
993
|
+
declare function getRotatedSize(width: number, height: number, transform: Pick<ImageTransform, 'rotate'>): {
|
|
994
|
+
width: number;
|
|
995
|
+
height: number;
|
|
996
|
+
};
|
|
997
|
+
/** Maps a natural-image point to target space. */
|
|
998
|
+
declare function projectImagePoint(pt: ImagePoint, p: ImageProjection): ImagePoint;
|
|
999
|
+
/** Exact inverse of {@link projectImagePoint}. */
|
|
1000
|
+
declare function unprojectCanvasPoint(pt: ImagePoint, p: ImageProjection): ImagePoint;
|
|
1001
|
+
/**
|
|
1002
|
+
* Applies the projection to a 2D context so that subsequent drawing in natural image
|
|
1003
|
+
* pixels lands exactly where {@link projectImagePoint} says it does.
|
|
1004
|
+
*/
|
|
1005
|
+
declare function applyImageProjectionToContext(ctx: Pick<CanvasRenderingContext2D, 'translate' | 'scale' | 'rotate'>, p: ImageProjection): void;
|
|
1006
|
+
/** Projects an image-space rectangle and returns its target-space bounding box. */
|
|
1007
|
+
declare function projectImageRect(rect: CropBox, p: ImageProjection): {
|
|
1008
|
+
x: number;
|
|
1009
|
+
y: number;
|
|
1010
|
+
width: number;
|
|
1011
|
+
height: number;
|
|
1012
|
+
};
|
|
1013
|
+
/** Clamps a crop box to the image bounds. */
|
|
1014
|
+
declare function clampCropToImage(crop: CropBox, width: number, height: number): CropBox;
|
|
1015
|
+
/**
|
|
1016
|
+
* Returns the natural-image -> canvas projection used by the interactive viewport.
|
|
1017
|
+
*/
|
|
1018
|
+
declare function getViewportProjection(state: ImageEditorState, vpWidth: number, vpHeight: number, isActivelyCropping?: boolean, cropOverride?: CropBox | null): ImageProjection;
|
|
1019
|
+
/**
|
|
1020
|
+
* Calculates current viewport projection metrics for canvas <-> image coordinate mapping.
|
|
1021
|
+
* `cropRect` is the on-screen (rotated/flipped) rectangle of the crop box.
|
|
1022
|
+
*/
|
|
1023
|
+
declare function getViewportMetrics(state: ImageEditorState, vpWidth: number, vpHeight: number, isActivelyCropping?: boolean, cropOverride?: CropBox | null): ViewportMetrics;
|
|
1024
|
+
/**
|
|
1025
|
+
* Converts a point on the canvas (in internal canvas pixel space) to natural image pixel
|
|
1026
|
+
* space, accounting for zoom, pan, fit scale, crop offset, rotation and flips.
|
|
1027
|
+
*/
|
|
1028
|
+
declare function canvasToImagePoint(canvasPt: ImagePoint, state: ImageEditorState, vpWidth: number, vpHeight: number, isActivelyCropping?: boolean): ImagePoint;
|
|
1029
|
+
/**
|
|
1030
|
+
* Converts a point in natural image pixel space to internal canvas pixel space.
|
|
1031
|
+
* Exact inverse of {@link canvasToImagePoint}.
|
|
1032
|
+
*/
|
|
1033
|
+
declare function imageToCanvasPoint(imgPt: ImagePoint, state: ImageEditorState, vpWidth: number, vpHeight: number, isActivelyCropping?: boolean): ImagePoint;
|
|
1034
|
+
/**
|
|
1035
|
+
* Converts a crop handle in screen orientation to the equivalent edge/corner of the crop
|
|
1036
|
+
* box in natural image space, or the reverse with `toScreen = true`.
|
|
1037
|
+
*/
|
|
1038
|
+
declare function mapCropHandle(handle: CropHandle, transform: ImageTransform, toScreen?: boolean): CropHandle;
|
|
1039
|
+
/**
|
|
1040
|
+
* Hit-tests the crop box and its corner/edge handles given a canvas point.
|
|
1041
|
+
* The returned handle names the edge/corner of the crop box in natural image space
|
|
1042
|
+
* (what {@link calculateCropDrag} expects); use `getCropCursor(handle, state.transform)`
|
|
1043
|
+
* to obtain the matching on-screen cursor.
|
|
1044
|
+
*/
|
|
1045
|
+
declare function hitTestCrop(canvasPt: ImagePoint, state: ImageEditorState, vpWidth: number, vpHeight: number, handleThreshold?: number, cropOverride?: CropBox | null): CropHandle;
|
|
1046
|
+
/**
|
|
1047
|
+
* Returns CSS cursor style corresponding to a crop handle. Pass the current transform when
|
|
1048
|
+
* the handle comes from {@link hitTestCrop} (image space) so the cursor matches the
|
|
1049
|
+
* on-screen orientation under rotation/flip.
|
|
1050
|
+
*/
|
|
1051
|
+
declare function getCropCursor(handle: CropHandle, transform?: ImageTransform): string;
|
|
1052
|
+
/**
|
|
1053
|
+
* Calculates updated crop rectangle given a drag interaction.
|
|
1054
|
+
*/
|
|
1055
|
+
declare function calculateCropDrag(startCrop: CropBox, handle: CropHandle, startImgPt: ImagePoint, currentImgPt: ImagePoint, imgWidth: number, imgHeight: number, aspectRatio?: number | null, transform?: ImageTransform): CropBox;
|
|
1056
|
+
/**
|
|
1057
|
+
* Calculates bounding box of an annotation.
|
|
1058
|
+
*/
|
|
1059
|
+
declare function getAnnotationBounds(ann: Annotation): {
|
|
1060
|
+
x: number;
|
|
1061
|
+
y: number;
|
|
1062
|
+
width: number;
|
|
1063
|
+
height: number;
|
|
1064
|
+
};
|
|
1065
|
+
/**
|
|
1066
|
+
* Hit tests if a point in image space is within an annotation's bounds.
|
|
1067
|
+
*/
|
|
1068
|
+
declare function hitTestAnnotation(imgPt: ImagePoint, ann: Annotation, padding?: number): boolean;
|
|
1069
|
+
|
|
1070
|
+
/** Properties of a layer mask that leave its pixels intact (Photoshop's Properties › Masks). */
|
|
1071
|
+
interface LayerMaskProps {
|
|
1072
|
+
/** 0..1 (default 1): at 0.5 the masked-out areas still get half of the adjustment. */
|
|
1073
|
+
density?: number;
|
|
1074
|
+
/** Gaussian feather σ in pixels, 0..1000 (default 0). */
|
|
1075
|
+
feather?: number;
|
|
1076
|
+
/** Disabled masks are kept but ignored (the layer applies everywhere). Default true. */
|
|
1077
|
+
enabled?: boolean;
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* A clean layer mask from stored data, or `null` when it is unusable. Defaults are left out
|
|
1081
|
+
* (density 1, feather 0, enabled), so a plain mask serializes as `{width, height, rle}`. The
|
|
1082
|
+
* RLE is only decoded when rendering.
|
|
1083
|
+
*/
|
|
1084
|
+
declare function normalizeLayerMask(raw: unknown): AdjustmentLayerMask | null;
|
|
1085
|
+
/** A layer mask holding the selection's pixels (Add Layer Mask › Reveal Selection). */
|
|
1086
|
+
declare function layerMaskFromSelection(selection: SelectionMask, props?: LayerMaskProps): AdjustmentLayerMask;
|
|
1087
|
+
/** Applies property changes; `undefined` fields keep their value. */
|
|
1088
|
+
declare function updateLayerMaskProps(mask: AdjustmentLayerMask, props: LayerMaskProps): AdjustmentLayerMask;
|
|
1089
|
+
/** The mask's pixels as a selection (Load Selection from mask), or `null` when the data is damaged. */
|
|
1090
|
+
declare function decodeLayerMask(mask: AdjustmentLayerMask): SelectionMask | null;
|
|
1091
|
+
/** Cache key of everything about a mask that changes pixels. */
|
|
1092
|
+
declare function layerMaskKey(mask: AdjustmentLayerMask | undefined): string;
|
|
1093
|
+
/**
|
|
1094
|
+
* The mask's effective coverage (0..1, mask resolution): feathered (σ = feather, borders
|
|
1095
|
+
* replicated), then density applied as `1 − density·(1 − v)`. `null` for a disabled or damaged
|
|
1096
|
+
* mask, meaning "no mask".
|
|
1097
|
+
*/
|
|
1098
|
+
declare function layerMaskCoverage(mask: AdjustmentLayerMask): Float32Array | null;
|
|
1099
|
+
/**
|
|
1100
|
+
* Resamples mask coverage (natural-image aligned, any resolution) into a target raster drawn
|
|
1101
|
+
* through `projection` (the base canvas of the renderer: crop, rotation, flips): each target
|
|
1102
|
+
* pixel centre is unprojected to natural pixels and sampled bilinearly.
|
|
1103
|
+
*/
|
|
1104
|
+
declare function projectMaskCoverage(coverage: Float32Array, maskWidth: number, maskHeight: number, naturalWidth: number, naturalHeight: number, projection: ImageProjection, targetWidth: number, targetHeight: number): Float32Array;
|
|
1105
|
+
/**
|
|
1106
|
+
* Per-layer mask coverage for a render target, keyed by layer id; `undefined` when no layer has
|
|
1107
|
+
* an enabled, valid mask (so mask-free stacks take the exact same path as before).
|
|
1108
|
+
*/
|
|
1109
|
+
declare function buildLayerMaskPlanes(layers: readonly AdjustmentLayer[] | undefined, naturalWidth: number, naturalHeight: number, projection: ImageProjection, targetWidth: number, targetHeight: number): Map<string, Float32Array> | undefined;
|
|
1110
|
+
|
|
630
1111
|
/** Latest serialized schema version (`2`: adjustment layers). */
|
|
631
1112
|
declare const IMAGE_EDITOR_SCHEMA_VERSION: 2;
|
|
632
1113
|
/** Changes to an adjustment layer; `params` is merged into the current parameters. */
|
|
@@ -636,6 +1117,22 @@ interface AdjustmentLayerUpdate<K extends AdjustmentKind = AdjustmentKind> {
|
|
|
636
1117
|
opacity?: number;
|
|
637
1118
|
blend?: BlendMode;
|
|
638
1119
|
name?: string;
|
|
1120
|
+
/** A layer mask, or `null` to remove it. */
|
|
1121
|
+
mask?: AdjustmentLayerMask | null;
|
|
1122
|
+
}
|
|
1123
|
+
/** Options shared by the selection commands. */
|
|
1124
|
+
interface SelectionCommandOptions {
|
|
1125
|
+
/** How the result combines with the current selection (default `replace`). */
|
|
1126
|
+
mode?: SelectionMode;
|
|
1127
|
+
/** Feather the new shape by this many pixels before combining (default 0). */
|
|
1128
|
+
feather?: number;
|
|
1129
|
+
}
|
|
1130
|
+
/** Where the selection tools read colours from. */
|
|
1131
|
+
interface SampleOptions {
|
|
1132
|
+
/** Sample the adjusted image (base adjustments and layers) instead of the source pixels. */
|
|
1133
|
+
sampleMerged?: boolean;
|
|
1134
|
+
/** Pixels to use instead of reading the source image (natural size, RGBA). */
|
|
1135
|
+
pixels?: PixelBuffer;
|
|
639
1136
|
}
|
|
640
1137
|
/** A new adjustment layer: its kind plus optional initial values. */
|
|
641
1138
|
interface AdjustmentLayerInit<K extends AdjustmentKind = AdjustmentKind> extends AdjustmentLayerUpdate<K> {
|
|
@@ -674,6 +1171,9 @@ declare class ImageEditorController {
|
|
|
674
1171
|
private maxHistoryDepth;
|
|
675
1172
|
private isApplyingHistory;
|
|
676
1173
|
private initialSnapshot;
|
|
1174
|
+
/** Pixels the selection tools sample (host-provided or read back from the source). */
|
|
1175
|
+
private samplePixels;
|
|
1176
|
+
private samplePixelsOverride;
|
|
677
1177
|
constructor(options?: ImageEditorOptions);
|
|
678
1178
|
/**
|
|
679
1179
|
* Loads a new source image and makes it the baseline that `reset()` returns to.
|
|
@@ -735,6 +1235,79 @@ declare class ImageEditorController {
|
|
|
735
1235
|
toggleAdjustmentLayer(id: string, enabled?: boolean): boolean;
|
|
736
1236
|
/** Removes every adjustment layer as one undo step. */
|
|
737
1237
|
clearAdjustmentLayers(): void;
|
|
1238
|
+
/** The active selection, or `null`. */
|
|
1239
|
+
getSelection(): SelectionMask | null;
|
|
1240
|
+
get hasSelection(): boolean;
|
|
1241
|
+
private get naturalSize();
|
|
1242
|
+
private dropMismatchedSelection;
|
|
1243
|
+
/**
|
|
1244
|
+
* Replaces the selection, or combines `mask` with it by `mode`, as one undo step. A mask of a
|
|
1245
|
+
* different size (e.g. an AI segmentation at another resolution) is resampled to the image.
|
|
1246
|
+
* Returns false when nothing changed.
|
|
1247
|
+
*/
|
|
1248
|
+
setSelection(mask: SelectionMask | null, mode?: SelectionMode): boolean;
|
|
1249
|
+
/** Select › All. */
|
|
1250
|
+
selectAll(): boolean;
|
|
1251
|
+
/** Select › Deselect. */
|
|
1252
|
+
deselect(): boolean;
|
|
1253
|
+
/** Select › Inverse (with nothing selected, selects everything). */
|
|
1254
|
+
invertSelection(): boolean;
|
|
1255
|
+
private shapeCommand;
|
|
1256
|
+
/** Rectangular marquee in natural image pixels. */
|
|
1257
|
+
selectRect(rect: CropBox, options?: SelectionCommandOptions & ShapeSelectionOptions): boolean;
|
|
1258
|
+
/** Elliptical marquee inscribed in `rect`. */
|
|
1259
|
+
selectEllipse(rect: CropBox, options?: SelectionCommandOptions & ShapeSelectionOptions): boolean;
|
|
1260
|
+
/** Lasso / polygonal lasso. */
|
|
1261
|
+
selectPolygon(points: ImagePoint[], options?: SelectionCommandOptions & ShapeSelectionOptions): boolean;
|
|
1262
|
+
/**
|
|
1263
|
+
* Supplies the pixels the selection tools sample (natural size RGBA), e.g. decoded in a worker
|
|
1264
|
+
* or in a test; `null` goes back to reading the source image. A new source image clears it.
|
|
1265
|
+
*/
|
|
1266
|
+
setSamplePixels(pixels: PixelBuffer | null): void;
|
|
1267
|
+
/**
|
|
1268
|
+
* The pixels the selection tools sample: the source image at natural size, or with
|
|
1269
|
+
* `sampleMerged` the source after the base adjustments and adjustment layers (no crop,
|
|
1270
|
+
* rotation or annotations). `null` without pixel access (no DOM, tainted canvas).
|
|
1271
|
+
*/
|
|
1272
|
+
getSamplePixels(options?: SampleOptions): Promise<PixelBuffer | null>;
|
|
1273
|
+
private requirePixels;
|
|
1274
|
+
/**
|
|
1275
|
+
* Magic wand at `point` (natural image pixels). Resolves to the resulting selection (null when
|
|
1276
|
+
* nothing is selected).
|
|
1277
|
+
*/
|
|
1278
|
+
magicWand(point: ImagePoint, options?: MagicWandOptions & SelectionCommandOptions & SampleOptions): Promise<SelectionMask | null>;
|
|
1279
|
+
/** Select › Color Range with colour samples (`#rrggbb` or `[r, g, b]`, optionally where they were picked). */
|
|
1280
|
+
selectColorRange(samples: ColorRangeSample[], options?: ColorRangeOptions & SelectionCommandOptions & SampleOptions): Promise<SelectionMask | null>;
|
|
1281
|
+
/** Select › Modify: grow, shrink, feather, border or smooth by `radius` pixels (one undo step). */
|
|
1282
|
+
modifySelection(op: SelectionModifyOp, radius: number): boolean;
|
|
1283
|
+
/**
|
|
1284
|
+
* Refine Edge: snaps the selection (e.g. a coarse AI mask loaded with `loadSelectionFromImage`)
|
|
1285
|
+
* to the image's edges with a guided filter, then smooth / feather / contrast / shift edge.
|
|
1286
|
+
*/
|
|
1287
|
+
refineSelection(params: RefineEdgeParams, options?: SampleOptions): Promise<boolean>;
|
|
1288
|
+
/**
|
|
1289
|
+
* Loads a selection from a mask image (an AI segmentation, a saved mask): a data URL / URL or
|
|
1290
|
+
* RGBA pixels, by luminance (white = selected) or a channel. Any size; it is resampled.
|
|
1291
|
+
*/
|
|
1292
|
+
loadSelectionFromImage(source: string | PixelBuffer, options?: {
|
|
1293
|
+
channel?: SelectionChannel;
|
|
1294
|
+
invert?: boolean;
|
|
1295
|
+
threshold?: number;
|
|
1296
|
+
mode?: SelectionMode;
|
|
1297
|
+
}): Promise<SelectionMask | null>;
|
|
1298
|
+
/** Quick Mask view (tints the unselected area). View state: no undo step. */
|
|
1299
|
+
setQuickMask(on: boolean): void;
|
|
1300
|
+
/**
|
|
1301
|
+
* Adds the selection as the layer's mask (Reveal Selection), replacing any mask, as one undo
|
|
1302
|
+
* step. Without a selection, returns false.
|
|
1303
|
+
*/
|
|
1304
|
+
applySelectionAsLayerMask(layerId: string, props?: LayerMaskProps): boolean;
|
|
1305
|
+
/** Sets (from a selection-shaped mask) or removes (`null`) a layer's mask as one undo step. */
|
|
1306
|
+
setAdjustmentLayerMask(layerId: string, mask: SelectionMask | null, props?: LayerMaskProps): boolean;
|
|
1307
|
+
/** Changes a layer mask's density (0..1), feather (px) or enabled flag; the mask pixels are kept. */
|
|
1308
|
+
setAdjustmentLayerMaskProps(layerId: string, props: LayerMaskProps, commitToHistory?: boolean): boolean;
|
|
1309
|
+
/** Load Selection from a layer mask (its pixels; density and feather are not applied). */
|
|
1310
|
+
selectionFromLayerMask(layerId: string, mode?: SelectionMode): boolean;
|
|
738
1311
|
/**
|
|
739
1312
|
* Histogram of the last rendered preview (after adjustments and layers, before annotations),
|
|
740
1313
|
* or `null` before the first render or without canvas pixel access.
|
|
@@ -762,10 +1335,12 @@ declare class ImageEditorController {
|
|
|
762
1335
|
renderMask(options?: {
|
|
763
1336
|
useAnnotations?: boolean;
|
|
764
1337
|
useCrop?: boolean;
|
|
1338
|
+
useSelection?: boolean;
|
|
765
1339
|
}): Promise<HTMLCanvasElement>;
|
|
766
1340
|
toMaskDataURL(options?: {
|
|
767
1341
|
useAnnotations?: boolean;
|
|
768
1342
|
useCrop?: boolean;
|
|
1343
|
+
useSelection?: boolean;
|
|
769
1344
|
}): Promise<string>;
|
|
770
1345
|
/**
|
|
771
1346
|
* Renders the current source image at natural size with no crop, rotation, flip,
|
|
@@ -785,135 +1360,13 @@ declare class ImageEditorController {
|
|
|
785
1360
|
*/
|
|
786
1361
|
applyBackgroundRemovedImage(newDataUrl: string): Promise<void>;
|
|
787
1362
|
private replaceSource;
|
|
1363
|
+
/** The serializable state; `selection` is included (run-length encoded) only when something is selected. */
|
|
788
1364
|
toJSON(): SerializedImageEditorState;
|
|
789
1365
|
loadJSON(data: SerializedImageEditorState): void;
|
|
790
1366
|
private serializeState;
|
|
791
1367
|
private applySerializedState;
|
|
792
1368
|
}
|
|
793
1369
|
|
|
794
|
-
type CropHandle = 'nw' | 'ne' | 'se' | 'sw' | 'n' | 's' | 'e' | 'w' | 'inside' | null;
|
|
795
|
-
interface ViewportMetrics {
|
|
796
|
-
vpWidth: number;
|
|
797
|
-
vpHeight: number;
|
|
798
|
-
centerX: number;
|
|
799
|
-
centerY: number;
|
|
800
|
-
baseW: number;
|
|
801
|
-
baseH: number;
|
|
802
|
-
fitScale: number;
|
|
803
|
-
renderW: number;
|
|
804
|
-
renderH: number;
|
|
805
|
-
totalScale: number;
|
|
806
|
-
imageRect: {
|
|
807
|
-
x: number;
|
|
808
|
-
y: number;
|
|
809
|
-
width: number;
|
|
810
|
-
height: number;
|
|
811
|
-
};
|
|
812
|
-
cropRect: {
|
|
813
|
-
x: number;
|
|
814
|
-
y: number;
|
|
815
|
-
width: number;
|
|
816
|
-
height: number;
|
|
817
|
-
} | null;
|
|
818
|
-
}
|
|
819
|
-
/**
|
|
820
|
-
* A complete description of the natural-image -> target mapping (see module comment).
|
|
821
|
-
*/
|
|
822
|
-
interface ImageProjection {
|
|
823
|
-
/** Visible region in natural image pixels (crop box or full image). */
|
|
824
|
-
region: CropBox;
|
|
825
|
-
/** Rotation in degrees, normalised to [0, 360). */
|
|
826
|
-
angle: number;
|
|
827
|
-
flipH: boolean;
|
|
828
|
-
flipV: boolean;
|
|
829
|
-
/** Uniform scale from image pixels to target pixels. */
|
|
830
|
-
scale: number;
|
|
831
|
-
/** Target-space point that the centre of `region` maps to. */
|
|
832
|
-
originX: number;
|
|
833
|
-
originY: number;
|
|
834
|
-
}
|
|
835
|
-
/** Normalises any rotation in degrees to [0, 360). */
|
|
836
|
-
declare function normalizeAngle(degrees: number): number;
|
|
837
|
-
/** Whether the rotation swaps the displayed width and height. */
|
|
838
|
-
declare function isQuarterTurnSwapped(transform: Pick<ImageTransform, 'rotate'>): boolean;
|
|
839
|
-
/** Size of a region once rotated (bounding box for arbitrary angles). */
|
|
840
|
-
declare function getRotatedSize(width: number, height: number, transform: Pick<ImageTransform, 'rotate'>): {
|
|
841
|
-
width: number;
|
|
842
|
-
height: number;
|
|
843
|
-
};
|
|
844
|
-
/** Maps a natural-image point to target space. */
|
|
845
|
-
declare function projectImagePoint(pt: ImagePoint, p: ImageProjection): ImagePoint;
|
|
846
|
-
/** Exact inverse of {@link projectImagePoint}. */
|
|
847
|
-
declare function unprojectCanvasPoint(pt: ImagePoint, p: ImageProjection): ImagePoint;
|
|
848
|
-
/**
|
|
849
|
-
* Applies the projection to a 2D context so that subsequent drawing in natural image
|
|
850
|
-
* pixels lands exactly where {@link projectImagePoint} says it does.
|
|
851
|
-
*/
|
|
852
|
-
declare function applyImageProjectionToContext(ctx: Pick<CanvasRenderingContext2D, 'translate' | 'scale' | 'rotate'>, p: ImageProjection): void;
|
|
853
|
-
/** Projects an image-space rectangle and returns its target-space bounding box. */
|
|
854
|
-
declare function projectImageRect(rect: CropBox, p: ImageProjection): {
|
|
855
|
-
x: number;
|
|
856
|
-
y: number;
|
|
857
|
-
width: number;
|
|
858
|
-
height: number;
|
|
859
|
-
};
|
|
860
|
-
/** Clamps a crop box to the image bounds. */
|
|
861
|
-
declare function clampCropToImage(crop: CropBox, width: number, height: number): CropBox;
|
|
862
|
-
/**
|
|
863
|
-
* Returns the natural-image -> canvas projection used by the interactive viewport.
|
|
864
|
-
*/
|
|
865
|
-
declare function getViewportProjection(state: ImageEditorState, vpWidth: number, vpHeight: number, isActivelyCropping?: boolean, cropOverride?: CropBox | null): ImageProjection;
|
|
866
|
-
/**
|
|
867
|
-
* Calculates current viewport projection metrics for canvas <-> image coordinate mapping.
|
|
868
|
-
* `cropRect` is the on-screen (rotated/flipped) rectangle of the crop box.
|
|
869
|
-
*/
|
|
870
|
-
declare function getViewportMetrics(state: ImageEditorState, vpWidth: number, vpHeight: number, isActivelyCropping?: boolean, cropOverride?: CropBox | null): ViewportMetrics;
|
|
871
|
-
/**
|
|
872
|
-
* Converts a point on the canvas (in internal canvas pixel space) to natural image pixel
|
|
873
|
-
* space, accounting for zoom, pan, fit scale, crop offset, rotation and flips.
|
|
874
|
-
*/
|
|
875
|
-
declare function canvasToImagePoint(canvasPt: ImagePoint, state: ImageEditorState, vpWidth: number, vpHeight: number, isActivelyCropping?: boolean): ImagePoint;
|
|
876
|
-
/**
|
|
877
|
-
* Converts a point in natural image pixel space to internal canvas pixel space.
|
|
878
|
-
* Exact inverse of {@link canvasToImagePoint}.
|
|
879
|
-
*/
|
|
880
|
-
declare function imageToCanvasPoint(imgPt: ImagePoint, state: ImageEditorState, vpWidth: number, vpHeight: number, isActivelyCropping?: boolean): ImagePoint;
|
|
881
|
-
/**
|
|
882
|
-
* Converts a crop handle in screen orientation to the equivalent edge/corner of the crop
|
|
883
|
-
* box in natural image space, or the reverse with `toScreen = true`.
|
|
884
|
-
*/
|
|
885
|
-
declare function mapCropHandle(handle: CropHandle, transform: ImageTransform, toScreen?: boolean): CropHandle;
|
|
886
|
-
/**
|
|
887
|
-
* Hit-tests the crop box and its corner/edge handles given a canvas point.
|
|
888
|
-
* The returned handle names the edge/corner of the crop box in natural image space
|
|
889
|
-
* (what {@link calculateCropDrag} expects); use `getCropCursor(handle, state.transform)`
|
|
890
|
-
* to obtain the matching on-screen cursor.
|
|
891
|
-
*/
|
|
892
|
-
declare function hitTestCrop(canvasPt: ImagePoint, state: ImageEditorState, vpWidth: number, vpHeight: number, handleThreshold?: number, cropOverride?: CropBox | null): CropHandle;
|
|
893
|
-
/**
|
|
894
|
-
* Returns CSS cursor style corresponding to a crop handle. Pass the current transform when
|
|
895
|
-
* the handle comes from {@link hitTestCrop} (image space) so the cursor matches the
|
|
896
|
-
* on-screen orientation under rotation/flip.
|
|
897
|
-
*/
|
|
898
|
-
declare function getCropCursor(handle: CropHandle, transform?: ImageTransform): string;
|
|
899
|
-
/**
|
|
900
|
-
* Calculates updated crop rectangle given a drag interaction.
|
|
901
|
-
*/
|
|
902
|
-
declare function calculateCropDrag(startCrop: CropBox, handle: CropHandle, startImgPt: ImagePoint, currentImgPt: ImagePoint, imgWidth: number, imgHeight: number, aspectRatio?: number | null, transform?: ImageTransform): CropBox;
|
|
903
|
-
/**
|
|
904
|
-
* Calculates bounding box of an annotation.
|
|
905
|
-
*/
|
|
906
|
-
declare function getAnnotationBounds(ann: Annotation): {
|
|
907
|
-
x: number;
|
|
908
|
-
y: number;
|
|
909
|
-
width: number;
|
|
910
|
-
height: number;
|
|
911
|
-
};
|
|
912
|
-
/**
|
|
913
|
-
* Hit tests if a point in image space is within an annotation's bounds.
|
|
914
|
-
*/
|
|
915
|
-
declare function hitTestAnnotation(imgPt: ImagePoint, ann: Annotation, padding?: number): boolean;
|
|
916
|
-
|
|
917
1370
|
/** The `version` that `ImageEditorController.toJSON()` writes. */
|
|
918
1371
|
declare const IMAGE_EDITOR_STATE_VERSION = 1;
|
|
919
1372
|
/**
|
|
@@ -934,7 +1387,8 @@ interface ImageEditorDocumentLoad {
|
|
|
934
1387
|
* - Runs `imageEditorStateMigrations` up to `IMAGE_EDITOR_STATE_VERSION`; a missing
|
|
935
1388
|
* `version` is taken as current.
|
|
936
1389
|
* - A newer `version` is still loaded but reported `readOnly`: do not save over it.
|
|
937
|
-
* - Each section (`crop`, `transform`, `adjustments`, `depthMask`, `annotations
|
|
1390
|
+
* - Each section (`crop`, `transform`, `adjustments`, `depthMask`, `annotations`, and the
|
|
1391
|
+
* optional run-length encoded `selection`)
|
|
938
1392
|
* falls back to its default on its own; invalid annotations are dropped one by one.
|
|
939
1393
|
* - Unknown top-level keys are returned in `unknown`.
|
|
940
1394
|
*
|
|
@@ -976,6 +1430,7 @@ declare function createAdjustmentLayer<K extends AdjustmentKind>(kind: K, option
|
|
|
976
1430
|
enabled?: boolean;
|
|
977
1431
|
opacity?: number;
|
|
978
1432
|
blend?: BlendMode;
|
|
1433
|
+
mask?: AdjustmentLayerMask;
|
|
979
1434
|
}): AdjustmentLayerOf<K>;
|
|
980
1435
|
/**
|
|
981
1436
|
* A clean, deep-copied layer from stored or hand-written data: missing fields get neutral
|
|
@@ -1076,8 +1531,12 @@ declare function evaluateAdjustmentLayers(color: readonly number[], layers: read
|
|
|
1076
1531
|
* Applies an adjustment-layer stack to 8-bit straight RGBA pixels in place. Each pixel is
|
|
1077
1532
|
* decoded once, run through every layer in float, and encoded once. Transparent pixels are
|
|
1078
1533
|
* left alone; alpha is never changed.
|
|
1534
|
+
*
|
|
1535
|
+
* `masks` (layer id → 0..1 coverage per pixel of `imageData`, see `buildLayerMaskPlanes`)
|
|
1536
|
+
* scales each masked layer's opacity per pixel: coverage 0 leaves the pixel as the layers below
|
|
1537
|
+
* made it, 1 applies the layer fully.
|
|
1079
1538
|
*/
|
|
1080
|
-
declare function applyAdjustmentLayers(imageData: ImageData, layers: readonly AdjustmentLayer[] | undefined): void;
|
|
1539
|
+
declare function applyAdjustmentLayers(imageData: Pick<ImageData, 'data'>, layers: readonly AdjustmentLayer[] | undefined, masks?: ReadonlyMap<string, ArrayLike<number>>): void;
|
|
1081
1540
|
/** Stable cache key of a layer stack's pixel effect (for renderer caches). */
|
|
1082
1541
|
declare function adjustmentLayersKey(layers: readonly AdjustmentLayer[] | undefined): string;
|
|
1083
1542
|
|
|
@@ -1179,6 +1638,8 @@ interface ImageEditorToolProviderOptions {
|
|
|
1179
1638
|
* control ranges and the applied values are echoed.
|
|
1180
1639
|
* - `add_adjustment_layer {kind, params?, opacity?, blend?, name?}`.
|
|
1181
1640
|
* - `render_preview {maxSide}`: the rendered image as a PNG, longest side at most `maxSide`.
|
|
1641
|
+
* - Selections and masks: `get_selection`, `select_region`, `select_by_color`, `modify_selection`,
|
|
1642
|
+
* `refine_selection`, `apply_selection_as_mask` (see `createImageSelectionTools`).
|
|
1182
1643
|
*/
|
|
1183
1644
|
declare function createImageEditorToolProvider(controller: ImageEditorController, options?: ImageEditorToolProviderOptions): AgentToolProvider;
|
|
1184
1645
|
|
|
@@ -1203,4 +1664,108 @@ declare function moveCurvePoint(points: readonly CurvePoint[], index: number, p:
|
|
|
1203
1664
|
/** Removes point `index`; a curve keeps at least two points. */
|
|
1204
1665
|
declare function removeCurvePoint(points: readonly CurvePoint[], index: number): CurvePoint[];
|
|
1205
1666
|
|
|
1206
|
-
|
|
1667
|
+
/**
|
|
1668
|
+
* The selection's outline at `threshold` (0..255, default 128) as axis-aligned segments on pixel
|
|
1669
|
+
* boundaries, `[x0, y0, x1, y1, …]` in natural image pixels, with collinear neighbours merged.
|
|
1670
|
+
* This is what marching ants are drawn from. Linear in the pixel count.
|
|
1671
|
+
*/
|
|
1672
|
+
declare function selectionOutline(mask: SelectionMask, threshold?: number): Float32Array;
|
|
1673
|
+
interface QuickMaskStyle {
|
|
1674
|
+
/** Overlay colour, `[r, g, b]` 0..255 (default Photoshop's rubylith red). */
|
|
1675
|
+
color?: readonly [number, number, number];
|
|
1676
|
+
/** 0..1 (default 0.5): opacity over fully unselected pixels. */
|
|
1677
|
+
opacity?: number;
|
|
1678
|
+
}
|
|
1679
|
+
/**
|
|
1680
|
+
* Quick Mask view: RGBA pixels (natural image size) tinting the *unselected* area, so the
|
|
1681
|
+
* selection shows through clear, as Photoshop's rubylith overlay.
|
|
1682
|
+
*/
|
|
1683
|
+
declare function quickMaskPixels(mask: SelectionMask, style?: QuickMaskStyle): Uint8ClampedArray;
|
|
1684
|
+
|
|
1685
|
+
/** Selection tools of the image editor UI. */
|
|
1686
|
+
type SelectionToolKind = 'wand' | 'rect' | 'ellipse' | 'lasso';
|
|
1687
|
+
declare const SELECTION_TOOLS: readonly {
|
|
1688
|
+
id: SelectionToolKind;
|
|
1689
|
+
label: string;
|
|
1690
|
+
}[];
|
|
1691
|
+
declare const SELECTION_MODE_LABELS: Record<SelectionMode, string>;
|
|
1692
|
+
/** The options bar of the selection tools (shared by the React and Svelte UIs). */
|
|
1693
|
+
interface SelectionToolOptions {
|
|
1694
|
+
tool: SelectionToolKind;
|
|
1695
|
+
mode: SelectionMode;
|
|
1696
|
+
/** Magic wand tolerance, 0..255. */
|
|
1697
|
+
tolerance: number;
|
|
1698
|
+
contiguous: boolean;
|
|
1699
|
+
antiAlias: boolean;
|
|
1700
|
+
/** Sample the adjusted image instead of the source. */
|
|
1701
|
+
sampleMerged: boolean;
|
|
1702
|
+
distance: ColorDistance;
|
|
1703
|
+
}
|
|
1704
|
+
declare const DEFAULT_SELECTION_TOOL_OPTIONS: SelectionToolOptions;
|
|
1705
|
+
/**
|
|
1706
|
+
* Photoshop's modifier keys: Shift adds, Alt/Option subtracts, both intersect; otherwise the
|
|
1707
|
+
* options bar mode.
|
|
1708
|
+
*/
|
|
1709
|
+
declare function selectionModeFromModifiers(modifiers: {
|
|
1710
|
+
shiftKey?: boolean;
|
|
1711
|
+
altKey?: boolean;
|
|
1712
|
+
}, fallback: SelectionMode): SelectionMode;
|
|
1713
|
+
interface RefineEdgeControl {
|
|
1714
|
+
id: keyof Omit<RefineEdgeParams, 'smartRadius'>;
|
|
1715
|
+
label: string;
|
|
1716
|
+
min: number;
|
|
1717
|
+
max: number;
|
|
1718
|
+
step: number;
|
|
1719
|
+
unit: string;
|
|
1720
|
+
}
|
|
1721
|
+
/** Sliders of the Refine Edge panel. */
|
|
1722
|
+
declare const REFINE_EDGE_CONTROLS: readonly RefineEdgeControl[];
|
|
1723
|
+
/** A one-line status: "No selection" or "W × H px selected (n % of the image)". */
|
|
1724
|
+
declare function describeSelection(mask: SelectionMask | null | undefined): string;
|
|
1725
|
+
|
|
1726
|
+
interface GestureModifiers {
|
|
1727
|
+
shiftKey?: boolean;
|
|
1728
|
+
altKey?: boolean;
|
|
1729
|
+
}
|
|
1730
|
+
/**
|
|
1731
|
+
* Pointer gestures of the selection tools, shared by the React and Svelte image editors: feed
|
|
1732
|
+
* it pointer positions in natural image pixels (`canvasToImagePoint(..., false)`).
|
|
1733
|
+
*
|
|
1734
|
+
* - Magic wand: selects on `begin` (async, as it may read pixels).
|
|
1735
|
+
* - Rectangle / ellipse: drag a box; a click without a drag deselects (replace mode).
|
|
1736
|
+
* - Lasso: drag a free-hand path, closed on `end`.
|
|
1737
|
+
*
|
|
1738
|
+
* Shift adds, Alt subtracts, both intersect (overriding the options bar mode). While dragging,
|
|
1739
|
+
* {@link draftPath} is the outline to show (`RenderOptions.draftSelectionPath`).
|
|
1740
|
+
*/
|
|
1741
|
+
declare class SelectionGesture {
|
|
1742
|
+
readonly controller: ImageEditorController;
|
|
1743
|
+
private readonly getOptions;
|
|
1744
|
+
private start;
|
|
1745
|
+
private points;
|
|
1746
|
+
private current;
|
|
1747
|
+
private modifiers;
|
|
1748
|
+
/** The last error (e.g. pixels unavailable for the wand), for the UI to show. */
|
|
1749
|
+
error: string | null;
|
|
1750
|
+
constructor(controller: ImageEditorController, getOptions: () => SelectionToolOptions);
|
|
1751
|
+
get active(): boolean;
|
|
1752
|
+
/** The outline of the shape being drawn, or `null`. */
|
|
1753
|
+
get draftPath(): ImagePoint[] | null;
|
|
1754
|
+
/** Pointer down. Resolves once a wand click has been applied. */
|
|
1755
|
+
begin(point: ImagePoint, modifiers?: GestureModifiers): Promise<void>;
|
|
1756
|
+
/** Pointer move; returns true when the draft changed (re-render). */
|
|
1757
|
+
move(point: ImagePoint): boolean;
|
|
1758
|
+
/** Pointer up: commits the shape. Returns true when the selection changed. */
|
|
1759
|
+
end(point?: ImagePoint, modifiers?: GestureModifiers): boolean;
|
|
1760
|
+
/** Abandons a drag without changing the selection. */
|
|
1761
|
+
cancel(): void;
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
/**
|
|
1765
|
+
* Agent tools for selections and masks (part of `createImageEditorToolProvider`):
|
|
1766
|
+
* `get_selection`, `select_region`, `select_by_color`, `modify_selection`, `refine_selection`
|
|
1767
|
+
* and `apply_selection_as_mask`. Coordinates are natural pixels of the source image.
|
|
1768
|
+
*/
|
|
1769
|
+
declare function createImageSelectionTools(controller: ImageEditorController): AgentTool[];
|
|
1770
|
+
|
|
1771
|
+
export { ADJUSTMENT_KINDS, ADJUSTMENT_LAYER_CONTROLS, ADJUSTMENT_LAYER_OPACITY_CONTROL, ADJUSTMENT_LUT_SIZE, AS_SHOT_KELVIN, type AdjustmentKind, type AdjustmentKindInfo, type AdjustmentLayer, type AdjustmentLayerBase, type AdjustmentLayerInit, type AdjustmentLayerMask, type AdjustmentLayerOf, type AdjustmentLayerUpdate, type AdjustmentParamsMap, type Annotation, type AnnotationType, type ArrowAnnotation, type AspectRatio, BLEND_MODES, type BaseAnnotation, type BlackWhiteParams, type BlendMode, type BlendModeInfo, type Chromaticity, type CircleAnnotation, type ColorBalanceParams, type ColorBalanceTone, type ColorDistance, type ColorRangeOptions, type ColorRangeSample, type ControlSection, type ControlSpec, type ControlTrack, type CreateAnnotationPayload, type CropBox, type CropHandle, type CurvePoint, type CurvesParams, D65, DEFAULT_ADJUSTMENTS, DEFAULT_DEPTH_MASK, DEFAULT_REFINE_EDGE_PARAMS, DEFAULT_SELECTION_TOOL_OPTIONS, DEFAULT_TRANSFORM, DIRECT_GAUSSIAN_MAX_SIGMA, type DepthMaskOptions, EMPTY_DISTANCE, type ExportOptions, GUIDED_FILTER_EPS, type GestureModifiers, HISTOGRAM_BINS, HUE_RANGE_LABELS, type HistogramChannel, type HueRange, type HueSaturationParams, IDENTITY_MATRIX3, IMAGE_ADJUSTMENT_CONTROLS, IMAGE_EDITOR_SCHEMA_VERSION, IMAGE_EDITOR_STATE_VERSION, type ImageAdjustments, type ImageAnnotation, type ImageDimensions, type ImageEditorAIHooks, ImageEditorController, type ImageEditorDocumentLoad, type ImageEditorOptions, ImageEditorRenderer, type ImageEditorState, type ImageEditorTool, type ImageEditorToolProviderOptions, type ImageHistogram, type ImagePoint, type ImageProcessVersion, type ImageProjection, type ImageTransform, type InpaintHook, type InpaintOptions, type InvertParams, LATEST_PROCESS_VERSION, LEGACY_PROCESS_VERSION, LUMA_709, type LayerMaskProps, type LevelsChannel, type LevelsParams, type LineAnnotation, MAX_KELVIN, MIN_KELVIN, MIRED_PER_TEMPERATURE_UNIT, type MagicWandOptions, type Matrix3, type PenAnnotation, type PhotoFilterParams, type PixelBuffer, type PixelOp, type PosterizeParams, type QuickMaskStyle, REFINE_EDGE_CONTROLS, type RectAnnotation, type RefineEdgeControl, type RefineEdgeParams, type RemoveBackgroundHook, type RemoveBackgroundOptions, type RenderOptions, type Rgb$1 as Rgb, type Rgba, SELECTION_MODES, SELECTION_MODE_LABELS, SELECTION_MODIFY_OPS, SELECTION_TOOLS, type SampleOptions, type SelectionChannel, type SelectionCommandOptions, SelectionGesture, type SelectionMask, type SelectionMode, type SelectionModifyOp, type SelectionToolKind, type SelectionToolOptions, type SerializedImageEditorState, type SerializedSelection, type ShapeSelectionOptions, TINT_SCALE, TONE_LUT_SIZE, TONE_RANGE_PRESETS, type TextAnnotation, type ThresholdParams, type ToneRangePreset, type UnitLevels, VIBRANCE_GREY, type VibranceParams, type ViewportMetrics, activeAdjustmentLayers, adjustmentKindLabel, adjustmentLayersKey, applyAdjustmentLayers, applyAdjustments, applyDepthMask, applyImageProjectionToContext, applyLegacyAdjustments, applyMatrix3, applyProcess2Adjustments, blackWhiteGray, blendChannel, blendImageData, blendLum, blendPixel, blendRgb, borderCoverage, boxMean, boxToCurvePoint, bradfordAdaptation, buildLayerMaskPlanes, buildToneLut, calculateCropDrag, canvasCompositeOperation, canvasToImagePoint, clampControlValue, clampCropToImage, colorBalanceChannel, colorRange, combineSelections, compileAdjustmentLayer, computeHistogram, computeSelectionBounds, contractCoverage, controlPosition, controlTrackBackground, coverageToByte, createAdjustmentLayer, createImageEditorToolProvider, createImageSelectionTools, createSelectionMask, curveLut, curveLutFromLevels, curvePointToBox, curveSvgPath, decodeLayerMask, decodeSelectionRle, defaultAdjustmentParams, describeSelection, deserializeSelection, distanceTransform, edgeWidth, ellipsePoints, ellipseSelection, encodeSelectionRle, evaluateAdjustmentLayers, expandCoverage, featherCoverage, findAdjustmentControl, findLayerControl, formatControlValue, fullSelection, gaussianBlur, getAnnotationBounds, getControlPath, getCropCursor, getRotatedSize, getViewportMetrics, getViewportProjection, globalImageCache, greyMorphology, guidePlanes, guidedFilterColor, hashMaskContent, hexToRgb, histogramPath, hitTestAnnotation, hitTestCrop, hitTestCurvePoint, hslToRgb, hueRange, hueRangeTables, hueRangeWeight, hueSaturation, identityCurve, identityLevels, imageEditorStateMigrations, imageToCanvasPoint, insertCurvePoint, invertMatrix3, invertSelection, isAdjustmentKind, isBlendMode, isQuarterTurnSwapped, isSelectionEmpty, isSelectionMode, isSeparableBlendMode, kelvinToTemperature, layerMaskCoverage, layerMaskFromSelection, layerMaskKey, levelsValue, linearSrgbToXy, linearToSrgb, loadImageEditorDocument, magicWand, mapCropHandle, migrateSerializedImageEditorState, modifySelection, moveCurvePoint, mulMatrix3, neutralHueRange, normalizeAdjustmentLayer, normalizeAdjustmentLayers, normalizeAngle, normalizeBlendMode, normalizeLayerMask, normalizeProcessVersion, normalizeRect, normalizeRefineEdgeParams, normalizeStoredAdjustments, parseSelectionMode, photoFilterMatrix, polygonCoverage, polygonSelection, posterizeValue, projectImagePoint, projectImageRect, projectMaskCoverage, quickMaskPixels, rangeLightness, readAdjustmentControls, rectSelection, refineCoverage, refineEdgeHalo, refineSelection, removeAlpha, removeCurvePoint, resizeSelection, rgbToGray, rgbToHsl, sampleLut, sampleToneLut, selectionArea, selectionFromCoverage, selectionFromPixels, selectionModeFromModifiers, selectionOutline, selectionToCoverage, selectionToPixels, selectionValueAt, serializeSelection, setControlPath, setLum, shiftCoverage, smoothCoverage, srgb8ToLab, srgbToLinear, tempTintToXy, temperatureToKelvin, toneCurve, toneLuts, toneRange, unprojectCanvasPoint, updateLayerMaskProps, uvToXy, vibranceLinear, vibrancePixel, wbMatrix, whiteBalanceFromSample, whiteBalanceMatrix, xyToTempTint, xyToUv };
|