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.
Files changed (40) hide show
  1. package/dist/index.dev.cjs +1405 -70
  2. package/dist/index.dev.cjs.map +1 -1
  3. package/dist/index.dev.js +1355 -68
  4. package/dist/index.dev.js.map +1 -1
  5. package/dist/index.prod.cjs +1405 -70
  6. package/dist/index.prod.cjs.map +1 -1
  7. package/dist/index.prod.d.ts +581 -64
  8. package/dist/index.prod.js +1355 -68
  9. package/dist/index.prod.js.map +1 -1
  10. package/package.json +14 -3
  11. package/src/Algorithm/floodFillSelection.ts +229 -0
  12. package/src/Canvas/PixelCanvas.ts +31 -0
  13. package/src/Canvas/ReusableCanvas.ts +44 -0
  14. package/src/Canvas/_constants.ts +2 -0
  15. package/src/Clipboard/getImageDataFromClipboard.ts +42 -0
  16. package/src/Clipboard/writeImageDataToClipboard.ts +25 -0
  17. package/src/Clipboard/writeImgBlobToClipboard.ts +13 -0
  18. package/src/ImageData/{extractImageData.ts → extractImageDataPixels.ts} +21 -3
  19. package/src/ImageData/imageDataToAlphaMask.ts +35 -0
  20. package/src/ImageData/imageDataToDataUrl.ts +27 -0
  21. package/src/ImageData/imageDataToImgBlob.ts +31 -0
  22. package/src/ImageData/imgBlobToImageData.ts +52 -0
  23. package/src/ImageData/invertImageData.ts +10 -0
  24. package/src/ImageData/resizeImageData.ts +75 -0
  25. package/src/ImageData/{writeImageData.ts → writeImageDataPixels.ts} +22 -3
  26. package/src/Input/fileInputChangeToImageData.ts +37 -0
  27. package/src/Input/fileToImageData.ts +75 -0
  28. package/src/Input/getSupportedRasterFormats.ts +74 -0
  29. package/src/Mask/extractMask.ts +86 -0
  30. package/src/Mask/mergeMasks.ts +1 -6
  31. package/src/PixelData/blendColorPixelData.ts +9 -9
  32. package/src/PixelData/fillPixelData.ts +51 -12
  33. package/src/PixelData/invertPixelData.ts +16 -0
  34. package/src/PixelData/pixelDataToAlphaMask.ts +28 -0
  35. package/src/Rect/trimRectBounds.ts +118 -0
  36. package/src/_types.ts +37 -20
  37. package/src/blend-modes.ts +506 -66
  38. package/src/color.ts +6 -6
  39. package/src/globals.d.ts +2 -0
  40. package/src/index.ts +37 -1
@@ -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<ArrayBuffer>;
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
- * @Defaults 0.
71
- * */
70
+ * @default 0
71
+ */
72
72
  x?: number;
73
73
  /**
74
74
  * The starting Y coordinate in the destination buffer.
75
- * @Default 0.
76
- * */
75
+ * @default 0
76
+ */
77
77
  y?: number;
78
78
  /**
79
79
  * The width of the region to process.
80
- * @Default Source width.
81
- * */
80
+ * @default Source width.
81
+ */
82
82
  w?: number;
83
83
  /**
84
84
  * The height of the region to process.
85
- * @Default Source height.
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. Defaults to MaskType.Binary. */
110
+ /** The interpretation logic for the provided mask.
111
+ * @default {@link MaskType.BINARY}
112
+ */
111
113
  maskType?: MaskType;
112
- /** If true the inverse of the mask will be applied */
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
- /** The specific blending function/algorithm to use for pixel math. */
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
- /** The blending logic used to combine source and destination pixels. */
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
- * Screen: Lightens the destination (inverse of Multiply).
144
- * Result = 1 - ((1 - Src) * (1 - Dst))
173
+ * 255 - ((255 - src) * (255 - dst))
145
174
  */
146
175
  declare const screenColor32: BlendColor32;
147
- /**
148
- * Linear Dodge (Additive): Simply adds the source to the destination.
149
- * Clamps at 255.
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
- * Multiply: Darkens the destination based on the source color.
154
- * Result = (Src * Dst) / 255
155
- */
156
- declare const multiplyColor32: BlendColor32;
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
- * Color Burn: Darkens the destination to reflect the source color.
169
- * Intense saturation in the darks.
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 overlayColor32: BlendColor32;
177
- declare const COLOR_32_BLEND_MODES: {
178
- sourceOver: BlendColor32;
179
- screen: BlendColor32;
180
- linearDodge: BlendColor32;
181
- multiply: BlendColor32;
182
- difference: BlendColor32;
183
- overlay: BlendColor32;
184
- hardLight: BlendColor32;
185
- colorBurn: BlendColor32;
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
- * @note Subject to a 1-bit drift (rounding down) due to fast bit-shift division.
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
- declare function extractImageData(imageData: ImageDataLike, rect: Rect): Uint8ClampedArray;
233
- declare function extractImageData(imageData: ImageDataLike, x: number, y: number, w: number, h: number): Uint8ClampedArray;
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
- declare class PixelData {
247
- readonly imageData: ImageDataLike;
248
- readonly data32: Uint32Array;
249
- readonly width: number;
250
- readonly height: number;
251
- constructor(imageData: ImageDataLike);
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
- export { type AlphaMask, type AnyMask, type ApplyMaskOptions, type Base64EncodedUInt8Array, type BinaryMask, type BlendColor32, COLOR_32_BLEND_MODES, type Color32, type ColorBlendOptions, type ImageDataLike, MaskType, type PixelBlendOptions, type PixelOptions, type RGBA, type Rect, type SerializedImageData, base64DecodeArrayBuffer, base64EncodeArrayBuffer, blendPixelData, color32ToCssRGBA, color32ToHex, colorBurnColor32, colorDistance, copyImageData, copyImageDataLike, deserializeImageData, deserializeNullableImageData, deserializeRawImageData, differenceColor32, extractImageData, hardLightColor32, lerpColor32, lerpColor32Fast, linearDodgeColor32, multiplyColor32, overlayColor32, packColor, packRGBA, screenColor32, serializeImageData, serializeNullableImageData, sourceOverColor32, unpackAlpha, unpackBlue, unpackColor, unpackColorTo, unpackGreen, unpackRed };
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 };