@pixerate/editor 0.87.0 → 0.89.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 +4387 -690
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +1677 -590
- package/dist/image-editor/index.d.ts +1677 -590
- package/dist/image-editor/index.js +4273 -576
- 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/dist/video-editor/index.cjs +930 -503
- package/dist/video-editor/index.cjs.map +1 -1
- package/dist/video-editor/index.d.cts +158 -11
- package/dist/video-editor/index.d.ts +158 -11
- package/dist/video-editor/index.js +841 -414
- package/dist/video-editor/index.js.map +1 -1
- package/package.json +13 -2
- package/skills/pixerate-image-editor/SKILL.md +111 -11
- package/skills/pixerate-video-editor/SKILL.md +11 -2
- /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
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Photoshop blend modes on straight (non-premultiplied) 0..1 colours.
|
|
3
|
+
*
|
|
4
|
+
* Formulas follow the W3C Compositing / ISO 32000 definitions, with Photoshop's variants where
|
|
5
|
+
* they differ (Soft Light, Vivid / Linear / Pin Light, Hard Mix, Linear Burn / Dodge, Subtract,
|
|
6
|
+
* Divide, Darker / Lighter Color), and the hardened `ClipColor` for the non-separable modes.
|
|
7
|
+
*/
|
|
8
|
+
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';
|
|
9
|
+
interface BlendModeInfo {
|
|
10
|
+
id: BlendMode;
|
|
11
|
+
label: string;
|
|
12
|
+
/** Canvas `globalCompositeOperation` with the same maths, when there is one. */
|
|
13
|
+
canvas: GlobalCompositeOperation | null;
|
|
14
|
+
}
|
|
15
|
+
/** Every blend mode, in Photoshop's menu order. */
|
|
16
|
+
declare const BLEND_MODES: readonly BlendModeInfo[];
|
|
17
|
+
declare function isBlendMode(value: unknown): value is BlendMode;
|
|
18
|
+
/** A stored blend mode, or `normal` for a missing / unknown value. */
|
|
19
|
+
declare function normalizeBlendMode(value: unknown): BlendMode;
|
|
20
|
+
/**
|
|
21
|
+
* The canvas composite operation that implements `mode` exactly, or `null` when the canvas has
|
|
22
|
+
* none (draw through {@link blendImageData} instead).
|
|
23
|
+
*/
|
|
24
|
+
declare function canvasCompositeOperation(mode: BlendMode | undefined): GlobalCompositeOperation | null;
|
|
25
|
+
/** Whether a mode works on whole colours (hue, saturation, colour, luminosity, darker / lighter colour). */
|
|
26
|
+
declare function isSeparableBlendMode(mode: BlendMode): boolean;
|
|
27
|
+
/** Separable blend function `B(cb, cs)` of one channel. Non-separable modes return `cs`. */
|
|
28
|
+
declare function blendChannel(mode: BlendMode, cb: number, cs: number): number;
|
|
29
|
+
type Rgb = [number, number, number];
|
|
30
|
+
type Rgba = [number, number, number, number];
|
|
31
|
+
/** Luminosity of the non-separable modes (W3C / ISO 32000 weights). */
|
|
32
|
+
declare function blendLum(c: readonly number[]): number;
|
|
33
|
+
/** `c` with its luminosity moved to `l`, clipped back into gamut towards grey (SetLum + ClipColor). */
|
|
34
|
+
declare function setLum(c: readonly number[], l: number): Rgb;
|
|
35
|
+
/** `B(Cb, Cs)` of a whole colour, including the non-separable modes. */
|
|
36
|
+
declare function blendRgb(mode: BlendMode, cb: readonly number[], cs: readonly number[]): Rgb;
|
|
37
|
+
/**
|
|
38
|
+
* Composites a straight-alpha `source` over a straight-alpha `backdrop` (both RGBA in 0..1) with a
|
|
39
|
+
* blend mode and an extra `alpha` (opacity), using the W3C general formula:
|
|
40
|
+
* `αo = αs + αb(1 − αs)`, `αo·Co = (1 − αs)·αb·Cb + (1 − αb)·αs·Cs + αs·αb·B(Cb, Cs)`.
|
|
41
|
+
*/
|
|
42
|
+
declare function blendPixel(mode: BlendMode, backdrop: readonly number[], source: readonly number[], alpha?: number): Rgba;
|
|
43
|
+
/**
|
|
44
|
+
* Blends `source` into `backdrop` in place (8-bit straight RGBA of the same size) with
|
|
45
|
+
* {@link blendPixel}. The scalar fallback for modes the canvas cannot composite.
|
|
46
|
+
*/
|
|
47
|
+
declare function blendImageData(backdrop: ImageData, source: ImageData, mode: BlendMode, alpha?: number): void;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Tiled, sparse, copy-on-write pixel storage (photocraft's `Surface`): 256 px square tiles in a
|
|
51
|
+
* map keyed by tile coordinate, a default value for every missing tile, and shared tiles.
|
|
52
|
+
*
|
|
53
|
+
* - Pixels are 8-bit, straight alpha: RGBA for layers (4 channels, the same as `ImageData`), one
|
|
54
|
+
* byte for masks.
|
|
55
|
+
* - A surface is never mutated. A write returns a new surface that shares every tile it did not
|
|
56
|
+
* touch, so undo history and caches can keep old surfaces by reference.
|
|
57
|
+
* - A tile whose pixels all hold one value is a *uniform* tile; one instance per value is shared,
|
|
58
|
+
* so a solid fill or a "hide all" mask costs one tile however large it is.
|
|
59
|
+
* - Coordinates are document pixels and may be negative or past the canvas (layers can extend
|
|
60
|
+
* beyond it, as PSD layer rects do).
|
|
61
|
+
*
|
|
62
|
+
* The module has no DOM dependency, so it runs in Node, tests and workers.
|
|
63
|
+
*/
|
|
64
|
+
/** A pixel rectangle (`x`, `y` of the top-left corner, `width`, `height`). */
|
|
65
|
+
interface RasterRect {
|
|
66
|
+
x: number;
|
|
67
|
+
y: number;
|
|
68
|
+
width: number;
|
|
69
|
+
height: number;
|
|
70
|
+
}
|
|
71
|
+
type CropBox = RasterRect;
|
|
72
|
+
declare const TILE = 256;
|
|
73
|
+
declare const TILE_SHIFT = 8;
|
|
74
|
+
/** A tile coordinate packed into one number (tx, ty in −32768..32767). */
|
|
75
|
+
type TileKey = number;
|
|
76
|
+
declare function tileKey(tx: number, ty: number): TileKey;
|
|
77
|
+
declare function tileCoord(key: TileKey): {
|
|
78
|
+
tx: number;
|
|
79
|
+
ty: number;
|
|
80
|
+
};
|
|
81
|
+
/** A tile's pixel rectangle in document space. */
|
|
82
|
+
declare function tileRect(tx: number, ty: number): CropBox;
|
|
83
|
+
/** One tile: TILE × TILE pixels of `channels` bytes. Never mutate `data` after it is shared. */
|
|
84
|
+
interface Tile {
|
|
85
|
+
readonly data: Uint8ClampedArray;
|
|
86
|
+
/** The packed value of every pixel when the tile is uniform, else `null`. */
|
|
87
|
+
readonly uniform: number | null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* An immutable tiled surface. `channels` is 4 (RGBA) for layers and 1 for masks. Missing tiles
|
|
91
|
+
* hold `defaultValue` in every byte (0: transparent black for layers; 0 or 255 for masks).
|
|
92
|
+
*/
|
|
93
|
+
declare class TiledSurface {
|
|
94
|
+
readonly channels: 1 | 4;
|
|
95
|
+
readonly tiles: ReadonlyMap<TileKey, Tile>;
|
|
96
|
+
readonly defaultValue: number;
|
|
97
|
+
/** Unique per instance: a cache key that changes whenever the pixels can have changed. */
|
|
98
|
+
readonly id: number;
|
|
99
|
+
private boundsCache;
|
|
100
|
+
constructor(channels: 1 | 4, tiles: ReadonlyMap<TileKey, Tile>, defaultValue?: number);
|
|
101
|
+
/** Bounds of the stored (non-default) tiles, tile-aligned; `null` when there are none. */
|
|
102
|
+
get bounds(): CropBox | null;
|
|
103
|
+
get tileCount(): number;
|
|
104
|
+
getTile(tx: number, ty: number): Tile | undefined;
|
|
105
|
+
}
|
|
106
|
+
type PixelSurface = TiledSurface;
|
|
107
|
+
type MaskSurface = TiledSurface;
|
|
108
|
+
/** The shared tile whose every pixel is `value` (packed RGBA, or one byte for masks). */
|
|
109
|
+
declare function uniformTile(channels: 1 | 4, value: number): Tile;
|
|
110
|
+
/** Packs an RGBA colour (0..255 each) the way uniform tiles store it. */
|
|
111
|
+
declare function packRgba(r: number, g: number, b: number, a: number): number;
|
|
112
|
+
/**
|
|
113
|
+
* Turns freshly written tile data into a stored tile: `null` when it equals the surface default
|
|
114
|
+
* (the tile is dropped), the shared uniform tile when it is uniform, else a tile owning `data`.
|
|
115
|
+
*/
|
|
116
|
+
declare function finishTile(data: Uint8ClampedArray, channels: 1 | 4, defaultValue: number): Tile | null;
|
|
117
|
+
/** An empty surface (every pixel is `defaultValue`). */
|
|
118
|
+
declare function emptySurface(channels?: 1 | 4, defaultValue?: number): TiledSurface;
|
|
119
|
+
/** A surface filled with one value over `rect` (packed RGBA for layers, a byte for masks). */
|
|
120
|
+
declare function solidSurface(channels: 1 | 4, rect: CropBox, value: number, defaultValue?: number): TiledSurface;
|
|
121
|
+
/**
|
|
122
|
+
* A surface holding `width × height` interleaved pixels placed at (`x`, `y`) in document space.
|
|
123
|
+
* Tiles equal to the default are left out; uniform tiles are shared.
|
|
124
|
+
*/
|
|
125
|
+
declare function surfaceFromPixels(pixels: {
|
|
126
|
+
width: number;
|
|
127
|
+
height: number;
|
|
128
|
+
data: ArrayLike<number>;
|
|
129
|
+
}, channels?: 1 | 4, x?: number, y?: number, defaultValue?: number): TiledSurface;
|
|
130
|
+
/** Tile coordinates covering `rect`, row by row. */
|
|
131
|
+
declare function tilesInRect(rect: CropBox): Array<{
|
|
132
|
+
tx: number;
|
|
133
|
+
ty: number;
|
|
134
|
+
}>;
|
|
135
|
+
/**
|
|
136
|
+
* Copies `rect` of the surface into `out` (or a new buffer), `rect.width × rect.height`
|
|
137
|
+
* interleaved pixels; missing tiles read as the default.
|
|
138
|
+
*/
|
|
139
|
+
declare function readRegion(surface: TiledSurface, rect: CropBox, out?: Uint8ClampedArray): Uint8ClampedArray;
|
|
140
|
+
/** One pixel's bytes (RGBA or the mask byte). */
|
|
141
|
+
declare function readPixel(surface: TiledSurface, x: number, y: number): number[];
|
|
142
|
+
/**
|
|
143
|
+
* Exact bounds of the pixels that differ from the default (for a layer: non-transparent), or
|
|
144
|
+
* `null`. Scans the stored tiles; uniform tiles count whole.
|
|
145
|
+
*/
|
|
146
|
+
declare function contentBounds(surface: TiledSurface): CropBox | null;
|
|
147
|
+
/**
|
|
148
|
+
* A private, mutable copy of the tiles a write touches. `tile(tx, ty)` copies the tile on first
|
|
149
|
+
* use; `commit()` returns a new surface sharing every untouched tile. Use it for strokes:
|
|
150
|
+
* edit through the draft while the pointer moves and commit once at pointer-up.
|
|
151
|
+
*/
|
|
152
|
+
declare class SurfaceDraft {
|
|
153
|
+
readonly base: TiledSurface;
|
|
154
|
+
private readonly copies;
|
|
155
|
+
constructor(base: TiledSurface);
|
|
156
|
+
get channels(): 1 | 4;
|
|
157
|
+
/** The writable data of tile (tx, ty), copied from the base on first use. */
|
|
158
|
+
tile(tx: number, ty: number): Uint8ClampedArray;
|
|
159
|
+
/** Replaces a whole tile with `data` (owned by the draft from now on). */
|
|
160
|
+
replace(tx: number, ty: number, data: Uint8ClampedArray): void;
|
|
161
|
+
/** The current data of a tile without copying it (base tile, draft copy or `null` for default). */
|
|
162
|
+
peek(tx: number, ty: number): Uint8ClampedArray | null;
|
|
163
|
+
/** Keys of the tiles changed so far. */
|
|
164
|
+
get touched(): TileKey[];
|
|
165
|
+
/** A new surface with the draft's tiles; the draft must not be used afterwards. */
|
|
166
|
+
commit(): TiledSurface;
|
|
167
|
+
}
|
|
168
|
+
/** Writes `rect.width × rect.height` interleaved pixels at `rect`; returns the new surface. */
|
|
169
|
+
declare function writeRegion(surface: TiledSurface, rect: CropBox, data: ArrayLike<number>): TiledSurface;
|
|
170
|
+
/** Fills `rect` with one pixel value (`bytes`, `channels` long). */
|
|
171
|
+
declare function fillRect(surface: TiledSurface, rect: CropBox, bytes: ArrayLike<number>): TiledSurface;
|
|
172
|
+
/** A copy of the surface moved by an integer offset (re-tiles; layers normally move by `offset`). */
|
|
173
|
+
declare function translateSurface(surface: TiledSurface, dx: number, dy: number): TiledSurface;
|
|
174
|
+
/** Bytes held by a surface's non-uniform tiles (uniform tiles are shared and nearly free). */
|
|
175
|
+
declare function surfaceBytes(surface: TiledSurface): number;
|
|
176
|
+
/** Adds every non-uniform tile of `surface` to `into` (for counting bytes shared across states). */
|
|
177
|
+
declare function collectTiles(surface: TiledSurface, into: Set<Tile>): void;
|
|
178
|
+
/** True when two surfaces hold the same pixels (cheap when they share tiles). */
|
|
179
|
+
declare function surfacesEqual(a: TiledSurface, b: TiledSurface): boolean;
|
|
180
|
+
|
|
181
|
+
export { solidSurface as A, type BlendMode as B, surfaceBytes as C, surfaceFromPixels as D, surfacesEqual as E, tileCoord as F, tileKey as G, tileRect as H, tilesInRect as I, translateSurface as J, uniformTile as K, writeRegion as L, type MaskSurface as M, type PixelSurface as P, type RasterRect as R, SurfaceDraft as S, TiledSurface as T, BLEND_MODES as a, type BlendModeInfo as b, type Rgb as c, type Rgba as d, TILE as e, TILE_SHIFT as f, type Tile as g, type TileKey as h, blendChannel as i, blendImageData as j, blendLum as k, blendPixel as l, blendRgb as m, canvasCompositeOperation as n, collectTiles as o, contentBounds as p, emptySurface as q, fillRect as r, finishTile as s, isBlendMode as t, isSeparableBlendMode as u, normalizeBlendMode as v, packRgba as w, readPixel as x, readRegion as y, setLum as z };
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Photoshop blend modes on straight (non-premultiplied) 0..1 colours.
|
|
3
|
+
*
|
|
4
|
+
* Formulas follow the W3C Compositing / ISO 32000 definitions, with Photoshop's variants where
|
|
5
|
+
* they differ (Soft Light, Vivid / Linear / Pin Light, Hard Mix, Linear Burn / Dodge, Subtract,
|
|
6
|
+
* Divide, Darker / Lighter Color), and the hardened `ClipColor` for the non-separable modes.
|
|
7
|
+
*/
|
|
8
|
+
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';
|
|
9
|
+
interface BlendModeInfo {
|
|
10
|
+
id: BlendMode;
|
|
11
|
+
label: string;
|
|
12
|
+
/** Canvas `globalCompositeOperation` with the same maths, when there is one. */
|
|
13
|
+
canvas: GlobalCompositeOperation | null;
|
|
14
|
+
}
|
|
15
|
+
/** Every blend mode, in Photoshop's menu order. */
|
|
16
|
+
declare const BLEND_MODES: readonly BlendModeInfo[];
|
|
17
|
+
declare function isBlendMode(value: unknown): value is BlendMode;
|
|
18
|
+
/** A stored blend mode, or `normal` for a missing / unknown value. */
|
|
19
|
+
declare function normalizeBlendMode(value: unknown): BlendMode;
|
|
20
|
+
/**
|
|
21
|
+
* The canvas composite operation that implements `mode` exactly, or `null` when the canvas has
|
|
22
|
+
* none (draw through {@link blendImageData} instead).
|
|
23
|
+
*/
|
|
24
|
+
declare function canvasCompositeOperation(mode: BlendMode | undefined): GlobalCompositeOperation | null;
|
|
25
|
+
/** Whether a mode works on whole colours (hue, saturation, colour, luminosity, darker / lighter colour). */
|
|
26
|
+
declare function isSeparableBlendMode(mode: BlendMode): boolean;
|
|
27
|
+
/** Separable blend function `B(cb, cs)` of one channel. Non-separable modes return `cs`. */
|
|
28
|
+
declare function blendChannel(mode: BlendMode, cb: number, cs: number): number;
|
|
29
|
+
type Rgb = [number, number, number];
|
|
30
|
+
type Rgba = [number, number, number, number];
|
|
31
|
+
/** Luminosity of the non-separable modes (W3C / ISO 32000 weights). */
|
|
32
|
+
declare function blendLum(c: readonly number[]): number;
|
|
33
|
+
/** `c` with its luminosity moved to `l`, clipped back into gamut towards grey (SetLum + ClipColor). */
|
|
34
|
+
declare function setLum(c: readonly number[], l: number): Rgb;
|
|
35
|
+
/** `B(Cb, Cs)` of a whole colour, including the non-separable modes. */
|
|
36
|
+
declare function blendRgb(mode: BlendMode, cb: readonly number[], cs: readonly number[]): Rgb;
|
|
37
|
+
/**
|
|
38
|
+
* Composites a straight-alpha `source` over a straight-alpha `backdrop` (both RGBA in 0..1) with a
|
|
39
|
+
* blend mode and an extra `alpha` (opacity), using the W3C general formula:
|
|
40
|
+
* `αo = αs + αb(1 − αs)`, `αo·Co = (1 − αs)·αb·Cb + (1 − αb)·αs·Cs + αs·αb·B(Cb, Cs)`.
|
|
41
|
+
*/
|
|
42
|
+
declare function blendPixel(mode: BlendMode, backdrop: readonly number[], source: readonly number[], alpha?: number): Rgba;
|
|
43
|
+
/**
|
|
44
|
+
* Blends `source` into `backdrop` in place (8-bit straight RGBA of the same size) with
|
|
45
|
+
* {@link blendPixel}. The scalar fallback for modes the canvas cannot composite.
|
|
46
|
+
*/
|
|
47
|
+
declare function blendImageData(backdrop: ImageData, source: ImageData, mode: BlendMode, alpha?: number): void;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Tiled, sparse, copy-on-write pixel storage (photocraft's `Surface`): 256 px square tiles in a
|
|
51
|
+
* map keyed by tile coordinate, a default value for every missing tile, and shared tiles.
|
|
52
|
+
*
|
|
53
|
+
* - Pixels are 8-bit, straight alpha: RGBA for layers (4 channels, the same as `ImageData`), one
|
|
54
|
+
* byte for masks.
|
|
55
|
+
* - A surface is never mutated. A write returns a new surface that shares every tile it did not
|
|
56
|
+
* touch, so undo history and caches can keep old surfaces by reference.
|
|
57
|
+
* - A tile whose pixels all hold one value is a *uniform* tile; one instance per value is shared,
|
|
58
|
+
* so a solid fill or a "hide all" mask costs one tile however large it is.
|
|
59
|
+
* - Coordinates are document pixels and may be negative or past the canvas (layers can extend
|
|
60
|
+
* beyond it, as PSD layer rects do).
|
|
61
|
+
*
|
|
62
|
+
* The module has no DOM dependency, so it runs in Node, tests and workers.
|
|
63
|
+
*/
|
|
64
|
+
/** A pixel rectangle (`x`, `y` of the top-left corner, `width`, `height`). */
|
|
65
|
+
interface RasterRect {
|
|
66
|
+
x: number;
|
|
67
|
+
y: number;
|
|
68
|
+
width: number;
|
|
69
|
+
height: number;
|
|
70
|
+
}
|
|
71
|
+
type CropBox = RasterRect;
|
|
72
|
+
declare const TILE = 256;
|
|
73
|
+
declare const TILE_SHIFT = 8;
|
|
74
|
+
/** A tile coordinate packed into one number (tx, ty in −32768..32767). */
|
|
75
|
+
type TileKey = number;
|
|
76
|
+
declare function tileKey(tx: number, ty: number): TileKey;
|
|
77
|
+
declare function tileCoord(key: TileKey): {
|
|
78
|
+
tx: number;
|
|
79
|
+
ty: number;
|
|
80
|
+
};
|
|
81
|
+
/** A tile's pixel rectangle in document space. */
|
|
82
|
+
declare function tileRect(tx: number, ty: number): CropBox;
|
|
83
|
+
/** One tile: TILE × TILE pixels of `channels` bytes. Never mutate `data` after it is shared. */
|
|
84
|
+
interface Tile {
|
|
85
|
+
readonly data: Uint8ClampedArray;
|
|
86
|
+
/** The packed value of every pixel when the tile is uniform, else `null`. */
|
|
87
|
+
readonly uniform: number | null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* An immutable tiled surface. `channels` is 4 (RGBA) for layers and 1 for masks. Missing tiles
|
|
91
|
+
* hold `defaultValue` in every byte (0: transparent black for layers; 0 or 255 for masks).
|
|
92
|
+
*/
|
|
93
|
+
declare class TiledSurface {
|
|
94
|
+
readonly channels: 1 | 4;
|
|
95
|
+
readonly tiles: ReadonlyMap<TileKey, Tile>;
|
|
96
|
+
readonly defaultValue: number;
|
|
97
|
+
/** Unique per instance: a cache key that changes whenever the pixels can have changed. */
|
|
98
|
+
readonly id: number;
|
|
99
|
+
private boundsCache;
|
|
100
|
+
constructor(channels: 1 | 4, tiles: ReadonlyMap<TileKey, Tile>, defaultValue?: number);
|
|
101
|
+
/** Bounds of the stored (non-default) tiles, tile-aligned; `null` when there are none. */
|
|
102
|
+
get bounds(): CropBox | null;
|
|
103
|
+
get tileCount(): number;
|
|
104
|
+
getTile(tx: number, ty: number): Tile | undefined;
|
|
105
|
+
}
|
|
106
|
+
type PixelSurface = TiledSurface;
|
|
107
|
+
type MaskSurface = TiledSurface;
|
|
108
|
+
/** The shared tile whose every pixel is `value` (packed RGBA, or one byte for masks). */
|
|
109
|
+
declare function uniformTile(channels: 1 | 4, value: number): Tile;
|
|
110
|
+
/** Packs an RGBA colour (0..255 each) the way uniform tiles store it. */
|
|
111
|
+
declare function packRgba(r: number, g: number, b: number, a: number): number;
|
|
112
|
+
/**
|
|
113
|
+
* Turns freshly written tile data into a stored tile: `null` when it equals the surface default
|
|
114
|
+
* (the tile is dropped), the shared uniform tile when it is uniform, else a tile owning `data`.
|
|
115
|
+
*/
|
|
116
|
+
declare function finishTile(data: Uint8ClampedArray, channels: 1 | 4, defaultValue: number): Tile | null;
|
|
117
|
+
/** An empty surface (every pixel is `defaultValue`). */
|
|
118
|
+
declare function emptySurface(channels?: 1 | 4, defaultValue?: number): TiledSurface;
|
|
119
|
+
/** A surface filled with one value over `rect` (packed RGBA for layers, a byte for masks). */
|
|
120
|
+
declare function solidSurface(channels: 1 | 4, rect: CropBox, value: number, defaultValue?: number): TiledSurface;
|
|
121
|
+
/**
|
|
122
|
+
* A surface holding `width × height` interleaved pixels placed at (`x`, `y`) in document space.
|
|
123
|
+
* Tiles equal to the default are left out; uniform tiles are shared.
|
|
124
|
+
*/
|
|
125
|
+
declare function surfaceFromPixels(pixels: {
|
|
126
|
+
width: number;
|
|
127
|
+
height: number;
|
|
128
|
+
data: ArrayLike<number>;
|
|
129
|
+
}, channels?: 1 | 4, x?: number, y?: number, defaultValue?: number): TiledSurface;
|
|
130
|
+
/** Tile coordinates covering `rect`, row by row. */
|
|
131
|
+
declare function tilesInRect(rect: CropBox): Array<{
|
|
132
|
+
tx: number;
|
|
133
|
+
ty: number;
|
|
134
|
+
}>;
|
|
135
|
+
/**
|
|
136
|
+
* Copies `rect` of the surface into `out` (or a new buffer), `rect.width × rect.height`
|
|
137
|
+
* interleaved pixels; missing tiles read as the default.
|
|
138
|
+
*/
|
|
139
|
+
declare function readRegion(surface: TiledSurface, rect: CropBox, out?: Uint8ClampedArray): Uint8ClampedArray;
|
|
140
|
+
/** One pixel's bytes (RGBA or the mask byte). */
|
|
141
|
+
declare function readPixel(surface: TiledSurface, x: number, y: number): number[];
|
|
142
|
+
/**
|
|
143
|
+
* Exact bounds of the pixels that differ from the default (for a layer: non-transparent), or
|
|
144
|
+
* `null`. Scans the stored tiles; uniform tiles count whole.
|
|
145
|
+
*/
|
|
146
|
+
declare function contentBounds(surface: TiledSurface): CropBox | null;
|
|
147
|
+
/**
|
|
148
|
+
* A private, mutable copy of the tiles a write touches. `tile(tx, ty)` copies the tile on first
|
|
149
|
+
* use; `commit()` returns a new surface sharing every untouched tile. Use it for strokes:
|
|
150
|
+
* edit through the draft while the pointer moves and commit once at pointer-up.
|
|
151
|
+
*/
|
|
152
|
+
declare class SurfaceDraft {
|
|
153
|
+
readonly base: TiledSurface;
|
|
154
|
+
private readonly copies;
|
|
155
|
+
constructor(base: TiledSurface);
|
|
156
|
+
get channels(): 1 | 4;
|
|
157
|
+
/** The writable data of tile (tx, ty), copied from the base on first use. */
|
|
158
|
+
tile(tx: number, ty: number): Uint8ClampedArray;
|
|
159
|
+
/** Replaces a whole tile with `data` (owned by the draft from now on). */
|
|
160
|
+
replace(tx: number, ty: number, data: Uint8ClampedArray): void;
|
|
161
|
+
/** The current data of a tile without copying it (base tile, draft copy or `null` for default). */
|
|
162
|
+
peek(tx: number, ty: number): Uint8ClampedArray | null;
|
|
163
|
+
/** Keys of the tiles changed so far. */
|
|
164
|
+
get touched(): TileKey[];
|
|
165
|
+
/** A new surface with the draft's tiles; the draft must not be used afterwards. */
|
|
166
|
+
commit(): TiledSurface;
|
|
167
|
+
}
|
|
168
|
+
/** Writes `rect.width × rect.height` interleaved pixels at `rect`; returns the new surface. */
|
|
169
|
+
declare function writeRegion(surface: TiledSurface, rect: CropBox, data: ArrayLike<number>): TiledSurface;
|
|
170
|
+
/** Fills `rect` with one pixel value (`bytes`, `channels` long). */
|
|
171
|
+
declare function fillRect(surface: TiledSurface, rect: CropBox, bytes: ArrayLike<number>): TiledSurface;
|
|
172
|
+
/** A copy of the surface moved by an integer offset (re-tiles; layers normally move by `offset`). */
|
|
173
|
+
declare function translateSurface(surface: TiledSurface, dx: number, dy: number): TiledSurface;
|
|
174
|
+
/** Bytes held by a surface's non-uniform tiles (uniform tiles are shared and nearly free). */
|
|
175
|
+
declare function surfaceBytes(surface: TiledSurface): number;
|
|
176
|
+
/** Adds every non-uniform tile of `surface` to `into` (for counting bytes shared across states). */
|
|
177
|
+
declare function collectTiles(surface: TiledSurface, into: Set<Tile>): void;
|
|
178
|
+
/** True when two surfaces hold the same pixels (cheap when they share tiles). */
|
|
179
|
+
declare function surfacesEqual(a: TiledSurface, b: TiledSurface): boolean;
|
|
180
|
+
|
|
181
|
+
export { solidSurface as A, type BlendMode as B, surfaceBytes as C, surfaceFromPixels as D, surfacesEqual as E, tileCoord as F, tileKey as G, tileRect as H, tilesInRect as I, translateSurface as J, uniformTile as K, writeRegion as L, type MaskSurface as M, type PixelSurface as P, type RasterRect as R, SurfaceDraft as S, TiledSurface as T, BLEND_MODES as a, type BlendModeInfo as b, type Rgb as c, type Rgba as d, TILE as e, TILE_SHIFT as f, type Tile as g, type TileKey as h, blendChannel as i, blendImageData as j, blendLum as k, blendPixel as l, blendRgb as m, canvasCompositeOperation as n, collectTiles as o, contentBounds as p, emptySurface as q, fillRect as r, finishTile as s, isBlendMode as t, isSeparableBlendMode as u, normalizeBlendMode as v, packRgba as w, readPixel as x, readRegion as y, setLum as z };
|