pixel-data-js 0.15.1 → 0.17.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 (36) hide show
  1. package/dist/index.dev.cjs +1884 -1203
  2. package/dist/index.dev.cjs.map +1 -1
  3. package/dist/index.dev.js +1858 -1190
  4. package/dist/index.dev.js.map +1 -1
  5. package/dist/index.prod.cjs +1884 -1203
  6. package/dist/index.prod.cjs.map +1 -1
  7. package/dist/index.prod.d.ts +320 -66
  8. package/dist/index.prod.js +1858 -1190
  9. package/dist/index.prod.js.map +1 -1
  10. package/package.json +1 -1
  11. package/src/BlendModes/BlendModeRegistry.ts +62 -0
  12. package/src/BlendModes/blend-modes-fast.ts +31 -84
  13. package/src/BlendModes/blend-modes-perfect.ts +343 -215
  14. package/src/BlendModes/blend-modes.ts +28 -30
  15. package/src/History/HistoryManager.ts +83 -0
  16. package/src/History/PixelAccumulator.ts +191 -0
  17. package/src/History/PixelEngineConfig.ts +18 -0
  18. package/src/History/PixelMutator/mutatorApplyMask.ts +20 -0
  19. package/src/History/PixelMutator/mutatorBlendColor.ts +22 -0
  20. package/src/History/PixelMutator/mutatorBlendPixel.ts +37 -0
  21. package/src/History/PixelMutator/mutatorBlendPixelData.ts +24 -0
  22. package/src/History/PixelMutator/mutatorFillPixelData.ts +21 -0
  23. package/src/History/PixelMutator/mutatorInvert.ts +18 -0
  24. package/src/History/PixelMutator.ts +18 -0
  25. package/src/History/PixelPatchTiles.ts +52 -0
  26. package/src/History/PixelWriter.ts +79 -0
  27. package/src/ImageData/{writeImageDataPixels.ts → writeImageDataBuffer.ts} +3 -3
  28. package/src/PixelData/applyCircleBrushToPixelData.ts +69 -0
  29. package/src/PixelData/applyMaskToPixelData.ts +1 -1
  30. package/src/PixelData/applyRectBrushToPixelData.ts +102 -0
  31. package/src/PixelData/blendPixelData.ts +2 -3
  32. package/src/PixelData/invertPixelData.ts +74 -7
  33. package/src/PixelData/writePixelDataBuffer.ts +65 -0
  34. package/src/_types.ts +31 -11
  35. package/src/index.ts +20 -10
  36. package/src/BlendModes/blend-mode-getters.ts +0 -14
@@ -67,7 +67,7 @@ type AnyMask = BinaryMask | AlphaMask;
67
67
  * Configuration for pixel manipulation operations.
68
68
  * Designed to be used by spreading a Rect object ({x, y, w, h}) directly.
69
69
  */
70
- interface PixelOptions {
70
+ interface PixelRectOptions {
71
71
  /**
72
72
  * The starting X coordinate in the destination buffer.
73
73
  * @default 0
@@ -88,11 +88,8 @@ interface PixelOptions {
88
88
  * @default Source height.
89
89
  */
90
90
  h?: number;
91
- /**
92
- * Overall layer opacity 0-255.
93
- * @default 255
94
- */
95
- alpha?: number;
91
+ }
92
+ interface PixelMaskRectOptions {
96
93
  /**
97
94
  * Mask width.
98
95
  * @default value of `w`
@@ -108,17 +105,34 @@ interface PixelOptions {
108
105
  * @default 0
109
106
  */
110
107
  my?: number;
108
+ }
109
+ interface PixelMaskInvertOptions {
110
+ /**
111
+ * If true the inverse of the mask will be applied
112
+ * @default false
113
+ */
114
+ invertMask?: boolean;
115
+ }
116
+ /**
117
+ * Configuration for pixel manipulation operations.
118
+ * Designed to be used by spreading a Rect object ({x, y, w, h}) directly.
119
+ */
120
+ interface PixelOptions extends PixelRectOptions, PixelMaskRectOptions, PixelMaskInvertOptions {
121
+ /**
122
+ * Overall layer opacity 0-255.
123
+ * @default 255
124
+ */
125
+ alpha?: number;
111
126
  /** An optional mask to restrict where pixels are written. */
112
127
  mask?: AnyMask | null;
113
128
  /** The interpretation logic for the provided mask.
114
129
  * @default {@link MaskType.ALPHA}
115
130
  */
116
131
  maskType?: MaskType;
117
- /**
118
- * If true the inverse of the mask will be applied
119
- * @default false
120
- */
121
- invertMask?: boolean;
132
+ }
133
+ interface PixelMutateOptions extends PixelRectOptions, PixelMaskRectOptions, PixelMaskInvertOptions {
134
+ /** An optional mask to restrict where pixels are mutated. */
135
+ mask?: BinaryMask | null;
122
136
  }
123
137
  /**
124
138
  * Configuration for blitting (copying/blending) one image into another.
@@ -262,32 +276,48 @@ type FloodFillResult = {
262
276
  */
263
277
  declare function floodFillSelection(img: ImageDataLike | PixelData, startX: number, startY: number, { contiguous, tolerance, bounds, }?: FloodFillImageDataOptions): FloodFillResult | null;
264
278
 
265
- declare enum BlendMode {
266
- overwrite = 0,
267
- sourceOver = 1,
268
- darken = 2,
269
- multiply = 3,
270
- colorBurn = 4,
271
- linearBurn = 5,
272
- darkerColor = 6,
273
- lighten = 7,
274
- screen = 8,
275
- colorDodge = 9,
276
- linearDodge = 10,
277
- lighterColor = 11,
278
- overlay = 12,
279
- softLight = 13,
280
- hardLight = 14,
281
- vividLight = 15,
282
- linearLight = 16,
283
- pinLight = 17,
284
- hardMix = 18,
285
- difference = 19,
286
- exclusion = 20,
287
- subtract = 21,
288
- divide = 22
279
+ declare const BaseBlendMode: {
280
+ readonly overwrite: 0;
281
+ readonly sourceOver: 1;
282
+ readonly darken: 2;
283
+ readonly multiply: 3;
284
+ readonly colorBurn: 4;
285
+ readonly linearBurn: 5;
286
+ readonly darkerColor: 6;
287
+ readonly lighten: 7;
288
+ readonly screen: 8;
289
+ readonly colorDodge: 9;
290
+ readonly linearDodge: 10;
291
+ readonly lighterColor: 11;
292
+ readonly overlay: 12;
293
+ readonly softLight: 13;
294
+ readonly hardLight: 14;
295
+ readonly vividLight: 15;
296
+ readonly linearLight: 16;
297
+ readonly pinLight: 17;
298
+ readonly hardMix: 18;
299
+ readonly difference: 19;
300
+ readonly exclusion: 20;
301
+ readonly subtract: 21;
302
+ readonly divide: 22;
303
+ };
304
+ interface RequiredBlendModes {
305
+ overwrite: 0;
289
306
  }
290
- type BlendModeIndex = typeof BlendMode[keyof typeof BlendMode];
307
+ type BaseBlendModes = RequiredBlendModes & Record<string, number>;
308
+ declare const overwriteBase: BlendColor32;
309
+
310
+ type BlendModeRegistry<BlendModes extends BaseBlendModes = BaseBlendModes, Name extends keyof BlendModes = keyof BlendModes, Index extends BlendModes[Name] = BlendModes[Name]> = ReturnType<typeof makeBlendModeRegistry<BlendModes, Name, Index>>;
311
+ declare function makeBlendModeRegistry<BlendModes extends BaseBlendModes, Name extends keyof BlendModes = keyof BlendModes, Index extends BlendModes[Name] = BlendModes[Name]>(blendModes: BlendModes, initialEntries: Record<Index, BlendColor32>): {
312
+ nameToBlend: { [K in keyof BlendModes]: BlendColor32; };
313
+ nameToIndex: Record<Name, Index>;
314
+ blendToIndex: Map<BlendColor32, Index>;
315
+ blendToName: Map<BlendColor32, Name>;
316
+ indexToBlend: BlendColor32[];
317
+ indexToName: Name[];
318
+ indexType: Index;
319
+ nameType: Name;
320
+ };
291
321
 
292
322
  declare const overwriteFast: BlendColor32;
293
323
  declare const sourceOverFast: BlendColor32;
@@ -335,15 +365,41 @@ declare const exclusionFast: BlendColor32;
335
365
  declare const subtractFast: BlendColor32;
336
366
  /** sr === 0 ? 255 : Math.min(255, (dr << 8) / sr) */
337
367
  declare const divideFast: BlendColor32;
338
- declare const FAST_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]];
339
- type RegisteredFastBlender = typeof FAST_BLENDER_REGISTRY[number][1];
340
- declare const FAST_BLEND_MODES: BlendColor32[];
341
- declare const FAST_BLEND_TO_INDEX: BaseBlendToIndexGetter<RegisteredFastBlender>;
342
- declare const INDEX_TO_FAST_BLEND: BaseIndexToBlendGetter<RegisteredFastBlender>;
343
- type FastBlendModes = {
344
- [K in keyof typeof BlendMode]: RegisteredFastBlender;
368
+ declare const BASE_FAST_BLEND_MODE_FUNCTIONS: Record<number, BlendColor32>;
369
+ declare function makeFastBlendModeRegistry(): {
370
+ nameToBlend: {
371
+ readonly overwrite: BlendColor32;
372
+ readonly sourceOver: BlendColor32;
373
+ readonly darken: BlendColor32;
374
+ readonly multiply: BlendColor32;
375
+ readonly colorBurn: BlendColor32;
376
+ readonly linearBurn: BlendColor32;
377
+ readonly darkerColor: BlendColor32;
378
+ readonly lighten: BlendColor32;
379
+ readonly screen: BlendColor32;
380
+ readonly colorDodge: BlendColor32;
381
+ readonly linearDodge: BlendColor32;
382
+ readonly lighterColor: BlendColor32;
383
+ readonly overlay: BlendColor32;
384
+ readonly softLight: BlendColor32;
385
+ readonly hardLight: BlendColor32;
386
+ readonly vividLight: BlendColor32;
387
+ readonly linearLight: BlendColor32;
388
+ readonly pinLight: BlendColor32;
389
+ readonly hardMix: BlendColor32;
390
+ readonly difference: BlendColor32;
391
+ readonly exclusion: BlendColor32;
392
+ readonly subtract: BlendColor32;
393
+ readonly divide: BlendColor32;
394
+ };
395
+ nameToIndex: Record<"overwrite" | "sourceOver" | "darken" | "multiply" | "colorBurn" | "linearBurn" | "darkerColor" | "lighten" | "screen" | "colorDodge" | "linearDodge" | "lighterColor" | "overlay" | "softLight" | "hardLight" | "vividLight" | "linearLight" | "pinLight" | "hardMix" | "difference" | "exclusion" | "subtract" | "divide", 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22>;
396
+ blendToIndex: Map<BlendColor32, 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22>;
397
+ blendToName: Map<BlendColor32, "overwrite" | "sourceOver" | "darken" | "multiply" | "colorBurn" | "linearBurn" | "darkerColor" | "lighten" | "screen" | "colorDodge" | "linearDodge" | "lighterColor" | "overlay" | "softLight" | "hardLight" | "vividLight" | "linearLight" | "pinLight" | "hardMix" | "difference" | "exclusion" | "subtract" | "divide">;
398
+ indexToBlend: BlendColor32[];
399
+ indexToName: ("overwrite" | "sourceOver" | "darken" | "multiply" | "colorBurn" | "linearBurn" | "darkerColor" | "lighten" | "screen" | "colorDodge" | "linearDodge" | "lighterColor" | "overlay" | "softLight" | "hardLight" | "vividLight" | "linearLight" | "pinLight" | "hardMix" | "difference" | "exclusion" | "subtract" | "divide")[];
400
+ indexType: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22;
401
+ nameType: "overwrite" | "sourceOver" | "darken" | "multiply" | "colorBurn" | "linearBurn" | "darkerColor" | "lighten" | "screen" | "colorDodge" | "linearDodge" | "lighterColor" | "overlay" | "softLight" | "hardLight" | "vividLight" | "linearLight" | "pinLight" | "hardMix" | "difference" | "exclusion" | "subtract" | "divide";
345
402
  };
346
- declare const FAST_BLEND_MODE_BY_NAME: FastBlendModes;
347
403
 
348
404
  declare const overwritePerfect: BlendColor32;
349
405
  declare const sourceOverPerfect: BlendColor32;
@@ -391,24 +447,41 @@ declare const exclusionPerfect: BlendColor32;
391
447
  declare const subtractPerfect: BlendColor32;
392
448
  /** sr === 0 ? 255 : Math.min(255, (dr << 8) / sr) */
393
449
  declare const dividePerfect: BlendColor32;
394
- declare const PERFECT_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]];
395
- type RegisteredPerfectBlender = typeof PERFECT_BLENDER_REGISTRY[number][1];
396
- declare const PERFECT_BLEND_MODES: BlendColor32[];
397
- declare const PERFECT_BLEND_TO_INDEX: BaseBlendToIndexGetter<RegisteredPerfectBlender>;
398
- declare const INDEX_TO_PERFECT_BLEND: BaseIndexToBlendGetter<RegisteredPerfectBlender>;
399
- type PerfectBlendModes = {
400
- [K in keyof typeof BlendMode]: RegisteredPerfectBlender;
450
+ declare const BASE_PERFECT_BLEND_MODE_FUNCTIONS: Record<number, BlendColor32>;
451
+ declare function makePerfectBlendModeRegistry(): {
452
+ nameToBlend: {
453
+ readonly overwrite: BlendColor32;
454
+ readonly sourceOver: BlendColor32;
455
+ readonly darken: BlendColor32;
456
+ readonly multiply: BlendColor32;
457
+ readonly colorBurn: BlendColor32;
458
+ readonly linearBurn: BlendColor32;
459
+ readonly darkerColor: BlendColor32;
460
+ readonly lighten: BlendColor32;
461
+ readonly screen: BlendColor32;
462
+ readonly colorDodge: BlendColor32;
463
+ readonly linearDodge: BlendColor32;
464
+ readonly lighterColor: BlendColor32;
465
+ readonly overlay: BlendColor32;
466
+ readonly softLight: BlendColor32;
467
+ readonly hardLight: BlendColor32;
468
+ readonly vividLight: BlendColor32;
469
+ readonly linearLight: BlendColor32;
470
+ readonly pinLight: BlendColor32;
471
+ readonly hardMix: BlendColor32;
472
+ readonly difference: BlendColor32;
473
+ readonly exclusion: BlendColor32;
474
+ readonly subtract: BlendColor32;
475
+ readonly divide: BlendColor32;
476
+ };
477
+ nameToIndex: Record<"overwrite" | "sourceOver" | "darken" | "multiply" | "colorBurn" | "linearBurn" | "darkerColor" | "lighten" | "screen" | "colorDodge" | "linearDodge" | "lighterColor" | "overlay" | "softLight" | "hardLight" | "vividLight" | "linearLight" | "pinLight" | "hardMix" | "difference" | "exclusion" | "subtract" | "divide", 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22>;
478
+ blendToIndex: Map<BlendColor32, 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22>;
479
+ blendToName: Map<BlendColor32, "overwrite" | "sourceOver" | "darken" | "multiply" | "colorBurn" | "linearBurn" | "darkerColor" | "lighten" | "screen" | "colorDodge" | "linearDodge" | "lighterColor" | "overlay" | "softLight" | "hardLight" | "vividLight" | "linearLight" | "pinLight" | "hardMix" | "difference" | "exclusion" | "subtract" | "divide">;
480
+ indexToBlend: BlendColor32[];
481
+ indexToName: ("overwrite" | "sourceOver" | "darken" | "multiply" | "colorBurn" | "linearBurn" | "darkerColor" | "lighten" | "screen" | "colorDodge" | "linearDodge" | "lighterColor" | "overlay" | "softLight" | "hardLight" | "vividLight" | "linearLight" | "pinLight" | "hardMix" | "difference" | "exclusion" | "subtract" | "divide")[];
482
+ indexType: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22;
483
+ nameType: "overwrite" | "sourceOver" | "darken" | "multiply" | "colorBurn" | "linearBurn" | "darkerColor" | "lighten" | "screen" | "colorDodge" | "linearDodge" | "lighterColor" | "overlay" | "softLight" | "hardLight" | "vividLight" | "linearLight" | "pinLight" | "hardMix" | "difference" | "exclusion" | "subtract" | "divide";
401
484
  };
402
- declare const PERFECT_BLEND_MODE_BY_NAME: PerfectBlendModes;
403
-
404
- type BaseIndexToBlendGetter<B extends BlendColor32> = {
405
- get: (index: BlendModeIndex) => B;
406
- };
407
- type IndexToBlendGetter = typeof INDEX_TO_FAST_BLEND | typeof INDEX_TO_PERFECT_BLEND;
408
- type BaseBlendToIndexGetter<B extends BlendColor32> = {
409
- get: (blend: B) => BlendModeIndex;
410
- };
411
- type BlendToIndexGetter = typeof FAST_BLEND_TO_INDEX | typeof PERFECT_BLEND_TO_INDEX;
412
485
 
413
486
  type PixelCanvas = {
414
487
  readonly canvas: HTMLCanvasElement;
@@ -488,6 +561,144 @@ declare function writeImageDataToClipboard(imageData: ImageData): Promise<void>;
488
561
  */
489
562
  declare function writeImgBlobToClipboard(blob: Blob): Promise<void>;
490
563
 
564
+ declare class PixelEngineConfig {
565
+ readonly tileSize: number;
566
+ readonly tileShift: number;
567
+ readonly tileMask: number;
568
+ readonly tileArea: number;
569
+ constructor(tileSize?: number);
570
+ }
571
+
572
+ type PixelPatchTiles = {
573
+ beforeTiles: PixelTile[];
574
+ afterTiles: PixelTile[];
575
+ };
576
+ declare class PixelTile {
577
+ id: number;
578
+ tx: number;
579
+ ty: number;
580
+ data32: Uint32Array;
581
+ constructor(id: number, tx: number, ty: number, tileArea: number);
582
+ }
583
+ declare function applyPatchTiles(target: PixelData, tiles: PixelTile[], tileSize?: number): void;
584
+
585
+ declare class PixelAccumulator {
586
+ target: PixelData;
587
+ readonly config: PixelEngineConfig;
588
+ lookup: (PixelTile | undefined)[];
589
+ beforeTiles: PixelTile[];
590
+ pool: PixelTile[];
591
+ constructor(target: PixelData, config: PixelEngineConfig);
592
+ getTile(id: number, tx: number, ty: number): PixelTile;
593
+ recyclePatch(patch: PixelPatchTiles): void;
594
+ /**
595
+ * @param x pixel x coordinate
596
+ * @param y pixel y coordinate
597
+ */
598
+ storeTileBeforeState(x: number, y: number): void;
599
+ /**
600
+ *
601
+ * @param x pixel x coordinate
602
+ * @param y pixel y coordinate
603
+ * @param w pixel width
604
+ * @param h pixel height
605
+ */
606
+ storeRegionBeforeState(x: number, y: number, w: number, h: number): void;
607
+ extractState(tile: PixelTile): void;
608
+ extractAfterTiles(): PixelTile[];
609
+ reset(): void;
610
+ }
611
+
612
+ interface HistoryAction {
613
+ undo: () => void;
614
+ redo: () => void;
615
+ dispose?: () => void;
616
+ }
617
+ declare class HistoryManager {
618
+ maxSteps: number;
619
+ undoStack: HistoryAction[];
620
+ redoStack: HistoryAction[];
621
+ listeners: Set<() => void>;
622
+ constructor(maxSteps?: number);
623
+ get canUndo(): boolean;
624
+ get canRedo(): boolean;
625
+ subscribe(fn: () => void): () => boolean;
626
+ notify(): void;
627
+ commit(action: HistoryAction): void;
628
+ undo(): void;
629
+ redo(): void;
630
+ clearRedoStack(): void;
631
+ }
632
+
633
+ interface PixelWriterOptions {
634
+ maxHistorySteps?: number;
635
+ tileSize?: number;
636
+ historyManager?: HistoryManager;
637
+ }
638
+ /**
639
+ * @example
640
+ * const targ = new PixelData(new ImageData(10, 10))
641
+ * const writer = new PixelWriter(targ, (writer) => {
642
+ * return {
643
+ * ...mutatorApplyMask(writer),
644
+ * ...mutatorBlendPixelData(writer),
645
+ * ...mutatorBlendColor(writer),
646
+ * ...mutatorBlendPixel(writer),
647
+ * ...mutatorFill(writer),
648
+ * }
649
+ * })
650
+ *
651
+ * // to import all mutator functions
652
+ * const writer = new PixelWriter(targ, makeFullPixelMutator)
653
+ *
654
+ * writer.withHistory((mutator) => {
655
+ * mutator.applyMask()
656
+ * mutator.blendPixelData()
657
+ * })
658
+ */
659
+ declare class PixelWriter<M> {
660
+ target: PixelData;
661
+ historyManager: HistoryManager;
662
+ accumulator: PixelAccumulator;
663
+ protected config: PixelEngineConfig;
664
+ private mutator;
665
+ constructor(target: PixelData, mutatorFactory: (writer: PixelWriter<any>) => M, { tileSize, maxHistorySteps, historyManager, }?: PixelWriterOptions);
666
+ withHistory(cb: (mutator: M) => void): void;
667
+ }
668
+
669
+ declare function makeFullPixelMutator(writer: PixelWriter<any>): {
670
+ invert(opts?: PixelMutateOptions): void;
671
+ fill(color: Color32, rect?: Partial<Rect>): void;
672
+ blendPixel(x: number, y: number, color: Color32, alpha?: number, blendFn?: BlendColor32): void;
673
+ blendColor(color: Color32, opts?: ColorBlendOptions): void;
674
+ blendPixelData(src: PixelData, opts: PixelBlendOptions): void;
675
+ applyMask: (mask: AnyMask, opts?: ApplyMaskOptions) => void;
676
+ };
677
+
678
+ declare function mutatorApplyMask(writer: PixelWriter<any>): {
679
+ applyMask: (mask: AnyMask, opts?: ApplyMaskOptions) => void;
680
+ };
681
+
682
+ declare function mutatorBlendColor(writer: PixelWriter<any>): {
683
+ blendColor(color: Color32, opts?: ColorBlendOptions): void;
684
+ };
685
+
686
+ declare function mutatorBlendPixel(writer: PixelWriter<any>): {
687
+ blendPixel(x: number, y: number, color: Color32, alpha?: number, blendFn?: BlendColor32): void;
688
+ };
689
+
690
+ declare function mutatorBlendPixelData(writer: PixelWriter<any>): {
691
+ blendPixelData(src: PixelData, opts: PixelBlendOptions): void;
692
+ };
693
+
694
+ declare function mutatorFill(writer: PixelWriter<any>): {
695
+ fill(color: Color32, rect?: Partial<Rect>): void;
696
+ };
697
+
698
+ declare function mutatorInvert(writer: PixelWriter<any>): {
699
+ invert(opts?: PixelMutateOptions): void;
700
+ };
701
+
491
702
  type ReusableImageData = ReturnType<typeof makeReusableImageData>;
492
703
  /**
493
704
  * Creates a factory function that manages a single, reusable ImageData instance.
@@ -678,7 +889,7 @@ declare function writeImageData(target: ImageData, source: ImageData, x: number,
678
889
  * @param data - The source pixel data (RGBA).
679
890
  * @param rect - A {@link Rect} object defining the destination region.
680
891
  */
681
- declare function writeImageDataPixels(imageData: ImageData, data: Uint8ClampedArray, rect: Rect): void;
892
+ declare function writeImageDataBuffer(imageData: ImageData, data: Uint8ClampedArray, rect: Rect): void;
682
893
  /**
683
894
  * @param imageData - The target {@link ImageData} to write into.
684
895
  * @param data - The source pixel data (RGBA). Must match the width/height.
@@ -687,7 +898,7 @@ declare function writeImageDataPixels(imageData: ImageData, data: Uint8ClampedAr
687
898
  * @param w - The width of the region to write.
688
899
  * @param h - The height of the region to write.
689
900
  */
690
- declare function writeImageDataPixels(imageData: ImageData, data: Uint8ClampedArray, x: number, y: number, w: number, h: number): void;
901
+ declare function writeImageDataBuffer(imageData: ImageData, data: Uint8ClampedArray, x: number, y: number, w: number, h: number): void;
691
902
 
692
903
  /**
693
904
  * Represents an image using a palette-based indexing system.
@@ -900,11 +1111,45 @@ declare function invertAlphaMask(dst: AlphaMask): void;
900
1111
  */
901
1112
  declare function mergeMasks(dst: AlphaMask, dstWidth: number, src: AnyMask, opts: ApplyMaskOptions): void;
902
1113
 
1114
+ /**
1115
+ * Applies a circular brush to pixel data, blending a color with optional falloff.
1116
+ *
1117
+ * @param target The PixelData to modify.
1118
+ * @param color The brush color.
1119
+ * @param centerX The center x-coordinate of the brush.
1120
+ * @param centerY The center y-coordinate of the brush.
1121
+ * @param brushSize The diameter of the brush.
1122
+ * @param alpha The overall opacity of the brush (0-255).
1123
+ * @default 255
1124
+ * @param fallOff A function that returns an alpha multiplier (0-1) based on the normalized distance (0-1) from the circle's center.
1125
+ * @param blendFn
1126
+ * @default sourceOverPerfect
1127
+ */
1128
+ declare function applyCircleBrushToPixelData(target: PixelData, color: Color32, centerX: number, centerY: number, brushSize: number, alpha?: number, fallOff?: (dist: number) => number, blendFn?: BlendColor32): void;
1129
+
903
1130
  /**
904
1131
  * Directly applies a mask to a region of PixelData,
905
1132
  * modifying the destination's alpha channel in-place.
906
1133
  */
907
- declare function applyMaskToPixelData(dst: PixelData, mask: AnyMask, opts: ApplyMaskOptions): void;
1134
+ declare function applyMaskToPixelData(dst: PixelData, mask: AnyMask, opts?: ApplyMaskOptions): void;
1135
+
1136
+ /**
1137
+ * Applies a rectangular brush to pixel data, blending a color with optional falloff.
1138
+ *
1139
+ * @param target The PixelData to modify.
1140
+ * @param color The brush color.
1141
+ * @param centerX The center x-coordinate of the brush.
1142
+ * @param centerY The center y-coordinate of the brush.
1143
+ * @param brushWidth
1144
+ * @param brushHeight
1145
+ * @param alpha The overall opacity of the brush (0-255).
1146
+ * @default 255
1147
+ * @param fallOff A function that returns an alpha multiplier (0-1) based on the normalized distance (0-1) from the circle's center.
1148
+ * @param blendFn
1149
+ * @default sourceOverPerfect
1150
+ */
1151
+ declare function applyRectBrushToPixelData(target: PixelData, color: Color32, centerX: number, centerY: number, brushWidth: number, brushHeight: number, alpha?: number, fallOff?: (dist: number) => number, blendFn?: BlendColor32): void;
1152
+ declare function getRectBrushBounds(centerX: number, centerY: number, brushWidth: number, brushHeight: number, targetWidth?: number, targetHeight?: number): Rect;
908
1153
 
909
1154
  /**
910
1155
  * Fills a rectangle in the destination PixelData with a single color,
@@ -967,7 +1212,7 @@ declare function fillPixelData(dst: PixelData, color: Color32, rect?: Partial<Re
967
1212
  */
968
1213
  declare function fillPixelData(dst: PixelData, color: Color32, x: number, y: number, w: number, h: number): void;
969
1214
 
970
- declare function invertPixelData(pixelData: PixelData): PixelData;
1215
+ declare function invertPixelData(pixelData: PixelData, opts?: PixelMutateOptions): void;
971
1216
 
972
1217
  /**
973
1218
  * Extracts the alpha channel from PixelData into a single-channel mask.
@@ -996,6 +1241,15 @@ declare function resamplePixelData(pixelData: PixelData, factor: number): PixelD
996
1241
  */
997
1242
  declare function rotatePixelData(pixelData: PixelData): void;
998
1243
 
1244
+ /**
1245
+ * Copies a pixel buffer into a specific region of a {@link PixelData} object.
1246
+ *
1247
+ * This function performs a direct memory copy from a {@link Uint32Array}
1248
+ * into the target {@link PixelData} buffer.
1249
+ */
1250
+ declare function writePixelDataBuffer(target: PixelData, data: Uint32Array, rect: Rect): void;
1251
+ declare function writePixelDataBuffer(target: PixelData, data: Uint32Array, x: number, y: number, w: number, h: number): void;
1252
+
999
1253
  /**
1000
1254
  * Intersects a target rectangle with a boundary, trimming dimensions and masks in-place.
1001
1255
  * This utility calculates the axis-aligned intersection between the `target` and `bounds`.
@@ -1012,4 +1266,4 @@ declare function rotatePixelData(pixelData: PixelData): void;
1012
1266
  */
1013
1267
  declare function trimRectBounds<T extends Rect | SelectionRect>(target: T, bounds: Rect): void;
1014
1268
 
1015
- export { type AlphaMask, type AnyMask, type ApplyMaskOptions, type Base64EncodedUInt8Array, type BinaryMask, type BlendColor32, BlendMode, type BlendModeIndex, type BlendToIndexGetter, type Color32, type ColorBlendOptions, FAST_BLENDER_REGISTRY, FAST_BLEND_MODES, FAST_BLEND_MODE_BY_NAME, FAST_BLEND_TO_INDEX, type FastBlendModes, type FloodFillImageDataOptions, type FloodFillResult, INDEX_TO_FAST_BLEND, INDEX_TO_PERFECT_BLEND, type ImageDataLike, type IndexToBlendGetter, IndexedImage, MaskType, PERFECT_BLENDER_REGISTRY, PERFECT_BLEND_MODES, PERFECT_BLEND_MODE_BY_NAME, PERFECT_BLEND_TO_INDEX, type PerfectBlendModes, type PixelBlendOptions, type PixelCanvas, PixelData, type PixelOptions, type Point, type RGBA, type Rect, type RegisteredFastBlender, type RegisteredPerfectBlender, type ReusableCanvas, type ReusableImageData, type SelectionRect, type SerializedImageData, UnsupportedFormatError, applyMaskToPixelData, base64DecodeArrayBuffer, base64EncodeArrayBuffer, blendColorPixelData, blendPixelData, clearPixelData, color32ToCssRGBA, color32ToHex, colorBurnFast, colorBurnPerfect, colorDistance, colorDodgeFast, colorDodgePerfect, copyImageData, copyImageDataLike, copyMask, darkenFast, darkenPerfect, darkerFast, darkerPerfect, deserializeImageData, deserializeNullableImageData, deserializeRawImageData, differenceFast, differencePerfect, divideFast, dividePerfect, exclusionFast, exclusionPerfect, extractImageDataBuffer, extractMask, extractPixelData, extractPixelDataBuffer, fileInputChangeToImageData, fileToImageData, fillPixelData, floodFillSelection, getImageDataFromClipboard, getIndexedImageColorCounts, getSupportedPixelFormats, hardLightFast, hardLightPerfect, hardMixFast, hardMixPerfect, imageDataToAlphaMask, imageDataToDataUrl, imageDataToImgBlob, imageDataToUInt32Array, imgBlobToImageData, indexedImageToAverageColor, indexedImageToImageData, invertAlphaMask, invertBinaryMask, invertImageData, invertPixelData, lerpColor32, lerpColor32Fast, lightenFast, lightenPerfect, lighterFast, lighterPerfect, linearBurnFast, linearBurnPerfect, linearDodgeFast, linearDodgePerfect, linearLightFast, linearLightPerfect, makePixelCanvas, makeReusableCanvas, makeReusableImageData, mergeMasks, multiplyFast, multiplyPerfect, overlayFast, overlayPerfect, overwriteFast, overwritePerfect, packColor, packRGBA, pinLightFast, pinLightPerfect, pixelDataToAlphaMask, reflectPixelDataHorizontal, reflectPixelDataVertical, resampleImageData, resampleIndexedImage, resamplePixelData, resizeImageData, rotatePixelData, screenFast, screenPerfect, serializeImageData, serializeNullableImageData, softLightFast, softLightPerfect, sourceOverFast, sourceOverPerfect, subtractFast, subtractPerfect, trimRectBounds, unpackAlpha, unpackBlue, unpackColor, unpackColorTo, unpackGreen, unpackRed, vividLightFast, vividLightPerfect, writeImageData, writeImageDataPixels, writeImageDataToClipboard, writeImgBlobToClipboard };
1269
+ export { type AlphaMask, type AnyMask, type ApplyMaskOptions, BASE_FAST_BLEND_MODE_FUNCTIONS, BASE_PERFECT_BLEND_MODE_FUNCTIONS, type Base64EncodedUInt8Array, BaseBlendMode, type BaseBlendModes, type BinaryMask, type BlendColor32, type BlendModeRegistry, type Color32, type ColorBlendOptions, type FloodFillImageDataOptions, type FloodFillResult, type HistoryAction, HistoryManager, type ImageDataLike, IndexedImage, MaskType, PixelAccumulator, type PixelBlendOptions, type PixelCanvas, PixelData, PixelEngineConfig, type PixelMaskInvertOptions, type PixelMaskRectOptions, type PixelMutateOptions, type PixelOptions, type PixelPatchTiles, type PixelRectOptions, PixelTile, PixelWriter, type PixelWriterOptions, type Point, type RGBA, type Rect, type RequiredBlendModes, type ReusableCanvas, type ReusableImageData, type SelectionRect, type SerializedImageData, UnsupportedFormatError, applyCircleBrushToPixelData, applyMaskToPixelData, applyPatchTiles, applyRectBrushToPixelData, base64DecodeArrayBuffer, base64EncodeArrayBuffer, blendColorPixelData, blendPixelData, clearPixelData, color32ToCssRGBA, color32ToHex, colorBurnFast, colorBurnPerfect, colorDistance, colorDodgeFast, colorDodgePerfect, copyImageData, copyImageDataLike, copyMask, darkenFast, darkenPerfect, darkerFast, darkerPerfect, deserializeImageData, deserializeNullableImageData, deserializeRawImageData, differenceFast, differencePerfect, divideFast, dividePerfect, exclusionFast, exclusionPerfect, extractImageDataBuffer, extractMask, extractPixelData, extractPixelDataBuffer, fileInputChangeToImageData, fileToImageData, fillPixelData, floodFillSelection, getImageDataFromClipboard, getIndexedImageColorCounts, getRectBrushBounds, getSupportedPixelFormats, hardLightFast, hardLightPerfect, hardMixFast, hardMixPerfect, imageDataToAlphaMask, imageDataToDataUrl, imageDataToImgBlob, imageDataToUInt32Array, imgBlobToImageData, indexedImageToAverageColor, indexedImageToImageData, invertAlphaMask, invertBinaryMask, invertImageData, invertPixelData, lerpColor32, lerpColor32Fast, lightenFast, lightenPerfect, lighterFast, lighterPerfect, linearBurnFast, linearBurnPerfect, linearDodgeFast, linearDodgePerfect, linearLightFast, linearLightPerfect, makeBlendModeRegistry, makeFastBlendModeRegistry, makeFullPixelMutator, makePerfectBlendModeRegistry, makePixelCanvas, makeReusableCanvas, makeReusableImageData, mergeMasks, multiplyFast, multiplyPerfect, mutatorApplyMask, mutatorBlendColor, mutatorBlendPixel, mutatorBlendPixelData, mutatorFill, mutatorInvert, overlayFast, overlayPerfect, overwriteBase, overwriteFast, overwritePerfect, packColor, packRGBA, pinLightFast, pinLightPerfect, pixelDataToAlphaMask, reflectPixelDataHorizontal, reflectPixelDataVertical, resampleImageData, resampleIndexedImage, resamplePixelData, resizeImageData, rotatePixelData, screenFast, screenPerfect, serializeImageData, serializeNullableImageData, softLightFast, softLightPerfect, sourceOverFast, sourceOverPerfect, subtractFast, subtractPerfect, trimRectBounds, unpackAlpha, unpackBlue, unpackColor, unpackColorTo, unpackGreen, unpackRed, vividLightFast, vividLightPerfect, writeImageData, writeImageDataBuffer, writeImageDataToClipboard, writeImgBlobToClipboard, writePixelDataBuffer };