pixel-data-js 0.3.0 → 0.5.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/dist/index.dev.cjs +1405 -70
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +1355 -68
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +1405 -70
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +581 -64
- package/dist/index.prod.js +1355 -68
- package/dist/index.prod.js.map +1 -1
- package/package.json +14 -3
- package/src/Algorithm/floodFillSelection.ts +229 -0
- package/src/Canvas/PixelCanvas.ts +31 -0
- package/src/Canvas/ReusableCanvas.ts +44 -0
- package/src/Canvas/_constants.ts +2 -0
- package/src/Clipboard/getImageDataFromClipboard.ts +42 -0
- package/src/Clipboard/writeImageDataToClipboard.ts +25 -0
- package/src/Clipboard/writeImgBlobToClipboard.ts +13 -0
- package/src/ImageData/{extractImageData.ts → extractImageDataPixels.ts} +21 -3
- package/src/ImageData/imageDataToAlphaMask.ts +35 -0
- package/src/ImageData/imageDataToDataUrl.ts +27 -0
- package/src/ImageData/imageDataToImgBlob.ts +31 -0
- package/src/ImageData/imgBlobToImageData.ts +52 -0
- package/src/ImageData/invertImageData.ts +10 -0
- package/src/ImageData/resizeImageData.ts +75 -0
- package/src/ImageData/{writeImageData.ts → writeImageDataPixels.ts} +22 -3
- package/src/Input/fileInputChangeToImageData.ts +37 -0
- package/src/Input/fileToImageData.ts +75 -0
- package/src/Input/getSupportedRasterFormats.ts +74 -0
- package/src/Mask/extractMask.ts +86 -0
- package/src/Mask/mergeMasks.ts +1 -6
- package/src/PixelData/blendColorPixelData.ts +9 -9
- package/src/PixelData/fillPixelData.ts +51 -12
- package/src/PixelData/invertPixelData.ts +16 -0
- package/src/PixelData/pixelDataToAlphaMask.ts +28 -0
- package/src/Rect/trimRectBounds.ts +118 -0
- package/src/_types.ts +37 -20
- package/src/blend-modes.ts +506 -66
- package/src/color.ts +6 -6
- package/src/globals.d.ts +2 -0
- package/src/index.ts +37 -1
package/dist/index.prod.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ type BlendColor32 = (src: Color32, dst: Color32) => Color32;
|
|
|
19
19
|
type ImageDataLike = {
|
|
20
20
|
width: number;
|
|
21
21
|
height: number;
|
|
22
|
-
data: Uint8ClampedArray<
|
|
22
|
+
data: Uint8ClampedArray<ArrayBufferLike>;
|
|
23
23
|
};
|
|
24
24
|
type SerializedImageData = {
|
|
25
25
|
width: number;
|
|
@@ -67,23 +67,23 @@ type AnyMask = BinaryMask | AlphaMask;
|
|
|
67
67
|
interface PixelOptions {
|
|
68
68
|
/**
|
|
69
69
|
* The starting X coordinate in the destination buffer.
|
|
70
|
-
* @
|
|
71
|
-
|
|
70
|
+
* @default 0
|
|
71
|
+
*/
|
|
72
72
|
x?: number;
|
|
73
73
|
/**
|
|
74
74
|
* The starting Y coordinate in the destination buffer.
|
|
75
|
-
* @
|
|
76
|
-
|
|
75
|
+
* @default 0
|
|
76
|
+
*/
|
|
77
77
|
y?: number;
|
|
78
78
|
/**
|
|
79
79
|
* The width of the region to process.
|
|
80
|
-
* @
|
|
81
|
-
|
|
80
|
+
* @default Source width.
|
|
81
|
+
*/
|
|
82
82
|
w?: number;
|
|
83
83
|
/**
|
|
84
84
|
* The height of the region to process.
|
|
85
|
-
* @
|
|
86
|
-
|
|
85
|
+
* @default Source height.
|
|
86
|
+
*/
|
|
87
87
|
h?: number;
|
|
88
88
|
/**
|
|
89
89
|
* Overall layer opacity 0-255.
|
|
@@ -92,24 +92,29 @@ interface PixelOptions {
|
|
|
92
92
|
alpha?: number;
|
|
93
93
|
/**
|
|
94
94
|
* Mask width.
|
|
95
|
-
* @default w
|
|
96
|
-
|
|
95
|
+
* @default value of `w`
|
|
96
|
+
*/
|
|
97
97
|
mw?: number;
|
|
98
98
|
/**
|
|
99
99
|
* X offset into the mask buffer.
|
|
100
100
|
* @default 0
|
|
101
|
-
|
|
101
|
+
*/
|
|
102
102
|
mx?: number;
|
|
103
103
|
/**
|
|
104
104
|
* Y offset into the mask buffer.
|
|
105
105
|
* @default 0
|
|
106
|
-
|
|
106
|
+
*/
|
|
107
107
|
my?: number;
|
|
108
108
|
/** An optional mask to restrict where pixels are written. */
|
|
109
109
|
mask?: AnyMask | null;
|
|
110
|
-
/** The interpretation logic for the provided mask.
|
|
110
|
+
/** The interpretation logic for the provided mask.
|
|
111
|
+
* @default {@link MaskType.BINARY}
|
|
112
|
+
*/
|
|
111
113
|
maskType?: MaskType;
|
|
112
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* If true the inverse of the mask will be applied
|
|
116
|
+
* @default false
|
|
117
|
+
*/
|
|
113
118
|
invertMask?: boolean;
|
|
114
119
|
}
|
|
115
120
|
/**
|
|
@@ -126,63 +131,114 @@ interface PixelBlendOptions extends PixelOptions {
|
|
|
126
131
|
* @default 0
|
|
127
132
|
*/
|
|
128
133
|
sy?: number;
|
|
129
|
-
/**
|
|
134
|
+
/**
|
|
135
|
+
* The blending algorithm to use for blending pixels.
|
|
136
|
+
* @default {@link sourceOverColor32}
|
|
137
|
+
*/
|
|
130
138
|
blendFn?: BlendColor32;
|
|
131
139
|
}
|
|
132
140
|
/**
|
|
133
141
|
* Configuration for operations that require color blending.
|
|
134
142
|
*/
|
|
135
143
|
interface ColorBlendOptions extends PixelOptions {
|
|
136
|
-
/**
|
|
144
|
+
/**
|
|
145
|
+
* The blending algorithm to use for blending pixels.
|
|
146
|
+
* @default {@link sourceOverColor32}
|
|
147
|
+
*/
|
|
137
148
|
blendFn?: BlendColor32;
|
|
138
149
|
}
|
|
139
150
|
type ApplyMaskOptions = Omit<PixelOptions, 'mask'>;
|
|
151
|
+
type SelectionRect = Rect & ({
|
|
152
|
+
mask: Uint8Array;
|
|
153
|
+
maskType: MaskType;
|
|
154
|
+
} | {
|
|
155
|
+
mask?: null;
|
|
156
|
+
maskType?: null;
|
|
157
|
+
});
|
|
140
158
|
|
|
159
|
+
declare const overwriteColor32: BlendColor32;
|
|
141
160
|
declare const sourceOverColor32: BlendColor32;
|
|
161
|
+
/** Math.min(src, dst) */
|
|
162
|
+
declare const darkenColor32: BlendColor32;
|
|
163
|
+
/** (src * dst) / 255 */
|
|
164
|
+
declare const multiplyColor32: BlendColor32;
|
|
165
|
+
/** 255 - (255-src)/dst */
|
|
166
|
+
declare const colorBurnColor32: BlendColor32;
|
|
167
|
+
/** src + dst - 255 */
|
|
168
|
+
declare const linearBurnColor32: BlendColor32;
|
|
169
|
+
declare const darkerColor32: BlendColor32;
|
|
170
|
+
/** Math.max(src, dst) */
|
|
171
|
+
declare const lightenColor32: BlendColor32;
|
|
142
172
|
/**
|
|
143
|
-
*
|
|
144
|
-
* Result = 1 - ((1 - Src) * (1 - Dst))
|
|
173
|
+
* 255 - ((255 - src) * (255 - dst))
|
|
145
174
|
*/
|
|
146
175
|
declare const screenColor32: BlendColor32;
|
|
147
|
-
/**
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
*/
|
|
176
|
+
/** src === 255 ? 255 : Math.min(255, (dst << 8) / (255 - src)) */
|
|
177
|
+
declare const colorDodgeColor32: BlendColor32;
|
|
178
|
+
/** src + dst */
|
|
151
179
|
declare const linearDodgeColor32: BlendColor32;
|
|
152
|
-
|
|
153
|
-
*
|
|
154
|
-
|
|
155
|
-
*/
|
|
156
|
-
declare const
|
|
157
|
-
/**
|
|
158
|
-
* Difference: Subtracts the darker color from the lighter color.
|
|
159
|
-
* Result = |Src - Dst|
|
|
160
|
-
*/
|
|
161
|
-
declare const differenceColor32: BlendColor32;
|
|
162
|
-
/**
|
|
163
|
-
* Hard Light: Decides Multiply vs Screen based on SOURCE brightness.
|
|
164
|
-
* Acts like a harsh spotlight.
|
|
165
|
-
*/
|
|
180
|
+
declare const lighterColor32: BlendColor32;
|
|
181
|
+
/** src < 128 ? (2 * src * dst) : (255 - 2 * (255 - src) * (255 - dst)) */
|
|
182
|
+
declare const overlayColor32: BlendColor32;
|
|
183
|
+
/** ((255 - dst) * ((src * dst) >> 8) + dst * (255 - (((255 - src) * (255 - dst)) >> 8))) >> 8 */
|
|
184
|
+
declare const softLightColor32: BlendColor32;
|
|
185
|
+
/** If src < 128 (50% gray), Multiply; otherwise, Screen */
|
|
166
186
|
declare const hardLightColor32: BlendColor32;
|
|
167
187
|
/**
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*/
|
|
171
|
-
declare const colorBurnColor32: BlendColor32;
|
|
172
|
-
/**
|
|
173
|
-
* Overlay: The classic "Contrast" mode.
|
|
174
|
-
* Decides Multiply vs Screen based on DESTINATION brightness.
|
|
188
|
+
* If src < 128: Burn(dst, 2 * src)
|
|
189
|
+
* If src >= 128: Dodge(dst, 2 * (src - 128))
|
|
175
190
|
*/
|
|
176
|
-
declare const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
191
|
+
declare const vividLightColor32: BlendColor32;
|
|
192
|
+
/** dst + 2 * src - 255 (Clamped to 0-255) */
|
|
193
|
+
declare const linearLightColor32: BlendColor32;
|
|
194
|
+
/** src < 128 ? min(dst, 2 * src) : max(dst, 2 * (src - 128)) */
|
|
195
|
+
declare const pinLightColor32: BlendColor32;
|
|
196
|
+
/** (Vivid Light logic forced to 0 or 255) */
|
|
197
|
+
declare const hardMixColor32: BlendColor32;
|
|
198
|
+
/** Math.abs(src - dst) */
|
|
199
|
+
declare const differenceColor32: BlendColor32;
|
|
200
|
+
/** dst + src - ((dst * src) >> 7) */
|
|
201
|
+
declare const exclusionColor32: BlendColor32;
|
|
202
|
+
/** Math.max(0, dst - src) */
|
|
203
|
+
declare const subtractColor32: BlendColor32;
|
|
204
|
+
/** sr === 0 ? 255 : Math.min(255, (dr << 8) / sr) */
|
|
205
|
+
declare const divideColor32: BlendColor32;
|
|
206
|
+
declare enum BlendMode {
|
|
207
|
+
overwrite = 0,
|
|
208
|
+
sourceOver = 1,
|
|
209
|
+
darken = 2,
|
|
210
|
+
multiply = 3,
|
|
211
|
+
colorBurn = 4,
|
|
212
|
+
linearBurn = 5,
|
|
213
|
+
darkerColor = 6,
|
|
214
|
+
lighten = 7,
|
|
215
|
+
screen = 8,
|
|
216
|
+
colorDodge = 9,
|
|
217
|
+
linearDodge = 10,
|
|
218
|
+
lighterColor = 11,
|
|
219
|
+
overlay = 12,
|
|
220
|
+
softLight = 13,
|
|
221
|
+
hardLight = 14,
|
|
222
|
+
vividLight = 15,
|
|
223
|
+
linearLight = 16,
|
|
224
|
+
pinLight = 17,
|
|
225
|
+
hardMix = 18,
|
|
226
|
+
difference = 19,
|
|
227
|
+
exclusion = 20,
|
|
228
|
+
subtract = 21,
|
|
229
|
+
divide = 22
|
|
230
|
+
}
|
|
231
|
+
declare const BLENDER_REGISTRY: readonly [readonly [BlendMode.overwrite, BlendColor32], readonly [BlendMode.sourceOver, BlendColor32], readonly [BlendMode.darken, BlendColor32], readonly [BlendMode.multiply, BlendColor32], readonly [BlendMode.colorBurn, BlendColor32], readonly [BlendMode.linearBurn, BlendColor32], readonly [BlendMode.darkerColor, BlendColor32], readonly [BlendMode.lighten, BlendColor32], readonly [BlendMode.screen, BlendColor32], readonly [BlendMode.colorDodge, BlendColor32], readonly [BlendMode.linearDodge, BlendColor32], readonly [BlendMode.lighterColor, BlendColor32], readonly [BlendMode.overlay, BlendColor32], readonly [BlendMode.softLight, BlendColor32], readonly [BlendMode.hardLight, BlendColor32], readonly [BlendMode.vividLight, BlendColor32], readonly [BlendMode.linearLight, BlendColor32], readonly [BlendMode.pinLight, BlendColor32], readonly [BlendMode.hardMix, BlendColor32], readonly [BlendMode.difference, BlendColor32], readonly [BlendMode.exclusion, BlendColor32], readonly [BlendMode.subtract, BlendColor32], readonly [BlendMode.divide, BlendColor32]];
|
|
232
|
+
type RegisteredBlender = typeof BLENDER_REGISTRY[number][1];
|
|
233
|
+
type BlendModeIndex = number & {
|
|
234
|
+
readonly __brandBlendModeIndex: unique symbol;
|
|
235
|
+
};
|
|
236
|
+
declare const COLOR_32_BLEND_MODES: BlendColor32[];
|
|
237
|
+
declare const COLOR_32_BLEND_TO_INDEX: {
|
|
238
|
+
get: (blend: RegisteredBlender) => BlendModeIndex;
|
|
239
|
+
};
|
|
240
|
+
declare const INDEX_TO_COLOR_32_BLEND: {
|
|
241
|
+
get: (index: BlendModeIndex) => RegisteredBlender;
|
|
186
242
|
};
|
|
187
243
|
|
|
188
244
|
/**
|
|
@@ -213,7 +269,7 @@ declare function lerpColor32(a: Color32, b: Color32, t: number): Color32;
|
|
|
213
269
|
* Linearly interpolates between two 32-bit colors using integer fixed-point math.
|
|
214
270
|
* Highly optimized for image processing and real-time blitting. It processes
|
|
215
271
|
* channels in parallel using bitmasks (RB and GA pairs).
|
|
216
|
-
*
|
|
272
|
+
* **Note:** Subject to a 1-bit drift (rounding down) due to fast bit-shift division.
|
|
217
273
|
* @param src - The source (foreground) color as a 32-bit integer.
|
|
218
274
|
* @param dst - The destination (background) color as a 32-bit integer.
|
|
219
275
|
* @param w - The blend weight as a byte value from 0 to 255. Where 0 is 100% dst and 255 is 100% src
|
|
@@ -226,11 +282,268 @@ declare function color32ToHex(color: Color32): string;
|
|
|
226
282
|
*/
|
|
227
283
|
declare function color32ToCssRGBA(color: Color32): string;
|
|
228
284
|
|
|
285
|
+
declare class PixelData {
|
|
286
|
+
readonly imageData: ImageDataLike;
|
|
287
|
+
readonly data32: Uint32Array;
|
|
288
|
+
readonly width: number;
|
|
289
|
+
readonly height: number;
|
|
290
|
+
constructor(imageData: ImageDataLike);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
type FloodFillImageDataOptions = {
|
|
294
|
+
contiguous?: boolean;
|
|
295
|
+
tolerance?: number;
|
|
296
|
+
bounds?: Rect;
|
|
297
|
+
};
|
|
298
|
+
type FloodFillResult = {
|
|
299
|
+
startX: number;
|
|
300
|
+
startY: number;
|
|
301
|
+
selectionRect: SelectionRect;
|
|
302
|
+
pixels: Uint8ClampedArray;
|
|
303
|
+
};
|
|
304
|
+
/**
|
|
305
|
+
* Performs a color-based flood fill selection on {@link ImageData} or {@link PixelData}.
|
|
306
|
+
* This utility identifies pixels starting from a specific coordinate that fall within a
|
|
307
|
+
* color tolerance. It can operate in "contiguous" mode (classic bucket fill) or
|
|
308
|
+
* "non-contiguous" mode (selects all matching pixels in the buffer).
|
|
309
|
+
*
|
|
310
|
+
* @param img - The source image data to process.
|
|
311
|
+
* @param startX - The starting horizontal coordinate.
|
|
312
|
+
* @param startY - The starting vertical coordinate.
|
|
313
|
+
* @param options - Configuration for the fill operation.
|
|
314
|
+
* @param options.contiguous - @default true. If true, only connected pixels are
|
|
315
|
+
* selected. If false, all pixels within tolerance are selected regardless of position.
|
|
316
|
+
* @param options.tolerance - @default 0. The maximum allowed difference in color
|
|
317
|
+
* distance (0-255) for a pixel to be included.
|
|
318
|
+
* @param options.bounds - Optional bounding box to restrict the search area.
|
|
319
|
+
*
|
|
320
|
+
* @returns A {@link FloodFillResult} containing the mask and bounds of the selection,
|
|
321
|
+
* or `null` if the starting coordinates are out of bounds.
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* ```typescript
|
|
325
|
+
* const result = floodFillImageDataSelection(
|
|
326
|
+
* ctx.getImageData(0, 0, 100, 100),
|
|
327
|
+
* 50,
|
|
328
|
+
* 50,
|
|
329
|
+
* {
|
|
330
|
+
* tolerance: 20,
|
|
331
|
+
* contiguous: true
|
|
332
|
+
* }
|
|
333
|
+
* );
|
|
334
|
+
* ```
|
|
335
|
+
*/
|
|
336
|
+
declare function floodFillSelection(img: ImageDataLike | PixelData, startX: number, startY: number, { contiguous, tolerance, bounds, }?: FloodFillImageDataOptions): FloodFillResult | null;
|
|
337
|
+
|
|
338
|
+
type PixelCanvas = {
|
|
339
|
+
readonly canvas: HTMLCanvasElement;
|
|
340
|
+
readonly ctx: CanvasRenderingContext2D;
|
|
341
|
+
readonly resize: (w: number, h: number) => void;
|
|
342
|
+
};
|
|
343
|
+
/**
|
|
344
|
+
* Ensures the canvas ctx is always set to imageSmoothingEnabled = false.
|
|
345
|
+
* Intended for canvas elements that are already part of the DOM.
|
|
346
|
+
* @see makeReusableCanvas
|
|
347
|
+
* @throws {Error} If the {@link HTMLCanvasElement} context cannot be initialized.
|
|
348
|
+
*/
|
|
349
|
+
declare function makePixelCanvas(canvas: HTMLCanvasElement): PixelCanvas;
|
|
350
|
+
|
|
351
|
+
type ReusableCanvas = {
|
|
352
|
+
readonly canvas: HTMLCanvasElement;
|
|
353
|
+
readonly ctx: CanvasRenderingContext2D;
|
|
354
|
+
};
|
|
355
|
+
/**
|
|
356
|
+
* Creates a reusable canvas and context that are not part of the DOM.
|
|
357
|
+
* Ensures it is always set to `context.imageSmoothingEnabled = false`
|
|
358
|
+
* @see makePixelCanvas
|
|
359
|
+
* @throws {Error} If the {@link HTMLCanvasElement} context cannot be initialized.
|
|
360
|
+
*/
|
|
361
|
+
declare function makeReusableCanvas(): {
|
|
362
|
+
(width: number, height: number): ReusableCanvas;
|
|
363
|
+
reset(): void;
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Extracts {@link ImageData} from a clipboard event if an image is present.
|
|
368
|
+
*
|
|
369
|
+
* This function iterates through the {@link DataTransferItemList} to find
|
|
370
|
+
* the first item with an image MIME type and decodes it.
|
|
371
|
+
*
|
|
372
|
+
* @param clipboardEvent - The event object from a `paste` listener.
|
|
373
|
+
*
|
|
374
|
+
* @returns A promise resolving to {@link ImageData}, or `null` if no
|
|
375
|
+
* image was found in the clipboard.
|
|
376
|
+
*
|
|
377
|
+
* @example
|
|
378
|
+
* ```typescript
|
|
379
|
+
* window.addEventListener('paste', async (event) => {
|
|
380
|
+
* const data = await getImageDataFromClipboard(event)
|
|
381
|
+
* if (data) {
|
|
382
|
+
* console.log('Pasted image dimensions:', data.width, data.height)
|
|
383
|
+
* }
|
|
384
|
+
* });
|
|
385
|
+
* ```
|
|
386
|
+
*/
|
|
387
|
+
declare function getImageDataFromClipboard(clipboardEvent: ClipboardEvent): Promise<ImageData | null>;
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Converts {@link ImageData} to a PNG {@link Blob} and writes it to the system clipboard.
|
|
391
|
+
* This is a high-level utility that combines {@link imageDataToImgBlob} and
|
|
392
|
+
* {@link writeImgBlobToClipboard}.
|
|
393
|
+
* @param imageData - The image data to copy to the clipboard.
|
|
394
|
+
* @returns A promise that resolves when the image has been successfully copied.
|
|
395
|
+
* @throws {Error}
|
|
396
|
+
* If the conversion to blob fails or clipboard permissions are denied.
|
|
397
|
+
*
|
|
398
|
+
* @example
|
|
399
|
+
* ```typescript
|
|
400
|
+
* const canvas = document.querySelector('canvas')
|
|
401
|
+
* const ctx = canvas.getContext('2d')
|
|
402
|
+
* const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
|
|
403
|
+
* await writeImageDataToClipboard(imageData)
|
|
404
|
+
* ```
|
|
405
|
+
*/
|
|
406
|
+
declare function writeImageDataToClipboard(imageData: ImageData): Promise<void>;
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Writes a {@link Blob} image to the system clipboard.
|
|
410
|
+
*
|
|
411
|
+
* @param blob - The image {@link Blob} (typically `image/png`) to copy.
|
|
412
|
+
* @returns A promise that resolves when the clipboard has been updated.
|
|
413
|
+
*/
|
|
414
|
+
declare function writeImgBlobToClipboard(blob: Blob): Promise<void>;
|
|
415
|
+
|
|
229
416
|
declare function copyImageData({ data, width, height }: ImageDataLike): ImageData;
|
|
230
417
|
declare function copyImageDataLike({ data, width, height }: ImageDataLike): ImageDataLike;
|
|
231
418
|
|
|
232
|
-
|
|
233
|
-
|
|
419
|
+
/**
|
|
420
|
+
* Extracts a specific rectangular region of pixels from a larger {@link ImageDataLike}
|
|
421
|
+
* source into a new {@link Uint8ClampedArray}.
|
|
422
|
+
*
|
|
423
|
+
* This is a "read-only" operation that returns a copy of the pixel data.
|
|
424
|
+
*
|
|
425
|
+
* @param imageData - The source image data to read from.
|
|
426
|
+
* @param rect - A {@link Rect} object defining the region to extract.
|
|
427
|
+
* @returns A {@link Uint8ClampedArray} containing the RGBA pixel data of the region.
|
|
428
|
+
*/
|
|
429
|
+
declare function extractImageDataPixels(imageData: ImageDataLike, rect: Rect): Uint8ClampedArray;
|
|
430
|
+
/**
|
|
431
|
+
* @param imageData - The source image data to read from.
|
|
432
|
+
* @param x - The starting horizontal coordinate.
|
|
433
|
+
* @param y - The starting vertical coordinate.
|
|
434
|
+
* @param w - The width of the region to extract.
|
|
435
|
+
* @param h - The height of the region to extract.
|
|
436
|
+
* @returns A {@link Uint8ClampedArray} containing the RGBA pixel data of the region.
|
|
437
|
+
*/
|
|
438
|
+
declare function extractImageDataPixels(imageData: ImageDataLike, x: number, y: number, w: number, h: number): Uint8ClampedArray;
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Extracts the alpha channel from raw ImageData into an AlphaMask.
|
|
442
|
+
* When possible use {@link pixelDataToAlphaMask} instead.
|
|
443
|
+
* Repeat calls to the same data will use less memory.
|
|
444
|
+
*/
|
|
445
|
+
declare function imageDataToAlphaMask(imageData: ImageData): AlphaMask;
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Converts an {@link ImageData} object into a base64-encoded Data URL string.
|
|
449
|
+
*
|
|
450
|
+
* @param imageData - The pixel data to be converted.
|
|
451
|
+
*
|
|
452
|
+
* @returns A string representing the image in `image/png` format as a
|
|
453
|
+
* [Data URL](https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes/data).
|
|
454
|
+
* @throws {Error} If the {@link HTMLCanvasElement} context cannot be initialized.
|
|
455
|
+
* @example
|
|
456
|
+
* ```typescript
|
|
457
|
+
* const dataUrl = imageDataToDataUrl(imageData);
|
|
458
|
+
* const img = new Image();
|
|
459
|
+
* img.src = dataUrl;
|
|
460
|
+
* ```
|
|
461
|
+
*/
|
|
462
|
+
declare function imageDataToDataUrl(imageData: ImageData): string;
|
|
463
|
+
declare namespace imageDataToDataUrl {
|
|
464
|
+
var reset: () => void;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Converts an {@link ImageData} object into a {@link Blob} in PNG format.
|
|
469
|
+
*
|
|
470
|
+
* This operation is asynchronous and uses {@link OffscreenCanvas}
|
|
471
|
+
* to perform the encoding, making it suitable for usage in both the main
|
|
472
|
+
* thread and Web Workers.
|
|
473
|
+
*
|
|
474
|
+
* @param imageData - The pixel data to be encoded.
|
|
475
|
+
*
|
|
476
|
+
* @returns A promise that resolves to a {@link Blob} with the MIME type `image/png`.
|
|
477
|
+
*
|
|
478
|
+
* @throws {Error}
|
|
479
|
+
* Thrown if the {@link OffscreenCanvas} context cannot be initialized or the blob
|
|
480
|
+
* encoding fails.
|
|
481
|
+
*
|
|
482
|
+
* @example
|
|
483
|
+
* ```typescript
|
|
484
|
+
* const blob = await imageDataToImgBlob(imageData);
|
|
485
|
+
* const url = URL.createObjectURL(blob);
|
|
486
|
+
* ```
|
|
487
|
+
*/
|
|
488
|
+
declare function imageDataToImgBlob(imageData: ImageData): Promise<Blob>;
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Decodes a {@link Blob} (typically PNG) back into an {@link ImageData} object.
|
|
492
|
+
*
|
|
493
|
+
* This function uses hardware-accelerated decoding via {@link createImageBitmap}
|
|
494
|
+
* and processes the data using an {@link OffscreenCanvas} to ensure
|
|
495
|
+
* compatibility with Web Workers.
|
|
496
|
+
*
|
|
497
|
+
* @param blob - The binary image data to decode.
|
|
498
|
+
*
|
|
499
|
+
* @returns A promise resolving to the decoded {@link ImageData}.
|
|
500
|
+
*
|
|
501
|
+
* @throws {Error}
|
|
502
|
+
* Thrown if the blob is corrupted or the browser cannot decode the format.
|
|
503
|
+
*
|
|
504
|
+
* @example
|
|
505
|
+
* ```typescript
|
|
506
|
+
* const blob = await getBlobFromStorage();
|
|
507
|
+
*
|
|
508
|
+
* const imageData = await pngBlobToImageData(blob);
|
|
509
|
+
* ```
|
|
510
|
+
*/
|
|
511
|
+
declare function imgBlobToImageData(blob: Blob): Promise<ImageData>;
|
|
512
|
+
|
|
513
|
+
declare function invertImageData(imageData: ImageData): ImageData;
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Non destructively resizes the {@link ImageData} buffer to new dimensions, optionally
|
|
517
|
+
* offsetting the original content.
|
|
518
|
+
* This operation creates a new buffer. It does not scale or stretch pixels;
|
|
519
|
+
* instead, it crops or pads the image based on the new dimensions and
|
|
520
|
+
* provides an offset for repositioning.
|
|
521
|
+
*
|
|
522
|
+
* @param current The source {@link ImageData} to resize.
|
|
523
|
+
* @param newWidth The target width in pixels.
|
|
524
|
+
* @param newHeight The target height in pixels.
|
|
525
|
+
* @param offsetX The horizontal offset for placing the
|
|
526
|
+
* original image within the new buffer.
|
|
527
|
+
* @default 0
|
|
528
|
+
* @param offsetY The vertical offset for placing the
|
|
529
|
+
* original image within the new buffer.
|
|
530
|
+
* @default 0
|
|
531
|
+
*
|
|
532
|
+
* @returns A new {@link ImageData} instance with the specified dimensions.
|
|
533
|
+
*
|
|
534
|
+
* @example
|
|
535
|
+
* ```typescript
|
|
536
|
+
* // Centers an 80x80 image in a new 100x100 buffer
|
|
537
|
+
* const resized = resizeImageData(
|
|
538
|
+
* originalData,
|
|
539
|
+
* 100,
|
|
540
|
+
* 100,
|
|
541
|
+
* 10,
|
|
542
|
+
* 10
|
|
543
|
+
* );
|
|
544
|
+
* ```
|
|
545
|
+
*/
|
|
546
|
+
declare function resizeImageData(current: ImageData, newWidth: number, newHeight: number, offsetX?: number, offsetY?: number): ImageData;
|
|
234
547
|
|
|
235
548
|
declare function base64EncodeArrayBuffer(buffer: ArrayBufferLike): Base64EncodedUInt8Array;
|
|
236
549
|
declare function base64DecodeArrayBuffer(encoded: Base64EncodedUInt8Array): Uint8ClampedArray<ArrayBuffer>;
|
|
@@ -243,13 +556,168 @@ declare function deserializeRawImageData<T extends SerializedImageData>(serializ
|
|
|
243
556
|
declare function deserializeImageData<T extends SerializedImageData>(serialized: T): ImageData;
|
|
244
557
|
declare function deserializeNullableImageData<T extends SerializedImageData | null>(serialized: T): T extends null ? null : ImageData;
|
|
245
558
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
559
|
+
/**
|
|
560
|
+
* Copies a pixel buffer into a specific region of an {@link ImageData} object.
|
|
561
|
+
*
|
|
562
|
+
* This function performs a direct memory copy from a {@link Uint8ClampedArray}
|
|
563
|
+
* into the target {@link ImageData} buffer. It supports both {@link Rect}
|
|
564
|
+
* objects and discrete coordinates.
|
|
565
|
+
*
|
|
566
|
+
* @param imageData - The target {@link ImageData} to write into. Must match the rect width/height.
|
|
567
|
+
* @param data - The source pixel data (RGBA).
|
|
568
|
+
* @param rect - A {@link Rect} object defining the destination region.
|
|
569
|
+
*/
|
|
570
|
+
declare function writeImageDataPixels(imageData: ImageData, data: Uint8ClampedArray, rect: Rect): void;
|
|
571
|
+
/**
|
|
572
|
+
* @param imageData - The target {@link ImageData} to write into.
|
|
573
|
+
* @param data - The source pixel data (RGBA). Must match the width/height.
|
|
574
|
+
* @param x - The starting horizontal coordinate in the target.
|
|
575
|
+
* @param y - The starting vertical coordinate in the target.
|
|
576
|
+
* @param w - The width of the region to write.
|
|
577
|
+
* @param h - The height of the region to write.
|
|
578
|
+
*/
|
|
579
|
+
declare function writeImageDataPixels(imageData: ImageData, data: Uint8ClampedArray, x: number, y: number, w: number, h: number): void;
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* A convenience wrapper that extracts the first {@link File} from an
|
|
583
|
+
* {@link HTMLInputElement} change event and converts it into {@link ImageData}.
|
|
584
|
+
*
|
|
585
|
+
* This function handles the boilerplate of accessing the file list and checking
|
|
586
|
+
* for existence. It is ideal for use directly in an `onchange` event listener.
|
|
587
|
+
*
|
|
588
|
+
* @param event - The change {@link Event} from an `<input type="file">` element.
|
|
589
|
+
*
|
|
590
|
+
* @returns A promise that resolves to {@link ImageData} if a file was successfully
|
|
591
|
+
* processed, or `null` if no file was selected or the input was cleared.
|
|
592
|
+
*
|
|
593
|
+
* @example
|
|
594
|
+
* ```typescript
|
|
595
|
+
* const input = document.querySelector('input[type="file"]');
|
|
596
|
+
*
|
|
597
|
+
* input.addEventListener('change', async (event) => {
|
|
598
|
+
* const imageData = await fileInputChangeToImageData(event);
|
|
599
|
+
*
|
|
600
|
+
* if (imageData) {
|
|
601
|
+
* console.log('Image loaded:', imageData.width, imageData.height);
|
|
602
|
+
* }
|
|
603
|
+
* });
|
|
604
|
+
* ```
|
|
605
|
+
*/
|
|
606
|
+
declare function fileInputChangeToImageData(event: Event): Promise<ImageData | null>;
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Thrown when the user provides a file that isn't an image.
|
|
610
|
+
*/
|
|
611
|
+
declare class UnsupportedFormatError extends Error {
|
|
612
|
+
constructor(mimeType: string);
|
|
252
613
|
}
|
|
614
|
+
/**
|
|
615
|
+
* Converts a browser {@link File} object into {@link ImageData}.
|
|
616
|
+
* This utility handles the full pipeline of image decoding using hardware-accelerated
|
|
617
|
+
* APIs {@link createImageBitmap} and {@link OffscreenCanvas}. It ensures that underlying
|
|
618
|
+
* resources like `ImageBitmap` are properly closed even if the conversion fails.
|
|
619
|
+
*
|
|
620
|
+
* @param file - The image file to convert. Can be null or undefined.
|
|
621
|
+
* @returns A `Promise` resolving to the pixel data as {@link ImageData},
|
|
622
|
+
* or `null` if no file was provided.
|
|
623
|
+
* @throws {@link UnsupportedFormatError}
|
|
624
|
+
* Thrown if the provided file's MIME type does not start with `image/`.
|
|
625
|
+
* @example
|
|
626
|
+
* ```typescript
|
|
627
|
+
* try {
|
|
628
|
+
* const imageData = await fileToImageData(file);
|
|
629
|
+
* if (imageData) {
|
|
630
|
+
* console.log('Pixels:', imageData.data);
|
|
631
|
+
* }
|
|
632
|
+
* } catch (err) {
|
|
633
|
+
* if (err instanceof UnsupportedFormatError) {
|
|
634
|
+
* // Handle bad file type
|
|
635
|
+
* }
|
|
636
|
+
* }
|
|
637
|
+
* ```
|
|
638
|
+
*/
|
|
639
|
+
declare function fileToImageData(file: File | null | undefined): Promise<ImageData | null>;
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Probes the browser environment to determine which image MIME types are
|
|
643
|
+
* supported for pixel-level operations.
|
|
644
|
+
* This function performs a one-time check by attempting to convert a
|
|
645
|
+
* {@link OffscreenCanvas} to MIME types. The result is
|
|
646
|
+
* cached to prevent redundant hardware-accelerated operations on
|
|
647
|
+
* subsequent calls.
|
|
648
|
+
* @param rasterMimes List of MIME types to check
|
|
649
|
+
* @default ['image/png',
|
|
650
|
+
* 'image/jpeg',
|
|
651
|
+
* 'image/webp',
|
|
652
|
+
* 'image/avif',
|
|
653
|
+
* 'image/gif',
|
|
654
|
+
* 'image/bmp']
|
|
655
|
+
* @returns A `Promise` resolving to an array of supported MIME
|
|
656
|
+
* types from the `rasterMimes` list.
|
|
657
|
+
* @throws {Error} If the {@link OffscreenCanvas} context cannot be initialized.
|
|
658
|
+
* @example
|
|
659
|
+
* ```typescript
|
|
660
|
+
* const supported = await getSupportedPixelFormats();
|
|
661
|
+
* if (supported.includes('image/avif')) {
|
|
662
|
+
* console.log('High-efficiency formats available');
|
|
663
|
+
* }
|
|
664
|
+
* ```
|
|
665
|
+
*/
|
|
666
|
+
declare function getSupportedPixelFormats(rasterMimes?: string[]): Promise<string[]>;
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* Creates a new copy of a mask.
|
|
670
|
+
* Uses the underlying buffer's slice method for high-performance memory copying.
|
|
671
|
+
*/
|
|
672
|
+
declare function copyMask<T extends AnyMask>(src: T): T;
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Extracts a rectangular region from a 1D {@link Uint8Array} mask.
|
|
676
|
+
* This utility calculates the necessary offsets based on the `maskWidth` to
|
|
677
|
+
* slice out a specific area.
|
|
678
|
+
*
|
|
679
|
+
* @param mask - The source 1D array representing the full 2D mask.
|
|
680
|
+
* @param maskWidth - The width of the original source mask (stride).
|
|
681
|
+
* @param rect - A {@link Rect} object defining the region to extract.
|
|
682
|
+
* @returns A new {@link Uint8Array} containing the extracted region.
|
|
683
|
+
*/
|
|
684
|
+
declare function extractMask(mask: Uint8Array, maskWidth: number, rect: Rect): Uint8Array;
|
|
685
|
+
/**
|
|
686
|
+
* @param mask - The source 1D array representing the full 2D mask.
|
|
687
|
+
* @param maskWidth - The width of the original source mask (stride).
|
|
688
|
+
* @param x - The starting horizontal coordinate.
|
|
689
|
+
* @param y - The starting vertical coordinate.
|
|
690
|
+
* @param w - The width of the region to extract.
|
|
691
|
+
* @param h - The height of the region to extract.
|
|
692
|
+
* @returns A new {@link Uint8Array} containing the extracted region.
|
|
693
|
+
*/
|
|
694
|
+
declare function extractMask(mask: Uint8Array, maskWidth: number, x: number, y: number, w: number, h: number): Uint8Array;
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Inverts a BinaryMask in-place.
|
|
698
|
+
*/
|
|
699
|
+
declare function invertBinaryMask(dst: BinaryMask): void;
|
|
700
|
+
/**
|
|
701
|
+
* Inverts an AlphaMask in-place.
|
|
702
|
+
*/
|
|
703
|
+
declare function invertAlphaMask(dst: AlphaMask): void;
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* Merges a source mask into a destination AlphaMask.
|
|
707
|
+
*/
|
|
708
|
+
declare function mergeMasks(dst: AlphaMask, dstWidth: number, src: AnyMask, opts: ApplyMaskOptions): void;
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Directly applies a mask to a region of PixelData,
|
|
712
|
+
* modifying the destination's alpha channel in-place.
|
|
713
|
+
*/
|
|
714
|
+
declare function applyMaskToPixelData(dst: PixelData, mask: AnyMask, opts: ApplyMaskOptions): void;
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* Fills a rectangle in the destination PixelData with a single color,
|
|
718
|
+
* supporting blend modes, global alpha, and masking.
|
|
719
|
+
*/
|
|
720
|
+
declare function blendColorPixelData(dst: PixelData, color: Color32, opts: ColorBlendOptions): void;
|
|
253
721
|
|
|
254
722
|
/**
|
|
255
723
|
* Blits source PixelData into a destination PixelData using 32-bit integer bitwise blending.
|
|
@@ -267,4 +735,53 @@ declare class PixelData {
|
|
|
267
735
|
*/
|
|
268
736
|
declare function blendPixelData(dst: PixelData, src: PixelData, opts: PixelBlendOptions): void;
|
|
269
737
|
|
|
270
|
-
|
|
738
|
+
/**
|
|
739
|
+
* Clears a region of the PixelData to transparent (0x00000000).
|
|
740
|
+
* Internally uses the optimized fillPixelData.
|
|
741
|
+
*/
|
|
742
|
+
declare function clearPixelData(dst: PixelData, rect?: Partial<Rect>): void;
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Fills a region or the {@link PixelData} buffer with a solid color.
|
|
746
|
+
*
|
|
747
|
+
* @param dst - The target {@link PixelData} to modify.
|
|
748
|
+
* @param color - The {@link Color32} value to apply.
|
|
749
|
+
* @param rect - A {@link Rect} defining the area to fill. If omitted, the entire
|
|
750
|
+
* buffer is filled.
|
|
751
|
+
*/
|
|
752
|
+
declare function fillPixelData(dst: PixelData, color: Color32, rect?: Partial<Rect>): void;
|
|
753
|
+
/**
|
|
754
|
+
* @param dst - The target {@link PixelData} to modify.
|
|
755
|
+
* @param color - The {@link Color32} value to apply.
|
|
756
|
+
* @param x - Starting horizontal coordinate.
|
|
757
|
+
* @param y - Starting vertical coordinate.
|
|
758
|
+
* @param w - Width of the fill area.
|
|
759
|
+
* @param h - Height of the fill area.
|
|
760
|
+
*/
|
|
761
|
+
declare function fillPixelData(dst: PixelData, color: Color32, x: number, y: number, w: number, h: number): void;
|
|
762
|
+
|
|
763
|
+
declare function invertPixelData(pixelData: PixelData): PixelData;
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* Extracts the alpha channel from PixelData into a single-channel mask.
|
|
767
|
+
* Returns a Uint8Array branded as AlphaMask.
|
|
768
|
+
*/
|
|
769
|
+
declare function pixelDataToAlphaMask(pixelData: PixelData): AlphaMask;
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* Intersects a target rectangle with a boundary, trimming dimensions and masks in-place.
|
|
773
|
+
* This utility calculates the axis-aligned intersection between the `target` and `bounds`.
|
|
774
|
+
* If the `target` includes a `mask` (as in a {@link SelectionRect}), the mask is physically
|
|
775
|
+
* cropped and re-aligned using `extractMask` to match the new dimensions.
|
|
776
|
+
* @param target - The rectangle or selection object to be trimmed. **Note:** This object is mutated in-place.
|
|
777
|
+
* @param bounds - The boundary rectangle defining the maximum allowable area (e.g., canvas dimensions).
|
|
778
|
+
* @example
|
|
779
|
+
* const selection = { x: -10, y: -10, w: 50, h: 50, mask: new Uint8Array(2500) };
|
|
780
|
+
* const canvas = { x: 0, y: 0, w: 100, h: 100 };
|
|
781
|
+
* // Selection will be moved to (0,0) and resized to 40x40.
|
|
782
|
+
* // The mask is cropped by 10 px on the top and left.
|
|
783
|
+
* trimRectBounds(selection, canvas);
|
|
784
|
+
*/
|
|
785
|
+
declare function trimRectBounds<T extends Rect | SelectionRect>(target: T, bounds: Rect): void;
|
|
786
|
+
|
|
787
|
+
export { type AlphaMask, type AnyMask, type ApplyMaskOptions, type Base64EncodedUInt8Array, type BinaryMask, type BlendColor32, BlendMode, type BlendModeIndex, COLOR_32_BLEND_MODES, COLOR_32_BLEND_TO_INDEX, type Color32, type ColorBlendOptions, type FloodFillImageDataOptions, type FloodFillResult, INDEX_TO_COLOR_32_BLEND, type ImageDataLike, MaskType, type PixelBlendOptions, type PixelCanvas, PixelData, type PixelOptions, type RGBA, type Rect, type RegisteredBlender, type ReusableCanvas, type SelectionRect, type SerializedImageData, UnsupportedFormatError, applyMaskToPixelData, base64DecodeArrayBuffer, base64EncodeArrayBuffer, blendColorPixelData, blendPixelData, clearPixelData, color32ToCssRGBA, color32ToHex, colorBurnColor32, colorDistance, colorDodgeColor32, copyImageData, copyImageDataLike, copyMask, darkenColor32, darkerColor32, deserializeImageData, deserializeNullableImageData, deserializeRawImageData, differenceColor32, divideColor32, exclusionColor32, extractImageDataPixels, extractMask, fileInputChangeToImageData, fileToImageData, fillPixelData, floodFillSelection, getImageDataFromClipboard, getSupportedPixelFormats, hardLightColor32, hardMixColor32, imageDataToAlphaMask, imageDataToDataUrl, imageDataToImgBlob, imgBlobToImageData, invertAlphaMask, invertBinaryMask, invertImageData, invertPixelData, lerpColor32, lerpColor32Fast, lightenColor32, lighterColor32, linearBurnColor32, linearDodgeColor32, linearLightColor32, makePixelCanvas, makeReusableCanvas, mergeMasks, multiplyColor32, overlayColor32, overwriteColor32, packColor, packRGBA, pinLightColor32, pixelDataToAlphaMask, resizeImageData, screenColor32, serializeImageData, serializeNullableImageData, softLightColor32, sourceOverColor32, subtractColor32, trimRectBounds, unpackAlpha, unpackBlue, unpackColor, unpackColorTo, unpackGreen, unpackRed, vividLightColor32, writeImageDataPixels, writeImageDataToClipboard, writeImgBlobToClipboard };
|