@pixerate/editor 0.88.0 → 0.90.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/THIRD_PARTY_NOTICES.md +8 -2
- package/dist/agent/index.cjs +28 -28
- package/dist/agent/index.js +3 -3
- package/dist/canvas/index.cjs +3 -3
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.js +16 -16
- package/dist/{chunk-TYOAJDFD.cjs → chunk-66IMF6OD.cjs} +3 -3
- package/dist/{chunk-TYOAJDFD.cjs.map → chunk-66IMF6OD.cjs.map} +1 -1
- package/dist/chunk-D4ZCU72J.js +604 -0
- package/dist/chunk-D4ZCU72J.js.map +1 -0
- package/dist/{chunk-IMSX4IVG.js → chunk-FWEO3HSL.js} +4 -4
- package/dist/chunk-H543GD6T.cjs +1696 -0
- package/dist/chunk-H543GD6T.cjs.map +1 -0
- package/dist/{chunk-ROXFP2LQ.cjs → chunk-HNDSPZ5T.cjs} +4 -4
- package/dist/{chunk-ROXFP2LQ.cjs.map → chunk-HNDSPZ5T.cjs.map} +1 -1
- package/dist/{chunk-MXF4DP2C.cjs → chunk-J3B45HTA.cjs} +74 -74
- package/dist/{chunk-MXF4DP2C.cjs.map → chunk-J3B45HTA.cjs.map} +1 -1
- package/dist/{chunk-GNO5PEMH.js → chunk-OK7T2LHK.js} +2 -2
- package/dist/chunk-P5TPUNBZ.js +1696 -0
- package/dist/chunk-P5TPUNBZ.js.map +1 -0
- package/dist/chunk-PDCITYBT.cjs +416 -0
- package/dist/chunk-PDCITYBT.cjs.map +1 -0
- package/dist/{chunk-RKJDBXTY.cjs → chunk-T4XWVPJK.cjs} +3 -3
- package/dist/{chunk-RKJDBXTY.cjs.map → chunk-T4XWVPJK.cjs.map} +1 -1
- package/dist/{chunk-ZQNDSUZO.js → chunk-UKI64KUD.js} +6 -6
- package/dist/{chunk-SVW2UNUC.js → chunk-WON34HKM.js} +2 -2
- package/dist/chunk-YLB2WVNA.js +416 -0
- package/dist/chunk-YLB2WVNA.js.map +1 -0
- package/dist/chunk-ZOOEX3WT.cjs +604 -0
- package/dist/chunk-ZOOEX3WT.cjs.map +1 -0
- package/dist/extensions/index.cjs +6 -6
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.js +5 -5
- package/dist/image-editor/index.cjs +7146 -855
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +2050 -532
- package/dist/image-editor/index.d.ts +2050 -532
- package/dist/image-editor/index.js +8134 -1843
- package/dist/image-editor/index.js.map +1 -1
- package/dist/index.cjs +27 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +10 -10
- package/dist/paint/index.cjs +38 -0
- package/dist/paint/index.cjs.map +1 -0
- package/dist/paint/index.d.cts +167 -0
- package/dist/paint/index.d.ts +167 -0
- package/dist/paint/index.js +38 -0
- package/dist/paint/index.js.map +1 -0
- package/dist/raster/index.cjs +121 -0
- package/dist/raster/index.cjs.map +1 -0
- package/dist/raster/index.d.cts +365 -0
- package/dist/raster/index.d.ts +365 -0
- package/dist/raster/index.js +121 -0
- package/dist/raster/index.js.map +1 -0
- package/dist/serializers/index.cjs +4 -4
- package/dist/serializers/index.cjs.map +1 -1
- package/dist/serializers/index.js +3 -3
- package/dist/surface-fJhkmNQn.d.cts +181 -0
- package/dist/surface-fJhkmNQn.d.ts +181 -0
- package/package.json +13 -2
- package/skills/pixerate-image-editor/SKILL.md +111 -11
- /package/dist/{chunk-IMSX4IVG.js.map → chunk-FWEO3HSL.js.map} +0 -0
- /package/dist/{chunk-GNO5PEMH.js.map → chunk-OK7T2LHK.js.map} +0 -0
- /package/dist/{chunk-ZQNDSUZO.js.map → chunk-UKI64KUD.js.map} +0 -0
- /package/dist/{chunk-SVW2UNUC.js.map → chunk-WON34HKM.js.map} +0 -0
|
@@ -1,56 +1,14 @@
|
|
|
1
|
+
import { P as PixelSurface, T as TiledSurface, B as BlendMode } from '../surface-fJhkmNQn.js';
|
|
2
|
+
export { a as BLEND_MODES, b as BlendModeInfo, M as MaskSurface, R as RasterRect, c as Rgb, d as Rgba, S as SurfaceDraft, e as TILE, f as TILE_SHIFT, g as Tile, h as TileKey, i as blendChannel, j as blendImageData, k as blendLum, l as blendPixel, m as blendRgb, n as canvasCompositeOperation, o as collectTiles, p as contentBounds, q as emptySurface, r as fillRect, s as finishTile, t as isBlendMode, u as isSeparableBlendMode, v as normalizeBlendMode, w as packRgba, x as readPixel, y as readRegion, z as setLum, A as solidSurface, C as surfaceBytes, D as surfaceFromPixels, E as surfacesEqual, F as tileCoord, G as tileKey, H as tileRect, I as tilesInRect, J as translateSurface, K as uniformTile, L as writeRegion } from '../surface-fJhkmNQn.js';
|
|
3
|
+
import { RasterLayerBase, RasterMask as RasterMask$1, RasterPixelLayer, GroupBlendMode, LayerLocation as LayerLocation$1, LayerLocks, RasterSources, RasterCompositor, CompositorOptions } from '../raster/index.js';
|
|
4
|
+
export { CompositeCallOptions, CompositeStats, DIRECT_GAUSSIAN_MAX_SIGMA, DecodedPng, ZlibError, adler32, base64ToBytes, blendTile, bytesToBase64, changedTiles, decodePng, deflate, deflateRaw, encodePng, findLayer, flattenLayers, gaussianBlur, inflate, inflateRaw, insertLayer, isLayerLocked, isPng, mapLayer, parseDataUrl, pngDataUrl } from '../raster/index.js';
|
|
5
|
+
import { BrushSettings, StrokeCoverage, StrokeApply, StrokePoint } from '../paint/index.js';
|
|
6
|
+
export { CoverageMap, DEFAULT_BRUSH, Dab, DabWalker, MAX_BRUSH_SIZE, applyStrokeToTile, coverageTileCoord, dabCoverage, dabRect, normalizeBrush, rasterizeDab, smoothPoints, tipFalloff, tipReach, tipShape, walkDabs } from '../paint/index.js';
|
|
1
7
|
import { b as LoadReport, J as JsonObject, f as MigrationStep } from '../migrate-iTlm3a8h.js';
|
|
2
8
|
import { a as AgentToolProvider, A as AgentTool } from '../registry-D-4fit9C.js';
|
|
3
9
|
import { b as CaptureSurface } from '../capture-wwNGaW05.js';
|
|
4
10
|
import '../schema-Di0CS6Pe.js';
|
|
5
11
|
|
|
6
|
-
/**
|
|
7
|
-
* Photoshop blend modes on straight (non-premultiplied) 0..1 colours.
|
|
8
|
-
*
|
|
9
|
-
* Formulas follow the W3C Compositing / ISO 32000 definitions, with Photoshop's variants where
|
|
10
|
-
* they differ (Soft Light, Vivid / Linear / Pin Light, Hard Mix, Linear Burn / Dodge, Subtract,
|
|
11
|
-
* Divide, Darker / Lighter Color), and the hardened `ClipColor` for the non-separable modes.
|
|
12
|
-
*/
|
|
13
|
-
type BlendMode = 'normal' | 'darken' | 'multiply' | 'color-burn' | 'linear-burn' | 'darker-color' | 'lighten' | 'screen' | 'color-dodge' | 'linear-dodge' | 'lighter-color' | 'overlay' | 'soft-light' | 'hard-light' | 'vivid-light' | 'linear-light' | 'pin-light' | 'hard-mix' | 'difference' | 'exclusion' | 'subtract' | 'divide' | 'hue' | 'saturation' | 'color' | 'luminosity';
|
|
14
|
-
interface BlendModeInfo {
|
|
15
|
-
id: BlendMode;
|
|
16
|
-
label: string;
|
|
17
|
-
/** Canvas `globalCompositeOperation` with the same maths, when there is one. */
|
|
18
|
-
canvas: GlobalCompositeOperation | null;
|
|
19
|
-
}
|
|
20
|
-
/** Every blend mode, in Photoshop's menu order. */
|
|
21
|
-
declare const BLEND_MODES: readonly BlendModeInfo[];
|
|
22
|
-
declare function isBlendMode(value: unknown): value is BlendMode;
|
|
23
|
-
/** A stored blend mode, or `normal` for a missing / unknown value. */
|
|
24
|
-
declare function normalizeBlendMode(value: unknown): BlendMode;
|
|
25
|
-
/**
|
|
26
|
-
* The canvas composite operation that implements `mode` exactly, or `null` when the canvas has
|
|
27
|
-
* none (draw through {@link blendImageData} instead).
|
|
28
|
-
*/
|
|
29
|
-
declare function canvasCompositeOperation(mode: BlendMode | undefined): GlobalCompositeOperation | null;
|
|
30
|
-
/** Whether a mode works on whole colours (hue, saturation, colour, luminosity, darker / lighter colour). */
|
|
31
|
-
declare function isSeparableBlendMode(mode: BlendMode): boolean;
|
|
32
|
-
/** Separable blend function `B(cb, cs)` of one channel. Non-separable modes return `cs`. */
|
|
33
|
-
declare function blendChannel(mode: BlendMode, cb: number, cs: number): number;
|
|
34
|
-
type Rgb$1 = [number, number, number];
|
|
35
|
-
type Rgba = [number, number, number, number];
|
|
36
|
-
/** Luminosity of the non-separable modes (W3C / ISO 32000 weights). */
|
|
37
|
-
declare function blendLum(c: readonly number[]): number;
|
|
38
|
-
/** `c` with its luminosity moved to `l`, clipped back into gamut towards grey (SetLum + ClipColor). */
|
|
39
|
-
declare function setLum(c: readonly number[], l: number): Rgb$1;
|
|
40
|
-
/** `B(Cb, Cs)` of a whole colour, including the non-separable modes. */
|
|
41
|
-
declare function blendRgb(mode: BlendMode, cb: readonly number[], cs: readonly number[]): Rgb$1;
|
|
42
|
-
/**
|
|
43
|
-
* Composites a straight-alpha `source` over a straight-alpha `backdrop` (both RGBA in 0..1) with a
|
|
44
|
-
* blend mode and an extra `alpha` (opacity), using the W3C general formula:
|
|
45
|
-
* `αo = αs + αb(1 − αs)`, `αo·Co = (1 − αs)·αb·Cb + (1 − αb)·αs·Cs + αs·αb·B(Cb, Cs)`.
|
|
46
|
-
*/
|
|
47
|
-
declare function blendPixel(mode: BlendMode, backdrop: readonly number[], source: readonly number[], alpha?: number): Rgba;
|
|
48
|
-
/**
|
|
49
|
-
* Blends `source` into `backdrop` in place (8-bit straight RGBA of the same size) with
|
|
50
|
-
* {@link blendPixel}. The scalar fallback for modes the canvas cannot composite.
|
|
51
|
-
*/
|
|
52
|
-
declare function blendImageData(backdrop: ImageData, source: ImageData, mode: BlendMode, alpha?: number): void;
|
|
53
|
-
|
|
54
12
|
/**
|
|
55
13
|
* A selection: one 8-bit coverage value per image pixel (0 = not selected, 255 = fully
|
|
56
14
|
* selected), row-major over the whole source image in natural pixels — the same space as the
|
|
@@ -139,478 +97,245 @@ declare function deserializeSelection(value: unknown): SelectionMask;
|
|
|
139
97
|
/** A short, stable hash of a string or bytes (FNV-1a, 32-bit, hex) for cache keys. */
|
|
140
98
|
declare function hashMaskContent(content: string | Uint8Array): string;
|
|
141
99
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
100
|
+
/**
|
|
101
|
+
* The image editor's layer stack: pixel, adjustment, group and annotation layers in one ordered
|
|
102
|
+
* tree (bottom to top), all in document space (natural pixels of the document).
|
|
103
|
+
*
|
|
104
|
+
* Layer objects are immutable. Every change builds new objects along the path from the root to
|
|
105
|
+
* the changed layer and shares everything else, so undo history, the compositor's caches and
|
|
106
|
+
* serialization can compare layers by identity.
|
|
107
|
+
*/
|
|
108
|
+
|
|
109
|
+
/** Blend modes of a layer; groups also accept `pass-through`. */
|
|
110
|
+
type LayerBlendMode = GroupBlendMode;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* A layer mask (see the raster module's `RasterMask`) whose parametric `source` is a depth map:
|
|
114
|
+
* a depth mask is generated from it instead of painted, and its surface is unused.
|
|
115
|
+
*/
|
|
116
|
+
type RasterMask = RasterMask$1<DepthMaskOptions>;
|
|
117
|
+
interface LayerBase extends RasterLayerBase {
|
|
118
|
+
mask?: RasterMask;
|
|
161
119
|
}
|
|
162
|
-
|
|
120
|
+
/** The base sliders of the old document-level adjustments, as a filter on one layer. */
|
|
121
|
+
interface DevelopSettings {
|
|
163
122
|
brightness: number;
|
|
164
123
|
contrast: number;
|
|
165
124
|
saturation: number;
|
|
166
125
|
exposure: number;
|
|
167
126
|
temperature: number;
|
|
168
|
-
/**
|
|
169
|
-
* -100 (green) to 100 (magenta), 0 is default. White-balance tint correction in Duv × 3000
|
|
170
|
-
* (process 2 only; the legacy process ignores it).
|
|
171
|
-
*/
|
|
172
127
|
tint?: number;
|
|
173
|
-
|
|
174
|
-
opacity: number;
|
|
175
|
-
/**
|
|
176
|
-
* Rendering process the values are interpreted by. `2` (the latest; new edits and Reset get
|
|
177
|
-
* it): linear-light exposure, Bradford white balance, LUT tone curve without intermediate
|
|
178
|
-
* clipping. `1` or missing: the legacy 8-bit rendering, so edits saved before process
|
|
179
|
-
* versions existed look exactly as they did. See `normalizeProcessVersion`.
|
|
180
|
-
*/
|
|
128
|
+
/** Rendering process (see `ImageAdjustments.process`). */
|
|
181
129
|
process?: 1 | 2;
|
|
182
|
-
/**
|
|
183
|
-
* Non-destructive adjustment layers, evaluated bottom (first) to top (last) after the base
|
|
184
|
-
* adjustments above, on the encoded sRGB result. Missing or empty: no layers (edits saved
|
|
185
|
-
* before layers existed render exactly as before).
|
|
186
|
-
*/
|
|
187
|
-
layers?: AdjustmentLayer[];
|
|
188
|
-
}
|
|
189
|
-
type AdjustmentKind = 'curves' | 'levels' | 'hueSaturation' | 'vibrance' | 'colorBalance' | 'blackWhite' | 'invert' | 'posterize' | 'threshold' | 'photoFilter';
|
|
190
|
-
/** A Curves point; `input` and `output` are levels, 0..255. */
|
|
191
|
-
interface CurvePoint {
|
|
192
|
-
input: number;
|
|
193
|
-
output: number;
|
|
194
|
-
}
|
|
195
|
-
/** Curves: each channel's curve first, then the master (composite) curve, as in Photoshop. */
|
|
196
|
-
interface CurvesParams {
|
|
197
|
-
master: CurvePoint[];
|
|
198
|
-
red: CurvePoint[];
|
|
199
|
-
green: CurvePoint[];
|
|
200
|
-
blue: CurvePoint[];
|
|
201
|
-
}
|
|
202
|
-
/** One Levels record. Black / white points are levels (0..255); `gamma` is the midtone slider (0.1..9.99). */
|
|
203
|
-
interface LevelsChannel {
|
|
204
|
-
inBlack: number;
|
|
205
|
-
inWhite: number;
|
|
206
|
-
gamma: number;
|
|
207
|
-
outBlack: number;
|
|
208
|
-
outWhite: number;
|
|
209
|
-
}
|
|
210
|
-
/** Levels: each channel's record first, then the master record, as in Photoshop. */
|
|
211
|
-
interface LevelsParams {
|
|
212
|
-
master: LevelsChannel;
|
|
213
|
-
red: LevelsChannel;
|
|
214
|
-
green: LevelsChannel;
|
|
215
|
-
blue: LevelsChannel;
|
|
216
|
-
}
|
|
217
|
-
/** One of Hue/Saturation's six colour ranges (reds, yellows, greens, cyans, blues, magentas). */
|
|
218
|
-
interface HueRange {
|
|
219
|
-
/** Hue shift in degrees (-180..180). */
|
|
220
|
-
hue: number;
|
|
221
|
-
/** Saturation change in percent (-100..100). */
|
|
222
|
-
saturation: number;
|
|
223
|
-
/** Lightness change in percent (-100..100). */
|
|
224
|
-
lightness: number;
|
|
225
|
-
/** Hue degrees where the range starts fading in, is fully on, starts fading out and ends (may wrap). */
|
|
226
|
-
bounds: [number, number, number, number];
|
|
227
|
-
}
|
|
228
|
-
interface HueSaturationParams {
|
|
229
|
-
/** Master hue shift in degrees (-180..180), or the hue when colorizing (0..360). */
|
|
230
|
-
hue: number;
|
|
231
|
-
/** Percent, -100..100 (0..100 when colorizing). */
|
|
232
|
-
saturation: number;
|
|
233
|
-
/** Percent, -100..100. */
|
|
234
|
-
lightness: number;
|
|
235
|
-
colorize: boolean;
|
|
236
|
-
/** Six ranges: reds, yellows, greens, cyans, blues, magentas. */
|
|
237
|
-
ranges: HueRange[];
|
|
238
|
-
}
|
|
239
|
-
interface VibranceParams {
|
|
240
|
-
/** -100..100 */
|
|
241
|
-
vibrance: number;
|
|
242
|
-
/** -100..100 */
|
|
243
|
-
saturation: number;
|
|
244
|
-
}
|
|
245
|
-
/** Cyan–red, magenta–green, yellow–blue sliders, -100..100 each. */
|
|
246
|
-
type ColorBalanceTone = [number, number, number];
|
|
247
|
-
interface ColorBalanceParams {
|
|
248
|
-
shadows: ColorBalanceTone;
|
|
249
|
-
midtones: ColorBalanceTone;
|
|
250
|
-
highlights: ColorBalanceTone;
|
|
251
|
-
preserveLuminosity: boolean;
|
|
252
|
-
}
|
|
253
|
-
/** Black & White: percent weights of the six colours (Photoshop defaults 40 60 40 60 20 80). */
|
|
254
|
-
interface BlackWhiteParams {
|
|
255
|
-
reds: number;
|
|
256
|
-
yellows: number;
|
|
257
|
-
greens: number;
|
|
258
|
-
cyans: number;
|
|
259
|
-
blues: number;
|
|
260
|
-
magentas: number;
|
|
261
|
-
/** Tint colour (`#rrggbb`), applied like the Color blend mode, or `null` for none. */
|
|
262
|
-
tint: string | null;
|
|
263
|
-
}
|
|
264
|
-
interface PhotoFilterParams {
|
|
265
|
-
/** Filter colour, `#rrggbb`. */
|
|
266
|
-
color: string;
|
|
267
|
-
/** Percent, 0..100. */
|
|
268
|
-
density: number;
|
|
269
|
-
preserveLuminosity: boolean;
|
|
270
|
-
}
|
|
271
|
-
interface PosterizeParams {
|
|
272
|
-
/** 2..255 */
|
|
273
|
-
levels: number;
|
|
274
|
-
}
|
|
275
|
-
interface ThresholdParams {
|
|
276
|
-
/** 1..255: luma at or above it becomes white. */
|
|
277
|
-
level: number;
|
|
278
|
-
}
|
|
279
|
-
type InvertParams = Record<string, never>;
|
|
280
|
-
interface AdjustmentParamsMap {
|
|
281
|
-
curves: CurvesParams;
|
|
282
|
-
levels: LevelsParams;
|
|
283
|
-
hueSaturation: HueSaturationParams;
|
|
284
|
-
vibrance: VibranceParams;
|
|
285
|
-
colorBalance: ColorBalanceParams;
|
|
286
|
-
blackWhite: BlackWhiteParams;
|
|
287
|
-
invert: InvertParams;
|
|
288
|
-
posterize: PosterizeParams;
|
|
289
|
-
threshold: ThresholdParams;
|
|
290
|
-
photoFilter: PhotoFilterParams;
|
|
291
130
|
}
|
|
292
|
-
|
|
131
|
+
type DevelopFilter = {
|
|
293
132
|
id: string;
|
|
294
|
-
|
|
295
|
-
name?: string;
|
|
133
|
+
kind: 'develop';
|
|
296
134
|
enabled: boolean;
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
135
|
+
} & DevelopSettings;
|
|
136
|
+
/** Box blur of `radius` pixels (the old `adjustments.blur`), clamped at the canvas edges. */
|
|
137
|
+
interface BlurFilter {
|
|
138
|
+
id: string;
|
|
139
|
+
kind: 'blur';
|
|
140
|
+
enabled: boolean;
|
|
141
|
+
radius: number;
|
|
142
|
+
}
|
|
143
|
+
type LayerFilter = DevelopFilter | BlurFilter;
|
|
144
|
+
type LayerFilterKind = LayerFilter['kind'];
|
|
145
|
+
interface PixelLayer extends LayerBase, Omit<RasterPixelLayer, keyof RasterLayerBase> {
|
|
146
|
+
/** Live filters, applied bottom (first) to top before the mask and blend. */
|
|
147
|
+
filters?: LayerFilter[];
|
|
301
148
|
/**
|
|
302
|
-
*
|
|
303
|
-
*
|
|
149
|
+
* `'document'`: the pixels are the document's source image, unmodified (the Background of an
|
|
150
|
+
* opened image). Such a layer's `surface` is a placeholder; read its pixels through the
|
|
151
|
+
* controller. Painting it drops the flag.
|
|
304
152
|
*/
|
|
305
|
-
|
|
153
|
+
source?: 'document';
|
|
306
154
|
}
|
|
155
|
+
type AdjustmentLayerNode<K extends AdjustmentKind = AdjustmentKind> = {
|
|
156
|
+
[P in K]: LayerBase & {
|
|
157
|
+
type: 'adjustment';
|
|
158
|
+
kind: P;
|
|
159
|
+
params: AdjustmentParamsMap[P];
|
|
160
|
+
};
|
|
161
|
+
}[K];
|
|
162
|
+
interface GroupLayer extends Omit<LayerBase, 'blend'> {
|
|
163
|
+
type: 'group';
|
|
164
|
+
blend: LayerBlendMode;
|
|
165
|
+
/** Bottom to top. */
|
|
166
|
+
children: ImageLayer[];
|
|
167
|
+
/** UI only. */
|
|
168
|
+
collapsed?: boolean;
|
|
169
|
+
}
|
|
170
|
+
/** One annotation (pen, shape, arrow, text, image) as a layer, drawn by the annotation renderer. */
|
|
171
|
+
interface AnnotationLayer extends LayerBase {
|
|
172
|
+
type: 'annotation';
|
|
173
|
+
annotation: Annotation;
|
|
174
|
+
}
|
|
175
|
+
type ImageLayer = PixelLayer | AdjustmentLayerNode | GroupLayer | AnnotationLayer;
|
|
176
|
+
type ImageLayerType = ImageLayer['type'];
|
|
177
|
+
/** Which part of the active layer painting targets. */
|
|
178
|
+
type LayerTarget = 'pixels' | 'mask';
|
|
179
|
+
/** A fresh id with `prefix` (`layer`, `flt`, …). */
|
|
180
|
+
declare function newLayerId(prefix?: string): string;
|
|
181
|
+
type LayerLocation = LayerLocation$1<ImageLayer>;
|
|
182
|
+
|
|
183
|
+
/** The top-level and nested pixel layers. */
|
|
184
|
+
declare function pixelLayers(layers: readonly ImageLayer[]): PixelLayer[];
|
|
185
|
+
/** The develop filter of a pixel layer, if any. */
|
|
186
|
+
declare function developFilter(layer: PixelLayer): DevelopFilter | undefined;
|
|
187
|
+
declare function blurFilter(layer: PixelLayer): BlurFilter | undefined;
|
|
188
|
+
/** True for filters that change pixels (enabled, non-neutral). */
|
|
189
|
+
declare function isActiveFilter(f: LayerFilter): boolean;
|
|
190
|
+
/** True when a filter needs neighbouring pixels (it can't run tile by tile). */
|
|
191
|
+
declare function isSpatialFilter(f: LayerFilter): boolean;
|
|
192
|
+
/** Document-space bounds of a pixel layer's stored tiles, or `null`. */
|
|
193
|
+
declare function pixelLayerBounds(layer: PixelLayer, surface?: PixelSurface): CropBox | null;
|
|
194
|
+
/** Human label of a layer kind. */
|
|
195
|
+
declare function layerTypeLabel(type: ImageLayerType): string;
|
|
196
|
+
|
|
307
197
|
/**
|
|
308
|
-
*
|
|
309
|
-
*
|
|
198
|
+
* Schema version 3 of the image editor document: the layer tree, with pixel layers and painted
|
|
199
|
+
* masks stored as PNG assets (cropped to their content and placed by position), plus the
|
|
200
|
+
* document-level crop, transform, output opacity, migrated blur and selection.
|
|
201
|
+
*
|
|
202
|
+
* Encoding is synchronous and exact (see `png.ts`). Each surface's encoding is memoised, so
|
|
203
|
+
* saving an unchanged layer again costs nothing.
|
|
310
204
|
*/
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
205
|
+
|
|
206
|
+
declare const LAYERED_SCHEMA_VERSION: 3;
|
|
207
|
+
/** A stored raster mask. Pixels: `asset` (grey PNG) placed at `x`, `y`; elsewhere `defaultValue`. */
|
|
208
|
+
interface SerializedRasterMask {
|
|
209
|
+
defaultValue: 0 | 255;
|
|
210
|
+
asset?: string;
|
|
211
|
+
x?: number;
|
|
212
|
+
y?: number;
|
|
317
213
|
density?: number;
|
|
318
|
-
/** Gaussian σ in pixels (missing = 0). */
|
|
319
214
|
feather?: number;
|
|
320
|
-
/** `false` keeps the mask but ignores it. */
|
|
321
215
|
enabled?: boolean;
|
|
216
|
+
source?: DepthMaskOptions;
|
|
322
217
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
218
|
+
interface SerializedLayerBase {
|
|
219
|
+
id: string;
|
|
220
|
+
name: string;
|
|
221
|
+
visible: boolean;
|
|
222
|
+
opacity: number;
|
|
223
|
+
blend: string;
|
|
224
|
+
clipped?: boolean;
|
|
225
|
+
mask?: SerializedRasterMask;
|
|
226
|
+
locks?: LayerLocks;
|
|
227
|
+
}
|
|
228
|
+
interface SerializedPixelLayer extends SerializedLayerBase {
|
|
229
|
+
type: 'pixel';
|
|
230
|
+
/** Asset id of the pixels (RGBA PNG) placed at `x`, `y` in layer space; missing when empty. */
|
|
231
|
+
asset?: string;
|
|
232
|
+
x?: number;
|
|
233
|
+
y?: number;
|
|
234
|
+
offset: {
|
|
235
|
+
x: number;
|
|
236
|
+
y: number;
|
|
328
237
|
};
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
238
|
+
fillOpacity?: number;
|
|
239
|
+
filters?: LayerFilter[];
|
|
240
|
+
/** `'document'`: the pixels are the document's source image (no asset is stored). */
|
|
241
|
+
source?: 'document';
|
|
242
|
+
}
|
|
243
|
+
interface SerializedAdjustmentLayer extends SerializedLayerBase {
|
|
244
|
+
type: 'adjustment';
|
|
245
|
+
kind: string;
|
|
246
|
+
params: unknown;
|
|
247
|
+
}
|
|
248
|
+
interface SerializedGroupLayer extends SerializedLayerBase {
|
|
249
|
+
type: 'group';
|
|
250
|
+
children: SerializedLayer[];
|
|
251
|
+
collapsed?: boolean;
|
|
252
|
+
}
|
|
253
|
+
interface SerializedAnnotationLayer extends SerializedLayerBase {
|
|
254
|
+
type: 'annotation';
|
|
255
|
+
annotation: Annotation;
|
|
256
|
+
}
|
|
257
|
+
type SerializedLayer = SerializedPixelLayer | SerializedAdjustmentLayer | SerializedGroupLayer | SerializedAnnotationLayer;
|
|
258
|
+
/** A version 3 document (layers). */
|
|
259
|
+
interface SerializedLayeredImageEditorState {
|
|
260
|
+
version: 3;
|
|
261
|
+
/** Canvas size in pixels. */
|
|
262
|
+
width: number;
|
|
263
|
+
height: number;
|
|
264
|
+
/** Bottom to top. */
|
|
265
|
+
layers: SerializedLayer[];
|
|
266
|
+
/** Asset id → PNG data URL (or an external reference, see `ImageEditorAssetStore`). */
|
|
267
|
+
assets: Record<string, string>;
|
|
268
|
+
activeLayerId: string | null;
|
|
269
|
+
crop: CropBox | null;
|
|
270
|
+
transform: ImageTransform;
|
|
271
|
+
/** Export alpha, 0..1. */
|
|
272
|
+
opacity: number;
|
|
273
|
+
/** Blur migrated from a v1 / v2 document with adjustment layers (runs after the layers). */
|
|
274
|
+
legacyOutputBlur?: number;
|
|
275
|
+
selection?: SerializedSelection;
|
|
340
276
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
id: string;
|
|
344
|
-
type: AnnotationType;
|
|
277
|
+
interface EncodedSurface {
|
|
278
|
+
url: string;
|
|
345
279
|
x: number;
|
|
346
280
|
y: number;
|
|
347
|
-
rotation?: number;
|
|
348
|
-
opacity?: number;
|
|
349
|
-
/** Blend mode the annotation is drawn with (default `normal`). */
|
|
350
|
-
blend?: BlendMode;
|
|
351
281
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
282
|
+
/** The surface's content (non-default pixels) as a PNG data URL and its position, or `null`. */
|
|
283
|
+
declare function encodeSurface(surface: TiledSurface): EncodedSurface | null;
|
|
284
|
+
interface SerializeContext {
|
|
285
|
+
/** Adds an asset and returns its id. */
|
|
286
|
+
addAsset(url: string, hint: string): string;
|
|
287
|
+
}
|
|
288
|
+
declare function serializeLayer(layer: ImageLayer, ctx: SerializeContext): SerializedLayer;
|
|
289
|
+
/** Serializes a layer tree with inline assets (asset ids are derived from layer ids). */
|
|
290
|
+
declare function serializeLayers(layers: readonly ImageLayer[]): {
|
|
291
|
+
layers: SerializedLayer[];
|
|
292
|
+
assets: Record<string, string>;
|
|
293
|
+
};
|
|
294
|
+
/**
|
|
295
|
+
* Where a host keeps layer pixels outside the JSON (`toJSON({ assets: 'external', store })`):
|
|
296
|
+
* `put` stores a PNG and returns a reference (a URL, a key) that `get` resolves later.
|
|
297
|
+
*/
|
|
298
|
+
interface ImageEditorAssetStore {
|
|
299
|
+
put(blob: Blob, info: {
|
|
300
|
+
id: string;
|
|
301
|
+
width: number;
|
|
302
|
+
height: number;
|
|
303
|
+
}): Promise<string>;
|
|
304
|
+
get(ref: string): Promise<Blob>;
|
|
357
305
|
}
|
|
358
|
-
|
|
359
|
-
|
|
306
|
+
/**
|
|
307
|
+
* Serializes a layer tree with its assets in `store`: each PNG is uploaded once per store (by
|
|
308
|
+
* content), and `assets` maps asset ids to the store's references.
|
|
309
|
+
*/
|
|
310
|
+
declare function serializeLayersExternal(layers: readonly ImageLayer[], store: ImageEditorAssetStore): Promise<{
|
|
311
|
+
layers: SerializedLayer[];
|
|
312
|
+
assets: Record<string, string>;
|
|
313
|
+
}>;
|
|
314
|
+
/**
|
|
315
|
+
* Turns external asset references back into data URLs through `store.get` (data URLs pass through),
|
|
316
|
+
* so the document loads like an inline one. References that fail are reported and left out.
|
|
317
|
+
*/
|
|
318
|
+
declare function resolveExternalAssets(assets: Record<string, string>, store: ImageEditorAssetStore | undefined, problems: string[]): Promise<Record<string, string>>;
|
|
319
|
+
interface DeserializeContext {
|
|
320
|
+
assets: Record<string, string>;
|
|
321
|
+
/** Decodes an asset (PNG data URL by default). Throw for an unusable asset. */
|
|
322
|
+
decodeAsset?(ref: string, channels: 1 | 4): {
|
|
323
|
+
width: number;
|
|
324
|
+
height: number;
|
|
325
|
+
data: ArrayLike<number>;
|
|
326
|
+
};
|
|
327
|
+
/** Problems found while reading (unknown kinds, broken assets); the rest still loads. */
|
|
328
|
+
problems: string[];
|
|
329
|
+
}
|
|
330
|
+
/** Decodes a PNG data URL into pixels of `channels` bytes each. */
|
|
331
|
+
declare function decodePngDataUrl(url: string, channels: 1 | 4): {
|
|
360
332
|
width: number;
|
|
361
333
|
height: number;
|
|
362
|
-
|
|
363
|
-
strokeWidth: number;
|
|
364
|
-
fillColor?: string;
|
|
365
|
-
cornerRadius?: number;
|
|
366
|
-
}
|
|
367
|
-
interface CircleAnnotation extends BaseAnnotation {
|
|
368
|
-
type: 'circle';
|
|
369
|
-
radiusX: number;
|
|
370
|
-
radiusY: number;
|
|
371
|
-
strokeColor: string;
|
|
372
|
-
strokeWidth: number;
|
|
373
|
-
fillColor?: string;
|
|
374
|
-
}
|
|
375
|
-
interface ArrowAnnotation extends BaseAnnotation {
|
|
376
|
-
type: 'arrow';
|
|
377
|
-
endX: number;
|
|
378
|
-
endY: number;
|
|
379
|
-
strokeColor: string;
|
|
380
|
-
strokeWidth: number;
|
|
381
|
-
}
|
|
382
|
-
interface LineAnnotation extends BaseAnnotation {
|
|
383
|
-
type: 'line';
|
|
384
|
-
endX: number;
|
|
385
|
-
endY: number;
|
|
386
|
-
strokeColor: string;
|
|
387
|
-
strokeWidth: number;
|
|
388
|
-
}
|
|
389
|
-
interface TextAnnotation extends BaseAnnotation {
|
|
390
|
-
type: 'text';
|
|
391
|
-
text: string;
|
|
392
|
-
fontSize: number;
|
|
393
|
-
fontFamily?: string;
|
|
394
|
-
color: string;
|
|
395
|
-
fontWeight?: string | number;
|
|
396
|
-
}
|
|
397
|
-
interface ImageAnnotation extends BaseAnnotation {
|
|
398
|
-
type: 'image';
|
|
399
|
-
src: string;
|
|
400
|
-
width: number;
|
|
401
|
-
height: number;
|
|
402
|
-
}
|
|
403
|
-
type Annotation = PenAnnotation | RectAnnotation | CircleAnnotation | ArrowAnnotation | LineAnnotation | TextAnnotation | ImageAnnotation;
|
|
404
|
-
type CreateAnnotationPayload = Omit<PenAnnotation, 'id'> | Omit<RectAnnotation, 'id'> | Omit<CircleAnnotation, 'id'> | Omit<ArrowAnnotation, 'id'> | Omit<LineAnnotation, 'id'> | Omit<TextAnnotation, 'id'> | Omit<ImageAnnotation, 'id'>;
|
|
405
|
-
type ImageEditorTool = 'select' | 'crop' | 'pen' | 'rect' | 'circle' | 'arrow' | 'line' | 'text' | 'watermark';
|
|
406
|
-
interface ImageEditorState {
|
|
407
|
-
sourceUrl: string | null;
|
|
408
|
-
imageDimensions: ImageDimensions;
|
|
409
|
-
crop: CropBox | null;
|
|
410
|
-
transform: ImageTransform;
|
|
411
|
-
adjustments: ImageAdjustments;
|
|
412
|
-
depthMask: DepthMaskOptions;
|
|
413
|
-
annotations: Annotation[];
|
|
414
|
-
selectedAnnotationId: string | null;
|
|
415
|
-
activeTool: ImageEditorTool;
|
|
416
|
-
zoom: number;
|
|
417
|
-
pan: ImagePoint;
|
|
418
|
-
isOriginalCompared: boolean;
|
|
419
|
-
/**
|
|
420
|
-
* The active selection (8-bit coverage over the source image), or null/missing when nothing is
|
|
421
|
-
* selected. Recorded in undo history and saved as `selection` in `toJSON()`.
|
|
422
|
-
*/
|
|
423
|
-
selection?: SelectionMask | null;
|
|
424
|
-
/** Quick Mask view: tint the unselected area instead of drawing marching ants (view state). */
|
|
425
|
-
quickMask?: boolean;
|
|
426
|
-
}
|
|
427
|
-
interface SerializedImageEditorState {
|
|
428
|
-
/**
|
|
429
|
-
* Schema version. `2` adds `adjustments.layers`; states without layers are still written as
|
|
430
|
-
* `1` so they round-trip unchanged. See `migrateSerializedImageEditorState`.
|
|
431
|
-
*/
|
|
432
|
-
version: 1 | 2;
|
|
433
|
-
crop: CropBox | null;
|
|
434
|
-
transform: ImageTransform;
|
|
435
|
-
adjustments: ImageAdjustments;
|
|
436
|
-
depthMask: DepthMaskOptions;
|
|
437
|
-
annotations: Annotation[];
|
|
438
|
-
/** The active selection, run-length encoded. Missing when nothing is selected. */
|
|
439
|
-
selection?: SerializedSelection;
|
|
440
|
-
}
|
|
441
|
-
interface ExportOptions {
|
|
442
|
-
format?: 'image/png' | 'image/jpeg' | 'image/webp';
|
|
443
|
-
quality?: number;
|
|
444
|
-
width?: number;
|
|
445
|
-
height?: number;
|
|
446
|
-
includeAnnotations?: boolean;
|
|
447
|
-
}
|
|
448
|
-
interface ImageEditorOptions {
|
|
449
|
-
image?: string | HTMLImageElement;
|
|
450
|
-
initialState?: Partial<SerializedImageEditorState>;
|
|
451
|
-
onStateChange?: (state: ImageEditorState) => void;
|
|
452
|
-
maxHistoryDepth?: number;
|
|
453
|
-
}
|
|
454
|
-
interface InpaintOptions {
|
|
455
|
-
prompt: string;
|
|
456
|
-
imageDataUrl: string;
|
|
457
|
-
maskDataUrl?: string;
|
|
458
|
-
cropBox?: CropBox | null;
|
|
459
|
-
}
|
|
460
|
-
interface RemoveBackgroundOptions {
|
|
461
|
-
imageDataUrl: string;
|
|
462
|
-
}
|
|
463
|
-
type InpaintHook = (options: InpaintOptions) => Promise<string | void> | string | void;
|
|
464
|
-
type RemoveBackgroundHook = (options: RemoveBackgroundOptions) => Promise<string | void> | string | void;
|
|
465
|
-
interface ImageEditorAIHooks {
|
|
466
|
-
onInpaint?: InpaintHook;
|
|
467
|
-
onRemoveBackground?: RemoveBackgroundHook;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
/**
|
|
471
|
-
* Applies color and tone adjustments (brightness, contrast, saturation, exposure, temperature, tint,
|
|
472
|
-
* opacity, then any adjustment `layers`, then blur) directly to the pixel data of an ImageData buffer.
|
|
473
|
-
*
|
|
474
|
-
* `adjustments.process` selects the rendering: `2` is the linear-light pipeline
|
|
475
|
-
* ({@link applyProcess2Adjustments}); anything else (including a missing value, as in edits saved
|
|
476
|
-
* before process versions existed) is the frozen legacy rendering ({@link applyLegacyAdjustments}).
|
|
477
|
-
*/
|
|
478
|
-
declare function applyAdjustments(imageData: ImageData, adjustments: ImageAdjustments, options?: {
|
|
479
|
-
layerMasks?: ReadonlyMap<string, ArrayLike<number>>;
|
|
480
|
-
}): void;
|
|
481
|
-
/**
|
|
482
|
-
* Process 1: the original 8-bit gamma-space rendering, clamping after every step. Frozen so
|
|
483
|
-
* that edits saved without a `process` look exactly as they always have. `tint` is ignored.
|
|
484
|
-
*/
|
|
485
|
-
declare function applyLegacyAdjustments(imageData: ImageData, adjustments: ImageAdjustments): void;
|
|
486
|
-
/**
|
|
487
|
-
* Process 2: decode sRGB to linear float once; apply exposure (gain) and white balance (a
|
|
488
|
-
* Bradford matrix relative to as-shot) in linear light; a per-channel tone LUT for the
|
|
489
|
-
* highlight shoulder, contrast and brightness; luminance-preserving saturation in linear light;
|
|
490
|
-
* then encode back to sRGB through a LUT. Nothing is clamped between stages, only at the final
|
|
491
|
-
* encode. Neutral settings are the identity.
|
|
492
|
-
*/
|
|
493
|
-
declare function applyProcess2Adjustments(imageData: ImageData, adjustments: ImageAdjustments): void;
|
|
494
|
-
/**
|
|
495
|
-
* Blends a depth/alpha mask into the main image data based on Gleamforge depth masking.
|
|
496
|
-
* Supports threshold range with softness gradation, brightness mode, and optional inversion.
|
|
497
|
-
*/
|
|
498
|
-
declare function applyDepthMask(mainImageData: ImageData, maskImageData: ImageData, options: DepthMaskOptions): void;
|
|
499
|
-
/**
|
|
500
|
-
* Removes alpha channel by setting all alpha bytes to 255 (completely opaque).
|
|
501
|
-
* From Gleamforge image-filters.ts.
|
|
502
|
-
*/
|
|
503
|
-
declare function removeAlpha(imageData: ImageData): void;
|
|
504
|
-
|
|
505
|
-
/**
|
|
506
|
-
* Colour science for the image editor's process 2 rendering: sRGB transfer functions,
|
|
507
|
-
* correlated colour temperature / tint (Kim et al. Planckian locus, tint as Duv), Bradford
|
|
508
|
-
* white-balance adaptation relative to "as shot", and the display-referred tone curve.
|
|
509
|
-
*/
|
|
510
|
-
/** A CIE 1931 chromaticity. */
|
|
511
|
-
interface Chromaticity {
|
|
512
|
-
x: number;
|
|
513
|
-
y: number;
|
|
514
|
-
}
|
|
515
|
-
/** A row-major 3×3 matrix (`[m00, m01, m02, m10, …, m22]`). */
|
|
516
|
-
type Matrix3 = [number, number, number, number, number, number, number, number, number];
|
|
517
|
-
/** The rendering of adjustments from before process versions existed. Frozen. */
|
|
518
|
-
declare const LEGACY_PROCESS_VERSION: 1;
|
|
519
|
-
/** The process new edits and Reset get. */
|
|
520
|
-
declare const LATEST_PROCESS_VERSION: 2;
|
|
521
|
-
type ImageProcessVersion = 1 | 2;
|
|
522
|
-
/**
|
|
523
|
-
* Reads a stored process number leniently: a missing or damaged value (not a whole number) is
|
|
524
|
-
* the legacy process, so a saved edit from before process versions renders exactly as it did. A
|
|
525
|
-
* whole number newer than this build knows renders with the latest process.
|
|
526
|
-
*/
|
|
527
|
-
declare function normalizeProcessVersion(value: unknown): ImageProcessVersion;
|
|
528
|
-
declare function srgbToLinear(v: number): number;
|
|
529
|
-
declare function linearToSrgb(v: number): number;
|
|
530
|
-
/** Rec.709 / sRGB luminance weights (linear light). */
|
|
531
|
-
declare const LUMA_709: readonly [number, number, number];
|
|
532
|
-
declare const IDENTITY_MATRIX3: Matrix3;
|
|
533
|
-
declare function mulMatrix3(a: Matrix3, b: Matrix3): Matrix3;
|
|
534
|
-
declare function applyMatrix3(m: Matrix3, v: readonly [number, number, number]): [number, number, number];
|
|
535
|
-
declare function invertMatrix3(m: Matrix3): Matrix3 | null;
|
|
536
|
-
declare const D65: Chromaticity;
|
|
537
|
-
/** Bradford chromatic adaptation (XYZ → XYZ) from white `src` to white `dst`. */
|
|
538
|
-
declare function bradfordAdaptation(src: Chromaticity, dst: Chromaticity): Matrix3;
|
|
539
|
-
/**
|
|
540
|
-
* Matrix (linear sRGB → linear sRGB) that white-balances a scene lit by `src` so that it
|
|
541
|
-
* renders as if lit by D65.
|
|
542
|
-
*/
|
|
543
|
-
declare function wbMatrix(src: Chromaticity): Matrix3;
|
|
544
|
-
/** The chromaticity of a linear sRGB colour. */
|
|
545
|
-
declare function linearSrgbToXy(rgb: readonly [number, number, number]): Chromaticity;
|
|
546
|
-
/** Tint units per unit of Duv. */
|
|
547
|
-
declare const TINT_SCALE = 3000;
|
|
548
|
-
declare const MIN_KELVIN = 1667;
|
|
549
|
-
declare const MAX_KELVIN = 25000;
|
|
550
|
-
/** CIE 1931 xy → CIE 1960 uv. */
|
|
551
|
-
declare function xyToUv(p: Chromaticity): [number, number];
|
|
552
|
-
/** CIE 1960 uv → CIE 1931 xy. */
|
|
553
|
-
declare function uvToXy(u: number, v: number): Chromaticity;
|
|
554
|
-
/**
|
|
555
|
-
* Source illuminant chromaticity for temperature `kelvin` and correction `tint`.
|
|
556
|
-
* Positive tint means a green source white, whose correction adds magenta to the image.
|
|
557
|
-
*/
|
|
558
|
-
declare function tempTintToXy(kelvin: number, tint: number): Chromaticity;
|
|
559
|
-
/** Inverse of {@link tempTintToXy}: nearest locus temperature (searched in mired space) and tint. */
|
|
560
|
-
declare function xyToTempTint(p: Chromaticity): {
|
|
561
|
-
kelvin: number;
|
|
562
|
-
tint: number;
|
|
563
|
-
};
|
|
564
|
-
/** Rendered images carry no as-shot white: "as shot" is 6500 K / tint 0 and maps to the identity. */
|
|
565
|
-
declare const AS_SHOT_KELVIN = 6500;
|
|
566
|
-
/** Mireds per unit of the `temperature` slider (−100…100). */
|
|
567
|
-
declare const MIRED_PER_TEMPERATURE_UNIT = 1;
|
|
568
|
-
/**
|
|
569
|
-
* Maps the `temperature` slider (−100 cool … +100 warm) to the Kelvin white-balance setting:
|
|
570
|
-
* one mired per unit around 6500 K, so 0 → 6500 K, +100 → ~18 570 K (a strong warming
|
|
571
|
-
* correction), −100 → ~3 940 K (a strong cooling correction). Mireds are perceptually even,
|
|
572
|
-
* so equal slider steps look like equal changes.
|
|
573
|
-
*/
|
|
574
|
-
declare function temperatureToKelvin(temperature: number): number;
|
|
575
|
-
/** Inverse of {@link temperatureToKelvin}. */
|
|
576
|
-
declare function kelvinToTemperature(kelvin: number): number;
|
|
577
|
-
/**
|
|
578
|
-
* White-balance matrix (linear sRGB) for the `temperature` / `tint` sliders, relative to
|
|
579
|
-
* "as shot": the identity at 0 / 0. Normalised so neutral luminance is preserved (white
|
|
580
|
-
* balance doesn't change exposure).
|
|
581
|
-
*/
|
|
582
|
-
declare function whiteBalanceMatrix(temperature: number, tint?: number): Matrix3;
|
|
583
|
-
/**
|
|
584
|
-
* Neutral-point eyedropper: the `temperature` / `tint` that render the sampled sRGB colour
|
|
585
|
-
* (0–255 per channel, as it appears in the unadjusted image) neutral. Results are clamped to
|
|
586
|
-
* the slider range −100…100.
|
|
587
|
-
*/
|
|
588
|
-
declare function whiteBalanceFromSample(rgb: readonly [number, number, number] | {
|
|
589
|
-
r: number;
|
|
590
|
-
g: number;
|
|
591
|
-
b: number;
|
|
592
|
-
}): {
|
|
593
|
-
temperature: number;
|
|
594
|
-
tint: number;
|
|
334
|
+
data: Uint8ClampedArray;
|
|
595
335
|
};
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
* The process 2 tone curve for one linear input value in `[0, headroom]`:
|
|
600
|
-
*
|
|
601
|
-
* 1. A highlight shoulder (extended Reinhard with white point `headroom`) above a knee of 0.6
|
|
602
|
-
* rolls values above 1 (after exposure / white balance) back into range instead of clipping.
|
|
603
|
-
* With no headroom (`headroom = 1`) it is exactly the identity.
|
|
604
|
-
* 2. In a gamma-2.2 perceptual domain, contrast is an S-curve anchored at 0, middle grey and 1
|
|
605
|
-
* (as `ToneMap::display`), and brightness a midtone lift anchored at 0 and 1.
|
|
606
|
-
*
|
|
607
|
-
* `contrast` and `brightness` are −100…100; both 0 with `headroom = 1` is the identity.
|
|
608
|
-
*/
|
|
609
|
-
declare function toneCurve(y: number, contrast: number, brightness: number, headroom?: number): number;
|
|
610
|
-
/** Tabulates {@link toneCurve} over `[0, headroom]` in {@link TONE_LUT_SIZE} steps. */
|
|
611
|
-
declare function buildToneLut(contrast: number, brightness: number, headroom?: number): Float32Array;
|
|
612
|
-
/** Linearly interpolated lookup into a LUT from {@link buildToneLut}. */
|
|
613
|
-
declare function sampleToneLut(lut: Float32Array, headroom: number, y: number): number;
|
|
336
|
+
declare function deserializeLayer(raw: unknown, ctx: DeserializeContext): ImageLayer | null;
|
|
337
|
+
/** Reads a stored layer tree (layers that cannot be read are dropped and reported). */
|
|
338
|
+
declare function deserializeLayers(raw: unknown, ctx: DeserializeContext): ImageLayer[];
|
|
614
339
|
|
|
615
340
|
/** Display bins of a histogram. */
|
|
616
341
|
declare const HISTOGRAM_BINS = 256;
|
|
@@ -653,6 +378,39 @@ declare function histogramPath(histogram: ImageHistogram, channel: HistogramChan
|
|
|
653
378
|
max?: number;
|
|
654
379
|
}): string;
|
|
655
380
|
|
|
381
|
+
/**
|
|
382
|
+
* The image editor's compositor: the raster engine (`@pixerate/editor/raster`) with the photo
|
|
383
|
+
* layer kinds plugged in. Adjustment layers filter what is below them (a run of adjacent ones is
|
|
384
|
+
* one float pass with one rounding at the end, exactly as `applyAdjustmentLayers` does, so a
|
|
385
|
+
* document migrated from adjustment layers renders identically); annotation layers are drawn by
|
|
386
|
+
* the host; pixel layers can carry develop and blur filters; masks can be depth masks.
|
|
387
|
+
*/
|
|
388
|
+
|
|
389
|
+
/** What the compositor needs from its host besides the layers. */
|
|
390
|
+
interface CompositorSources extends RasterSources {
|
|
391
|
+
/** The pixels of a pixel layer (resolves layers whose pixels are the document source). */
|
|
392
|
+
surfaceOf?(layer: PixelLayer): PixelSurface;
|
|
393
|
+
/**
|
|
394
|
+
* A parametric mask's depth map as RGBA at canvas size (the red channel is the depth), or
|
|
395
|
+
* `null` while it is unavailable (the mask then reveals everything).
|
|
396
|
+
*/
|
|
397
|
+
depthMap?(source: DepthMaskOptions): {
|
|
398
|
+
width: number;
|
|
399
|
+
height: number;
|
|
400
|
+
data: ArrayLike<number>;
|
|
401
|
+
} | null;
|
|
402
|
+
/** Draws one annotation into RGBA for `rect` (canvas hosts only); `null` when unavailable. */
|
|
403
|
+
rasterizeAnnotation?(annotation: Annotation, rect: CropBox): Uint8ClampedArray | null;
|
|
404
|
+
}
|
|
405
|
+
/** The `AdjustmentLayer` shape `applyAdjustmentLayers` evaluates, for a node (memoised). */
|
|
406
|
+
declare function adjustmentNodeAsLayer(node: AdjustmentLayerNode): AdjustmentLayer;
|
|
407
|
+
/** Evaluates a depth mask (see `applyDepthMask`) into one coverage byte per depth sample. */
|
|
408
|
+
declare function depthMaskAlpha(depth: number, options: DepthMaskOptions): number;
|
|
409
|
+
/** The per-tile compositor for image editor layer stacks (see the raster module for the caches). */
|
|
410
|
+
declare class LayerCompositor extends RasterCompositor<ImageLayer, CompositorSources> {
|
|
411
|
+
constructor(options?: CompositorOptions);
|
|
412
|
+
}
|
|
413
|
+
|
|
656
414
|
interface RenderOptions {
|
|
657
415
|
viewportWidth?: number;
|
|
658
416
|
viewportHeight?: number;
|
|
@@ -661,6 +419,8 @@ interface RenderOptions {
|
|
|
661
419
|
interactive?: boolean;
|
|
662
420
|
draftAnnotation?: Annotation | null;
|
|
663
421
|
draftCrop?: CropBox | null;
|
|
422
|
+
/** Viewport fit mode: 'contain' scales to full viewport bounds; 'margin' scales to 85% with 1.0 cap (default). */
|
|
423
|
+
fit?: ImageEditorFit;
|
|
664
424
|
/**
|
|
665
425
|
* How the active selection is shown: marching ants (default when there is a selection),
|
|
666
426
|
* a Quick Mask tint over the unselected area (default when `state.quickMask`), or not at all.
|
|
@@ -670,6 +430,16 @@ interface RenderOptions {
|
|
|
670
430
|
antsOffset?: number;
|
|
671
431
|
/** A selection being drawn (e.g. a lasso), shown as a dashed outline in natural pixels. */
|
|
672
432
|
draftSelectionPath?: ImagePoint[] | null;
|
|
433
|
+
/** Document rectangles that are the only change since the last render (strokes); recomposites only there. */
|
|
434
|
+
dirty?: CropBox[];
|
|
435
|
+
/** The layer being edited: tiles keep a checkpoint below it so strokes and drags on it start there. */
|
|
436
|
+
checkpointLayerId?: string | null;
|
|
437
|
+
/** The paint tools' cursor: a circle of `diameter` px at (`x`, `y`) in natural pixels. */
|
|
438
|
+
brushCursor?: {
|
|
439
|
+
x: number;
|
|
440
|
+
y: number;
|
|
441
|
+
diameter: number;
|
|
442
|
+
} | null;
|
|
673
443
|
}
|
|
674
444
|
/**
|
|
675
445
|
* Image Cache to avoid refetching HTMLImageElement objects repeatedly during re-renders.
|
|
@@ -678,6 +448,8 @@ declare class ImageCache {
|
|
|
678
448
|
private cache;
|
|
679
449
|
get(src: string): Promise<HTMLImageElement>;
|
|
680
450
|
set(src: string, img: HTMLImageElement): void;
|
|
451
|
+
/** The loaded image for `src`, or `undefined` while it is not loaded yet. */
|
|
452
|
+
peek(src: string): HTMLImageElement | undefined;
|
|
681
453
|
clear(): void;
|
|
682
454
|
}
|
|
683
455
|
declare const globalImageCache: ImageCache;
|
|
@@ -698,6 +470,28 @@ declare class ImageEditorRenderer {
|
|
|
698
470
|
onPreviewHistogram?: (histogram: ImageHistogram | null) => void;
|
|
699
471
|
private sourceIds;
|
|
700
472
|
private nextSourceId;
|
|
473
|
+
/**
|
|
474
|
+
* The viewport's compositor. It only ever composites the viewport's stack, so its tile cache can
|
|
475
|
+
* trust dirty rectangles; exports use `exportCompositor`.
|
|
476
|
+
*/
|
|
477
|
+
compositor: LayerCompositor;
|
|
478
|
+
private exportCompositor;
|
|
479
|
+
/** How the host resolves layer pixels (set by the controller). */
|
|
480
|
+
layerSources?: LayerSourcesHost;
|
|
481
|
+
/**
|
|
482
|
+
* Debug / test switch: `'legacy'` forces the old base path for documents that still have the
|
|
483
|
+
* v1 / v2 shape, `'layers'` forces the compositor. Default: chosen per document.
|
|
484
|
+
*/
|
|
485
|
+
baseRoute: 'auto' | 'legacy' | 'layers';
|
|
486
|
+
/** Which path the last base render took. */
|
|
487
|
+
lastBaseRoute: 'legacy' | 'layers' | null;
|
|
488
|
+
private comp;
|
|
489
|
+
private depthMaps;
|
|
490
|
+
private assetVersion;
|
|
491
|
+
private scratch;
|
|
492
|
+
private cachedPostCanvas;
|
|
493
|
+
private cachedPostKey;
|
|
494
|
+
private cachedPostHistogram;
|
|
701
495
|
/**
|
|
702
496
|
* Helper to create a canvas element safely in browser/JSDOM.
|
|
703
497
|
*/
|
|
@@ -711,6 +505,32 @@ declare class ImageEditorRenderer {
|
|
|
711
505
|
* and the depth mask (which receives the identical transform so it stays aligned).
|
|
712
506
|
*/
|
|
713
507
|
private renderBaseImage;
|
|
508
|
+
/** Which base path renders `state` (see `needsLegacyBase`). */
|
|
509
|
+
private chooseRoute;
|
|
510
|
+
/** Compositor sources for a `width × height` canvas: layer pixels, depth maps and annotation rasterizing. */
|
|
511
|
+
compositorSources(width: number, height: number): CompositorSources;
|
|
512
|
+
/** Loads what the compositor reads synchronously: depth maps (at canvas size) and annotation images. */
|
|
513
|
+
/** Loads depth maps and annotation images the compositor reads synchronously. */
|
|
514
|
+
prepareLayerAssets(layers: readonly ImageLayer[], width: number, height: number): Promise<void>;
|
|
515
|
+
/** Whether annotation layers can be rasterized here (a 2D canvas with pixel access). */
|
|
516
|
+
canRasterize(): boolean;
|
|
517
|
+
/** One annotation drawn into a tile-sized RGBA buffer at `rect` (document space), or `null` without a canvas. */
|
|
518
|
+
private rasterizeAnnotation;
|
|
519
|
+
private putTile;
|
|
520
|
+
/**
|
|
521
|
+
* Brings the viewport's composite canvas (document space, covering `region`) up to date,
|
|
522
|
+
* uploading only the tiles that changed since the last render.
|
|
523
|
+
*/
|
|
524
|
+
private updateComposite;
|
|
525
|
+
/**
|
|
526
|
+
* The base canvas of a layered document: the composite drawn through the base projection (crop,
|
|
527
|
+
* rotation, flips at scale 1), then output opacity and the migrated blur, which run in the output
|
|
528
|
+
* frame. Cached until the composite or those settings change.
|
|
529
|
+
*/
|
|
530
|
+
private layeredBase;
|
|
531
|
+
/** Output opacity then the migrated blur, in place on a base canvas; returns its histogram. */
|
|
532
|
+
private applyPost;
|
|
533
|
+
private publishHistogram;
|
|
714
534
|
private quickMaskCache;
|
|
715
535
|
private outlineCache;
|
|
716
536
|
/** Rubylith over the unselected area, drawn in natural image space. */
|
|
@@ -731,6 +551,8 @@ declare class ImageEditorRenderer {
|
|
|
731
551
|
*/
|
|
732
552
|
private drawAnnotationBlended;
|
|
733
553
|
private drawAnnotationContent;
|
|
554
|
+
/** Draws an annotation synchronously; an image annotation draws `img` (skipped when `null`). */
|
|
555
|
+
drawAnnotationShape(ctx: CanvasRenderingContext2D, ann: Annotation, img: CanvasImageSource | null): void;
|
|
734
556
|
/**
|
|
735
557
|
* Draws selection box around active annotation.
|
|
736
558
|
*/
|
|
@@ -764,6 +586,12 @@ declare class ImageEditorRenderer {
|
|
|
764
586
|
}): Promise<HTMLCanvasElement>;
|
|
765
587
|
private drawAnnotationMask;
|
|
766
588
|
}
|
|
589
|
+
/** What the renderer asks its host (the controller) about layer pixels. */
|
|
590
|
+
interface LayerSourcesHost {
|
|
591
|
+
surfaceOf(layer: PixelLayer): PixelSurface;
|
|
592
|
+
sourceIsOpaque(): boolean;
|
|
593
|
+
version(): string;
|
|
594
|
+
}
|
|
767
595
|
|
|
768
596
|
interface ShapeSelectionOptions {
|
|
769
597
|
/** Partial coverage along the edge (default true). */
|
|
@@ -866,16 +694,6 @@ declare function borderCoverage(m: ArrayLike<number>, w: number, h: number, r: n
|
|
|
866
694
|
* re-thresholded at ½ — specks drop, corners round, straight edges stay hard.
|
|
867
695
|
*/
|
|
868
696
|
declare function smoothCoverage(m: ArrayLike<number>, w: number, h: number, r: number): Float32Array;
|
|
869
|
-
/** Above this σ a Gaussian is approximated by three box passes (cost independent of σ). */
|
|
870
|
-
declare const DIRECT_GAUSSIAN_MAX_SIGMA = 8;
|
|
871
|
-
type Edge = 'zero' | 'clamp';
|
|
872
|
-
/**
|
|
873
|
-
* Separable Gaussian blur of a single-channel float image. `edge` `zero` treats pixels beyond
|
|
874
|
-
* the image as 0 (selection feather), `clamp` replicates the border (mask refinement). σ up to
|
|
875
|
-
* {@link DIRECT_GAUSSIAN_MAX_SIGMA} is convolved directly; wider blurs use three box passes, so
|
|
876
|
-
* the cost per pixel never grows with σ.
|
|
877
|
-
*/
|
|
878
|
-
declare function gaussianBlur(src: ArrayLike<number>, w: number, h: number, sigma: number, edge?: Edge): Float32Array;
|
|
879
697
|
/** Select › Modify › Feather: Gaussian blur with σ = radius (as Photoshop), zero beyond the image. */
|
|
880
698
|
declare function featherCoverage(m: ArrayLike<number>, w: number, h: number, radius: number): Float32Array;
|
|
881
699
|
/** Grey dilation (`grow`) or erosion with a square of radius `r`, separable, O(1) per pixel. */
|
|
@@ -1109,10 +927,237 @@ declare function projectMaskCoverage(coverage: Float32Array, maskWidth: number,
|
|
|
1109
927
|
*/
|
|
1110
928
|
declare function buildLayerMaskPlanes(layers: readonly AdjustmentLayer[] | undefined, naturalWidth: number, naturalHeight: number, projection: ImageProjection, targetWidth: number, targetHeight: number): Map<string, Float32Array> | undefined;
|
|
1111
929
|
|
|
1112
|
-
/**
|
|
1113
|
-
declare
|
|
1114
|
-
|
|
1115
|
-
|
|
930
|
+
/** A refused layer operation; the message says why and how to fix it. */
|
|
931
|
+
declare class LayerOperationError extends Error {
|
|
932
|
+
constructor(message: string);
|
|
933
|
+
}
|
|
934
|
+
/** Where a layer goes: above or below a layer (in its group), or at a position in a group. */
|
|
935
|
+
interface LayerPlacement {
|
|
936
|
+
/** Directly above this layer, in the same group. */
|
|
937
|
+
aboveId?: string;
|
|
938
|
+
/** Directly below this layer, in the same group. */
|
|
939
|
+
belowId?: string;
|
|
940
|
+
/** Inside this group (at `index`, default the top). */
|
|
941
|
+
parentId?: string;
|
|
942
|
+
/** Index in the parent's children (or the top level), 0 = bottom. */
|
|
943
|
+
index?: number;
|
|
944
|
+
}
|
|
945
|
+
/** The layer with `id`, or a `LayerOperationError` listing the ids that exist. */
|
|
946
|
+
declare function requireLayer(layers: readonly ImageLayer[], id: string): LayerLocation$1<ImageLayer>;
|
|
947
|
+
/** Refuses when the layer is locked for `what` (and always for `all`). */
|
|
948
|
+
declare function requireUnlocked(layer: ImageLayer, what: keyof LayerLocks, action: string): void;
|
|
949
|
+
/** Inserts `layer` at `placement` (default: the top level at `defaultIndex`, or the top). */
|
|
950
|
+
declare function placeLayer(layers: readonly ImageLayer[], layer: ImageLayer, placement?: LayerPlacement, defaultIndex?: number): ImageLayer[];
|
|
951
|
+
/** Removes a layer (refused when it is locked). */
|
|
952
|
+
declare function removeLayer(layers: readonly ImageLayer[], id: string): ImageLayer[];
|
|
953
|
+
/** Moves a layer to `placement`. A group cannot go inside itself. Returns the new stack. */
|
|
954
|
+
declare function moveLayer(layers: readonly ImageLayer[], id: string, placement: LayerPlacement): ImageLayer[];
|
|
955
|
+
/** Every id in a subtree gets a fresh one (for duplicates). */
|
|
956
|
+
declare function withNewIds<T extends ImageLayer>(layer: T): T;
|
|
957
|
+
/** Duplicates a layer (and its children) directly above it. Returns the stack and the copy's id. */
|
|
958
|
+
declare function duplicateLayer(layers: readonly ImageLayer[], id: string, name?: string): {
|
|
959
|
+
layers: ImageLayer[];
|
|
960
|
+
id: string;
|
|
961
|
+
};
|
|
962
|
+
/** Properties `setLayerProperties` changes. */
|
|
963
|
+
interface LayerProperties {
|
|
964
|
+
name?: string;
|
|
965
|
+
visible?: boolean;
|
|
966
|
+
/** 0..1 */
|
|
967
|
+
opacity?: number;
|
|
968
|
+
/** 0..1, pixel layers only. */
|
|
969
|
+
fillOpacity?: number;
|
|
970
|
+
blend?: LayerBlendMode;
|
|
971
|
+
clipped?: boolean;
|
|
972
|
+
locks?: LayerLocks;
|
|
973
|
+
/** Groups only (UI state). */
|
|
974
|
+
collapsed?: boolean;
|
|
975
|
+
}
|
|
976
|
+
/** Validates and applies property changes to one layer. */
|
|
977
|
+
declare function setLayerProperties(layers: readonly ImageLayer[], id: string, props: LayerProperties): ImageLayer[];
|
|
978
|
+
/**
|
|
979
|
+
* Puts layers (siblings in one group or the top level) into a new group at the position of the
|
|
980
|
+
* topmost one, keeping their order. Returns the stack and the group id.
|
|
981
|
+
*/
|
|
982
|
+
declare function groupLayers(layers: readonly ImageLayer[], ids: string[], name?: string): {
|
|
983
|
+
layers: ImageLayer[];
|
|
984
|
+
id: string;
|
|
985
|
+
};
|
|
986
|
+
/** Replaces a group by its children (the group's own opacity, blend and mask are dropped). */
|
|
987
|
+
declare function ungroupLayer(layers: readonly ImageLayer[], id: string): {
|
|
988
|
+
layers: ImageLayer[];
|
|
989
|
+
ids: string[];
|
|
990
|
+
};
|
|
991
|
+
/** Sets a pixel layer's offset (refused when its position is locked). */
|
|
992
|
+
declare function offsetLayer(layers: readonly ImageLayer[], id: string, offset: {
|
|
993
|
+
x: number;
|
|
994
|
+
y: number;
|
|
995
|
+
}): ImageLayer[];
|
|
996
|
+
/** Sets or removes (`null`) a layer's mask. */
|
|
997
|
+
declare function setLayerMask(layers: readonly ImageLayer[], id: string, mask: RasterMask | null): ImageLayer[];
|
|
998
|
+
/** A clean filter from loose input (for tools and the UI). */
|
|
999
|
+
declare function normalizeFilter(raw: Partial<LayerFilter> & {
|
|
1000
|
+
kind: LayerFilter['kind'];
|
|
1001
|
+
}, id?: string): LayerFilter;
|
|
1002
|
+
/** Adds a filter on top of a pixel layer's filters. A layer has at most one filter of each kind. */
|
|
1003
|
+
declare function addLayerFilter(layers: readonly ImageLayer[], id: string, filter: LayerFilter): ImageLayer[];
|
|
1004
|
+
/** Changes one filter of a pixel layer (`changes` merged and validated). */
|
|
1005
|
+
declare function updateLayerFilter(layers: readonly ImageLayer[], id: string, filterId: string, changes: Record<string, unknown>): ImageLayer[];
|
|
1006
|
+
declare function removeLayerFilter(layers: readonly ImageLayer[], id: string, filterId: string): ImageLayer[];
|
|
1007
|
+
/** A blend mode check for tools. */
|
|
1008
|
+
declare function parseBlend(value: unknown, allowPassThrough?: boolean): BlendMode | 'pass-through' | undefined;
|
|
1009
|
+
/** The union of two rectangles (either may be null). */
|
|
1010
|
+
declare function unionRect(a: CropBox | null, b: CropBox | null): CropBox | null;
|
|
1011
|
+
|
|
1012
|
+
interface PlaneLayout {
|
|
1013
|
+
planes: number;
|
|
1014
|
+
width: number;
|
|
1015
|
+
height: number;
|
|
1016
|
+
depth: number;
|
|
1017
|
+
/** PSB: RLE row counts are 4 bytes. */
|
|
1018
|
+
psb: boolean;
|
|
1019
|
+
}
|
|
1020
|
+
/** Decodes planar channel data (`planes` planes of `height` rows each). */
|
|
1021
|
+
declare function decodePlanes(compression: number, data: Uint8Array, l: PlaneLayout): Uint8Array;
|
|
1022
|
+
/** RLE-encodes planar data: row counts (u16, or u32 in PSB), then the packed rows. */
|
|
1023
|
+
declare function encodeRle(decoded: Uint8Array, l: PlaneLayout): Uint8Array;
|
|
1024
|
+
|
|
1025
|
+
interface PsdHeader {
|
|
1026
|
+
psb: boolean;
|
|
1027
|
+
channels: number;
|
|
1028
|
+
height: number;
|
|
1029
|
+
width: number;
|
|
1030
|
+
depth: number;
|
|
1031
|
+
colorMode: number;
|
|
1032
|
+
}
|
|
1033
|
+
interface PsdRect {
|
|
1034
|
+
top: number;
|
|
1035
|
+
left: number;
|
|
1036
|
+
bottom: number;
|
|
1037
|
+
right: number;
|
|
1038
|
+
}
|
|
1039
|
+
interface PsdChannel {
|
|
1040
|
+
id: number;
|
|
1041
|
+
/** `null` for a zero-length channel. */
|
|
1042
|
+
compression: number | null;
|
|
1043
|
+
/** Encoded bytes, without the compression field. */
|
|
1044
|
+
data: Uint8Array;
|
|
1045
|
+
}
|
|
1046
|
+
interface PsdLayerMask {
|
|
1047
|
+
rect: PsdRect;
|
|
1048
|
+
defaultColor: number;
|
|
1049
|
+
flags: number;
|
|
1050
|
+
userDensity?: number;
|
|
1051
|
+
userFeather?: number;
|
|
1052
|
+
vectorDensity?: number;
|
|
1053
|
+
vectorFeather?: number;
|
|
1054
|
+
/** The real (vector-combined) user mask, when present. */
|
|
1055
|
+
real?: {
|
|
1056
|
+
flags: number;
|
|
1057
|
+
background: number;
|
|
1058
|
+
rect: PsdRect;
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
interface PsdTaggedBlock {
|
|
1062
|
+
key: string;
|
|
1063
|
+
data: Uint8Array;
|
|
1064
|
+
}
|
|
1065
|
+
interface PsdLayerRecord {
|
|
1066
|
+
rect: PsdRect;
|
|
1067
|
+
channels: PsdChannel[];
|
|
1068
|
+
blendKey: string;
|
|
1069
|
+
opacity: number;
|
|
1070
|
+
clipping: number;
|
|
1071
|
+
flags: number;
|
|
1072
|
+
mask?: PsdLayerMask;
|
|
1073
|
+
/** The legacy (Pascal) name; `layerName` prefers `luni`. */
|
|
1074
|
+
legacyName: string;
|
|
1075
|
+
blocks: PsdTaggedBlock[];
|
|
1076
|
+
}
|
|
1077
|
+
interface PsdResource {
|
|
1078
|
+
id: number;
|
|
1079
|
+
name: string;
|
|
1080
|
+
data: Uint8Array;
|
|
1081
|
+
}
|
|
1082
|
+
interface PsdFile {
|
|
1083
|
+
header: PsdHeader;
|
|
1084
|
+
colorModeData: Uint8Array;
|
|
1085
|
+
resources: PsdResource[];
|
|
1086
|
+
/** Bottom-most first, as stored. */
|
|
1087
|
+
layers: PsdLayerRecord[];
|
|
1088
|
+
/** The layer count was negative: the merged image's first extra channel is its alpha. */
|
|
1089
|
+
mergedAlpha: boolean;
|
|
1090
|
+
globalBlocks: PsdTaggedBlock[];
|
|
1091
|
+
imageCompression: number;
|
|
1092
|
+
imageData: Uint8Array;
|
|
1093
|
+
}
|
|
1094
|
+
/** Parses a PSD or PSB. Throws `PsdError` with what was wrong. */
|
|
1095
|
+
declare function readPsd(bytes: Uint8Array): PsdFile;
|
|
1096
|
+
declare function layerName(rec: PsdLayerRecord): string;
|
|
1097
|
+
interface PsdTreeNode {
|
|
1098
|
+
/** Index into `PsdFile.layers` (the folder record for a group). */
|
|
1099
|
+
index: number;
|
|
1100
|
+
children?: PsdTreeNode[];
|
|
1101
|
+
}
|
|
1102
|
+
/** The layer tree, bottom-most first (the stored order, as in our model), from the `lsct` dividers. */
|
|
1103
|
+
declare function layerTree(file: PsdFile): PsdTreeNode[];
|
|
1104
|
+
/** One layer channel decoded to `depth`-bit planar bytes, or `undefined` if the layer has none. */
|
|
1105
|
+
declare function decodeLayerChannel(file: PsdFile, rec: PsdLayerRecord, id: number): Uint8Array | undefined;
|
|
1106
|
+
/** The merged image's channels decoded, planar. */
|
|
1107
|
+
declare function decodeMergedImage(file: PsdFile): Uint8Array;
|
|
1108
|
+
/** Serializes a file. Channel data must already be encoded; `encodeName` writes legacy (Pascal) names. */
|
|
1109
|
+
declare function writePsd(file: PsdFile, encodeName: (s: string) => Uint8Array): Uint8Array;
|
|
1110
|
+
|
|
1111
|
+
/** PSD blend keys → our blend modes (`diss` is the one we lack). */
|
|
1112
|
+
declare const PSD_BLEND_KEYS: Record<string, LayerBlendMode>;
|
|
1113
|
+
/** What happened to one PSD layer on import. */
|
|
1114
|
+
interface PsdLayerSummary {
|
|
1115
|
+
name: string;
|
|
1116
|
+
/** Our layer type, or `null` when the layer was dropped. */
|
|
1117
|
+
type: 'pixel' | 'adjustment' | 'group' | null;
|
|
1118
|
+
/** `mapped`: held exactly; `approximated`: imported with losses; `dropped`: left out. */
|
|
1119
|
+
status: 'mapped' | 'approximated' | 'dropped';
|
|
1120
|
+
/** What Photoshop calls it (`pixel`, `type`, `smart-object`, `fill`, `shape`, `Levels` …). */
|
|
1121
|
+
psdKind: string;
|
|
1122
|
+
/** Why it is not `mapped`. */
|
|
1123
|
+
notes: string[];
|
|
1124
|
+
/** Our layer id (when imported). */
|
|
1125
|
+
id?: string;
|
|
1126
|
+
depth: number;
|
|
1127
|
+
}
|
|
1128
|
+
interface PsdImportResult {
|
|
1129
|
+
width: number;
|
|
1130
|
+
height: number;
|
|
1131
|
+
/** Bottom to top, as in our model. */
|
|
1132
|
+
layers: ImageLayer[];
|
|
1133
|
+
/** One sentence per problem, naming the affected layers. */
|
|
1134
|
+
warnings: string[];
|
|
1135
|
+
/** Every PSD layer, bottom first, a group before its children. */
|
|
1136
|
+
summary: PsdLayerSummary[];
|
|
1137
|
+
/** Pixels per inch, when the file says. */
|
|
1138
|
+
resolution?: number;
|
|
1139
|
+
info: {
|
|
1140
|
+
psb: boolean;
|
|
1141
|
+
depth: number;
|
|
1142
|
+
colorMode: string;
|
|
1143
|
+
channels: number;
|
|
1144
|
+
};
|
|
1145
|
+
}
|
|
1146
|
+
interface PsdImportOptions {
|
|
1147
|
+
/** Makes layer ids (defaults to `psd-<n>`). */
|
|
1148
|
+
newId?: (hint: string) => string;
|
|
1149
|
+
/** Skip decoding pixels (inspection only). */
|
|
1150
|
+
skipPixels?: boolean;
|
|
1151
|
+
}
|
|
1152
|
+
/** Maps a parsed PSD to our layers. */
|
|
1153
|
+
declare function psdToLayers(file: PsdFile, options?: PsdImportOptions): PsdImportResult;
|
|
1154
|
+
/** Parses and maps PSD / PSB bytes. Throws `PsdError` for files that cannot be read at all. */
|
|
1155
|
+
declare function importPsd(bytes: Uint8Array, options?: PsdImportOptions): PsdImportResult;
|
|
1156
|
+
|
|
1157
|
+
/** Latest serialized schema version (`3`: layers). Documents with the old shape still write 1 or 2. */
|
|
1158
|
+
declare const IMAGE_EDITOR_SCHEMA_VERSION: 3;
|
|
1159
|
+
/** Changes to an adjustment layer; `params` is merged into the current parameters. */
|
|
1160
|
+
interface AdjustmentLayerUpdate<K extends AdjustmentKind = AdjustmentKind> {
|
|
1116
1161
|
params?: Partial<AdjustmentParamsMap[K]>;
|
|
1117
1162
|
enabled?: boolean;
|
|
1118
1163
|
opacity?: number;
|
|
@@ -1128,17 +1173,130 @@ interface SelectionCommandOptions {
|
|
|
1128
1173
|
/** Feather the new shape by this many pixels before combining (default 0). */
|
|
1129
1174
|
feather?: number;
|
|
1130
1175
|
}
|
|
1176
|
+
/** Where an AI result goes (see `applyInpaintedImage`, `applyBackgroundRemovedImage`). */
|
|
1177
|
+
interface AIResultOptions {
|
|
1178
|
+
/** `new-layer`: a new layer (inpainting) or a mask (background removal); `replace`: the Background's pixels. Default: by `isMultiLayer`. */
|
|
1179
|
+
target?: 'new-layer' | 'replace';
|
|
1180
|
+
}
|
|
1131
1181
|
/** Where the selection tools read colours from. */
|
|
1132
1182
|
interface SampleOptions {
|
|
1183
|
+
/**
|
|
1184
|
+
* `composite` (default): the image, as before (with several layers: the composite of the pixel
|
|
1185
|
+
* layers, or with `sampleMerged` of every layer); `active-layer`: only the active pixel layer.
|
|
1186
|
+
*/
|
|
1187
|
+
sample?: 'composite' | 'active-layer';
|
|
1133
1188
|
/** Sample the adjusted image (base adjustments and layers) instead of the source pixels. */
|
|
1134
1189
|
sampleMerged?: boolean;
|
|
1135
1190
|
/** Pixels to use instead of reading the source image (natural size, RGBA). */
|
|
1136
1191
|
pixels?: PixelBuffer;
|
|
1137
1192
|
}
|
|
1138
|
-
/** A new adjustment layer: its kind plus optional initial values. */
|
|
1193
|
+
/** A new adjustment layer: its kind plus optional initial values and position. */
|
|
1139
1194
|
interface AdjustmentLayerInit<K extends AdjustmentKind = AdjustmentKind> extends AdjustmentLayerUpdate<K> {
|
|
1140
1195
|
kind: K;
|
|
1141
1196
|
id?: string;
|
|
1197
|
+
/** Put the new layer directly above this layer (in its group). */
|
|
1198
|
+
aboveId?: string;
|
|
1199
|
+
/** Put the new layer at the top of this group. */
|
|
1200
|
+
parentId?: string;
|
|
1201
|
+
}
|
|
1202
|
+
/** A new pixel layer: empty, a solid colour over the canvas, or given pixels, plus its properties and position. */
|
|
1203
|
+
interface PixelLayerInit extends LayerPlacement {
|
|
1204
|
+
id?: string;
|
|
1205
|
+
name?: string;
|
|
1206
|
+
/** Fill the canvas with this colour (`#rgb`, `#rrggbb`, `#rrggbbaa` or `[r, g, b, a?]` 0..255). */
|
|
1207
|
+
color?: string | number[];
|
|
1208
|
+
/** RGBA pixels placed at `x`, `y` (document pixels). */
|
|
1209
|
+
pixels?: PixelBuffer;
|
|
1210
|
+
x?: number;
|
|
1211
|
+
y?: number;
|
|
1212
|
+
visible?: boolean;
|
|
1213
|
+
/** 0..1 (default 1). */
|
|
1214
|
+
opacity?: number;
|
|
1215
|
+
fillOpacity?: number;
|
|
1216
|
+
blend?: BlendMode;
|
|
1217
|
+
}
|
|
1218
|
+
/** The paint tools' options (view state). */
|
|
1219
|
+
interface PaintOptions {
|
|
1220
|
+
brush: BrushSettings;
|
|
1221
|
+
/** `#rrggbb`: what the brush and Fill paint. */
|
|
1222
|
+
foreground: string;
|
|
1223
|
+
/** `#rrggbb`: what the eraser paints on transparency-locked layers and masks. */
|
|
1224
|
+
background: string;
|
|
1225
|
+
}
|
|
1226
|
+
/** A stroke: tool, target (default the active layer and target) and brush / colour overrides. */
|
|
1227
|
+
interface StrokeInit {
|
|
1228
|
+
tool?: 'brush' | 'eraser';
|
|
1229
|
+
layerId?: string;
|
|
1230
|
+
channel?: LayerTarget;
|
|
1231
|
+
/** Overrides of the paint options' brush. */
|
|
1232
|
+
brush?: Partial<BrushSettings>;
|
|
1233
|
+
/** Paint colour (default the foreground). Masks take its grey value. */
|
|
1234
|
+
color?: string | number[];
|
|
1235
|
+
/** Eraser colour on locked transparency / masks (default the background). */
|
|
1236
|
+
background?: string | number[];
|
|
1237
|
+
/** Kept with the stroke for replays (v1 brushes have no jitter). */
|
|
1238
|
+
seed?: number;
|
|
1239
|
+
}
|
|
1240
|
+
interface FillOptions {
|
|
1241
|
+
layerId?: string;
|
|
1242
|
+
channel?: LayerTarget;
|
|
1243
|
+
/** Default the foreground colour. */
|
|
1244
|
+
color?: string | number[];
|
|
1245
|
+
/** 0..1 (default 1). */
|
|
1246
|
+
opacity?: number;
|
|
1247
|
+
blend?: BlendMode;
|
|
1248
|
+
/** Limit to the selection when there is one (default true). */
|
|
1249
|
+
useSelection?: boolean;
|
|
1250
|
+
}
|
|
1251
|
+
/** What a stroke, fill or clear changed. */
|
|
1252
|
+
interface PaintStrokeResult {
|
|
1253
|
+
layerId: string;
|
|
1254
|
+
channel: LayerTarget;
|
|
1255
|
+
/** Document rectangle that changed (null when nothing did). */
|
|
1256
|
+
bounds: CropBox | null;
|
|
1257
|
+
dabs: number;
|
|
1258
|
+
}
|
|
1259
|
+
/** An opaque pre-stroke history snapshot. */
|
|
1260
|
+
type HistoryEntryHandle = {
|
|
1261
|
+
readonly __historyEntry: unique symbol;
|
|
1262
|
+
};
|
|
1263
|
+
/**
|
|
1264
|
+
* A stroke in progress (see `beginStroke`): `push` input points as they arrive, then `end` (one
|
|
1265
|
+
* undo step) or `cancel`.
|
|
1266
|
+
*/
|
|
1267
|
+
declare class PaintStrokeSession {
|
|
1268
|
+
private readonly controller;
|
|
1269
|
+
readonly target: {
|
|
1270
|
+
id: string;
|
|
1271
|
+
channel: LayerTarget;
|
|
1272
|
+
surface: TiledSurface;
|
|
1273
|
+
};
|
|
1274
|
+
private readonly stroke;
|
|
1275
|
+
private readonly apply;
|
|
1276
|
+
private readonly before;
|
|
1277
|
+
private readonly base;
|
|
1278
|
+
private readonly live;
|
|
1279
|
+
private readonly touched;
|
|
1280
|
+
private last;
|
|
1281
|
+
private closed;
|
|
1282
|
+
constructor(controller: ImageEditorController, target: {
|
|
1283
|
+
id: string;
|
|
1284
|
+
channel: LayerTarget;
|
|
1285
|
+
surface: TiledSurface;
|
|
1286
|
+
}, stroke: StrokeCoverage, apply: StrokeApply);
|
|
1287
|
+
get layerId(): string;
|
|
1288
|
+
/** Adds input points (document pixels); the stack shows the stroke so far. */
|
|
1289
|
+
push(points: readonly StrokePoint[]): void;
|
|
1290
|
+
private update;
|
|
1291
|
+
/** Finishes the stroke (one undo step) and returns what changed. */
|
|
1292
|
+
end(): PaintStrokeResult;
|
|
1293
|
+
/** Abandons the stroke and restores the layer. */
|
|
1294
|
+
cancel(): void;
|
|
1295
|
+
}
|
|
1296
|
+
/** Where a new annotation goes. */
|
|
1297
|
+
interface AnnotationPlacement {
|
|
1298
|
+
/** Put the annotation layer directly above this layer (default: the top of the stack). */
|
|
1299
|
+
aboveId?: string;
|
|
1142
1300
|
}
|
|
1143
1301
|
declare const DEFAULT_ADJUSTMENTS: ImageAdjustments;
|
|
1144
1302
|
/**
|
|
@@ -1147,13 +1305,24 @@ declare const DEFAULT_ADJUSTMENTS: ImageAdjustments;
|
|
|
1147
1305
|
*/
|
|
1148
1306
|
declare function normalizeStoredAdjustments(stored: Partial<ImageAdjustments> | undefined | null): ImageAdjustments;
|
|
1149
1307
|
/**
|
|
1150
|
-
* Brings a stored editor state of any schema version to
|
|
1151
|
-
* missing version) has no adjustment layers
|
|
1152
|
-
* and render exactly as before.
|
|
1308
|
+
* Brings a stored editor state of any schema version to a clean state of the same family:
|
|
1309
|
+
* version 1 (and a missing version) has no adjustment layers, version 2 has them, and both stay
|
|
1310
|
+
* in the document-level schema so old states load and render exactly as before. Version 3
|
|
1311
|
+
* (layers) is returned with its document fields cleaned. To lift a v1 / v2 state into layers,
|
|
1312
|
+
* use {@link migrateToLayeredState}.
|
|
1153
1313
|
*/
|
|
1154
1314
|
declare function migrateSerializedImageEditorState(data: Partial<SerializedImageEditorState> & {
|
|
1155
1315
|
version?: number;
|
|
1156
1316
|
}): SerializedImageEditorState;
|
|
1317
|
+
/**
|
|
1318
|
+
* Lifts a stored state of any version into the layered schema (v3) for a canvas of
|
|
1319
|
+
* `width × height`: the source becomes the Background layer with the base sliders as its
|
|
1320
|
+
* `develop` filter and the depth mask as its parametric mask, adjustment layers go above it and
|
|
1321
|
+
* annotations on top (see `layersFromLegacy`).
|
|
1322
|
+
*/
|
|
1323
|
+
declare function migrateToLayeredState(data: Partial<SerializedImageEditorState> & {
|
|
1324
|
+
version?: number;
|
|
1325
|
+
}, size: ImageDimensions): SerializedLayeredImageEditorState;
|
|
1157
1326
|
declare const DEFAULT_TRANSFORM: ImageTransform;
|
|
1158
1327
|
declare const DEFAULT_DEPTH_MASK: DepthMaskOptions;
|
|
1159
1328
|
/**
|
|
@@ -1170,11 +1339,17 @@ declare class ImageEditorController {
|
|
|
1170
1339
|
private undoStack;
|
|
1171
1340
|
private redoStack;
|
|
1172
1341
|
private maxHistoryDepth;
|
|
1342
|
+
private maxHistoryBytes;
|
|
1173
1343
|
private isApplyingHistory;
|
|
1174
1344
|
private initialSnapshot;
|
|
1175
1345
|
/** Pixels the selection tools sample (host-provided or read back from the source). */
|
|
1176
1346
|
private samplePixels;
|
|
1177
1347
|
private samplePixelsOverride;
|
|
1348
|
+
/** Decoded source pixels (the Background's surface), by the buffer or element they came from. */
|
|
1349
|
+
private sourceSurfaces;
|
|
1350
|
+
private viewKey;
|
|
1351
|
+
/** For `compositePixels` and mask evaluation (the renderer keeps its own for the viewport). */
|
|
1352
|
+
private compositor;
|
|
1178
1353
|
constructor(options?: ImageEditorOptions);
|
|
1179
1354
|
/**
|
|
1180
1355
|
* Loads a new source image and makes it the baseline that `reset()` returns to.
|
|
@@ -1186,10 +1361,24 @@ declare class ImageEditorController {
|
|
|
1186
1361
|
getImageElement(): CanvasImageSource | null;
|
|
1187
1362
|
getState(): ImageEditorState;
|
|
1188
1363
|
subscribe(listener: (state: ImageEditorState) => void): () => void;
|
|
1364
|
+
/**
|
|
1365
|
+
* Where layer pixels changed since the last viewport render, when only strokes changed them
|
|
1366
|
+
* (the renderer then recomposites just those rectangles); `'all'` after any other change.
|
|
1367
|
+
*/
|
|
1368
|
+
private pendingDirty;
|
|
1189
1369
|
private notify;
|
|
1370
|
+
/** Recomputes the compatibility views (`adjustments`, `depthMask`, `annotations`) when the stack changed. */
|
|
1371
|
+
private syncViews;
|
|
1372
|
+
private stack;
|
|
1190
1373
|
private captureHistoryEntry;
|
|
1191
1374
|
private restoreHistoryEntry;
|
|
1192
1375
|
private recordHistory;
|
|
1376
|
+
/**
|
|
1377
|
+
* Bytes of pixel tiles held only by undo / redo steps (not by the current state). The oldest
|
|
1378
|
+
* undo steps are dropped while it exceeds `maxHistoryBytes`.
|
|
1379
|
+
*/
|
|
1380
|
+
get historyBytes(): number;
|
|
1381
|
+
private trimHistoryBytes;
|
|
1193
1382
|
get canUndo(): boolean;
|
|
1194
1383
|
get canRedo(): boolean;
|
|
1195
1384
|
undo(): boolean;
|
|
@@ -1203,6 +1392,223 @@ declare class ImageEditorController {
|
|
|
1203
1392
|
setRotation(degrees: number): void;
|
|
1204
1393
|
flipHorizontal(): void;
|
|
1205
1394
|
flipVertical(): void;
|
|
1395
|
+
/** The layer stack, bottom to top (immutable objects). */
|
|
1396
|
+
getLayers(): ImageLayer[];
|
|
1397
|
+
getLayer(id: string): ImageLayer | undefined;
|
|
1398
|
+
/** The active layer, or `undefined`. */
|
|
1399
|
+
getActiveLayer(): ImageLayer | undefined;
|
|
1400
|
+
/**
|
|
1401
|
+
* Makes a layer the active one (or none) and chooses whether painting targets its pixels or
|
|
1402
|
+
* its mask. View state: no undo step. Returns false for an unknown id.
|
|
1403
|
+
*/
|
|
1404
|
+
setActiveLayer(id: string | null, target?: LayerTarget): boolean;
|
|
1405
|
+
/**
|
|
1406
|
+
* The pixels of a pixel layer, in document space (`x`, `y` is the top-left of the returned
|
|
1407
|
+
* buffer), or `null` for an unknown or empty layer. Resolves the Background's source pixels.
|
|
1408
|
+
*/
|
|
1409
|
+
getLayerPixels(id: string): (PixelBuffer & {
|
|
1410
|
+
x: number;
|
|
1411
|
+
y: number;
|
|
1412
|
+
}) | null;
|
|
1413
|
+
private boundsCache;
|
|
1414
|
+
/**
|
|
1415
|
+
* Document bounds of a layer's non-transparent pixels (pixel layers; the Background's source
|
|
1416
|
+
* included), or `null` for an empty or non-pixel layer.
|
|
1417
|
+
*/
|
|
1418
|
+
getLayerBounds(id: string): CropBox | null;
|
|
1419
|
+
/**
|
|
1420
|
+
* Composites the layer stack in document space without a canvas (annotation layers need one
|
|
1421
|
+
* and are left out): `rect` (default: the canvas) as RGBA, straight alpha. Crop, rotation and
|
|
1422
|
+
* output opacity are not applied. With `layerIds`, only those layers are composited.
|
|
1423
|
+
*/
|
|
1424
|
+
compositePixels(rect?: CropBox, options?: {
|
|
1425
|
+
layerIds?: string[];
|
|
1426
|
+
}): PixelBuffer;
|
|
1427
|
+
private compositorSources;
|
|
1428
|
+
private sourceIds;
|
|
1429
|
+
private nextSourceId;
|
|
1430
|
+
/** Changes whenever the Background's source pixels can have changed. */
|
|
1431
|
+
private sourceVersion;
|
|
1432
|
+
/** The pixels a pixel layer composites (the decoded source for the Background). */
|
|
1433
|
+
private surfaceOf;
|
|
1434
|
+
/**
|
|
1435
|
+
* The source image as a surface (cached): host-supplied sample pixels first, then the decoded
|
|
1436
|
+
* element, then pixels read back for the selection tools.
|
|
1437
|
+
*/
|
|
1438
|
+
private sourceSurface;
|
|
1439
|
+
private opaqueCache;
|
|
1440
|
+
/** Whether every source pixel is opaque (some legacy renders depend on it). */
|
|
1441
|
+
private sourceIsOpaque;
|
|
1442
|
+
/** Synchronously reads the source element's pixels through a canvas, or `null`. */
|
|
1443
|
+
private decodeSource;
|
|
1444
|
+
/** Records one undo step and applies a new stack (and any other state change in `extra`). */
|
|
1445
|
+
private commitLayers;
|
|
1446
|
+
/** The default position of a new layer: above the active layer, else the top of the stack. */
|
|
1447
|
+
private newLayerPlacement;
|
|
1448
|
+
/**
|
|
1449
|
+
* Adds a pixel layer (one undo step) and makes it active: empty, filled with `color` over the
|
|
1450
|
+
* canvas, or holding `pixels` placed at `x`, `y`. Goes above the active layer unless placed.
|
|
1451
|
+
* Returns its id.
|
|
1452
|
+
*/
|
|
1453
|
+
addPixelLayer(init?: PixelLayerInit): string;
|
|
1454
|
+
/**
|
|
1455
|
+
* `addPixelLayer` from an image: a PNG data URL or base64 PNG is decoded without a canvas;
|
|
1456
|
+
* other formats and URLs need a browser. Returns the new layer id.
|
|
1457
|
+
*/
|
|
1458
|
+
addPixelLayerFromImage(image: string, init?: Omit<PixelLayerInit, 'pixels' | 'color'>): Promise<string>;
|
|
1459
|
+
/** RGBA pixels of an image given as a data URL, base64 PNG or URL. */
|
|
1460
|
+
decodeImage(image: string): Promise<PixelBuffer>;
|
|
1461
|
+
private nextLayerName;
|
|
1462
|
+
/** Duplicates a layer (with its children) directly above it, as one undo step. Returns the copy's id. */
|
|
1463
|
+
duplicateLayer(id: string, name?: string): string;
|
|
1464
|
+
/** Deletes a layer (refused when locked), as one undo step. */
|
|
1465
|
+
removeLayer(id: string): void;
|
|
1466
|
+
/** Moves a layer above / below another, or into a group, as one undo step. Returns its new parent and index. */
|
|
1467
|
+
moveLayer(id: string, placement: LayerPlacement): {
|
|
1468
|
+
parentId: string | null;
|
|
1469
|
+
index: number;
|
|
1470
|
+
};
|
|
1471
|
+
/**
|
|
1472
|
+
* Changes name, visibility, opacity, fill, blend, clipping, locks or (groups) collapsed state, as
|
|
1473
|
+
* one undo step (`commitToHistory = false` for the moves of a slider drag). Returns the layer.
|
|
1474
|
+
*/
|
|
1475
|
+
setLayerProperties(id: string, props: LayerProperties, commitToHistory?: boolean): ImageLayer;
|
|
1476
|
+
/** Adds an empty pass-through group above the active layer (or at `placement`) and makes it active. Returns its id. */
|
|
1477
|
+
addGroup(init?: LayerPlacement & {
|
|
1478
|
+
name?: string;
|
|
1479
|
+
blend?: LayerBlendMode;
|
|
1480
|
+
}): string;
|
|
1481
|
+
/** Puts sibling layers into a new group (one undo step). Returns the group id. */
|
|
1482
|
+
groupLayers(ids: string[], name?: string): string;
|
|
1483
|
+
/** Replaces a group by its children (one undo step). Returns the child ids, bottom to top. */
|
|
1484
|
+
ungroupLayer(id: string): string[];
|
|
1485
|
+
/**
|
|
1486
|
+
* Moves a pixel layer to an absolute offset (`x`, `y`) or by `dx`, `dy`, as one undo step
|
|
1487
|
+
* (`commitToHistory = false` for the moves of a drag). Returns the offset and document bounds.
|
|
1488
|
+
*/
|
|
1489
|
+
offsetLayer(id: string, move: {
|
|
1490
|
+
x?: number;
|
|
1491
|
+
y?: number;
|
|
1492
|
+
dx?: number;
|
|
1493
|
+
dy?: number;
|
|
1494
|
+
}, commitToHistory?: boolean): {
|
|
1495
|
+
offset: {
|
|
1496
|
+
x: number;
|
|
1497
|
+
y: number;
|
|
1498
|
+
};
|
|
1499
|
+
bounds: CropBox | null;
|
|
1500
|
+
};
|
|
1501
|
+
/**
|
|
1502
|
+
* Adds a mask to a layer (one undo step): `reveal-all` (white), `hide-all` (black) or
|
|
1503
|
+
* `selection` (the selection's coverage). Replaces an existing mask. Makes the mask the paint
|
|
1504
|
+
* target when the layer is active.
|
|
1505
|
+
*/
|
|
1506
|
+
addLayerMask(id: string, from?: 'reveal-all' | 'hide-all' | 'selection', props?: LayerMaskProps): RasterMask;
|
|
1507
|
+
/** Removes a layer's mask (one undo step). */
|
|
1508
|
+
removeLayerMask(id: string): void;
|
|
1509
|
+
/** Changes any layer mask's density, feather or enabled flag (pixels kept). Returns the mask. */
|
|
1510
|
+
setLayerMaskProps(id: string, props: LayerMaskProps, commitToHistory?: boolean): RasterMask;
|
|
1511
|
+
/**
|
|
1512
|
+
* Bakes a pixel layer's mask into its pixels (alpha × coverage, including density, feather or
|
|
1513
|
+
* the depth map) and removes the mask, as one undo step.
|
|
1514
|
+
*/
|
|
1515
|
+
applyLayerMask(id: string): Promise<void>;
|
|
1516
|
+
/**
|
|
1517
|
+
* Layer via Copy (or via Cut): a new pixel layer with the selected pixels of a pixel layer (the
|
|
1518
|
+
* active one by default), directly above it, as one undo step. Returns the new id.
|
|
1519
|
+
*/
|
|
1520
|
+
layerViaCopy(options?: {
|
|
1521
|
+
layerId?: string;
|
|
1522
|
+
cut?: boolean;
|
|
1523
|
+
name?: string;
|
|
1524
|
+
}): string;
|
|
1525
|
+
/** Adds a `develop` or `blur` filter to a pixel layer (one undo step). Returns the layer's filters. */
|
|
1526
|
+
addLayerFilter(id: string, filter: Partial<LayerFilter> & {
|
|
1527
|
+
kind: LayerFilter['kind'];
|
|
1528
|
+
}): LayerFilter[];
|
|
1529
|
+
/** Changes one filter (one undo step, or none with `commitToHistory = false` during a drag). Returns the filters. */
|
|
1530
|
+
updateLayerFilter(id: string, filterId: string, changes: Record<string, unknown>, commitToHistory?: boolean): LayerFilter[];
|
|
1531
|
+
/** Removes one filter (one undo step). Returns the remaining filters. */
|
|
1532
|
+
removeLayerFilter(id: string, filterId: string): LayerFilter[];
|
|
1533
|
+
/** Composites `layers` (in isolation) over `rect` into a surface, loading depth maps first. */
|
|
1534
|
+
private compositeToSurface;
|
|
1535
|
+
/** Document bounds a layer can paint into (pixel content, annotations, or the canvas for the rest). */
|
|
1536
|
+
private paintBounds;
|
|
1537
|
+
/**
|
|
1538
|
+
* Merge Down: composites a layer onto the pixel layer directly below it (which keeps its name,
|
|
1539
|
+
* opacity and blend; masks, fill and filters are baked), as one undo step. Returns the merged id.
|
|
1540
|
+
*/
|
|
1541
|
+
mergeDown(id: string): Promise<string>;
|
|
1542
|
+
/**
|
|
1543
|
+
* Merge Visible: the visible top-level layers become one normal pixel layer (at the position of
|
|
1544
|
+
* the lowest of them); hidden layers stay. One undo step. Returns the merged id.
|
|
1545
|
+
*/
|
|
1546
|
+
mergeVisible(): Promise<string>;
|
|
1547
|
+
/** Flatten Image: every visible layer composited into one Background layer; hidden layers are discarded. One undo step. */
|
|
1548
|
+
flattenImage(): Promise<string>;
|
|
1549
|
+
private thumbCache;
|
|
1550
|
+
/**
|
|
1551
|
+
* A small RGBA preview of a pixel layer over the canvas (or of its mask with `mask: true`),
|
|
1552
|
+
* longest side `maxSide` px, point-sampled; `null` for layers without pixels.
|
|
1553
|
+
*/
|
|
1554
|
+
getLayerThumbnail(id: string, options?: {
|
|
1555
|
+
maxSide?: number;
|
|
1556
|
+
mask?: boolean;
|
|
1557
|
+
}): PixelBuffer | null;
|
|
1558
|
+
/** Brush settings, colours and tool options of the paint tools (view state, no undo). */
|
|
1559
|
+
setPaintOptions(options: Partial<Omit<PaintOptions, 'brush'>> & {
|
|
1560
|
+
brush?: Partial<BrushSettings>;
|
|
1561
|
+
}): PaintOptions;
|
|
1562
|
+
/** D: black foreground, white background. */
|
|
1563
|
+
resetPaintColors(): void;
|
|
1564
|
+
/** X: swaps the foreground and background colours. */
|
|
1565
|
+
swapPaintColors(): void;
|
|
1566
|
+
/** Resolves and validates what a stroke, fill or clear paints into. */
|
|
1567
|
+
private paintTarget;
|
|
1568
|
+
/** The layer with its pixels (or mask) replaced by `surface`. */
|
|
1569
|
+
private withSurface;
|
|
1570
|
+
/**
|
|
1571
|
+
* Starts a brush or eraser stroke on a layer's pixels or mask (default: the active layer and
|
|
1572
|
+
* target, the paint options' brush and colours). Feed points with `push`, finish with `end()`
|
|
1573
|
+
* (one undo step for the whole stroke) or `cancel()`. While it runs, the stack shows the stroke
|
|
1574
|
+
* without recording history.
|
|
1575
|
+
*/
|
|
1576
|
+
beginStroke(init?: StrokeInit): PaintStrokeSession;
|
|
1577
|
+
/** @internal Shows a stroke's live surface (no history). */
|
|
1578
|
+
_strokeUpdate(layerId: string, channel: LayerTarget, surface: TiledSurface, rects: CropBox[]): void;
|
|
1579
|
+
/** @internal Commits a finished stroke as one undo step (`before` is the pre-stroke state). */
|
|
1580
|
+
_strokeCommit(before: HistoryEntryHandle, layerId: string, channel: LayerTarget, surface: TiledSurface | null): void;
|
|
1581
|
+
/** @internal The pre-stroke snapshot. */
|
|
1582
|
+
_captureForStroke(): HistoryEntryHandle;
|
|
1583
|
+
/**
|
|
1584
|
+
* Paints a whole stroke in one call (agents, replays): `points` in document pixels with optional
|
|
1585
|
+
* pressure, through the brush or eraser. One undo step. Returns the layer, channel, the changed
|
|
1586
|
+
* document bounds and the number of dabs.
|
|
1587
|
+
*/
|
|
1588
|
+
paintStroke(init: StrokeInit & {
|
|
1589
|
+
points: StrokePoint[];
|
|
1590
|
+
}): PaintStrokeResult;
|
|
1591
|
+
/**
|
|
1592
|
+
* Edit › Fill: fills the selection (or, without one or with `useSelection: false`, the whole
|
|
1593
|
+
* canvas) on a layer's pixels or mask with a colour (default the foreground), at `opacity` with
|
|
1594
|
+
* `blend`. One undo step. Returns the changed bounds.
|
|
1595
|
+
*/
|
|
1596
|
+
fillPixels(options?: FillOptions): PaintStrokeResult;
|
|
1597
|
+
/**
|
|
1598
|
+
* Edit › Clear: removes the selected pixels (alpha to 0; on a transparency-locked layer or a mask
|
|
1599
|
+
* it fills with the background colour). Without a selection (or with `useSelection: false`) the
|
|
1600
|
+
* whole canvas. One undo step. Returns the changed bounds.
|
|
1601
|
+
*/
|
|
1602
|
+
clearPixels(options?: Omit<FillOptions, 'color' | 'blend'>): PaintStrokeResult;
|
|
1603
|
+
private fillOrClear;
|
|
1604
|
+
/** The pixel layer the base sliders edit: the active pixel layer, else the Background. */
|
|
1605
|
+
private developLayer;
|
|
1606
|
+
/**
|
|
1607
|
+
* Sets base adjustment values as one undo step (unless `commitToHistory` is false). The base
|
|
1608
|
+
* sliders edit the `develop` filter of the active pixel layer (or the Background), `blur` its
|
|
1609
|
+
* blur filter (or `legacyOutputBlur` in migrated documents), `opacity` the output opacity, and
|
|
1610
|
+
* `layers` replaces the adjustment layers.
|
|
1611
|
+
*/
|
|
1206
1612
|
setAdjustments(partial: Partial<ImageAdjustments>, commitToHistory?: boolean): void;
|
|
1207
1613
|
/** True when the adjustments use an older rendering process than {@link LATEST_PROCESS_VERSION}. */
|
|
1208
1614
|
get isProcessOutdated(): boolean;
|
|
@@ -1213,13 +1619,24 @@ declare class ImageEditorController {
|
|
|
1213
1619
|
upgradeProcess(): boolean;
|
|
1214
1620
|
/** Resets the base sliders (latest process). Adjustment layers are kept; see `clearAdjustmentLayers`. */
|
|
1215
1621
|
resetAdjustments(): void;
|
|
1216
|
-
/** The adjustment layers, bottom (first) to top (last). */
|
|
1622
|
+
/** The adjustment layers in stack order, bottom (first) to top (last). */
|
|
1217
1623
|
getAdjustmentLayers(): AdjustmentLayer[];
|
|
1218
1624
|
getAdjustmentLayer(id: string): AdjustmentLayer | undefined;
|
|
1219
|
-
private
|
|
1625
|
+
private adjustmentNodes;
|
|
1626
|
+
/**
|
|
1627
|
+
* Where a new layer goes when no position is given: directly above the topmost layer that is
|
|
1628
|
+
* not an annotation, so it adjusts what adjustment layers always adjusted (annotations stay on top).
|
|
1629
|
+
*/
|
|
1630
|
+
private defaultInsertIndex;
|
|
1631
|
+
/** Inserts `node` by `aboveId` / `parentId` / adjustment index / default position. */
|
|
1632
|
+
private placeLayer;
|
|
1633
|
+
/** `setAdjustments({ layers })`: updates nodes by id in place, removes missing ones, adds new ones. */
|
|
1634
|
+
private replaceAdjustmentNodes;
|
|
1220
1635
|
/**
|
|
1221
|
-
* Adds an adjustment layer
|
|
1222
|
-
*
|
|
1636
|
+
* Adds an adjustment layer and returns its id, as one undo step. With no position it goes
|
|
1637
|
+
* above the other adjustment layers (or, without any, above the topmost non-annotation layer,
|
|
1638
|
+
* so annotations stay on top); `index` counts adjustment layers (0 = below the others);
|
|
1639
|
+
* `aboveId` / `parentId` place it anywhere in the stack. `kind` alone gives neutral parameters.
|
|
1223
1640
|
*/
|
|
1224
1641
|
addAdjustmentLayer<K extends AdjustmentKind>(init: K | AdjustmentLayerInit<K>, index?: number): string;
|
|
1225
1642
|
/**
|
|
@@ -1230,7 +1647,8 @@ declare class ImageEditorController {
|
|
|
1230
1647
|
updateAdjustmentLayer(id: string, update: AdjustmentLayerUpdate, commitToHistory?: boolean): boolean;
|
|
1231
1648
|
/** Removes a layer as one undo step. Returns false for an unknown id. */
|
|
1232
1649
|
removeAdjustmentLayer(id: string): boolean;
|
|
1233
|
-
|
|
1650
|
+
private moveAdjustmentNode;
|
|
1651
|
+
/** Moves a layer to `toIndex` among the adjustment layers (0 = bottom) as one undo step. Returns false if nothing moved. */
|
|
1234
1652
|
moveAdjustmentLayer(id: string, toIndex: number): boolean;
|
|
1235
1653
|
/** Shows or hides a layer (flips it without `enabled`) as one undo step. */
|
|
1236
1654
|
toggleAdjustmentLayer(id: string, enabled?: boolean): boolean;
|
|
@@ -1262,13 +1680,14 @@ declare class ImageEditorController {
|
|
|
1262
1680
|
selectPolygon(points: ImagePoint[], options?: SelectionCommandOptions & ShapeSelectionOptions): boolean;
|
|
1263
1681
|
/**
|
|
1264
1682
|
* Supplies the pixels the selection tools sample (natural size RGBA), e.g. decoded in a worker
|
|
1265
|
-
* or in a test; `null` goes back to reading the source image.
|
|
1683
|
+
* or in a test; `null` goes back to reading the source image. Without a canvas (Node, workers)
|
|
1684
|
+
* these are also the Background layer's pixels.
|
|
1266
1685
|
*/
|
|
1267
1686
|
setSamplePixels(pixels: PixelBuffer | null): void;
|
|
1268
1687
|
/**
|
|
1269
1688
|
* The pixels the selection tools sample: the source image at natural size, or with
|
|
1270
|
-
* `sampleMerged` the
|
|
1271
|
-
*
|
|
1689
|
+
* `sampleMerged` the composite of the layers (no crop, rotation or annotations). `null`
|
|
1690
|
+
* without pixel access (no DOM, tainted canvas).
|
|
1272
1691
|
*/
|
|
1273
1692
|
getSamplePixels(options?: SampleOptions): Promise<PixelBuffer | null>;
|
|
1274
1693
|
private requirePixels;
|
|
@@ -1298,11 +1717,13 @@ declare class ImageEditorController {
|
|
|
1298
1717
|
}): Promise<SelectionMask | null>;
|
|
1299
1718
|
/** Quick Mask view (tints the unselected area). View state: no undo step. */
|
|
1300
1719
|
setQuickMask(on: boolean): void;
|
|
1720
|
+
private maskFromSelection;
|
|
1301
1721
|
/**
|
|
1302
1722
|
* Adds the selection as the layer's mask (Reveal Selection), replacing any mask, as one undo
|
|
1303
1723
|
* step. Without a selection, returns false.
|
|
1304
1724
|
*/
|
|
1305
1725
|
applySelectionAsLayerMask(layerId: string, props?: LayerMaskProps): boolean;
|
|
1726
|
+
private setLayerMask;
|
|
1306
1727
|
/** Sets (from a selection-shaped mask) or removes (`null`) a layer's mask as one undo step. */
|
|
1307
1728
|
setAdjustmentLayerMask(layerId: string, mask: SelectionMask | null, props?: LayerMaskProps): boolean;
|
|
1308
1729
|
/** Changes a layer mask's density (0..1), feather (px) or enabled flag; the mask pixels are kept. */
|
|
@@ -1316,9 +1737,12 @@ declare class ImageEditorController {
|
|
|
1316
1737
|
getHistogram(): ImageHistogram | null;
|
|
1317
1738
|
/** Calls `listener` now and whenever a render produces a new preview histogram. */
|
|
1318
1739
|
subscribeHistogram(listener: (histogram: ImageHistogram | null) => void): () => void;
|
|
1740
|
+
/** Sets the depth mask (a parametric mask on the active pixel layer, or the Background) as one undo step. */
|
|
1319
1741
|
setDepthMask(partial: Partial<DepthMaskOptions>): void;
|
|
1320
1742
|
resetDepthMask(): void;
|
|
1321
|
-
|
|
1743
|
+
private annotationLayer;
|
|
1744
|
+
/** Adds an annotation as its own layer (top of the stack unless `aboveId` is given). */
|
|
1745
|
+
addAnnotation(annotation: CreateAnnotationPayload, placement?: AnnotationPlacement): string;
|
|
1322
1746
|
updateAnnotation(id: string, partial: Partial<Annotation>, commitToHistory?: boolean): void;
|
|
1323
1747
|
removeAnnotation(id: string): void;
|
|
1324
1748
|
clearAnnotations(): void;
|
|
@@ -1329,6 +1753,14 @@ declare class ImageEditorController {
|
|
|
1329
1753
|
resetZoom(): void;
|
|
1330
1754
|
setPan(pan: ImagePoint): void;
|
|
1331
1755
|
setComparing(comparing: boolean): void;
|
|
1756
|
+
setFit(fit: ImageEditorFit): void;
|
|
1757
|
+
private blankSource;
|
|
1758
|
+
/**
|
|
1759
|
+
* What the renderer draws from: the source image, or, for a document without one (an opened
|
|
1760
|
+
* PSD, a v3 document loaded on its own), a transparent canvas of the document size, since every
|
|
1761
|
+
* pixel then comes from the layers. `null` when there is nothing to draw.
|
|
1762
|
+
*/
|
|
1763
|
+
private drawSource;
|
|
1332
1764
|
render(targetCanvas: HTMLCanvasElement, options?: RenderOptions): Promise<void>;
|
|
1333
1765
|
renderExport(options?: ExportOptions): Promise<HTMLCanvasElement>;
|
|
1334
1766
|
/**
|
|
@@ -1359,30 +1791,652 @@ declare class ImageEditorController {
|
|
|
1359
1791
|
* and the space that `applyInpaintedImage` / `applyBackgroundRemovedImage` expect back.
|
|
1360
1792
|
*/
|
|
1361
1793
|
renderSource(): Promise<HTMLCanvasElement>;
|
|
1794
|
+
/**
|
|
1795
|
+
* The image an AI hook should edit: the source (`toSourceDataURL`) when results replace the
|
|
1796
|
+
* Background, or the composite of the layers without annotations, in the source frame, when
|
|
1797
|
+
* they go to a new layer or mask (see `applyInpaintedImage`).
|
|
1798
|
+
*/
|
|
1799
|
+
toAIInputDataURL(options?: AIResultOptions): Promise<string>;
|
|
1362
1800
|
toSourceDataURL(options?: Pick<ExportOptions, 'format' | 'quality'>): Promise<string>;
|
|
1363
1801
|
/**
|
|
1364
|
-
*
|
|
1365
|
-
*
|
|
1802
|
+
* Whether AI results go to layers: the document has more than one pixel layer or group (adjustment
|
|
1803
|
+
* and annotation layers are edits of the image, not images of their own).
|
|
1804
|
+
*/
|
|
1805
|
+
/** `new-layer` in multi-layer documents and documents without a source image, else `replace`. */
|
|
1806
|
+
private defaultAITarget;
|
|
1807
|
+
/** No source image, and no layer reading one (an opened PSD): the layers are the whole document. */
|
|
1808
|
+
private isSourceless;
|
|
1809
|
+
get isMultiLayer(): boolean;
|
|
1810
|
+
/**
|
|
1811
|
+
* Applies an inpainted result (natural image space, see `toSourceDataURL`) as ONE undoable step.
|
|
1812
|
+
* In a document with several layers (see `isMultiLayer`), or with `target: 'new-layer'`, the
|
|
1813
|
+
* result goes to a new pixel layer above the active layer, limited to the selection. Otherwise
|
|
1814
|
+
* (`target: 'replace'`, the single-layer default) it replaces the Background's pixels and clears
|
|
1815
|
+
* the mask annotations, as before. Resolves to the new layer's id in new-layer mode.
|
|
1816
|
+
*/
|
|
1817
|
+
applyInpaintedImage(newDataUrl: string, options?: AIResultOptions): Promise<string | void>;
|
|
1818
|
+
/**
|
|
1819
|
+
* Applies a background-removed result as ONE undoable step. In a document with several layers
|
|
1820
|
+
* (or with `target: 'new-layer'`) the result's alpha becomes the mask of the active pixel layer
|
|
1821
|
+
* (or the Background), replacing its mask. Otherwise (`target: 'replace'`, the single-layer
|
|
1822
|
+
* default) it replaces the Background's pixels; crop and annotations are kept (rescaled if the
|
|
1823
|
+
* new image has different dimensions). Resolves to the masked layer's id in mask mode.
|
|
1824
|
+
*/
|
|
1825
|
+
applyBackgroundRemovedImage(newDataUrl: string, options?: AIResultOptions): Promise<string | void>;
|
|
1826
|
+
/**
|
|
1827
|
+
* Rasterize Layer: an annotation layer becomes a pixel layer with the same id, name and
|
|
1828
|
+
* properties (needs a canvas), and a pixel layer's filters are baked into its pixels. One undo
|
|
1829
|
+
* step. Returns the layer id.
|
|
1366
1830
|
*/
|
|
1367
|
-
|
|
1831
|
+
rasterizeLayer(id: string): Promise<string>;
|
|
1832
|
+
/** Pixels per inch of the last opened PSD (written back by `toPsd`). */
|
|
1833
|
+
private psdResolution;
|
|
1368
1834
|
/**
|
|
1369
|
-
*
|
|
1370
|
-
*
|
|
1835
|
+
* Opens PSD / PSB bytes as the document (one undo step): the layers replace the stack and the
|
|
1836
|
+
* document has no source image afterwards (every pixel comes from the layers). What the model
|
|
1837
|
+
* cannot hold is approximated or left out; `warnings` says what, naming the layers.
|
|
1838
|
+
* Throws `PsdError` for files that cannot be read at all.
|
|
1371
1839
|
*/
|
|
1372
|
-
|
|
1840
|
+
loadPsd(bytes: Uint8Array): {
|
|
1841
|
+
layerIds: string[];
|
|
1842
|
+
warnings: string[];
|
|
1843
|
+
width: number;
|
|
1844
|
+
height: number;
|
|
1845
|
+
summary: PsdImportResult['summary'];
|
|
1846
|
+
};
|
|
1847
|
+
/**
|
|
1848
|
+
* The document as an 8-bit RGB PSD (PSB above 30 000 px) with real layers, groups, adjustment
|
|
1849
|
+
* layers and masks, in the source frame. Layer filters and parametric (depth) masks are baked
|
|
1850
|
+
* into pixels and masks, annotation layers are rasterized (in a browser; elsewhere they are left
|
|
1851
|
+
* out), and the merged image is our composite. `warnings` lists every such change.
|
|
1852
|
+
*/
|
|
1853
|
+
toPsd(): Promise<{
|
|
1854
|
+
bytes: Uint8Array;
|
|
1855
|
+
warnings: string[];
|
|
1856
|
+
psb: boolean;
|
|
1857
|
+
width: number;
|
|
1858
|
+
height: number;
|
|
1859
|
+
}>;
|
|
1373
1860
|
private replaceSource;
|
|
1374
|
-
/**
|
|
1861
|
+
/**
|
|
1862
|
+
* The serializable state. A document whose layers still have the v1 / v2 shape (the
|
|
1863
|
+
* Background with its sliders and depth mask, adjustment layers, annotations) is written as
|
|
1864
|
+
* v1 / v2 exactly as before; anything else is written as v3 with the layer pixels as PNG
|
|
1865
|
+
* assets. `selection` is included (run-length encoded) only when something is selected.
|
|
1866
|
+
*/
|
|
1375
1867
|
toJSON(): SerializedImageEditorState;
|
|
1868
|
+
/**
|
|
1869
|
+
* With `assets: 'external'`, layer pixels go to `store` (each PNG uploaded once per store) and
|
|
1870
|
+
* the v3 document holds the store's references. Old-shape documents have no assets either way.
|
|
1871
|
+
*/
|
|
1872
|
+
toJSON(options: {
|
|
1873
|
+
assets: 'external';
|
|
1874
|
+
store: ImageEditorAssetStore;
|
|
1875
|
+
}): Promise<SerializedImageEditorState>;
|
|
1876
|
+
/**
|
|
1877
|
+
* Loads a stored state whose v3 assets may live in an asset store (references other than data
|
|
1878
|
+
* URLs are fetched with `store.get`), as one undo step. Assets that cannot be fetched are left
|
|
1879
|
+
* out and listed in `lastLoadProblems`.
|
|
1880
|
+
*/
|
|
1881
|
+
loadJSONAsync(data: SerializedImageEditorState, options?: {
|
|
1882
|
+
store?: ImageEditorAssetStore;
|
|
1883
|
+
}): Promise<void>;
|
|
1884
|
+
/** Loads a stored state of any version (one undo step). */
|
|
1376
1885
|
loadJSON(data: SerializedImageEditorState): void;
|
|
1886
|
+
/** Problems found by the last `loadJSON` / `initialState` of a v3 document (unreadable layers or assets). */
|
|
1887
|
+
lastLoadProblems: string[];
|
|
1888
|
+
private applyStored;
|
|
1377
1889
|
private serializeState;
|
|
1378
|
-
private applySerializedState;
|
|
1379
1890
|
}
|
|
1891
|
+
/** Bilinear resample of RGBA pixels to `width × height`. */
|
|
1892
|
+
declare function resizePixels(px: PixelBuffer, width: number, height: number): PixelBuffer;
|
|
1893
|
+
/** A colour as RGBA bytes: `#rgb`, `#rrggbb`, `#rrggbbaa` or `[r, g, b, a?]` (0..255). */
|
|
1894
|
+
declare function parseColor(value: string | number[]): [number, number, number, number];
|
|
1895
|
+
/** `#rrggbb` of RGBA bytes (alpha dropped). */
|
|
1896
|
+
declare function toHex(c: readonly number[]): string;
|
|
1897
|
+
|
|
1898
|
+
interface ImageDimensions {
|
|
1899
|
+
width: number;
|
|
1900
|
+
height: number;
|
|
1901
|
+
}
|
|
1902
|
+
interface ImagePoint {
|
|
1903
|
+
x: number;
|
|
1904
|
+
y: number;
|
|
1905
|
+
}
|
|
1906
|
+
interface CropBox {
|
|
1907
|
+
x: number;
|
|
1908
|
+
y: number;
|
|
1909
|
+
width: number;
|
|
1910
|
+
height: number;
|
|
1911
|
+
}
|
|
1912
|
+
type AspectRatio = number | null;
|
|
1913
|
+
interface ImageTransform {
|
|
1914
|
+
rotate: number;
|
|
1915
|
+
flipH: boolean;
|
|
1916
|
+
flipV: boolean;
|
|
1917
|
+
}
|
|
1918
|
+
interface ImageAdjustments {
|
|
1919
|
+
brightness: number;
|
|
1920
|
+
contrast: number;
|
|
1921
|
+
saturation: number;
|
|
1922
|
+
exposure: number;
|
|
1923
|
+
temperature: number;
|
|
1924
|
+
/**
|
|
1925
|
+
* -100 (green) to 100 (magenta), 0 is default. White-balance tint correction in Duv × 3000
|
|
1926
|
+
* (process 2 only; the legacy process ignores it).
|
|
1927
|
+
*/
|
|
1928
|
+
tint?: number;
|
|
1929
|
+
blur: number;
|
|
1930
|
+
opacity: number;
|
|
1931
|
+
/**
|
|
1932
|
+
* Rendering process the values are interpreted by. `2` (the latest; new edits and Reset get
|
|
1933
|
+
* it): linear-light exposure, Bradford white balance, LUT tone curve without intermediate
|
|
1934
|
+
* clipping. `1` or missing: the legacy 8-bit rendering, so edits saved before process
|
|
1935
|
+
* versions existed look exactly as they did. See `normalizeProcessVersion`.
|
|
1936
|
+
*/
|
|
1937
|
+
process?: 1 | 2;
|
|
1938
|
+
/**
|
|
1939
|
+
* Non-destructive adjustment layers, evaluated bottom (first) to top (last) after the base
|
|
1940
|
+
* adjustments above, on the encoded sRGB result. Missing or empty: no layers (edits saved
|
|
1941
|
+
* before layers existed render exactly as before).
|
|
1942
|
+
*/
|
|
1943
|
+
layers?: AdjustmentLayer[];
|
|
1944
|
+
}
|
|
1945
|
+
type AdjustmentKind = 'curves' | 'levels' | 'hueSaturation' | 'vibrance' | 'colorBalance' | 'blackWhite' | 'invert' | 'posterize' | 'threshold' | 'photoFilter';
|
|
1946
|
+
/** A Curves point; `input` and `output` are levels, 0..255. */
|
|
1947
|
+
interface CurvePoint {
|
|
1948
|
+
input: number;
|
|
1949
|
+
output: number;
|
|
1950
|
+
}
|
|
1951
|
+
/** Curves: each channel's curve first, then the master (composite) curve, as in Photoshop. */
|
|
1952
|
+
interface CurvesParams {
|
|
1953
|
+
master: CurvePoint[];
|
|
1954
|
+
red: CurvePoint[];
|
|
1955
|
+
green: CurvePoint[];
|
|
1956
|
+
blue: CurvePoint[];
|
|
1957
|
+
}
|
|
1958
|
+
/** One Levels record. Black / white points are levels (0..255); `gamma` is the midtone slider (0.1..9.99). */
|
|
1959
|
+
interface LevelsChannel {
|
|
1960
|
+
inBlack: number;
|
|
1961
|
+
inWhite: number;
|
|
1962
|
+
gamma: number;
|
|
1963
|
+
outBlack: number;
|
|
1964
|
+
outWhite: number;
|
|
1965
|
+
}
|
|
1966
|
+
/** Levels: each channel's record first, then the master record, as in Photoshop. */
|
|
1967
|
+
interface LevelsParams {
|
|
1968
|
+
master: LevelsChannel;
|
|
1969
|
+
red: LevelsChannel;
|
|
1970
|
+
green: LevelsChannel;
|
|
1971
|
+
blue: LevelsChannel;
|
|
1972
|
+
}
|
|
1973
|
+
/** One of Hue/Saturation's six colour ranges (reds, yellows, greens, cyans, blues, magentas). */
|
|
1974
|
+
interface HueRange {
|
|
1975
|
+
/** Hue shift in degrees (-180..180). */
|
|
1976
|
+
hue: number;
|
|
1977
|
+
/** Saturation change in percent (-100..100). */
|
|
1978
|
+
saturation: number;
|
|
1979
|
+
/** Lightness change in percent (-100..100). */
|
|
1980
|
+
lightness: number;
|
|
1981
|
+
/** Hue degrees where the range starts fading in, is fully on, starts fading out and ends (may wrap). */
|
|
1982
|
+
bounds: [number, number, number, number];
|
|
1983
|
+
}
|
|
1984
|
+
interface HueSaturationParams {
|
|
1985
|
+
/** Master hue shift in degrees (-180..180), or the hue when colorizing (0..360). */
|
|
1986
|
+
hue: number;
|
|
1987
|
+
/** Percent, -100..100 (0..100 when colorizing). */
|
|
1988
|
+
saturation: number;
|
|
1989
|
+
/** Percent, -100..100. */
|
|
1990
|
+
lightness: number;
|
|
1991
|
+
colorize: boolean;
|
|
1992
|
+
/** Six ranges: reds, yellows, greens, cyans, blues, magentas. */
|
|
1993
|
+
ranges: HueRange[];
|
|
1994
|
+
}
|
|
1995
|
+
interface VibranceParams {
|
|
1996
|
+
/** -100..100 */
|
|
1997
|
+
vibrance: number;
|
|
1998
|
+
/** -100..100 */
|
|
1999
|
+
saturation: number;
|
|
2000
|
+
}
|
|
2001
|
+
/** Cyan–red, magenta–green, yellow–blue sliders, -100..100 each. */
|
|
2002
|
+
type ColorBalanceTone = [number, number, number];
|
|
2003
|
+
interface ColorBalanceParams {
|
|
2004
|
+
shadows: ColorBalanceTone;
|
|
2005
|
+
midtones: ColorBalanceTone;
|
|
2006
|
+
highlights: ColorBalanceTone;
|
|
2007
|
+
preserveLuminosity: boolean;
|
|
2008
|
+
}
|
|
2009
|
+
/** Black & White: percent weights of the six colours (Photoshop defaults 40 60 40 60 20 80). */
|
|
2010
|
+
interface BlackWhiteParams {
|
|
2011
|
+
reds: number;
|
|
2012
|
+
yellows: number;
|
|
2013
|
+
greens: number;
|
|
2014
|
+
cyans: number;
|
|
2015
|
+
blues: number;
|
|
2016
|
+
magentas: number;
|
|
2017
|
+
/** Tint colour (`#rrggbb`), applied like the Color blend mode, or `null` for none. */
|
|
2018
|
+
tint: string | null;
|
|
2019
|
+
}
|
|
2020
|
+
interface PhotoFilterParams {
|
|
2021
|
+
/** Filter colour, `#rrggbb`. */
|
|
2022
|
+
color: string;
|
|
2023
|
+
/** Percent, 0..100. */
|
|
2024
|
+
density: number;
|
|
2025
|
+
preserveLuminosity: boolean;
|
|
2026
|
+
}
|
|
2027
|
+
interface PosterizeParams {
|
|
2028
|
+
/** 2..255 */
|
|
2029
|
+
levels: number;
|
|
2030
|
+
}
|
|
2031
|
+
interface ThresholdParams {
|
|
2032
|
+
/** 1..255: luma at or above it becomes white. */
|
|
2033
|
+
level: number;
|
|
2034
|
+
}
|
|
2035
|
+
type InvertParams = Record<string, never>;
|
|
2036
|
+
interface AdjustmentParamsMap {
|
|
2037
|
+
curves: CurvesParams;
|
|
2038
|
+
levels: LevelsParams;
|
|
2039
|
+
hueSaturation: HueSaturationParams;
|
|
2040
|
+
vibrance: VibranceParams;
|
|
2041
|
+
colorBalance: ColorBalanceParams;
|
|
2042
|
+
blackWhite: BlackWhiteParams;
|
|
2043
|
+
invert: InvertParams;
|
|
2044
|
+
posterize: PosterizeParams;
|
|
2045
|
+
threshold: ThresholdParams;
|
|
2046
|
+
photoFilter: PhotoFilterParams;
|
|
2047
|
+
}
|
|
2048
|
+
interface AdjustmentLayerBase {
|
|
2049
|
+
id: string;
|
|
2050
|
+
/** Optional display name. */
|
|
2051
|
+
name?: string;
|
|
2052
|
+
enabled: boolean;
|
|
2053
|
+
/** 0..1 */
|
|
2054
|
+
opacity: number;
|
|
2055
|
+
/** How the adjusted colour is blended over the layers below. */
|
|
2056
|
+
blend: BlendMode;
|
|
2057
|
+
/**
|
|
2058
|
+
* Optional layer mask (natural image pixels): where it is 0 the layer has no effect. Missing:
|
|
2059
|
+
* the layer applies everywhere (layers saved before masks existed are unchanged).
|
|
2060
|
+
*/
|
|
2061
|
+
mask?: AdjustmentLayerMask;
|
|
2062
|
+
}
|
|
2063
|
+
/**
|
|
2064
|
+
* A layer mask: 8-bit coverage of the source image, run-length encoded (see
|
|
2065
|
+
* `encodeSelectionRle`), plus non-destructive density and feather.
|
|
2066
|
+
*/
|
|
2067
|
+
interface AdjustmentLayerMask {
|
|
2068
|
+
width: number;
|
|
2069
|
+
height: number;
|
|
2070
|
+
/** `r1:` run-length encoding of the mask bytes. */
|
|
2071
|
+
rle: string;
|
|
2072
|
+
/** 0..1 (missing = 1). */
|
|
2073
|
+
density?: number;
|
|
2074
|
+
/** Gaussian σ in pixels (missing = 0). */
|
|
2075
|
+
feather?: number;
|
|
2076
|
+
/** `false` keeps the mask but ignores it. */
|
|
2077
|
+
enabled?: boolean;
|
|
2078
|
+
}
|
|
2079
|
+
/** A non-destructive adjustment layer (Photoshop's Layer › New Adjustment Layer). */
|
|
2080
|
+
type AdjustmentLayer = {
|
|
2081
|
+
[K in AdjustmentKind]: AdjustmentLayerBase & {
|
|
2082
|
+
kind: K;
|
|
2083
|
+
params: AdjustmentParamsMap[K];
|
|
2084
|
+
};
|
|
2085
|
+
}[AdjustmentKind];
|
|
2086
|
+
type AdjustmentLayerOf<K extends AdjustmentKind> = Extract<AdjustmentLayer, {
|
|
2087
|
+
kind: K;
|
|
2088
|
+
}>;
|
|
2089
|
+
interface DepthMaskOptions {
|
|
2090
|
+
enabled: boolean;
|
|
2091
|
+
maskSource: string | null;
|
|
2092
|
+
mode: 'threshold' | 'brightness';
|
|
2093
|
+
depthRange: [number, number];
|
|
2094
|
+
softness: number;
|
|
2095
|
+
invert: boolean;
|
|
2096
|
+
}
|
|
2097
|
+
type AnnotationType = 'pen' | 'rect' | 'circle' | 'arrow' | 'line' | 'text' | 'image';
|
|
2098
|
+
interface BaseAnnotation {
|
|
2099
|
+
id: string;
|
|
2100
|
+
type: AnnotationType;
|
|
2101
|
+
x: number;
|
|
2102
|
+
y: number;
|
|
2103
|
+
rotation?: number;
|
|
2104
|
+
opacity?: number;
|
|
2105
|
+
/** Blend mode the annotation is drawn with (default `normal`). */
|
|
2106
|
+
blend?: BlendMode;
|
|
2107
|
+
}
|
|
2108
|
+
interface PenAnnotation extends BaseAnnotation {
|
|
2109
|
+
type: 'pen';
|
|
2110
|
+
points: ImagePoint[];
|
|
2111
|
+
strokeColor: string;
|
|
2112
|
+
strokeWidth: number;
|
|
2113
|
+
}
|
|
2114
|
+
interface RectAnnotation extends BaseAnnotation {
|
|
2115
|
+
type: 'rect';
|
|
2116
|
+
width: number;
|
|
2117
|
+
height: number;
|
|
2118
|
+
strokeColor: string;
|
|
2119
|
+
strokeWidth: number;
|
|
2120
|
+
fillColor?: string;
|
|
2121
|
+
cornerRadius?: number;
|
|
2122
|
+
}
|
|
2123
|
+
interface CircleAnnotation extends BaseAnnotation {
|
|
2124
|
+
type: 'circle';
|
|
2125
|
+
radiusX: number;
|
|
2126
|
+
radiusY: number;
|
|
2127
|
+
strokeColor: string;
|
|
2128
|
+
strokeWidth: number;
|
|
2129
|
+
fillColor?: string;
|
|
2130
|
+
}
|
|
2131
|
+
interface ArrowAnnotation extends BaseAnnotation {
|
|
2132
|
+
type: 'arrow';
|
|
2133
|
+
endX: number;
|
|
2134
|
+
endY: number;
|
|
2135
|
+
strokeColor: string;
|
|
2136
|
+
strokeWidth: number;
|
|
2137
|
+
}
|
|
2138
|
+
interface LineAnnotation extends BaseAnnotation {
|
|
2139
|
+
type: 'line';
|
|
2140
|
+
endX: number;
|
|
2141
|
+
endY: number;
|
|
2142
|
+
strokeColor: string;
|
|
2143
|
+
strokeWidth: number;
|
|
2144
|
+
}
|
|
2145
|
+
interface TextAnnotation extends BaseAnnotation {
|
|
2146
|
+
type: 'text';
|
|
2147
|
+
text: string;
|
|
2148
|
+
fontSize: number;
|
|
2149
|
+
fontFamily?: string;
|
|
2150
|
+
color: string;
|
|
2151
|
+
fontWeight?: string | number;
|
|
2152
|
+
}
|
|
2153
|
+
interface ImageAnnotation extends BaseAnnotation {
|
|
2154
|
+
type: 'image';
|
|
2155
|
+
src: string;
|
|
2156
|
+
width: number;
|
|
2157
|
+
height: number;
|
|
2158
|
+
}
|
|
2159
|
+
type Annotation = PenAnnotation | RectAnnotation | CircleAnnotation | ArrowAnnotation | LineAnnotation | TextAnnotation | ImageAnnotation;
|
|
2160
|
+
type CreateAnnotationPayload = Omit<PenAnnotation, 'id'> | Omit<RectAnnotation, 'id'> | Omit<CircleAnnotation, 'id'> | Omit<ArrowAnnotation, 'id'> | Omit<LineAnnotation, 'id'> | Omit<TextAnnotation, 'id'> | Omit<ImageAnnotation, 'id'>;
|
|
2161
|
+
type ImageEditorTool = 'select' | 'crop' | 'pen' | 'rect' | 'circle' | 'arrow' | 'line' | 'text' | 'watermark' | 'move' | 'brush' | 'eraser';
|
|
2162
|
+
type ImageEditorFit = 'contain' | 'margin';
|
|
2163
|
+
interface ImageEditorState {
|
|
2164
|
+
sourceUrl: string | null;
|
|
2165
|
+
/** Canvas (document) size in pixels: the source image's natural size. */
|
|
2166
|
+
imageDimensions: ImageDimensions;
|
|
2167
|
+
crop: CropBox | null;
|
|
2168
|
+
transform: ImageTransform;
|
|
2169
|
+
/**
|
|
2170
|
+
* Compatibility view of the layer stack: the develop filter of the active pixel layer (or the
|
|
2171
|
+
* Background), its blur (or `legacyOutputBlur`), the output opacity and every adjustment layer
|
|
2172
|
+
* in stack order. Edit it with `setAdjustments` and the adjustment-layer methods.
|
|
2173
|
+
*/
|
|
2174
|
+
adjustments: ImageAdjustments;
|
|
2175
|
+
/** Compatibility view: the parametric depth mask of the active pixel layer (or the Background). */
|
|
2176
|
+
depthMask: DepthMaskOptions;
|
|
2177
|
+
/** Compatibility view: the annotation of every annotation layer, bottom to top. */
|
|
2178
|
+
annotations: Annotation[];
|
|
2179
|
+
selectedAnnotationId: string | null;
|
|
2180
|
+
activeTool: ImageEditorTool;
|
|
2181
|
+
zoom: number;
|
|
2182
|
+
pan: ImagePoint;
|
|
2183
|
+
isOriginalCompared: boolean;
|
|
2184
|
+
/** Viewport fit mode: 'contain' scales to full viewport bounds; 'margin' scales to 85% with 1.0 cap (default). */
|
|
2185
|
+
fit?: ImageEditorFit;
|
|
2186
|
+
/**
|
|
2187
|
+
* The active selection (8-bit coverage over the source image), or null/missing when nothing is
|
|
2188
|
+
* selected. Recorded in undo history and saved as `selection` in `toJSON()`.
|
|
2189
|
+
*/
|
|
2190
|
+
selection?: SelectionMask | null;
|
|
2191
|
+
/** Quick Mask view: tint the unselected area instead of drawing marching ants (view state). */
|
|
2192
|
+
quickMask?: boolean;
|
|
2193
|
+
/**
|
|
2194
|
+
* The layer stack, bottom to top. Opening an image gives one pixel layer, "Background", whose
|
|
2195
|
+
* pixels are the source image. Layers are immutable: compare them by identity.
|
|
2196
|
+
*/
|
|
2197
|
+
layers: ImageLayer[];
|
|
2198
|
+
/** The layer that layer commands, painting and `setAdjustments` act on, or `null`. */
|
|
2199
|
+
activeLayerId: string | null;
|
|
2200
|
+
/** Whether painting targets the active layer's pixels or its mask. */
|
|
2201
|
+
activeTarget: LayerTarget;
|
|
2202
|
+
/** Export alpha (0..1), applied after compositing; `adjustments.opacity` mirrors it. */
|
|
2203
|
+
outputOpacity: number;
|
|
2204
|
+
/**
|
|
2205
|
+
* Blur that runs after the adjustment layers, kept from v1 / v2 documents that had both so
|
|
2206
|
+
* they render as before. New edits blur a layer instead (`blur` filter).
|
|
2207
|
+
*/
|
|
2208
|
+
legacyOutputBlur?: number;
|
|
2209
|
+
/** Brush settings and foreground / background colours of the paint tools (view state). */
|
|
2210
|
+
paint: PaintOptions;
|
|
2211
|
+
}
|
|
2212
|
+
/**
|
|
2213
|
+
* A stored editor state in the document-level schema (versions 1 and 2). Documents whose layer
|
|
2214
|
+
* stack has exactly this shape are still written this way, byte for byte.
|
|
2215
|
+
*/
|
|
2216
|
+
interface LegacySerializedImageEditorState {
|
|
2217
|
+
/**
|
|
2218
|
+
* Schema version. `2` adds `adjustments.layers`; states without layers are still written as
|
|
2219
|
+
* `1` so they round-trip unchanged. See `migrateSerializedImageEditorState`.
|
|
2220
|
+
*/
|
|
2221
|
+
version: 1 | 2;
|
|
2222
|
+
crop: CropBox | null;
|
|
2223
|
+
transform: ImageTransform;
|
|
2224
|
+
adjustments: ImageAdjustments;
|
|
2225
|
+
depthMask: DepthMaskOptions;
|
|
2226
|
+
annotations: Annotation[];
|
|
2227
|
+
/** The active selection, run-length encoded. Missing when nothing is selected. */
|
|
2228
|
+
selection?: SerializedSelection;
|
|
2229
|
+
}
|
|
2230
|
+
/**
|
|
2231
|
+
* A stored editor state: the document-level schema (v1 / v2) or the layered schema (v3, see
|
|
2232
|
+
* `SerializedLayeredImageEditorState`). `toJSON()` writes v1 / v2 while the layer stack still
|
|
2233
|
+
* has the shape those versions describe.
|
|
2234
|
+
*/
|
|
2235
|
+
type SerializedImageEditorState = LegacySerializedImageEditorState | SerializedLayeredImageEditorState;
|
|
2236
|
+
interface ExportOptions {
|
|
2237
|
+
format?: 'image/png' | 'image/jpeg' | 'image/webp';
|
|
2238
|
+
quality?: number;
|
|
2239
|
+
width?: number;
|
|
2240
|
+
height?: number;
|
|
2241
|
+
includeAnnotations?: boolean;
|
|
2242
|
+
/** Render only these layers (groups with their children). */
|
|
2243
|
+
layerIds?: string[];
|
|
2244
|
+
}
|
|
2245
|
+
interface ImageEditorOptions {
|
|
2246
|
+
image?: string | HTMLImageElement;
|
|
2247
|
+
initialState?: Partial<SerializedImageEditorState>;
|
|
2248
|
+
onStateChange?: (state: ImageEditorState) => void;
|
|
2249
|
+
maxHistoryDepth?: number;
|
|
2250
|
+
/**
|
|
2251
|
+
* Upper bound for the pixel data held only by undo / redo steps (tiles shared with the
|
|
2252
|
+
* current state are free). The oldest steps are dropped first. Default 512 MiB.
|
|
2253
|
+
*/
|
|
2254
|
+
maxHistoryBytes?: number;
|
|
2255
|
+
/** Viewport fit mode: 'contain' scales to full viewport bounds; 'margin' scales to 85% with 1.0 cap (default). */
|
|
2256
|
+
fit?: ImageEditorFit;
|
|
2257
|
+
}
|
|
2258
|
+
interface InpaintOptions {
|
|
2259
|
+
prompt: string;
|
|
2260
|
+
imageDataUrl: string;
|
|
2261
|
+
maskDataUrl?: string;
|
|
2262
|
+
cropBox?: CropBox | null;
|
|
2263
|
+
}
|
|
2264
|
+
interface RemoveBackgroundOptions {
|
|
2265
|
+
imageDataUrl: string;
|
|
2266
|
+
}
|
|
2267
|
+
type InpaintHook = (options: InpaintOptions) => Promise<string | void> | string | void;
|
|
2268
|
+
type RemoveBackgroundHook = (options: RemoveBackgroundOptions) => Promise<string | void> | string | void;
|
|
2269
|
+
interface ImageEditorAIHooks {
|
|
2270
|
+
onInpaint?: InpaintHook;
|
|
2271
|
+
onRemoveBackground?: RemoveBackgroundHook;
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
/**
|
|
2275
|
+
* Applies color and tone adjustments (brightness, contrast, saturation, exposure, temperature, tint,
|
|
2276
|
+
* opacity, then any adjustment `layers`, then blur) directly to the pixel data of an ImageData buffer.
|
|
2277
|
+
*
|
|
2278
|
+
* `adjustments.process` selects the rendering: `2` is the linear-light pipeline
|
|
2279
|
+
* ({@link applyProcess2Adjustments}); anything else (including a missing value, as in edits saved
|
|
2280
|
+
* before process versions existed) is the frozen legacy rendering ({@link applyLegacyAdjustments}).
|
|
2281
|
+
*/
|
|
2282
|
+
declare function applyAdjustments(imageData: ImageData, adjustments: ImageAdjustments, options?: {
|
|
2283
|
+
layerMasks?: ReadonlyMap<string, ArrayLike<number>>;
|
|
2284
|
+
}): void;
|
|
2285
|
+
/**
|
|
2286
|
+
* Process 1: the original 8-bit gamma-space rendering, clamping after every step. Frozen so
|
|
2287
|
+
* that edits saved without a `process` look exactly as they always have. `tint` is ignored.
|
|
2288
|
+
*/
|
|
2289
|
+
declare function applyLegacyAdjustments(imageData: {
|
|
2290
|
+
data: Uint8ClampedArray;
|
|
2291
|
+
}, adjustments: ImageAdjustments): void;
|
|
2292
|
+
/**
|
|
2293
|
+
* Process 2: decode sRGB to linear float once; apply exposure (gain) and white balance (a
|
|
2294
|
+
* Bradford matrix relative to as-shot) in linear light; a per-channel tone LUT for the
|
|
2295
|
+
* highlight shoulder, contrast and brightness; luminance-preserving saturation in linear light;
|
|
2296
|
+
* then encode back to sRGB through a LUT. Nothing is clamped between stages, only at the final
|
|
2297
|
+
* encode. Neutral settings are the identity.
|
|
2298
|
+
*/
|
|
2299
|
+
declare function applyProcess2Adjustments(imageData: {
|
|
2300
|
+
data: Uint8ClampedArray;
|
|
2301
|
+
}, adjustments: ImageAdjustments): void;
|
|
2302
|
+
/**
|
|
2303
|
+
* Fast separable box blur running horizontally and vertically (`adjustments.blur` and the `blur`
|
|
2304
|
+
* layer filter): `radius` pixels each side, edges clamped, rounded after each pass.
|
|
2305
|
+
*/
|
|
2306
|
+
declare function applyBoxBlur(imageData: {
|
|
2307
|
+
width: number;
|
|
2308
|
+
height: number;
|
|
2309
|
+
data: Uint8ClampedArray;
|
|
2310
|
+
}, radius: number): void;
|
|
2311
|
+
/**
|
|
2312
|
+
* Blends a depth/alpha mask into the main image data based on Gleamforge depth masking.
|
|
2313
|
+
* Supports threshold range with softness gradation, brightness mode, and optional inversion.
|
|
2314
|
+
*/
|
|
2315
|
+
declare function applyDepthMask(mainImageData: ImageData, maskImageData: ImageData, options: DepthMaskOptions): void;
|
|
2316
|
+
/**
|
|
2317
|
+
* Removes alpha channel by setting all alpha bytes to 255 (completely opaque).
|
|
2318
|
+
* From Gleamforge image-filters.ts.
|
|
2319
|
+
*/
|
|
2320
|
+
declare function removeAlpha(imageData: ImageData): void;
|
|
2321
|
+
|
|
2322
|
+
/**
|
|
2323
|
+
* Colour science for the image editor's process 2 rendering: sRGB transfer functions,
|
|
2324
|
+
* correlated colour temperature / tint (Kim et al. Planckian locus, tint as Duv), Bradford
|
|
2325
|
+
* white-balance adaptation relative to "as shot", and the display-referred tone curve.
|
|
2326
|
+
*/
|
|
2327
|
+
/** A CIE 1931 chromaticity. */
|
|
2328
|
+
interface Chromaticity {
|
|
2329
|
+
x: number;
|
|
2330
|
+
y: number;
|
|
2331
|
+
}
|
|
2332
|
+
/** A row-major 3×3 matrix (`[m00, m01, m02, m10, …, m22]`). */
|
|
2333
|
+
type Matrix3 = [number, number, number, number, number, number, number, number, number];
|
|
2334
|
+
/** The rendering of adjustments from before process versions existed. Frozen. */
|
|
2335
|
+
declare const LEGACY_PROCESS_VERSION: 1;
|
|
2336
|
+
/** The process new edits and Reset get. */
|
|
2337
|
+
declare const LATEST_PROCESS_VERSION: 2;
|
|
2338
|
+
type ImageProcessVersion = 1 | 2;
|
|
2339
|
+
/**
|
|
2340
|
+
* Reads a stored process number leniently: a missing or damaged value (not a whole number) is
|
|
2341
|
+
* the legacy process, so a saved edit from before process versions renders exactly as it did. A
|
|
2342
|
+
* whole number newer than this build knows renders with the latest process.
|
|
2343
|
+
*/
|
|
2344
|
+
declare function normalizeProcessVersion(value: unknown): ImageProcessVersion;
|
|
2345
|
+
declare function srgbToLinear(v: number): number;
|
|
2346
|
+
declare function linearToSrgb(v: number): number;
|
|
2347
|
+
/** Rec.709 / sRGB luminance weights (linear light). */
|
|
2348
|
+
declare const LUMA_709: readonly [number, number, number];
|
|
2349
|
+
declare const IDENTITY_MATRIX3: Matrix3;
|
|
2350
|
+
declare function mulMatrix3(a: Matrix3, b: Matrix3): Matrix3;
|
|
2351
|
+
declare function applyMatrix3(m: Matrix3, v: readonly [number, number, number]): [number, number, number];
|
|
2352
|
+
declare function invertMatrix3(m: Matrix3): Matrix3 | null;
|
|
2353
|
+
declare const D65: Chromaticity;
|
|
2354
|
+
/** Bradford chromatic adaptation (XYZ → XYZ) from white `src` to white `dst`. */
|
|
2355
|
+
declare function bradfordAdaptation(src: Chromaticity, dst: Chromaticity): Matrix3;
|
|
2356
|
+
/**
|
|
2357
|
+
* Matrix (linear sRGB → linear sRGB) that white-balances a scene lit by `src` so that it
|
|
2358
|
+
* renders as if lit by D65.
|
|
2359
|
+
*/
|
|
2360
|
+
declare function wbMatrix(src: Chromaticity): Matrix3;
|
|
2361
|
+
/** The chromaticity of a linear sRGB colour. */
|
|
2362
|
+
declare function linearSrgbToXy(rgb: readonly [number, number, number]): Chromaticity;
|
|
2363
|
+
/** Tint units per unit of Duv. */
|
|
2364
|
+
declare const TINT_SCALE = 3000;
|
|
2365
|
+
declare const MIN_KELVIN = 1667;
|
|
2366
|
+
declare const MAX_KELVIN = 25000;
|
|
2367
|
+
/** CIE 1931 xy → CIE 1960 uv. */
|
|
2368
|
+
declare function xyToUv(p: Chromaticity): [number, number];
|
|
2369
|
+
/** CIE 1960 uv → CIE 1931 xy. */
|
|
2370
|
+
declare function uvToXy(u: number, v: number): Chromaticity;
|
|
2371
|
+
/**
|
|
2372
|
+
* Source illuminant chromaticity for temperature `kelvin` and correction `tint`.
|
|
2373
|
+
* Positive tint means a green source white, whose correction adds magenta to the image.
|
|
2374
|
+
*/
|
|
2375
|
+
declare function tempTintToXy(kelvin: number, tint: number): Chromaticity;
|
|
2376
|
+
/** Inverse of {@link tempTintToXy}: nearest locus temperature (searched in mired space) and tint. */
|
|
2377
|
+
declare function xyToTempTint(p: Chromaticity): {
|
|
2378
|
+
kelvin: number;
|
|
2379
|
+
tint: number;
|
|
2380
|
+
};
|
|
2381
|
+
/** Rendered images carry no as-shot white: "as shot" is 6500 K / tint 0 and maps to the identity. */
|
|
2382
|
+
declare const AS_SHOT_KELVIN = 6500;
|
|
2383
|
+
/** Mireds per unit of the `temperature` slider (−100…100). */
|
|
2384
|
+
declare const MIRED_PER_TEMPERATURE_UNIT = 1;
|
|
2385
|
+
/**
|
|
2386
|
+
* Maps the `temperature` slider (−100 cool … +100 warm) to the Kelvin white-balance setting:
|
|
2387
|
+
* one mired per unit around 6500 K, so 0 → 6500 K, +100 → ~18 570 K (a strong warming
|
|
2388
|
+
* correction), −100 → ~3 940 K (a strong cooling correction). Mireds are perceptually even,
|
|
2389
|
+
* so equal slider steps look like equal changes.
|
|
2390
|
+
*/
|
|
2391
|
+
declare function temperatureToKelvin(temperature: number): number;
|
|
2392
|
+
/** Inverse of {@link temperatureToKelvin}. */
|
|
2393
|
+
declare function kelvinToTemperature(kelvin: number): number;
|
|
2394
|
+
/**
|
|
2395
|
+
* White-balance matrix (linear sRGB) for the `temperature` / `tint` sliders, relative to
|
|
2396
|
+
* "as shot": the identity at 0 / 0. Normalised so neutral luminance is preserved (white
|
|
2397
|
+
* balance doesn't change exposure).
|
|
2398
|
+
*/
|
|
2399
|
+
declare function whiteBalanceMatrix(temperature: number, tint?: number): Matrix3;
|
|
2400
|
+
/**
|
|
2401
|
+
* Neutral-point eyedropper: the `temperature` / `tint` that render the sampled sRGB colour
|
|
2402
|
+
* (0–255 per channel, as it appears in the unadjusted image) neutral. Results are clamped to
|
|
2403
|
+
* the slider range −100…100.
|
|
2404
|
+
*/
|
|
2405
|
+
declare function whiteBalanceFromSample(rgb: readonly [number, number, number] | {
|
|
2406
|
+
r: number;
|
|
2407
|
+
g: number;
|
|
2408
|
+
b: number;
|
|
2409
|
+
}): {
|
|
2410
|
+
temperature: number;
|
|
2411
|
+
tint: number;
|
|
2412
|
+
};
|
|
2413
|
+
/** Number of intervals in a tone LUT (the table has `TONE_LUT_SIZE + 1` entries). */
|
|
2414
|
+
declare const TONE_LUT_SIZE = 4096;
|
|
2415
|
+
/**
|
|
2416
|
+
* The process 2 tone curve for one linear input value in `[0, headroom]`:
|
|
2417
|
+
*
|
|
2418
|
+
* 1. A highlight shoulder (extended Reinhard with white point `headroom`) above a knee of 0.6
|
|
2419
|
+
* rolls values above 1 (after exposure / white balance) back into range instead of clipping.
|
|
2420
|
+
* With no headroom (`headroom = 1`) it is exactly the identity.
|
|
2421
|
+
* 2. In a gamma-2.2 perceptual domain, contrast is an S-curve anchored at 0, middle grey and 1
|
|
2422
|
+
* (as `ToneMap::display`), and brightness a midtone lift anchored at 0 and 1.
|
|
2423
|
+
*
|
|
2424
|
+
* `contrast` and `brightness` are −100…100; both 0 with `headroom = 1` is the identity.
|
|
2425
|
+
*/
|
|
2426
|
+
declare function toneCurve(y: number, contrast: number, brightness: number, headroom?: number): number;
|
|
2427
|
+
/** Tabulates {@link toneCurve} over `[0, headroom]` in {@link TONE_LUT_SIZE} steps. */
|
|
2428
|
+
declare function buildToneLut(contrast: number, brightness: number, headroom?: number): Float32Array;
|
|
2429
|
+
/** Linearly interpolated lookup into a LUT from {@link buildToneLut}. */
|
|
2430
|
+
declare function sampleToneLut(lut: Float32Array, headroom: number, y: number): number;
|
|
1380
2431
|
|
|
1381
|
-
/** The `version` that `ImageEditorController.toJSON()` writes. */
|
|
1382
|
-
declare const IMAGE_EDITOR_STATE_VERSION = 1;
|
|
1383
2432
|
/**
|
|
1384
|
-
*
|
|
1385
|
-
*
|
|
2433
|
+
* The newest `version` that `ImageEditorController.toJSON()` writes (3: layers). Documents whose
|
|
2434
|
+
* layers still have the old shape are written as version 1 or 2.
|
|
2435
|
+
*/
|
|
2436
|
+
declare const IMAGE_EDITOR_STATE_VERSION = 3;
|
|
2437
|
+
/**
|
|
2438
|
+
* Migration steps for the document-level schema (versions 1 and 2), keyed by the version they
|
|
2439
|
+
* start from. Empty: version 2 only adds `adjustments.layers`, which version 1 readers keep.
|
|
1386
2440
|
*/
|
|
1387
2441
|
declare const imageEditorStateMigrations: Record<number, MigrationStep>;
|
|
1388
2442
|
interface ImageEditorDocumentLoad {
|
|
@@ -1507,6 +2561,10 @@ declare function colorBalanceChannel(tones: readonly [readonly number[], readonl
|
|
|
1507
2561
|
* blues, magentas).
|
|
1508
2562
|
*/
|
|
1509
2563
|
declare function blackWhiteGray(c: readonly number[], weights: readonly number[]): number;
|
|
2564
|
+
/** D50 white (ICC PCS). */
|
|
2565
|
+
declare const D50: readonly [0.96422, 1, 0.82521];
|
|
2566
|
+
/** D50 XYZ → linear sRGB. */
|
|
2567
|
+
declare const XYZ_D50_TO_SRGB: readonly [readonly [3.133856, -1.616867, -0.490615], readonly [-0.978768, 1.916142, 0.033454], readonly [0.071945, -0.228991, 1.405243]];
|
|
1510
2568
|
/**
|
|
1511
2569
|
* Photo Filter's linear-light RGB matrix (row-major 3×3): the pixel's D50 XYZ, relative to white,
|
|
1512
2570
|
* multiplied by the filter colour's mixed in by `density` (0..1). `normalizeY` keeps luminance Y.
|
|
@@ -1547,7 +2605,9 @@ declare function evaluateAdjustmentLayers(color: readonly number[], layers: read
|
|
|
1547
2605
|
* scales each masked layer's opacity per pixel: coverage 0 leaves the pixel as the layers below
|
|
1548
2606
|
* made it, 1 applies the layer fully.
|
|
1549
2607
|
*/
|
|
1550
|
-
declare function applyAdjustmentLayers(imageData:
|
|
2608
|
+
declare function applyAdjustmentLayers(imageData: {
|
|
2609
|
+
data: Uint8ClampedArray;
|
|
2610
|
+
}, layers: readonly AdjustmentLayer[] | undefined, masks?: ReadonlyMap<string, ArrayLike<number>>): void;
|
|
1551
2611
|
/** Stable cache key of a layer stack's pixel effect (for renderer caches). */
|
|
1552
2612
|
declare function adjustmentLayersKey(layers: readonly AdjustmentLayer[] | undefined): string;
|
|
1553
2613
|
|
|
@@ -1715,6 +2775,8 @@ interface SelectionToolOptions {
|
|
|
1715
2775
|
antiAlias: boolean;
|
|
1716
2776
|
/** Sample the adjusted image instead of the source. */
|
|
1717
2777
|
sampleMerged: boolean;
|
|
2778
|
+
/** Sample the whole image (`composite`, default) or only the active pixel layer. */
|
|
2779
|
+
sample?: 'composite' | 'active-layer';
|
|
1718
2780
|
distance: ColorDistance;
|
|
1719
2781
|
}
|
|
1720
2782
|
declare const DEFAULT_SELECTION_TOOL_OPTIONS: SelectionToolOptions;
|
|
@@ -1792,6 +2854,24 @@ declare function createImageSelectionTools(controller: ImageEditorController): A
|
|
|
1792
2854
|
*/
|
|
1793
2855
|
declare function createImageEditTools(controller: ImageEditorController): AgentTool[];
|
|
1794
2856
|
|
|
2857
|
+
/** A short description of a mask for agents (no pixels). */
|
|
2858
|
+
declare function maskSummary(mask: RasterMask | undefined): Record<string, unknown> | null;
|
|
2859
|
+
/**
|
|
2860
|
+
* A plain description of a layer (and its children) for agents: ids, types, names, document
|
|
2861
|
+
* bounds, visibility, opacity, fill, blend, clipping, locks, mask summary and whether it is
|
|
2862
|
+
* active. `boundsOf` gives a pixel layer's document bounds.
|
|
2863
|
+
*/
|
|
2864
|
+
declare function describeLayer(layer: ImageLayer, activeId: string | null, boundsOf: (layer: ImageLayer) => CropBox | null): Record<string, unknown>;
|
|
2865
|
+
/**
|
|
2866
|
+
* Agent tools for the image editor's layer stack: `list_layers`, `set_active_layer`,
|
|
2867
|
+
* `add_pixel_layer`, `duplicate_layer`, `remove_layer`, `move_layer`, `set_layer_properties`,
|
|
2868
|
+
* `group_layers`, `ungroup_layer`, `merge_down`, `merge_visible`, `flatten_image`, `offset_layer`,
|
|
2869
|
+
* `add_layer_mask`, `apply_layer_mask`, `remove_layer_mask`, `set_layer_mask_properties`,
|
|
2870
|
+
* `layer_via_copy`, `add_layer_filter`, `update_layer_filter` and `remove_layer_filter`. Each write
|
|
2871
|
+
* is one undo step, validates before changing anything and returns what it changed.
|
|
2872
|
+
*/
|
|
2873
|
+
declare function createImageLayerTools(controller: ImageEditorController): AgentTool[];
|
|
2874
|
+
|
|
1795
2875
|
/**
|
|
1796
2876
|
* Region-based mosaic (pixelation) and box-blur filters for redacting or anonymizing
|
|
1797
2877
|
* rectangular bounding boxes on an ImageData-like buffer.
|
|
@@ -1842,4 +2922,442 @@ declare function applyRegionBlur<T extends MosaicImageDataLike>(imageData: T, re
|
|
|
1842
2922
|
*/
|
|
1843
2923
|
declare function createImageCaptureSurface(controller: ImageEditorController): CaptureSurface;
|
|
1844
2924
|
|
|
1845
|
-
|
|
2925
|
+
/**
|
|
2926
|
+
* Between the old document-level model (schema v1 / v2: base sliders, adjustment layers, blur,
|
|
2927
|
+
* depth mask and annotations) and the layer stack:
|
|
2928
|
+
*
|
|
2929
|
+
* - `layersFromLegacy` lifts a v1 / v2 state into layers: the source becomes the Background
|
|
2930
|
+
* pixel layer carrying the base sliders as its `develop` filter and the depth mask as its
|
|
2931
|
+
* parametric mask; adjustment layers go above it, annotations on top in their order. Blur
|
|
2932
|
+
* becomes a `blur` filter on the Background, or `legacyOutputBlur` when adjustment layers
|
|
2933
|
+
* exist (blur used to run after them).
|
|
2934
|
+
* - `legacyView` reads the stack back as `adjustments` / `depthMask` / `annotations` (the
|
|
2935
|
+
* compatibility views on the editor state) and says whether the stack still has exactly the
|
|
2936
|
+
* legacy shape, in which case it serializes as v1 / v2 byte for byte.
|
|
2937
|
+
*/
|
|
2938
|
+
|
|
2939
|
+
declare const BACKGROUND_LAYER_ID = "background";
|
|
2940
|
+
declare const BACKGROUND_LAYER_NAME = "Background";
|
|
2941
|
+
declare const DEVELOP_FILTER_ID = "develop";
|
|
2942
|
+
declare const BLUR_FILTER_ID = "blur";
|
|
2943
|
+
/** The old document-level parts of the editor state. */
|
|
2944
|
+
interface LegacyParts {
|
|
2945
|
+
adjustments: ImageAdjustments;
|
|
2946
|
+
depthMask: DepthMaskOptions;
|
|
2947
|
+
annotations: Annotation[];
|
|
2948
|
+
}
|
|
2949
|
+
/** The stack as stored at document level next to the layers. */
|
|
2950
|
+
interface LayerStack {
|
|
2951
|
+
layers: ImageLayer[];
|
|
2952
|
+
/** Export alpha (the old `adjustments.opacity`), 0..1. */
|
|
2953
|
+
outputOpacity: number;
|
|
2954
|
+
/** Migrated blur that must run after the adjustment layers (never created by new edits). */
|
|
2955
|
+
legacyOutputBlur?: number;
|
|
2956
|
+
}
|
|
2957
|
+
/** A raster mask from an old adjustment-layer mask, resampled to the document if needed. */
|
|
2958
|
+
declare function rasterMaskFromLegacy(mask: AdjustmentLayerMask, width: number, height: number): RasterMask | null;
|
|
2959
|
+
/**
|
|
2960
|
+
* True when an adjustment layer's mask came from a v1 / v2 mask of another size than the canvas
|
|
2961
|
+
* (the old renderer resampled it per render; the stack holds a canvas-sized copy).
|
|
2962
|
+
*/
|
|
2963
|
+
declare function hasResampledLegacyMask(layers: readonly ImageLayer[], width: number, height: number): boolean;
|
|
2964
|
+
/** The old mask shape of a raster mask (its pixels over the canvas, run-length encoded). */
|
|
2965
|
+
declare function legacyMaskOf(mask: RasterMask, width: number, height: number): AdjustmentLayerMask;
|
|
2966
|
+
/** True when the depth mask settings are the defaults (no mask at all). */
|
|
2967
|
+
declare function isDefaultDepthMask(mask: DepthMaskOptions | undefined): boolean;
|
|
2968
|
+
declare function developFromAdjustments(adjustments: ImageAdjustments): DevelopFilter;
|
|
2969
|
+
/** The default name of an annotation layer. */
|
|
2970
|
+
declare function annotationLayerName(annotation: Annotation): string;
|
|
2971
|
+
declare function annotationLayerFor(annotation: Annotation): AnnotationLayer;
|
|
2972
|
+
declare function adjustmentNodeFromLegacy(layer: AdjustmentLayer, width: number, height: number): AdjustmentLayerNode;
|
|
2973
|
+
/** The Background layer of an opened image (its pixels are the document source). */
|
|
2974
|
+
declare function backgroundLayer(filters?: LayerFilter[], mask?: RasterMask): PixelLayer;
|
|
2975
|
+
/** A parametric depth mask on a layer. */
|
|
2976
|
+
declare function depthRasterMask(source: DepthMaskOptions): RasterMask;
|
|
2977
|
+
/** Lifts a v1 / v2 state into a layer stack (see the module comment). */
|
|
2978
|
+
declare function layersFromLegacy(parts: Partial<LegacyParts>, width: number, height: number): LayerStack;
|
|
2979
|
+
/** The old `AdjustmentLayer` shape of a node, keys in the order `normalizeAdjustmentLayer` writes. */
|
|
2980
|
+
declare function legacyAdjustmentLayer(node: AdjustmentLayerNode, width: number, height: number): AdjustmentLayer;
|
|
2981
|
+
/** The pixel layer whose develop filter the legacy API edits: the active one, else the Background. */
|
|
2982
|
+
declare function developTarget(layers: readonly ImageLayer[], activeLayerId: string | null): PixelLayer | null;
|
|
2983
|
+
interface LegacyViewResult extends LegacyParts {
|
|
2984
|
+
/**
|
|
2985
|
+
* True when the stack has exactly the shape a v1 / v2 document lifts to (an unpainted,
|
|
2986
|
+
* unmoved Background with develop / blur filters and an optional depth mask, then adjustment
|
|
2987
|
+
* layers, then plain annotation layers), so it can be written as v1 / v2.
|
|
2988
|
+
*/
|
|
2989
|
+
exact: boolean;
|
|
2990
|
+
}
|
|
2991
|
+
/** Reads the stack back as the old document-level parts (see `LegacyViewResult`). */
|
|
2992
|
+
declare function legacyView(stack: LayerStack, width: number, height: number, activeLayerId?: string | null): LegacyViewResult;
|
|
2993
|
+
/** See `LegacyViewResult.exact`. */
|
|
2994
|
+
declare function isLegacyShape(stack: LayerStack): boolean;
|
|
2995
|
+
|
|
2996
|
+
/**
|
|
2997
|
+
* Pure helpers between the compositor and the renderer: the output stage (projection to the
|
|
2998
|
+
* cropped, rotated frame, output opacity and the migrated blur), the routing rule that keeps
|
|
2999
|
+
* old-shape documents on the exact legacy path where document-space compositing cannot match it,
|
|
3000
|
+
* and per-tile histograms. No DOM.
|
|
3001
|
+
*/
|
|
3002
|
+
|
|
3003
|
+
/** True for 0, 90, 180 and 270 degrees. */
|
|
3004
|
+
declare function isQuarterTurn(rotate: number): boolean;
|
|
3005
|
+
/** The projection that draws `region` into a `baseW × baseH` buffer at scale 1 (the renderer's base canvas). */
|
|
3006
|
+
declare function baseProjection(region: CropBox, transform: ImageTransform, baseW: number, baseH: number): ImageProjection;
|
|
3007
|
+
/**
|
|
3008
|
+
* Projects `src` (RGBA covering `srcRect` in document space) into the base frame of `region`
|
|
3009
|
+
* under a quarter-turn `transform`: an exact pixel permutation (crop, flips, 90° steps), the
|
|
3010
|
+
* same mapping the canvas draws with. Returns the base buffer and its size.
|
|
3011
|
+
*/
|
|
3012
|
+
declare function projectQuarterTurn(src: ArrayLike<number>, srcRect: CropBox, region: CropBox, transform: ImageTransform): {
|
|
3013
|
+
width: number;
|
|
3014
|
+
height: number;
|
|
3015
|
+
data: Uint8ClampedArray;
|
|
3016
|
+
};
|
|
3017
|
+
/** Output opacity as the old base adjustments applied it (`clamp(a · opacity)`), then the migrated blur. */
|
|
3018
|
+
declare function applyOutputStage(img: {
|
|
3019
|
+
width: number;
|
|
3020
|
+
height: number;
|
|
3021
|
+
data: Uint8ClampedArray;
|
|
3022
|
+
}, opacity: number, legacyOutputBlur?: number): void;
|
|
3023
|
+
interface RouteInput {
|
|
3024
|
+
stack: LayerStack;
|
|
3025
|
+
region: CropBox;
|
|
3026
|
+
canvas: {
|
|
3027
|
+
width: number;
|
|
3028
|
+
height: number;
|
|
3029
|
+
};
|
|
3030
|
+
transform: ImageTransform;
|
|
3031
|
+
/** Whether the source image is fully opaque. */
|
|
3032
|
+
sourceOpaque: boolean;
|
|
3033
|
+
}
|
|
3034
|
+
/**
|
|
3035
|
+
* Whether a document must render through the legacy base path to look exactly as before. Only
|
|
3036
|
+
* documents that still have the v1 / v2 shape qualify, and only where compositing in document
|
|
3037
|
+
* space cannot reproduce the old order of operations:
|
|
3038
|
+
*
|
|
3039
|
+
* - a rotation that is not a quarter turn, or a crop with fractional coordinates (the old path
|
|
3040
|
+
* resampled before adjusting);
|
|
3041
|
+
* - an enabled depth mask (applied after the blur and resampled with the canvas);
|
|
3042
|
+
* - output opacity below 1 (it rounded alpha before the depth mask);
|
|
3043
|
+
* - a Background blur filter with a crop or a 90° / 270° turn (the old blur clamped at the crop
|
|
3044
|
+
* edge and ran on the rotated buffer);
|
|
3045
|
+
* - a migrated output blur over a source with transparency (canvas premultiplication would round
|
|
3046
|
+
* colours before blurring);
|
|
3047
|
+
* - an adjustment-layer mask stored at another size than the canvas (it was resampled through
|
|
3048
|
+
* the projection on every render).
|
|
3049
|
+
*/
|
|
3050
|
+
declare function needsLegacyBase(input: RouteInput): boolean;
|
|
3051
|
+
/**
|
|
3052
|
+
* Splits the stack into what the compositor rasterizes and the annotation layers at the top that
|
|
3053
|
+
* draw as crisp vectors over the result (as annotations always did): the trailing run of plain
|
|
3054
|
+
* top-level annotation layers (hidden ones are skipped).
|
|
3055
|
+
*/
|
|
3056
|
+
declare function splitOverlayAnnotations(layers: readonly ImageLayer[]): {
|
|
3057
|
+
composite: ImageLayer[];
|
|
3058
|
+
overlay: AnnotationLayer[];
|
|
3059
|
+
};
|
|
3060
|
+
/** The integer rectangle covering `region`. */
|
|
3061
|
+
declare function coveringRect(region: CropBox): CropBox;
|
|
3062
|
+
/**
|
|
3063
|
+
* The base image of a layered document without a canvas: the stack composited over `region`
|
|
3064
|
+
* (integer), projected under a quarter-turn `transform`, then output opacity and the migrated
|
|
3065
|
+
* blur. Annotation layers need a canvas and are skipped unless `sources` can rasterize them.
|
|
3066
|
+
* This is what the renderer's base canvas holds for such documents.
|
|
3067
|
+
*/
|
|
3068
|
+
declare function renderLayeredBase(stack: LayerStack, region: CropBox, transform: ImageTransform, sources: CompositorSources, compositor?: LayerCompositor): {
|
|
3069
|
+
width: number;
|
|
3070
|
+
height: number;
|
|
3071
|
+
data: Uint8ClampedArray;
|
|
3072
|
+
};
|
|
3073
|
+
/** An empty histogram. */
|
|
3074
|
+
declare function emptyHistogram(): ImageHistogram;
|
|
3075
|
+
/** Adds the pixels of `rect` (in tile-local coordinates of a `stride`-wide RGBA buffer) to `h`. */
|
|
3076
|
+
declare function addToHistogram(h: ImageHistogram, data: ArrayLike<number>, stride: number, rect: CropBox): void;
|
|
3077
|
+
/** Sums histograms (and recomputes `max`). */
|
|
3078
|
+
declare function sumHistograms(parts: Iterable<ImageHistogram>): ImageHistogram;
|
|
3079
|
+
|
|
3080
|
+
/**
|
|
3081
|
+
* The layers panel's view model, shared by the React and Svelte panels: the rows to show (top of
|
|
3082
|
+
* the stack first, groups indented, collapsed groups hiding their children), where a drop lands,
|
|
3083
|
+
* and the menu of layer operations with whether each one applies to the active layer.
|
|
3084
|
+
*/
|
|
3085
|
+
|
|
3086
|
+
interface LayerPanelRow {
|
|
3087
|
+
layer: ImageLayer;
|
|
3088
|
+
/** Nesting depth (0 = top level). */
|
|
3089
|
+
depth: number;
|
|
3090
|
+
parentId: string | null;
|
|
3091
|
+
/** Index among its siblings, 0 = bottom. */
|
|
3092
|
+
index: number;
|
|
3093
|
+
active: boolean;
|
|
3094
|
+
/** Display name (adjustment layers without a name show their kind). */
|
|
3095
|
+
label: string;
|
|
3096
|
+
/** Clipped to the layer below (drawn with an indent arrow). */
|
|
3097
|
+
clipped: boolean;
|
|
3098
|
+
}
|
|
3099
|
+
/** Rows top to bottom; children of collapsed groups are left out. */
|
|
3100
|
+
declare function layerPanelRows(layers: readonly ImageLayer[], activeId: string | null): LayerPanelRow[];
|
|
3101
|
+
declare function layerLabel(layer: ImageLayer): string;
|
|
3102
|
+
/** A short type badge for rows without a thumbnail. */
|
|
3103
|
+
declare function layerBadge(layer: ImageLayer): string;
|
|
3104
|
+
/** Where a row was dropped on: the top or bottom part of the row, or the middle of a group row. */
|
|
3105
|
+
type DropZone = 'above' | 'below' | 'inside';
|
|
3106
|
+
/** The zone for a pointer at `fraction` (0 top .. 1 bottom) of a row's height. */
|
|
3107
|
+
declare function dropZone(fraction: number, isGroup: boolean): DropZone;
|
|
3108
|
+
/** The placement for `move_layer` when `dragId` is dropped on row `targetId` in `zone`, or `null` for a no-op. */
|
|
3109
|
+
declare function dropPlacement(layers: readonly ImageLayer[], dragId: string, targetId: string, zone: DropZone): LayerPlacement | null;
|
|
3110
|
+
type LayerMenuAction = 'new-layer' | 'new-group' | 'duplicate' | 'delete' | 'group-selected' | 'ungroup' | 'merge-down' | 'merge-visible' | 'flatten' | 'via-copy' | 'via-cut' | 'add-mask' | 'add-mask-selection' | 'apply-mask' | 'delete-mask' | 'toggle-mask' | 'toggle-clip' | 'rasterize';
|
|
3111
|
+
interface LayerMenuItem {
|
|
3112
|
+
action: LayerMenuAction;
|
|
3113
|
+
label: string;
|
|
3114
|
+
enabled: boolean;
|
|
3115
|
+
}
|
|
3116
|
+
/** The layer menu for the controller's current state (active layer, selection). */
|
|
3117
|
+
declare function layerMenu(controller: ImageEditorController): LayerMenuItem[];
|
|
3118
|
+
/** Runs a menu action on the active layer. Resolves to the error message when it was refused. */
|
|
3119
|
+
declare function runLayerMenuAction(controller: ImageEditorController, action: LayerMenuAction): Promise<string | null>;
|
|
3120
|
+
|
|
3121
|
+
/**
|
|
3122
|
+
* Agent tools for painting: `paint_stroke` (brush or eraser along points, on pixels or a mask),
|
|
3123
|
+
* `fill_pixels` and `clear_pixels` (Edit › Fill / Clear inside the selection). Each is one undo
|
|
3124
|
+
* step and returns the layer, channel and changed bounds.
|
|
3125
|
+
*/
|
|
3126
|
+
declare function createImagePaintTools(controller: ImageEditorController): AgentTool[];
|
|
3127
|
+
|
|
3128
|
+
/**
|
|
3129
|
+
* The paint tools' view model, shared by the React and Svelte editors: the brush options bar's
|
|
3130
|
+
* controls, Photoshop's shortcuts (B, E, V, [ ], Shift+[ ], number keys, D, X) and a pointer
|
|
3131
|
+
* gesture that turns pointer events into strokes (Brush, Eraser) or layer moves (Move).
|
|
3132
|
+
*/
|
|
3133
|
+
|
|
3134
|
+
/** Controls of the brush options bar (`hardness`, `opacity`, `flow`, `smoothing` shown in %). */
|
|
3135
|
+
declare const BRUSH_OPTION_CONTROLS: readonly (ControlSpec & {
|
|
3136
|
+
id: 'size' | 'hardness' | 'opacity' | 'flow' | 'smoothing';
|
|
3137
|
+
})[];
|
|
3138
|
+
/** The paint tools in the toolbar. */
|
|
3139
|
+
declare const PAINT_TOOLS: readonly [{
|
|
3140
|
+
readonly id: "move";
|
|
3141
|
+
readonly label: "Move";
|
|
3142
|
+
readonly shortcut: "V";
|
|
3143
|
+
}, {
|
|
3144
|
+
readonly id: "brush";
|
|
3145
|
+
readonly label: "Brush";
|
|
3146
|
+
readonly shortcut: "B";
|
|
3147
|
+
}, {
|
|
3148
|
+
readonly id: "eraser";
|
|
3149
|
+
readonly label: "Eraser";
|
|
3150
|
+
readonly shortcut: "E";
|
|
3151
|
+
}];
|
|
3152
|
+
type PaintTool = (typeof PAINT_TOOLS)[number]['id'];
|
|
3153
|
+
declare const isPaintTool: (tool: string) => tool is PaintTool;
|
|
3154
|
+
interface ShortcutEvent {
|
|
3155
|
+
key: string;
|
|
3156
|
+
shiftKey?: boolean;
|
|
3157
|
+
ctrlKey?: boolean;
|
|
3158
|
+
metaKey?: boolean;
|
|
3159
|
+
altKey?: boolean;
|
|
3160
|
+
/** The event target: shortcuts are ignored while typing in inputs. */
|
|
3161
|
+
target?: unknown;
|
|
3162
|
+
}
|
|
3163
|
+
/**
|
|
3164
|
+
* Applies a paint shortcut. Returns true when it was one (the caller then prevents the default).
|
|
3165
|
+
* B / E / V choose the tool; [ and ] change the size, with Shift the hardness by 25 %; 1..9 set the
|
|
3166
|
+
* opacity to 10..90 % and 0 to 100 %; D resets the colours to black and white; X swaps them.
|
|
3167
|
+
*/
|
|
3168
|
+
declare function handlePaintShortcut(controller: ImageEditorController, e: ShortcutEvent): boolean;
|
|
3169
|
+
/** One pointer sample in document pixels. */
|
|
3170
|
+
interface PaintPointerSample extends ImagePoint {
|
|
3171
|
+
/** 0..1; a mouse is 1. */
|
|
3172
|
+
pressure: number;
|
|
3173
|
+
}
|
|
3174
|
+
/** Pressure of a pointer event: pens report it; mice report 0.5 while pressed, which means "full". */
|
|
3175
|
+
declare function pointerPressure(e: {
|
|
3176
|
+
pointerType?: string;
|
|
3177
|
+
pressure?: number;
|
|
3178
|
+
}): number;
|
|
3179
|
+
/**
|
|
3180
|
+
* Turns pointer events into strokes (Brush, Eraser on the active layer's target) or layer moves
|
|
3181
|
+
* (Move on the active pixel layer). `down` returns an error message when the tool cannot act.
|
|
3182
|
+
*/
|
|
3183
|
+
declare class PaintGesture {
|
|
3184
|
+
private readonly controller;
|
|
3185
|
+
private stroke;
|
|
3186
|
+
private move;
|
|
3187
|
+
/** The last refusal (e.g. "layer is locked"), for the editor to show. */
|
|
3188
|
+
error: string | null;
|
|
3189
|
+
constructor(controller: ImageEditorController);
|
|
3190
|
+
get active(): boolean;
|
|
3191
|
+
down(sample: PaintPointerSample): string | null;
|
|
3192
|
+
/** Feeds pointer samples (all coalesced events of one move, in order). */
|
|
3193
|
+
moveTo(samples: PaintPointerSample[]): void;
|
|
3194
|
+
up(): void;
|
|
3195
|
+
cancel(): void;
|
|
3196
|
+
}
|
|
3197
|
+
|
|
3198
|
+
/** A malformed or unsupported PSD; the message says what was wrong and where. */
|
|
3199
|
+
declare class PsdError extends Error {
|
|
3200
|
+
constructor(message: string);
|
|
3201
|
+
}
|
|
3202
|
+
|
|
3203
|
+
/**
|
|
3204
|
+
* Photoshop ActionDescriptors (the structured values inside `vibA`, `blwh` and other blocks):
|
|
3205
|
+
* read and write. Keys and class ids are 4-character codes, or longer strings.
|
|
3206
|
+
*/
|
|
3207
|
+
|
|
3208
|
+
interface DescClass {
|
|
3209
|
+
name: string;
|
|
3210
|
+
classId: string;
|
|
3211
|
+
}
|
|
3212
|
+
type ReferenceItem = {
|
|
3213
|
+
type: 'prop';
|
|
3214
|
+
class: DescClass;
|
|
3215
|
+
key: string;
|
|
3216
|
+
} | {
|
|
3217
|
+
type: 'Clss';
|
|
3218
|
+
class: DescClass;
|
|
3219
|
+
} | {
|
|
3220
|
+
type: 'Enmr';
|
|
3221
|
+
class: DescClass;
|
|
3222
|
+
typeId: string;
|
|
3223
|
+
value: string;
|
|
3224
|
+
} | {
|
|
3225
|
+
type: 'rele';
|
|
3226
|
+
class: DescClass;
|
|
3227
|
+
offset: number;
|
|
3228
|
+
} | {
|
|
3229
|
+
type: 'Idnt';
|
|
3230
|
+
class: DescClass;
|
|
3231
|
+
id: number;
|
|
3232
|
+
} | {
|
|
3233
|
+
type: 'indx';
|
|
3234
|
+
class: DescClass;
|
|
3235
|
+
index: number;
|
|
3236
|
+
} | {
|
|
3237
|
+
type: 'name';
|
|
3238
|
+
class: DescClass;
|
|
3239
|
+
name: string;
|
|
3240
|
+
};
|
|
3241
|
+
type DescValue = {
|
|
3242
|
+
type: 'obj ';
|
|
3243
|
+
items: ReferenceItem[];
|
|
3244
|
+
} | {
|
|
3245
|
+
type: 'Objc' | 'GlbO';
|
|
3246
|
+
value: Descriptor;
|
|
3247
|
+
} | {
|
|
3248
|
+
type: 'VlLs';
|
|
3249
|
+
items: DescValue[];
|
|
3250
|
+
} | {
|
|
3251
|
+
type: 'doub';
|
|
3252
|
+
value: number;
|
|
3253
|
+
} | {
|
|
3254
|
+
type: 'UntF';
|
|
3255
|
+
unit: string;
|
|
3256
|
+
value: number;
|
|
3257
|
+
} | {
|
|
3258
|
+
type: 'UnFl';
|
|
3259
|
+
unit: string;
|
|
3260
|
+
values: number[];
|
|
3261
|
+
} | {
|
|
3262
|
+
type: 'TEXT';
|
|
3263
|
+
value: string;
|
|
3264
|
+
} | {
|
|
3265
|
+
type: 'enum';
|
|
3266
|
+
typeId: string;
|
|
3267
|
+
value: string;
|
|
3268
|
+
} | {
|
|
3269
|
+
type: 'long';
|
|
3270
|
+
value: number;
|
|
3271
|
+
} | {
|
|
3272
|
+
type: 'comp';
|
|
3273
|
+
value: number;
|
|
3274
|
+
} | {
|
|
3275
|
+
type: 'bool';
|
|
3276
|
+
value: boolean;
|
|
3277
|
+
} | {
|
|
3278
|
+
type: 'type' | 'GlbC';
|
|
3279
|
+
class: DescClass;
|
|
3280
|
+
} | {
|
|
3281
|
+
type: 'alis' | 'Pth ' | 'tdta';
|
|
3282
|
+
data: Uint8Array;
|
|
3283
|
+
} | {
|
|
3284
|
+
type: 'ObAr';
|
|
3285
|
+
prefix: number;
|
|
3286
|
+
body: Descriptor;
|
|
3287
|
+
};
|
|
3288
|
+
interface Descriptor {
|
|
3289
|
+
name: string;
|
|
3290
|
+
classId: string;
|
|
3291
|
+
items: Array<[string, DescValue]>;
|
|
3292
|
+
}
|
|
3293
|
+
/** A versioned descriptor from the start of `bytes` (trailing bytes are ignored). */
|
|
3294
|
+
declare function parseVersionedDescriptor(bytes: Uint8Array): Descriptor;
|
|
3295
|
+
declare function versionedDescriptorBytes(d: Descriptor): Uint8Array;
|
|
3296
|
+
|
|
3297
|
+
/** Every adjustment block key Photoshop writes. */
|
|
3298
|
+
declare const ADJUSTMENT_KEYS: string[];
|
|
3299
|
+
/** Keys we read and write. */
|
|
3300
|
+
declare const SUPPORTED_ADJUSTMENT_KEYS: Record<string, AdjustmentKind>;
|
|
3301
|
+
type ParsedAdjustment = {
|
|
3302
|
+
[K in AdjustmentKind]: {
|
|
3303
|
+
kind: K;
|
|
3304
|
+
params: AdjustmentParamsMap[K];
|
|
3305
|
+
approximated?: string;
|
|
3306
|
+
};
|
|
3307
|
+
}[AdjustmentKind];
|
|
3308
|
+
/**
|
|
3309
|
+
* Our parameters for an adjustment block, or `null` when the key is not one of our kinds or the
|
|
3310
|
+
* block cannot be read.
|
|
3311
|
+
*/
|
|
3312
|
+
declare function parseAdjustmentBlock(key: string, data: Uint8Array): ParsedAdjustment | null;
|
|
3313
|
+
/** The PSD block (key and data) for one of our adjustment layers. */
|
|
3314
|
+
declare function writeAdjustmentBlock<K extends AdjustmentKind>(kind: K, params: AdjustmentParamsMap[K]): {
|
|
3315
|
+
key: string;
|
|
3316
|
+
data: Uint8Array;
|
|
3317
|
+
};
|
|
3318
|
+
|
|
3319
|
+
interface PsdExportInput {
|
|
3320
|
+
width: number;
|
|
3321
|
+
height: number;
|
|
3322
|
+
/** Prepared stack, bottom to top. */
|
|
3323
|
+
layers: readonly ImageLayer[];
|
|
3324
|
+
/** The composite, `width × height` RGBA, written as the merged image. */
|
|
3325
|
+
merged: ArrayLike<number>;
|
|
3326
|
+
/** Pixels per inch (default 72). */
|
|
3327
|
+
resolution?: number;
|
|
3328
|
+
}
|
|
3329
|
+
interface PsdExportResult {
|
|
3330
|
+
bytes: Uint8Array;
|
|
3331
|
+
psb: boolean;
|
|
3332
|
+
/** Layer records written (group folders and dividers included). */
|
|
3333
|
+
records: number;
|
|
3334
|
+
}
|
|
3335
|
+
/** Writes the prepared stack as PSD (or PSB) bytes. */
|
|
3336
|
+
declare function exportPsd(input: PsdExportInput): PsdExportResult;
|
|
3337
|
+
|
|
3338
|
+
/** Framework-free helpers behind the PSD buttons of the React and Svelte layer panels. */
|
|
3339
|
+
|
|
3340
|
+
/** Types the file pickers accept. */
|
|
3341
|
+
declare const PSD_FILE_ACCEPT = ".psd,.psb,image/vnd.adobe.photoshop,application/x-photoshop";
|
|
3342
|
+
/** Reads a picked file and opens it as the document (one undo step). Returns the import warnings. */
|
|
3343
|
+
declare function openPsdFile(controller: ImageEditorController, file: Blob): Promise<string[]>;
|
|
3344
|
+
/** A file name for the exported document: `name` with a `.psd` / `.psb` extension. */
|
|
3345
|
+
declare function psdFileName(name: string, psb: boolean): string;
|
|
3346
|
+
/**
|
|
3347
|
+
* Writes the document as a PSD and offers it as a download (in a browser). Returns the file
|
|
3348
|
+
* name and the export warnings.
|
|
3349
|
+
*/
|
|
3350
|
+
declare function downloadPsd(controller: ImageEditorController, name?: string): Promise<{
|
|
3351
|
+
fileName: string;
|
|
3352
|
+
warnings: string[];
|
|
3353
|
+
}>;
|
|
3354
|
+
|
|
3355
|
+
/** Base64 (or a data URL) → bytes, refusing anything that is not base64 text. */
|
|
3356
|
+
declare function psdBytesFromBase64(data: unknown): Uint8Array;
|
|
3357
|
+
/**
|
|
3358
|
+
* Agent tools for Photoshop files: `inspect_psd` (what a file holds and how it would map),
|
|
3359
|
+
* `import_psd` (open it as the document) and `export_psd` (the document as a PSD).
|
|
3360
|
+
*/
|
|
3361
|
+
declare function createImagePsdTools(controller: ImageEditorController): AgentTool[];
|
|
3362
|
+
|
|
3363
|
+
export { ADJUSTMENT_KEYS, ADJUSTMENT_KINDS, ADJUSTMENT_LAYER_CONTROLS, ADJUSTMENT_LAYER_OPACITY_CONTROL, ADJUSTMENT_LUT_SIZE, type AIResultOptions, AS_SHOT_KELVIN, type AdjustmentKind, type AdjustmentKindInfo, type AdjustmentLayer, type AdjustmentLayerBase, type AdjustmentLayerInit, type AdjustmentLayerMask, type AdjustmentLayerNode, type AdjustmentLayerOf, type AdjustmentLayerUpdate, type AdjustmentParamsMap, type Annotation, type AnnotationLayer, type AnnotationPlacement, type AnnotationType, type ArrowAnnotation, type AspectRatio, BACKGROUND_LAYER_ID, BACKGROUND_LAYER_NAME, BLUR_FILTER_ID, BRUSH_OPTION_CONTROLS, type BaseAnnotation, type BlackWhiteParams, BlendMode, type BlurFilter, BrushSettings, type Chromaticity, type CircleAnnotation, type ColorBalanceParams, type ColorBalanceTone, type ColorDistance, type ColorRangeOptions, type ColorRangeSample, CompositorOptions, type CompositorSources, type ControlSection, type ControlSpec, type ControlTrack, type CreateAnnotationPayload, type CropBox, type CropHandle, type CurvePoint, type CurvesParams, D50, D65, DEFAULT_ADJUSTMENTS, DEFAULT_DEPTH_MASK, DEFAULT_REFINE_EDGE_PARAMS, DEFAULT_SELECTION_TOOL_OPTIONS, DEFAULT_TRANSFORM, DEVELOP_FILTER_ID, type DepthMaskOptions, type DescValue, type Descriptor, type DeserializeContext, type DevelopFilter, type DevelopSettings, type DropZone, EMPTY_DISTANCE, type ExportOptions, type FillOptions, GUIDED_FILTER_EPS, type GestureModifiers, type GroupLayer, HISTOGRAM_BINS, HUE_RANGE_LABELS, type HistogramChannel, type HistoryEntryHandle, 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, type ImageEditorAssetStore, ImageEditorController, type ImageEditorDocumentLoad, type ImageEditorFit, type ImageEditorOptions, ImageEditorRenderer, type ImageEditorState, type ImageEditorTool, type ImageEditorToolProviderOptions, type ImageHistogram, type ImageLayer, type ImageLayerType, type ImagePoint, type ImageProcessVersion, type ImageProjection, type ImageTransform, type InpaintHook, type InpaintOptions, type InvertParams, LATEST_PROCESS_VERSION, LAYERED_SCHEMA_VERSION, LEGACY_PROCESS_VERSION, LUMA_709, type LayerBase, type LayerBlendMode, LayerCompositor, type LayerFilter, type LayerFilterKind, type LayerLocation, LayerLocks, type LayerMaskProps, type LayerMenuAction, type LayerMenuItem, LayerOperationError, type LayerPanelRow, type LayerPlacement, type LayerProperties, type LayerSourcesHost, type LayerStack, type LayerTarget, type LegacyParts, type LegacySerializedImageEditorState, type LegacyViewResult, type LevelsChannel, type LevelsParams, type LineAnnotation, MAX_KELVIN, MIN_KELVIN, MIRED_PER_TEMPERATURE_UNIT, type MagicWandOptions, type Matrix3, type MosaicImageDataLike, type MosaicRegion, PAINT_TOOLS, PSD_BLEND_KEYS, PSD_FILE_ACCEPT, PaintGesture, type PaintOptions, type PaintPointerSample, type PaintStrokeResult, PaintStrokeSession, type PaintTool, type ParsedAdjustment, type PenAnnotation, type PhotoFilterParams, type PixelBuffer, type PixelLayer, type PixelLayerInit, type PixelOp, PixelSurface, type PlaneLayout, type PosterizeParams, type PsdChannel, PsdError, type PsdExportInput, type PsdExportResult, type PsdFile, type PsdHeader, type PsdImportOptions, type PsdImportResult, type PsdLayerMask, type PsdLayerRecord, type PsdLayerSummary, type PsdRect, type PsdResource, type PsdTaggedBlock, type PsdTreeNode, type QuickMaskStyle, REFINE_EDGE_CONTROLS, type RasterMask, type RectAnnotation, type ReferenceItem, type RefineEdgeControl, type RefineEdgeParams, type RemoveBackgroundHook, type RemoveBackgroundOptions, type RenderOptions, type RouteInput, SELECTION_MODES, SELECTION_MODE_LABELS, SELECTION_MODIFY_OPS, SELECTION_TOOLS, SUPPORTED_ADJUSTMENT_KEYS, type SampleOptions, type SelectionChannel, type SelectionCommandOptions, SelectionGesture, type SelectionMask, type SelectionMode, type SelectionModifyOp, type SelectionToolKind, type SelectionToolOptions, type SerializeContext, type SerializedAdjustmentLayer, type SerializedAnnotationLayer, type SerializedGroupLayer, type SerializedImageEditorState, type SerializedLayer, type SerializedLayeredImageEditorState, type SerializedPixelLayer, type SerializedRasterMask, type SerializedSelection, type ShapeSelectionOptions, type ShortcutEvent, StrokeApply, StrokeCoverage, type StrokeInit, StrokePoint, TINT_SCALE, TONE_LUT_SIZE, TONE_RANGE_PRESETS, type TextAnnotation, type ThresholdParams, TiledSurface, type ToneRangePreset, type UnitLevels, VIBRANCE_GREY, type VibranceParams, type ViewportMetrics, XYZ_D50_TO_SRGB, activeAdjustmentLayers, addLayerFilter, addToHistogram, adjustmentKindLabel, adjustmentLayersKey, adjustmentNodeAsLayer, adjustmentNodeFromLegacy, annotationLayerFor, annotationLayerName, applyAdjustmentLayers, applyAdjustments, applyBoxBlur, applyDepthMask, applyImageProjectionToContext, applyLegacyAdjustments, applyMatrix3, applyOutputStage, applyProcess2Adjustments, applyRegionBlur, applyRegionMosaic, backgroundLayer, baseProjection, blackWhiteGray, blurFilter, borderCoverage, boxMean, boxToCurvePoint, bradfordAdaptation, buildLayerMaskPlanes, buildToneLut, calculateCropDrag, canvasToImagePoint, clampControlValue, clampCropToImage, colorBalanceChannel, colorRange, combineSelections, compileAdjustmentLayer, computeHistogram, computeSelectionBounds, contractCoverage, controlPosition, controlTrackBackground, coverageToByte, coveringRect, createAdjustmentLayer, createImageCaptureSurface, createImageEditTools, createImageEditorToolProvider, createImageLayerTools, createImagePaintTools, createImagePsdTools, createImageSelectionTools, createSelectionMask, curveLut, curveLutFromLevels, curvePointToBox, curveSvgPath, decodeLayerChannel, decodeLayerMask, decodeMergedImage, decodePlanes, decodePngDataUrl, decodeSelectionRle, defaultAdjustmentParams, depthMaskAlpha, depthRasterMask, describeLayer, describeSelection, deserializeLayer, deserializeLayers, deserializeSelection, developFilter, developFromAdjustments, developTarget, distanceTransform, downloadPsd, dropPlacement, dropZone, duplicateLayer, edgeWidth, ellipsePoints, ellipseSelection, emptyHistogram, encodeRle, encodeSelectionRle, encodeSurface, evaluateAdjustmentLayers, expandCoverage, exportPsd, featherCoverage, findAdjustmentControl, findLayerControl, formatControlValue, fullSelection, getAnnotationBounds, getControlPath, getCropCursor, getRotatedSize, getViewportMetrics, getViewportProjection, globalImageCache, greyMorphology, groupLayers, guidePlanes, guidedFilterColor, handlePaintShortcut, hasResampledLegacyMask, hashMaskContent, hexToRgb, histogramPath, hitTestAnnotation, hitTestCrop, hitTestCurvePoint, hslToRgb, hueRange, hueRangeTables, hueRangeWeight, hueSaturation, identityCurve, identityLevels, imageEditorStateMigrations, imageToCanvasPoint, importPsd, insertCurvePoint, invertMatrix3, invertSelection, isActiveFilter, isAdjustmentKind, isDefaultDepthMask, isLegacyShape, isPaintTool, isQuarterTurn, isQuarterTurnSwapped, isSelectionEmpty, isSelectionMode, isSpatialFilter, kelvinToTemperature, layerBadge, layerLabel, layerMaskCoverage, layerMaskFromSelection, layerMaskKey, layerMenu, layerName, layerPanelRows, layerTree, layerTypeLabel, layersFromLegacy, legacyAdjustmentLayer, legacyMaskOf, legacyView, levelsValue, linearSrgbToXy, linearToSrgb, loadImageEditorDocument, magicWand, mapCropHandle, maskSummary, migrateSerializedImageEditorState, migrateToLayeredState, modifySelection, moveCurvePoint, moveLayer, mulMatrix3, needsLegacyBase, neutralHueRange, newLayerId, normalizeAdjustmentLayer, normalizeAdjustmentLayers, normalizeAngle, normalizeFilter, normalizeLayerMask, normalizeProcessVersion, normalizeRect, normalizeRefineEdgeParams, normalizeStoredAdjustments, offsetLayer, openPsdFile, parseAdjustmentBlock, parseBlend, parseColor, parseSelectionMode, parseVersionedDescriptor, photoFilterMatrix, pixelLayerBounds, pixelLayers, placeLayer, pointerPressure, polygonCoverage, polygonSelection, posterizeValue, projectImagePoint, projectImageRect, projectMaskCoverage, projectQuarterTurn, psdBytesFromBase64, psdFileName, psdToLayers, quickMaskPixels, rangeLightness, rasterMaskFromLegacy, readAdjustmentControls, readPsd, rectSelection, refineCoverage, refineEdgeHalo, refineSelection, removeAlpha, removeCurvePoint, removeLayer, removeLayerFilter, renderLayeredBase, requireLayer, requireUnlocked, resizePixels, resizeSelection, resolveExternalAssets, resolveMosaicRegionBounds, rgbToGray, rgbToHsl, runLayerMenuAction, sampleLut, sampleToneLut, selectionArea, selectionFromCoverage, selectionFromPixels, selectionModeFromModifiers, selectionOutline, selectionToCoverage, selectionToPixels, selectionValueAt, serializeLayer, serializeLayers, serializeLayersExternal, serializeSelection, setControlPath, setLayerMask, setLayerProperties, shiftCoverage, smoothCoverage, splitOverlayAnnotations, srgb8ToLab, srgbToLinear, sumHistograms, tempTintToXy, temperatureToKelvin, toHex, toneCurve, toneLuts, toneRange, ungroupLayer, unionRect, unprojectCanvasPoint, updateLayerFilter, updateLayerMaskProps, uvToXy, versionedDescriptorBytes, vibranceLinear, vibrancePixel, wbMatrix, whiteBalanceFromSample, whiteBalanceMatrix, withNewIds, writeAdjustmentBlock, writePsd, xyToTempTint, xyToUv };
|