@pixerate/editor 0.95.0 → 0.96.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 +1 -0
- package/dist/{chunk-E2ILRYTJ.js → chunk-KFTQ2PKP.js} +18 -1
- package/dist/chunk-KFTQ2PKP.js.map +1 -0
- package/dist/{chunk-T6H3JDGA.cjs → chunk-T422YCHR.cjs} +18 -1
- package/dist/chunk-T422YCHR.cjs.map +1 -0
- package/dist/image-editor/index.cjs +1311 -315
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +98 -5
- package/dist/image-editor/index.d.ts +98 -5
- package/dist/image-editor/index.js +1081 -85
- package/dist/image-editor/index.js.map +1 -1
- package/dist/paint/index.d.cts +1 -1
- package/dist/paint/index.d.ts +1 -1
- package/dist/raster/index.cjs +2 -2
- package/dist/raster/index.d.cts +796 -5
- package/dist/raster/index.d.ts +796 -5
- package/dist/raster/index.js +1 -1
- package/dist/{surface-CgAiXVI3.d.cts → surface-DIA-XatS.d.cts} +1 -1
- package/dist/{surface-CgAiXVI3.d.ts → surface-DIA-XatS.d.ts} +1 -1
- package/package.json +1 -1
- package/skills/pixerate-image-editor/SKILL.md +13 -4
- package/dist/chunk-E2ILRYTJ.js.map +0 -1
- package/dist/chunk-T6H3JDGA.cjs.map +0 -1
- package/dist/zlib-B3LIoxF-.d.cts +0 -796
- package/dist/zlib-eiTEEj1z.d.ts +0 -796
package/dist/raster/index.d.cts
CHANGED
|
@@ -1,7 +1,732 @@
|
|
|
1
|
-
import { B as BlendMode } from '../surface-
|
|
2
|
-
export { a as BLEND_MODES, b as BlendModeInfo,
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { B as BlendMode, M as MaskSurface, P as PixelSurface, R as RasterRect, T as TiledSurface, h as TileKey } from '../surface-DIA-XatS.cjs';
|
|
2
|
+
export { a as BLEND_MODES, b as BlendModeInfo, c as Rgb, d as Rgba, S as SurfaceDraft, e as TILE, f as TILE_SHIFT, g as Tile, 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 mixPigment8, w as mixPigmentRgb, x as normalizeBlendMode, y as packRgba, z as readPixel, A as readRegion, C as setLum, D as solidSurface, E as surfaceBytes, F as surfaceFromPixels, G as surfacesEqual, H as tileCoord, I as tileKey, J as tileRect, K as tilesInRect, L as translateSurface, N as uniformTile, O as writeRegion } from '../surface-DIA-XatS.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Layer effects (Photoshop's layer styles) as data: drop and inner shadows, outer and inner
|
|
6
|
+
* glows, bevel & emboss, satin, colour / gradient / pattern overlays and strokes. Rendering lives
|
|
7
|
+
* in `./render`, PSD mapping in the image editor's PSD module.
|
|
8
|
+
*
|
|
9
|
+
* Angles are in degrees, counter-clockwise from 3 o'clock, and give the direction the light
|
|
10
|
+
* comes *from* (Photoshop's convention). Sizes and distances are in pixels, opacities and
|
|
11
|
+
* percentages in 0..1, colours are `#rrggbb`.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** One point of a contour curve (input → output, both 0..1). */
|
|
15
|
+
interface ContourPoint {
|
|
16
|
+
input: number;
|
|
17
|
+
output: number;
|
|
18
|
+
/** The curve bends sharply here instead of passing smoothly through (Photoshop's corner point). */
|
|
19
|
+
corner?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** A transfer curve applied to an effect's coverage. Missing on an effect = linear. */
|
|
22
|
+
interface EffectContour {
|
|
23
|
+
name: string;
|
|
24
|
+
points: ContourPoint[];
|
|
25
|
+
}
|
|
26
|
+
type GradientStyle = 'linear' | 'radial' | 'angle' | 'reflected' | 'diamond';
|
|
27
|
+
interface GradientColorStop {
|
|
28
|
+
/** 0..1 along the gradient. */
|
|
29
|
+
position: number;
|
|
30
|
+
color: string;
|
|
31
|
+
}
|
|
32
|
+
interface GradientOpacityStop {
|
|
33
|
+
position: number;
|
|
34
|
+
/** 0..1 */
|
|
35
|
+
opacity: number;
|
|
36
|
+
}
|
|
37
|
+
/** A gradient as overlays, gradient strokes and gradient glows paint it. */
|
|
38
|
+
interface EffectGradient {
|
|
39
|
+
stops: GradientColorStop[];
|
|
40
|
+
/** Missing or empty: opaque. */
|
|
41
|
+
opacityStops?: GradientOpacityStop[];
|
|
42
|
+
style: GradientStyle;
|
|
43
|
+
/** Degrees (90 = bottom to top). */
|
|
44
|
+
angle: number;
|
|
45
|
+
/** 1 = 100 %. */
|
|
46
|
+
scale: number;
|
|
47
|
+
reverse: boolean;
|
|
48
|
+
/** Align with the layer's bounds (else the canvas). */
|
|
49
|
+
align: boolean;
|
|
50
|
+
/** Centre offset as a fraction of the bounds. */
|
|
51
|
+
offset: {
|
|
52
|
+
x: number;
|
|
53
|
+
y: number;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** A pattern reference: the id of a document or built-in pattern (see `builtinPatternIds`). */
|
|
57
|
+
interface EffectPatternRef {
|
|
58
|
+
patternId: string;
|
|
59
|
+
/** Display name (PSD keeps it beside the id). */
|
|
60
|
+
name?: string;
|
|
61
|
+
/** 1 = 100 %. */
|
|
62
|
+
scale: number;
|
|
63
|
+
/** Rotation in degrees (counter-clockwise). */
|
|
64
|
+
angle?: number;
|
|
65
|
+
/** Tile from the layer's top-left ("Link with Layer", default) instead of the canvas origin. */
|
|
66
|
+
link?: boolean;
|
|
67
|
+
/** Origin offset in pixels. */
|
|
68
|
+
phase?: {
|
|
69
|
+
x: number;
|
|
70
|
+
y: number;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** What a stroke or glow paints with. */
|
|
74
|
+
type EffectFill = {
|
|
75
|
+
type: 'color';
|
|
76
|
+
color: string;
|
|
77
|
+
} | {
|
|
78
|
+
type: 'gradient';
|
|
79
|
+
gradient: EffectGradient;
|
|
80
|
+
} | ({
|
|
81
|
+
type: 'pattern';
|
|
82
|
+
} & EffectPatternRef);
|
|
83
|
+
interface EffectBase {
|
|
84
|
+
/** Unique within the layer. */
|
|
85
|
+
id: string;
|
|
86
|
+
enabled: boolean;
|
|
87
|
+
}
|
|
88
|
+
interface Blended {
|
|
89
|
+
blend: BlendMode;
|
|
90
|
+
/** 0..1 */
|
|
91
|
+
opacity: number;
|
|
92
|
+
}
|
|
93
|
+
interface DropShadowEffect extends EffectBase, Blended {
|
|
94
|
+
kind: 'drop-shadow';
|
|
95
|
+
color: string;
|
|
96
|
+
angle: number;
|
|
97
|
+
useGlobalLight: boolean;
|
|
98
|
+
distance: number;
|
|
99
|
+
/** 0..1 of the size grown solid before the blur. */
|
|
100
|
+
spread: number;
|
|
101
|
+
size: number;
|
|
102
|
+
contour?: EffectContour;
|
|
103
|
+
antiAlias: boolean;
|
|
104
|
+
/** 0..1 */
|
|
105
|
+
noise: number;
|
|
106
|
+
/** The layer hides the shadow beneath its see-through fill ("Layer Knocks Out Drop Shadow"). */
|
|
107
|
+
knocksOut: boolean;
|
|
108
|
+
}
|
|
109
|
+
interface InnerShadowEffect extends EffectBase, Blended {
|
|
110
|
+
kind: 'inner-shadow';
|
|
111
|
+
color: string;
|
|
112
|
+
angle: number;
|
|
113
|
+
useGlobalLight: boolean;
|
|
114
|
+
distance: number;
|
|
115
|
+
/** 0..1 of the size shrunk solid before the blur. */
|
|
116
|
+
choke: number;
|
|
117
|
+
size: number;
|
|
118
|
+
contour?: EffectContour;
|
|
119
|
+
antiAlias: boolean;
|
|
120
|
+
noise: number;
|
|
121
|
+
}
|
|
122
|
+
type GlowTechnique = 'softer' | 'precise';
|
|
123
|
+
interface OuterGlowEffect extends EffectBase, Blended {
|
|
124
|
+
kind: 'outer-glow';
|
|
125
|
+
/** Colour or gradient. */
|
|
126
|
+
fill: Extract<EffectFill, {
|
|
127
|
+
type: 'color' | 'gradient';
|
|
128
|
+
}>;
|
|
129
|
+
technique: GlowTechnique;
|
|
130
|
+
spread: number;
|
|
131
|
+
size: number;
|
|
132
|
+
contour?: EffectContour;
|
|
133
|
+
antiAlias: boolean;
|
|
134
|
+
/** 0..1 (default 0.5): the part of the glow the contour spans. */
|
|
135
|
+
range: number;
|
|
136
|
+
/** 0..1, varies a gradient glow's colours. Stored only (not rendered). */
|
|
137
|
+
jitter: number;
|
|
138
|
+
noise: number;
|
|
139
|
+
}
|
|
140
|
+
interface InnerGlowEffect extends EffectBase, Blended {
|
|
141
|
+
kind: 'inner-glow';
|
|
142
|
+
fill: Extract<EffectFill, {
|
|
143
|
+
type: 'color' | 'gradient';
|
|
144
|
+
}>;
|
|
145
|
+
technique: GlowTechnique;
|
|
146
|
+
choke: number;
|
|
147
|
+
size: number;
|
|
148
|
+
contour?: EffectContour;
|
|
149
|
+
antiAlias: boolean;
|
|
150
|
+
range: number;
|
|
151
|
+
jitter: number;
|
|
152
|
+
noise: number;
|
|
153
|
+
/** Glow from the edge inwards (default) or from the centre outwards. */
|
|
154
|
+
source: 'edge' | 'center';
|
|
155
|
+
}
|
|
156
|
+
type BevelStyle = 'inner-bevel' | 'outer-bevel' | 'emboss' | 'pillow-emboss' | 'stroke-emboss';
|
|
157
|
+
type BevelTechnique = 'smooth' | 'chisel-hard' | 'chisel-soft';
|
|
158
|
+
/** The Contour element of Bevel & Emboss: shapes the bevel's height profile. */
|
|
159
|
+
interface BevelContour {
|
|
160
|
+
contour: EffectContour;
|
|
161
|
+
/** 0..1 (default 0.5). Stored only. */
|
|
162
|
+
range: number;
|
|
163
|
+
antiAlias: boolean;
|
|
164
|
+
}
|
|
165
|
+
/** The Texture element of Bevel & Emboss: a pattern's luminance added to the height. */
|
|
166
|
+
interface BevelTexture extends EffectPatternRef {
|
|
167
|
+
/** -10..10 (1 = +100 %); negative carves the pattern in. */
|
|
168
|
+
depth: number;
|
|
169
|
+
invert: boolean;
|
|
170
|
+
}
|
|
171
|
+
interface BevelEmbossEffect extends EffectBase {
|
|
172
|
+
kind: 'bevel-emboss';
|
|
173
|
+
style: BevelStyle;
|
|
174
|
+
technique: BevelTechnique;
|
|
175
|
+
/** 0..10 (1 = 100 %). */
|
|
176
|
+
depth: number;
|
|
177
|
+
direction: 'up' | 'down';
|
|
178
|
+
size: number;
|
|
179
|
+
soften: number;
|
|
180
|
+
angle: number;
|
|
181
|
+
/** Light altitude in degrees (0..90). */
|
|
182
|
+
altitude: number;
|
|
183
|
+
useGlobalLight: boolean;
|
|
184
|
+
glossContour?: EffectContour;
|
|
185
|
+
highlightColor: string;
|
|
186
|
+
highlightBlend: BlendMode;
|
|
187
|
+
highlightOpacity: number;
|
|
188
|
+
shadowColor: string;
|
|
189
|
+
shadowBlend: BlendMode;
|
|
190
|
+
shadowOpacity: number;
|
|
191
|
+
/** Contour element (shapes the bevel's height profile), or missing when off. */
|
|
192
|
+
contourElement?: BevelContour;
|
|
193
|
+
/** Texture element, or missing when off. */
|
|
194
|
+
texture?: BevelTexture;
|
|
195
|
+
}
|
|
196
|
+
interface SatinEffect extends EffectBase, Blended {
|
|
197
|
+
kind: 'satin';
|
|
198
|
+
color: string;
|
|
199
|
+
angle: number;
|
|
200
|
+
distance: number;
|
|
201
|
+
size: number;
|
|
202
|
+
contour?: EffectContour;
|
|
203
|
+
antiAlias: boolean;
|
|
204
|
+
invert: boolean;
|
|
205
|
+
}
|
|
206
|
+
interface ColorOverlayEffect extends EffectBase, Blended {
|
|
207
|
+
kind: 'color-overlay';
|
|
208
|
+
color: string;
|
|
209
|
+
}
|
|
210
|
+
interface GradientOverlayEffect extends EffectBase, Blended {
|
|
211
|
+
kind: 'gradient-overlay';
|
|
212
|
+
gradient: EffectGradient;
|
|
213
|
+
dither: boolean;
|
|
214
|
+
}
|
|
215
|
+
interface PatternOverlayEffect extends EffectBase, Blended, EffectPatternRef {
|
|
216
|
+
kind: 'pattern-overlay';
|
|
217
|
+
}
|
|
218
|
+
type StrokePosition = 'outside' | 'inside' | 'center';
|
|
219
|
+
interface StrokeEffect extends EffectBase, Blended {
|
|
220
|
+
kind: 'stroke';
|
|
221
|
+
size: number;
|
|
222
|
+
position: StrokePosition;
|
|
223
|
+
fill: EffectFill;
|
|
224
|
+
}
|
|
225
|
+
/** One layer effect. Several of the same kind are allowed; the first listed of a kind is on top. */
|
|
226
|
+
type LayerEffect = DropShadowEffect | InnerShadowEffect | OuterGlowEffect | InnerGlowEffect | BevelEmbossEffect | SatinEffect | ColorOverlayEffect | GradientOverlayEffect | PatternOverlayEffect | StrokeEffect;
|
|
227
|
+
type LayerEffectKind = LayerEffect['kind'];
|
|
228
|
+
/** A layer's effects: the master switch, Layer Style › Scale Effects and the effect list. */
|
|
229
|
+
interface LayerEffects {
|
|
230
|
+
/** The master switch ("effects on"); `false` keeps the effects but renders none. */
|
|
231
|
+
enabled: boolean;
|
|
232
|
+
/** Scale Effects: multiplies every size, distance and pattern scale (1 = 100 %; missing = 1). */
|
|
233
|
+
scale?: number;
|
|
234
|
+
items: LayerEffect[];
|
|
235
|
+
/**
|
|
236
|
+
* The PSD block the effects were read from (`lfx2`, `lfxs` or `lmfx`), kept so export writes it
|
|
237
|
+
* back verbatim while the effects still map to the same values. Export regenerates it otherwise.
|
|
238
|
+
*/
|
|
239
|
+
psd?: {
|
|
240
|
+
key: string;
|
|
241
|
+
data: Uint8Array;
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/** The document-wide light that effects with `useGlobalLight` use. */
|
|
245
|
+
interface GlobalLight {
|
|
246
|
+
/** Degrees. */
|
|
247
|
+
angle: number;
|
|
248
|
+
/** Degrees. */
|
|
249
|
+
altitude: number;
|
|
250
|
+
}
|
|
251
|
+
declare const DEFAULT_GLOBAL_LIGHT: GlobalLight;
|
|
252
|
+
/** Every effect kind, in the order the Layer Style dialog lists them. */
|
|
253
|
+
declare const LAYER_EFFECT_KINDS: readonly LayerEffectKind[];
|
|
254
|
+
declare function layerEffectLabel(kind: LayerEffectKind): string;
|
|
255
|
+
declare function isLayerEffectKind(value: unknown): value is LayerEffectKind;
|
|
256
|
+
/** Photoshop's default black-to-white linear gradient. */
|
|
257
|
+
declare function defaultEffectGradient(): EffectGradient;
|
|
258
|
+
/** A fresh effect id. */
|
|
259
|
+
declare function newEffectId(): string;
|
|
260
|
+
/** An effect of `kind` with Photoshop's default settings. */
|
|
261
|
+
declare function defaultLayerEffect(kind: LayerEffectKind, id?: string): LayerEffect;
|
|
262
|
+
/** True when the master switch is on and at least one effect is enabled. */
|
|
263
|
+
declare function hasActiveEffects(effects: LayerEffects | undefined | null): effects is LayerEffects;
|
|
264
|
+
/** Maximum distance (px) an effect is rendered from the layer's shape. */
|
|
265
|
+
declare const MAX_EFFECT_REACH = 512;
|
|
266
|
+
/** How far (px, before Scale Effects) one effect paints beyond or into the layer's shape. */
|
|
267
|
+
declare function effectReach(e: LayerEffect): number;
|
|
268
|
+
/**
|
|
269
|
+
* Pixels an effect stack can reach beyond the layer's shape (its enabled effects, scaled), plus
|
|
270
|
+
* a little slack. 0 when no effect is active. Dirty areas and tile signatures grow by this.
|
|
271
|
+
*/
|
|
272
|
+
declare function effectsMargin(effects: LayerEffects | undefined | null): number;
|
|
273
|
+
/** Scale Effects as a usable factor (missing or invalid = 1). */
|
|
274
|
+
declare function effectsScale(effects: Pick<LayerEffects, 'scale'>): number;
|
|
275
|
+
/** `effect` with its sizes, distances and pattern scales multiplied by `s` (Scale Effects). */
|
|
276
|
+
declare function scaleLayerEffect<E extends LayerEffect>(e: E, s: number): E;
|
|
277
|
+
/** `#rrggbb` (or `#rgb`, `rrggbb`) as 0..1 RGB, or `null`. */
|
|
278
|
+
declare function parseEffectColor(value: unknown): [number, number, number] | null;
|
|
279
|
+
/** 0..1 RGB as `#rrggbb`. */
|
|
280
|
+
declare function effectColorHex(rgb: readonly number[]): string;
|
|
281
|
+
declare class LayerEffectError extends Error {
|
|
282
|
+
constructor(message: string);
|
|
283
|
+
}
|
|
284
|
+
declare function validateEffectGradient(v: unknown, path: string): void;
|
|
285
|
+
/** Every field an effect of `kind` has (required and optional), including `id` and `kind`. */
|
|
286
|
+
declare function layerEffectFields(kind: LayerEffectKind): string[];
|
|
287
|
+
/**
|
|
288
|
+
* Checks a complete effect (every field of its kind present and in range). Throws a
|
|
289
|
+
* {@link LayerEffectError} naming the first wrong field and how to fix it.
|
|
290
|
+
*/
|
|
291
|
+
declare function validateLayerEffect(v: unknown, path?: string): asserts v is LayerEffect;
|
|
292
|
+
/**
|
|
293
|
+
* Applies `changes` to `effect` and validates the result. `kind` and `id` cannot change. Nested
|
|
294
|
+
* objects (`fill`, `gradient`, `contour`, `texture`, `phase`, `offset`) are replaced whole; `null`
|
|
295
|
+
* removes an optional one (`contour`, `glossContour`, bevel `contour` / `texture`).
|
|
296
|
+
*/
|
|
297
|
+
declare function mergeLayerEffect(effect: LayerEffect, changes: Record<string, unknown>): LayerEffect;
|
|
298
|
+
/** A layer's effects with `items` validated; throws on the first bad effect. */
|
|
299
|
+
declare function validateLayerEffects(v: unknown): asserts v is LayerEffects;
|
|
300
|
+
/**
|
|
301
|
+
* Reads effects from JSON leniently: invalid effects are dropped (so one bad entry does not lose
|
|
302
|
+
* a document), and missing optional fields take their defaults. `null` when nothing usable.
|
|
303
|
+
*/
|
|
304
|
+
declare function normalizeLayerEffects(raw: unknown): LayerEffects | undefined;
|
|
305
|
+
/** Effects without ids or the PSD block, for comparing what two effect stacks render. */
|
|
306
|
+
declare function effectsFingerprint(effects: LayerEffects | undefined | null): string;
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Pattern paint for pattern overlays, pattern strokes and bevel textures: a tile repeated over
|
|
310
|
+
* the plane from an origin (the layer's top-left when linked, else the canvas origin, plus the
|
|
311
|
+
* phase), scaled and rotated about it. Samples are bilinear and wrap around, on premultiplied
|
|
312
|
+
* colour, so whole-pixel placements at 100 % reproduce the tile exactly.
|
|
313
|
+
*
|
|
314
|
+
* Patterns come from the document (PSD pattern resources) or from the built-in set below, so a
|
|
315
|
+
* pattern effect always has something to paint even in a document without patterns.
|
|
316
|
+
*/
|
|
317
|
+
/** A pattern tile: straight-alpha RGBA. */
|
|
318
|
+
interface EffectPattern {
|
|
319
|
+
id: string;
|
|
320
|
+
name: string;
|
|
321
|
+
width: number;
|
|
322
|
+
height: number;
|
|
323
|
+
data: Uint8ClampedArray;
|
|
324
|
+
}
|
|
325
|
+
/** A pattern converted once for sampling (premultiplied 0..1). */
|
|
326
|
+
declare class PatternTile {
|
|
327
|
+
readonly w: number;
|
|
328
|
+
readonly h: number;
|
|
329
|
+
private readonly px;
|
|
330
|
+
constructor(p: Pick<EffectPattern, 'width' | 'height' | 'data'>);
|
|
331
|
+
/** Bilinear wrapping sample at tile coordinates (pixel centres at `i + 0.5`), straight alpha into `out`. */
|
|
332
|
+
sample(u: number, v: number, out: Float32Array | number[]): void;
|
|
333
|
+
}
|
|
334
|
+
/** Where a pattern sits: maps a document point to tile coordinates. */
|
|
335
|
+
declare class PatternPlacement {
|
|
336
|
+
private readonly ox;
|
|
337
|
+
private readonly oy;
|
|
338
|
+
private readonly c;
|
|
339
|
+
private readonly s;
|
|
340
|
+
private readonly inv;
|
|
341
|
+
/** `anchor`: the layer's top-left (used when `link`); `phase` in px; `scale` a fraction; `angle` degrees counter-clockwise. */
|
|
342
|
+
constructor(anchor: {
|
|
343
|
+
x: number;
|
|
344
|
+
y: number;
|
|
345
|
+
}, link: boolean, phase: {
|
|
346
|
+
x: number;
|
|
347
|
+
y: number;
|
|
348
|
+
}, scale: number, angle: number);
|
|
349
|
+
/** Tile coordinates of the document point `(x, y)` into `out[0..1]`. */
|
|
350
|
+
map(x: number, y: number, out: number[]): void;
|
|
351
|
+
}
|
|
352
|
+
/** Ids of the built-in patterns (`checker`, `stripes`, `dots`, `grid`, `noise`). */
|
|
353
|
+
declare function builtinPatternIds(): string[];
|
|
354
|
+
/** A built-in pattern by id, or `null`. */
|
|
355
|
+
declare function builtinPattern(id: string): EffectPattern | null;
|
|
356
|
+
/**
|
|
357
|
+
* Deterministic per-pixel value in 0..1 hashed from document coordinates, so effect noise is
|
|
358
|
+
* stable across renders and tiles (photocraft's `hash_noise`).
|
|
359
|
+
*/
|
|
360
|
+
declare function hashNoise(x: number, y: number): number;
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* A layer stack that is not specific to any editor: pixel layers on tiled surfaces, groups (with
|
|
364
|
+
* pass-through), raster masks with density and feather, clipping, locks, opacity, fill and blend
|
|
365
|
+
* modes, plus pure tree helpers. Editors extend these types with their own layer kinds (the image
|
|
366
|
+
* editor adds adjustment and annotation layers, filters and parametric masks).
|
|
367
|
+
*
|
|
368
|
+
* Layer objects are immutable: every change builds new objects along the path from the root to
|
|
369
|
+
* the changed layer and shares everything else.
|
|
370
|
+
*/
|
|
371
|
+
|
|
372
|
+
/** Blend modes of a layer; groups also accept `pass-through`. */
|
|
373
|
+
type GroupBlendMode = BlendMode | 'pass-through';
|
|
374
|
+
interface LayerLocks {
|
|
375
|
+
/** Painting and filling are refused. */
|
|
376
|
+
pixels?: boolean;
|
|
377
|
+
/** Painting keeps each pixel's alpha. */
|
|
378
|
+
transparency?: boolean;
|
|
379
|
+
/** Moving (offset) is refused. */
|
|
380
|
+
position?: boolean;
|
|
381
|
+
/** Everything above, plus property changes and deletion. */
|
|
382
|
+
all?: boolean;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* A layer mask: 8-bit coverage (255 reveals, 0 hides) on a tiled surface, plus non-destructive
|
|
386
|
+
* density and feather. `source` is an editor-defined parametric mask (generated instead of
|
|
387
|
+
* painted; the compositor asks its profile for the coverage, and the surface is unused).
|
|
388
|
+
*/
|
|
389
|
+
interface RasterMask<Source = unknown> {
|
|
390
|
+
surface: MaskSurface;
|
|
391
|
+
/** Value outside the painted tiles (PSD's default colour); equals `surface.defaultValue`. */
|
|
392
|
+
defaultValue: 0 | 255;
|
|
393
|
+
/** 0..1 (missing = 1): at 0.5 hidden areas still show half. */
|
|
394
|
+
density?: number;
|
|
395
|
+
/** Gaussian σ in pixels (missing = 0). */
|
|
396
|
+
feather?: number;
|
|
397
|
+
/** `false` keeps the mask but ignores it. */
|
|
398
|
+
enabled?: boolean;
|
|
399
|
+
source?: Source;
|
|
400
|
+
}
|
|
401
|
+
interface RasterLayerBase {
|
|
402
|
+
id: string;
|
|
403
|
+
name: string;
|
|
404
|
+
visible: boolean;
|
|
405
|
+
/** 0..1 */
|
|
406
|
+
opacity: number;
|
|
407
|
+
blend: BlendMode;
|
|
408
|
+
/** Clip to the nearest unclipped layer below (Photoshop's clipping mask). */
|
|
409
|
+
clipped?: boolean;
|
|
410
|
+
mask?: RasterMask;
|
|
411
|
+
locks?: LayerLocks;
|
|
412
|
+
/** Live layer effects (drop shadow, stroke, …), rendered between the content and its blend. */
|
|
413
|
+
effects?: LayerEffects;
|
|
414
|
+
}
|
|
415
|
+
interface RasterPixelLayer extends RasterLayerBase {
|
|
416
|
+
type: 'pixel';
|
|
417
|
+
/** Pixels in layer space; document position = layer position + `offset`. A mask moves with it. */
|
|
418
|
+
surface: PixelSurface;
|
|
419
|
+
/** Integer move without re-tiling. */
|
|
420
|
+
offset: {
|
|
421
|
+
x: number;
|
|
422
|
+
y: number;
|
|
423
|
+
};
|
|
424
|
+
/** 0..1, PSD "Fill" (missing = 1). */
|
|
425
|
+
fillOpacity?: number;
|
|
426
|
+
}
|
|
427
|
+
interface RasterGroupLayer<L = RasterLayer> extends Omit<RasterLayerBase, 'blend'> {
|
|
428
|
+
type: 'group';
|
|
429
|
+
blend: GroupBlendMode;
|
|
430
|
+
/** Bottom to top. */
|
|
431
|
+
children: L[];
|
|
432
|
+
/** UI only. */
|
|
433
|
+
collapsed?: boolean;
|
|
434
|
+
}
|
|
435
|
+
/** The plain stack: pixel layers and groups. */
|
|
436
|
+
type RasterLayer = RasterPixelLayer | RasterGroupLayer<RasterLayer>;
|
|
437
|
+
/** What the tree helpers need of a layer: an id, a type, and `children` on groups. */
|
|
438
|
+
interface RasterNode {
|
|
439
|
+
id: string;
|
|
440
|
+
type: string;
|
|
441
|
+
}
|
|
442
|
+
/** The group members of a layer union. */
|
|
443
|
+
type GroupIn<T> = Extract<T, {
|
|
444
|
+
type: 'group';
|
|
445
|
+
}>;
|
|
446
|
+
interface LayerLocation<T extends RasterNode = RasterLayer> {
|
|
447
|
+
layer: T;
|
|
448
|
+
/** The containing group, or `null` at the top level. */
|
|
449
|
+
parent: GroupIn<T> | null;
|
|
450
|
+
/** Index within the parent's children (or the top-level list). */
|
|
451
|
+
index: number;
|
|
452
|
+
/** Ancestors from the top level down to the parent. */
|
|
453
|
+
path: GroupIn<T>[];
|
|
454
|
+
}
|
|
455
|
+
/** Every layer, depth first, bottom to top (a group comes before its children). */
|
|
456
|
+
declare function flattenLayers<T extends RasterNode>(layers: readonly T[]): T[];
|
|
457
|
+
declare function findLayer<T extends RasterNode>(layers: readonly T[], id: string): LayerLocation<T> | null;
|
|
458
|
+
/** Replaces the layer with `id` by `fn(layer)` (or removes it when `fn` returns `null`). */
|
|
459
|
+
declare function mapLayer<T extends RasterNode>(layers: readonly T[], id: string, fn: (layer: T) => T | null): T[];
|
|
460
|
+
/** Inserts `layer` into `parentId`'s children (or the top level) at `index` (default: top). */
|
|
461
|
+
declare function insertLayer<T extends RasterNode>(layers: readonly T[], layer: T, parentId: string | null, index?: number): T[];
|
|
462
|
+
declare function isLayerLocked(layer: {
|
|
463
|
+
locks?: LayerLocks;
|
|
464
|
+
}, what: keyof LayerLocks): boolean;
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* The per-tile layer compositor engine. Composites a layer stack (pixel layers and groups with
|
|
468
|
+
* masks, clipping, blend modes, opacity, fill and pass-through) tile by tile in document space,
|
|
469
|
+
* in pure TypeScript, so results are deterministic and testable in Node and Workers.
|
|
470
|
+
*
|
|
471
|
+
* Editors add their own layer kinds through a {@link CompositorProfile}: layers that filter
|
|
472
|
+
* what is below them (adjustment layers), content layers drawn by the editor (annotations),
|
|
473
|
+
* per-layer pixel filters, and parametric mask sources.
|
|
474
|
+
*
|
|
475
|
+
* Caches:
|
|
476
|
+
* - Each top-level *step* (a content layer and the layers clipped to it, a run of filter layers,
|
|
477
|
+
* a group) has a per-tile *signature*: its properties plus the identity of every surface tile
|
|
478
|
+
* it reads. A tile whose signatures are unchanged returns the cached result (same buffer
|
|
479
|
+
* object, so callers can skip uploading it).
|
|
480
|
+
* - A prefix cache keeps the accumulator *before* the step that changed last time (and, when the
|
|
481
|
+
* caller names it, before the active layer). Dragging a slider on layer k, or a stroke on layer
|
|
482
|
+
* k, recomposites from step k upwards only; `dirty` rectangles limit that to where it changed.
|
|
483
|
+
* - Spatial filters and feathered or parametric masks are computed once over the canvas and
|
|
484
|
+
* cached by the identity of their inputs.
|
|
485
|
+
* - Layer effects: a layer's effect maps (shadow, glow, bevel, stroke distance fields) are built
|
|
486
|
+
* once over the layer's region (its bounds grown by the effects' margin, within the canvas grown
|
|
487
|
+
* the same) and cached by the identity of every surface tile the shape reads; tiles crop them.
|
|
488
|
+
* A tile's signature then reads the layer within the margin around it (or the whole region when
|
|
489
|
+
* an effect is laid out over the layer's bounds), and `dirty` rectangles grow by the margin.
|
|
490
|
+
*/
|
|
491
|
+
|
|
492
|
+
/** What the compositor needs from its host besides the layers. */
|
|
493
|
+
interface RasterSources {
|
|
494
|
+
/** Canvas (document) size: spatial filters and mask feathering clamp at this rect. */
|
|
495
|
+
width: number;
|
|
496
|
+
height: number;
|
|
497
|
+
/** The pixels of a pixel layer (lets a host resolve layers whose pixels live elsewhere). */
|
|
498
|
+
surfaceOf?(layer: CompositorLayer): PixelSurface;
|
|
499
|
+
/** Changes whenever one of the host's callbacks would return something new for the same layers. */
|
|
500
|
+
version?: number | string;
|
|
501
|
+
/** The document's global light for effects that use it (default angle 120°, altitude 30°). */
|
|
502
|
+
globalLight?: GlobalLight;
|
|
503
|
+
/** A document pattern by id for pattern effects (built-in patterns are found without it). */
|
|
504
|
+
pattern?(id: string): EffectPattern | null;
|
|
505
|
+
}
|
|
506
|
+
/** The fields the engine reads; editor layer types are wider. */
|
|
507
|
+
interface CompositorLayer extends RasterNode {
|
|
508
|
+
visible: boolean;
|
|
509
|
+
opacity: number;
|
|
510
|
+
blend: string;
|
|
511
|
+
clipped?: boolean;
|
|
512
|
+
mask?: RasterMask;
|
|
513
|
+
/** Pixel layers. */
|
|
514
|
+
surface?: PixelSurface;
|
|
515
|
+
offset?: {
|
|
516
|
+
x: number;
|
|
517
|
+
y: number;
|
|
518
|
+
};
|
|
519
|
+
fillOpacity?: number;
|
|
520
|
+
/** Layer effects. */
|
|
521
|
+
effects?: LayerEffects;
|
|
522
|
+
/** Groups. */
|
|
523
|
+
children?: readonly CompositorLayer[];
|
|
524
|
+
}
|
|
525
|
+
/** A pixel layer's filters as the engine runs them. */
|
|
526
|
+
interface PixelFilterSpec {
|
|
527
|
+
/** Identifies the settings (part of the cache key). */
|
|
528
|
+
key: string;
|
|
529
|
+
/** Needs neighbouring pixels: runs once over the canvas instead of per tile. */
|
|
530
|
+
spatial: boolean;
|
|
531
|
+
/** Filters RGBA `data` (`width × height`) in place. */
|
|
532
|
+
apply(data: Uint8ClampedArray, width: number, height: number): void;
|
|
533
|
+
}
|
|
534
|
+
/** How an editor's own layer kinds composite. Every hook is optional. */
|
|
535
|
+
interface CompositorProfile<L extends CompositorLayer, S extends RasterSources> {
|
|
536
|
+
/** Layers that change what is below them; adjacent ones run as one step. */
|
|
537
|
+
isFilterLayer?(layer: L): boolean;
|
|
538
|
+
/** Applies a run of visible filter layers to `acc` (RGBA over `r`); `coverage` holds masked ones by id. */
|
|
539
|
+
applyFilterRun?(layers: L[], acc: Uint8ClampedArray, r: RasterRect, coverage: Map<string, Float32Array> | undefined, sources: S): void;
|
|
540
|
+
/** RGBA of a content layer that is neither a pixel layer nor a group, over `r`, or `null`. */
|
|
541
|
+
contentTile?(layer: L, r: RasterRect, sources: S): Uint8ClampedArray | null;
|
|
542
|
+
/** The blend mode a content layer draws with (default `layer.blend`). */
|
|
543
|
+
contentBlend?(layer: L): BlendMode;
|
|
544
|
+
/** Properties of a layer beyond the generic ones that change its pixels (part of its signature). */
|
|
545
|
+
layerKey?(layer: L): unknown;
|
|
546
|
+
/** Active filters of a pixel layer, or `null`. */
|
|
547
|
+
pixelFilters?(layer: L): PixelFilterSpec | null;
|
|
548
|
+
/** Canvas coverage (0..1, `width × height`) of a parametric mask source, or `null` to reveal all. */
|
|
549
|
+
maskSourcePlane?(source: unknown, width: number, height: number, sources: S): Float32Array | null;
|
|
550
|
+
}
|
|
551
|
+
interface CompositorOptions {
|
|
552
|
+
/** Upper bound for cached tile buffers (default 256 MiB). */
|
|
553
|
+
maxCacheBytes?: number;
|
|
554
|
+
}
|
|
555
|
+
interface CompositeCallOptions {
|
|
556
|
+
/**
|
|
557
|
+
* The layer about to be edited (the active layer): every tile composited in this call keeps a
|
|
558
|
+
* checkpoint below its step, so strokes and slider drags on it start there.
|
|
559
|
+
*/
|
|
560
|
+
checkpointLayerId?: string | null;
|
|
561
|
+
/**
|
|
562
|
+
* Where the layers changed since the previous call, when the caller knows (a stroke's dabs).
|
|
563
|
+
* Changed tiles are then recomposited only inside these rectangles. Changes outside them would
|
|
564
|
+
* be missed, so pass nothing when unsure.
|
|
565
|
+
*/
|
|
566
|
+
dirty?: RasterRect[];
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Blends straight-alpha `src` over `dst` (both RGBA) in place with `mode`, scaling the source
|
|
570
|
+
* alpha by `alpha` and, per pixel, by `coverage`. Same maths as `blendPixel` (including the
|
|
571
|
+
* `pigment` paint mix, which caches each 8-bit colour's spectrum).
|
|
572
|
+
*/
|
|
573
|
+
declare function blendTile(dst: Uint8ClampedArray, src: ArrayLike<number>, mode: BlendMode, alpha: number, coverage: ArrayLike<number> | null): void;
|
|
574
|
+
/** Statistics of the last `composite` call (for benchmarks and tests). */
|
|
575
|
+
interface CompositeStats {
|
|
576
|
+
tiles: number;
|
|
577
|
+
/** Tiles returned straight from the cache. */
|
|
578
|
+
cached: number;
|
|
579
|
+
/** Steps actually run, summed over tiles. */
|
|
580
|
+
stepsRun: number;
|
|
581
|
+
}
|
|
582
|
+
declare class RasterCompositor<L extends CompositorLayer = CompositorLayer, S extends RasterSources = RasterSources> {
|
|
583
|
+
private readonly profile;
|
|
584
|
+
private readonly tiles;
|
|
585
|
+
private readonly maxCacheBytes;
|
|
586
|
+
private cacheBytes;
|
|
587
|
+
private stamp;
|
|
588
|
+
private sources;
|
|
589
|
+
private sourcesVersion;
|
|
590
|
+
private filteredCache;
|
|
591
|
+
private planeCache;
|
|
592
|
+
private planeIds;
|
|
593
|
+
private nextPlaneId;
|
|
594
|
+
private contentCache;
|
|
595
|
+
private readonly stepsCache;
|
|
596
|
+
private readonly propsKeyCache;
|
|
597
|
+
/** Effect maps by layer id (see the module comment), least recently used first. */
|
|
598
|
+
private effectCache;
|
|
599
|
+
/** Effect maps already validated in this call, by layer object. */
|
|
600
|
+
private effectMemo;
|
|
601
|
+
private readonly patternTiles;
|
|
602
|
+
private readonly reachCache;
|
|
603
|
+
private fxContext;
|
|
604
|
+
lastStats: CompositeStats;
|
|
605
|
+
private hint;
|
|
606
|
+
constructor(profile?: CompositorProfile<L, S>, options?: CompositorOptions);
|
|
607
|
+
/** Drops every cached tile and plane. */
|
|
608
|
+
clear(): void;
|
|
609
|
+
private setSources;
|
|
610
|
+
/** The composite of `layers` over `rect` as `rect.width × rect.height` RGBA (straight alpha). */
|
|
611
|
+
composite(layers: readonly L[], rect: RasterRect, sources: S, options?: CompositeCallOptions): Uint8ClampedArray;
|
|
612
|
+
/**
|
|
613
|
+
* Composites every tile intersecting `rect` and calls `onTile` with each tile's RGBA buffer
|
|
614
|
+
* (TILE × TILE). A tile whose inputs did not change since the last call returns the same buffer
|
|
615
|
+
* object; never mutate it.
|
|
616
|
+
*/
|
|
617
|
+
compositeTiles(layers: readonly L[], rect: RasterRect, sources: S, onTile: (tx: number, ty: number, data: Uint8ClampedArray, changed: boolean) => void, options?: CompositeCallOptions): void;
|
|
618
|
+
/** The composite of one tile (cached; do not mutate the result). */
|
|
619
|
+
tile(layers: readonly L[], tx: number, ty: number, sources: S): Uint8ClampedArray;
|
|
620
|
+
/**
|
|
621
|
+
* A layer's effective mask coverage (0..1, after density, feather or parametric evaluation)
|
|
622
|
+
* over `r` in document space, or `null` when it reveals all of `r`.
|
|
623
|
+
*/
|
|
624
|
+
maskCoverage(layer: L, r: RasterRect, sources: S): Float32Array | null;
|
|
625
|
+
private isFilter;
|
|
626
|
+
/**
|
|
627
|
+
* Groups a layer list into compositing steps: clipped layers join the nearest unclipped
|
|
628
|
+
* content or group layer below; consecutive unclipped filter layers form one run.
|
|
629
|
+
*/
|
|
630
|
+
private buildSteps;
|
|
631
|
+
/** The index of the top-level step that holds layer `id` (searching groups and clipped layers), or -1. */
|
|
632
|
+
private stepIndexOf;
|
|
633
|
+
/** Properties of a layer that change pixels, minus its surfaces (memoised per object). */
|
|
634
|
+
private propsKey;
|
|
635
|
+
private compositeTile;
|
|
636
|
+
private entryBytes;
|
|
637
|
+
private evict;
|
|
638
|
+
private stepSig;
|
|
639
|
+
private layerSig;
|
|
640
|
+
private groupSig;
|
|
641
|
+
private plainGroupSig;
|
|
642
|
+
private contentSig;
|
|
643
|
+
private plainContentSig;
|
|
644
|
+
private hasEffects;
|
|
645
|
+
/** The largest effects margin of any visible layer in the stack (memoised per root). */
|
|
646
|
+
private effectsReach;
|
|
647
|
+
private effectContext;
|
|
648
|
+
/**
|
|
649
|
+
* Where a layer's effect maps are built: its bounds (pixel layers; the canvas otherwise) grown by
|
|
650
|
+
* the effects' margin, within the canvas grown the same.
|
|
651
|
+
*/
|
|
652
|
+
private effectRegion;
|
|
653
|
+
/** The surface tiles (and mask refs) a layer's shape reads over `region`. */
|
|
654
|
+
private shapeRefs;
|
|
655
|
+
private lightKey;
|
|
656
|
+
/**
|
|
657
|
+
* The signature of a layer with effects for tile (tx, ty): its properties and the tiles its shape
|
|
658
|
+
* reads within the effects' margin around the tile, or over its whole region when an effect is
|
|
659
|
+
* laid out over the layer's bounds.
|
|
660
|
+
*/
|
|
661
|
+
private effectSig;
|
|
662
|
+
/** A layer's effect maps over its region (cached; see the module comment). */
|
|
663
|
+
private effectMapsOf;
|
|
664
|
+
/** A layer's alpha over `r` after its mask (0..1, quantised to bytes as tiles see it). */
|
|
665
|
+
private layerShape;
|
|
666
|
+
/** A content or group layer's own pixels over `r` with its mask applied to alpha, or `null` when empty. */
|
|
667
|
+
private ownPixels;
|
|
668
|
+
/**
|
|
669
|
+
* The part of `r` a layer with effects can change: its shape's bounds grown by the effects'
|
|
670
|
+
* margin. Beyond it the layer and every effect are transparent, so the backdrop stays as it is.
|
|
671
|
+
*/
|
|
672
|
+
private effectArea;
|
|
673
|
+
/**
|
|
674
|
+
* Composites `layer`'s pixels (with `clipped` applied) and its effects onto `acc` (RGBA over `r`),
|
|
675
|
+
* only where they can reach. `keepAlpha`: clipped layers keep the base's alpha.
|
|
676
|
+
*/
|
|
677
|
+
private compositeEffects;
|
|
678
|
+
/** Composites a layer with active effects onto `acc` over `r`; returns whether `acc` is still empty. */
|
|
679
|
+
private runEffectStep;
|
|
680
|
+
private maskRefs;
|
|
681
|
+
/**
|
|
682
|
+
* A pixel layer's pixels after spatial filters: the surface and the offset to apply. Layers
|
|
683
|
+
* with a spatial filter are filtered once over the canvas (in document space, offset 0).
|
|
684
|
+
*/
|
|
685
|
+
private layerPixels;
|
|
686
|
+
/** RGBA of a content layer over `r` (document space, inside one tile), or `null` when it has nothing there. */
|
|
687
|
+
private contentTile;
|
|
688
|
+
private planeKey;
|
|
689
|
+
/** Canvas-sized coverage of a feathered or parametric mask (cached). */
|
|
690
|
+
private planeFor;
|
|
691
|
+
private maskTile;
|
|
692
|
+
/** Runs one step onto `acc`; returns whether `acc` is still empty. */
|
|
693
|
+
private runStep;
|
|
694
|
+
private runSteps;
|
|
695
|
+
private contentBlend;
|
|
696
|
+
private blendOnto;
|
|
697
|
+
private applyClipped;
|
|
698
|
+
private applyFilterRun;
|
|
699
|
+
}
|
|
700
|
+
/** Tiles that differ between two surfaces (by tile identity), as tile keys. */
|
|
701
|
+
declare function changedTiles(a: TiledSurface, b: TiledSurface): TileKey[];
|
|
702
|
+
|
|
703
|
+
/** Above this σ a Gaussian is approximated by three box passes (cost independent of σ). */
|
|
704
|
+
declare const DIRECT_GAUSSIAN_MAX_SIGMA = 8;
|
|
705
|
+
/** How a blur treats pixels beyond the image: `zero`, or `clamp` (replicate the border). */
|
|
706
|
+
type BlurEdge = 'zero' | 'clamp';
|
|
707
|
+
type Edge = BlurEdge;
|
|
708
|
+
/**
|
|
709
|
+
* Separable Gaussian blur of a single-channel float image. `edge` `zero` treats pixels beyond
|
|
710
|
+
* the image as 0 (selection feather), `clamp` replicates the border (mask refinement). σ up to
|
|
711
|
+
* {@link DIRECT_GAUSSIAN_MAX_SIGMA} is convolved directly; wider blurs use three box passes, so
|
|
712
|
+
* the cost per pixel never grows with σ.
|
|
713
|
+
*/
|
|
714
|
+
declare function gaussianBlur(src: ArrayLike<number>, w: number, h: number, sigma: number, edge?: Edge): Float32Array;
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* Curve lookup tables shared by Curves adjustments and layer-effect contours.
|
|
718
|
+
*/
|
|
719
|
+
/** Entries of a curve LUT (input 0..1 in `size - 1` steps). */
|
|
720
|
+
declare const CURVE_LUT_SIZE = 4096;
|
|
721
|
+
/**
|
|
722
|
+
* Photoshop curve: a natural cubic spline through the points (0..1 in and out; it may overshoot
|
|
723
|
+
* between points, as Photoshop's does), constant outside the first / last point, clamped to
|
|
724
|
+
* 0..1, sampled into a LUT. Fewer than two distinct points: the identity.
|
|
725
|
+
*/
|
|
726
|
+
declare function curveLut(points: ReadonlyArray<{
|
|
727
|
+
input: number;
|
|
728
|
+
output: number;
|
|
729
|
+
}>, size?: number): Float32Array;
|
|
5
730
|
|
|
6
731
|
/**
|
|
7
732
|
* CPU renderer for layer effects.
|
|
@@ -113,4 +838,70 @@ declare function renderLayerEffects(effects: LayerEffects, layer: {
|
|
|
113
838
|
fillOpacity?: number;
|
|
114
839
|
}, backdrop: Uint8ClampedArray, canvas: EffectRect, ctx: EffectContext): void;
|
|
115
840
|
|
|
116
|
-
|
|
841
|
+
/**
|
|
842
|
+
* Dependency-free, synchronous PNG encode / decode for layer pixels and masks, plus base64 and
|
|
843
|
+
* data-URL helpers. Canvas `toDataURL` is lossy for partly transparent pixels (it goes through
|
|
844
|
+
* premultiplied alpha), so layer assets use this codec and round-trip exactly.
|
|
845
|
+
*
|
|
846
|
+
* Encodes 8-bit greyscale (masks) or RGBA (layers). Decodes non-interlaced 1/2/4/8/16-bit
|
|
847
|
+
* greyscale, RGB, palette, grey + alpha and RGBA, always to 8-bit RGBA or grey.
|
|
848
|
+
*/
|
|
849
|
+
interface DecodedPng {
|
|
850
|
+
width: number;
|
|
851
|
+
height: number;
|
|
852
|
+
/** 4 for RGBA output, 1 for greyscale without alpha when `keepGray` was asked for. */
|
|
853
|
+
channels: 1 | 4;
|
|
854
|
+
data: Uint8ClampedArray;
|
|
855
|
+
}
|
|
856
|
+
/** PNG bytes for `width × height` pixels of 1 (grey) or 4 (RGBA) bytes each. */
|
|
857
|
+
declare function encodePng(width: number, height: number, data: ArrayLike<number>, channels?: 1 | 4): Uint8Array;
|
|
858
|
+
declare function isPng(bytes: Uint8Array): boolean;
|
|
859
|
+
/**
|
|
860
|
+
* Decodes a PNG. Output is RGBA (4 channels) unless `keepGray` is set and the image is
|
|
861
|
+
* greyscale without alpha, in which case it is one byte per pixel.
|
|
862
|
+
*/
|
|
863
|
+
declare function decodePng(bytes: Uint8Array, options?: {
|
|
864
|
+
keepGray?: boolean;
|
|
865
|
+
maxPixels?: number;
|
|
866
|
+
}): DecodedPng;
|
|
867
|
+
declare function bytesToBase64(bytes: Uint8Array): string;
|
|
868
|
+
declare function base64ToBytes(text: string): Uint8Array;
|
|
869
|
+
/** The bytes and MIME type of a `data:` URL (base64 or percent-encoded). */
|
|
870
|
+
declare function parseDataUrl(url: string): {
|
|
871
|
+
mime: string;
|
|
872
|
+
bytes: Uint8Array;
|
|
873
|
+
} | null;
|
|
874
|
+
declare function pngDataUrl(width: number, height: number, data: ArrayLike<number>, channels?: 1 | 4): string;
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* Synchronous zlib (RFC 1950) and raw deflate (RFC 1951), dependency-free, for the image editor's
|
|
878
|
+
* layer PNGs and PSD ZIP channels. `CompressionStream` is asynchronous and not everywhere, and
|
|
879
|
+
* layer pixels must serialize inside the synchronous `toJSON()`.
|
|
880
|
+
*
|
|
881
|
+
* - `inflate` handles stored, fixed and dynamic blocks and refuses to produce more than
|
|
882
|
+
* `maxOutput` bytes (a decompression bomb guard).
|
|
883
|
+
* - `deflate` is a greedy LZ77 (hash chains, 32 KiB window) with one dynamic Huffman block per
|
|
884
|
+
* 64 Ki symbols. It favours simplicity over the last few percent of ratio.
|
|
885
|
+
*/
|
|
886
|
+
declare class ZlibError extends Error {
|
|
887
|
+
constructor(message: string);
|
|
888
|
+
}
|
|
889
|
+
/** Inflates raw deflate data (no zlib header). */
|
|
890
|
+
declare function inflateRaw(data: Uint8Array, options?: {
|
|
891
|
+
maxOutput?: number;
|
|
892
|
+
sizeHint?: number;
|
|
893
|
+
}): Uint8Array;
|
|
894
|
+
/** Adler-32 checksum (zlib trailer). */
|
|
895
|
+
declare function adler32(data: Uint8Array): number;
|
|
896
|
+
/** Inflates zlib data (header, deflate stream, Adler-32 trailer). */
|
|
897
|
+
declare function inflate(data: Uint8Array, options?: {
|
|
898
|
+
maxOutput?: number;
|
|
899
|
+
sizeHint?: number;
|
|
900
|
+
verify?: boolean;
|
|
901
|
+
}): Uint8Array;
|
|
902
|
+
/** Raw deflate (no zlib header). `level` 0 stores the data uncompressed. */
|
|
903
|
+
declare function deflateRaw(data: Uint8Array, level?: 0 | 1): Uint8Array;
|
|
904
|
+
/** zlib stream: header, raw deflate, Adler-32. */
|
|
905
|
+
declare function deflate(data: Uint8Array, level?: 0 | 1): Uint8Array;
|
|
906
|
+
|
|
907
|
+
export { type BevelContour, type BevelEmbossEffect, type BevelStyle, type BevelTechnique, type BevelTexture, BlendMode, type BlurEdge, CURVE_LUT_SIZE, type ColorOverlayEffect, type CompositeCallOptions, type CompositeStats, type CompositorLayer, type CompositorOptions, type CompositorProfile, type ContourPoint, DEFAULT_GLOBAL_LIGHT, DIRECT_GAUSSIAN_MAX_SIGMA, type DecodedPng, type DropShadowEffect, type EffectCompositeInput, type EffectContext, type EffectContour, type EffectFill, type EffectGradient, type EffectMaps, type EffectPattern, type EffectPatternRef, type EffectRect, type GlobalLight, type GlowTechnique, type GradientColorStop, type GradientOpacityStop, type GradientOverlayEffect, type GradientStyle, type GroupBlendMode, type GroupIn, type InnerGlowEffect, type InnerShadowEffect, LAYER_EFFECT_KINDS, type LayerEffect, LayerEffectError, type LayerEffectKind, type LayerEffects, type LayerLocation, type LayerLocks, MAX_EFFECT_REACH, MaskSurface, type OuterGlowEffect, type PatternOverlayEffect, PatternPlacement, PatternTile, type PixelFilterSpec, PixelSurface, RasterCompositor, type RasterGroupLayer, type RasterLayer, type RasterLayerBase, type RasterMask, type RasterNode, type RasterPixelLayer, RasterRect, type RasterSources, STROKE_CHAMFER_MAX, type SatinEffect, type StrokeEffect, type StrokePosition, TileKey, TiledSurface, ZlibError, activeEffectItems, adler32, base64ToBytes, blendTile, buildEffectMaps, builtinPattern, builtinPatternIds, bytesToBase64, changedTiles, compositeLayerEffects, contourLut, curveLut, decodePng, defaultEffectGradient, defaultLayerEffect, deflate, deflateRaw, effectColorHex, effectReach, effectsAreLocal, effectsFingerprint, effectsMargin, effectsScale, encodePng, findLayer, flattenLayers, gaussianBlur, gradientT, hasActiveEffects, hashNoise, inflate, inflateRaw, insertLayer, isLayerEffectKind, isLayerLocked, isPng, layerEffectFields, layerEffectLabel, mapLayer, mergeLayerEffect, newEffectId, normalizeLayerEffects, parseDataUrl, parseEffectColor, pngDataUrl, renderLayerEffects, scaleLayerEffect, validateEffectGradient, validateLayerEffect, validateLayerEffects };
|