pixel-data-js 0.34.0 → 0.36.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 (33) hide show
  1. package/dist/index.prod.cjs +188 -56
  2. package/dist/index.prod.cjs.map +1 -1
  3. package/dist/index.prod.d.ts +30 -14
  4. package/dist/index.prod.js +184 -55
  5. package/dist/index.prod.js.map +1 -1
  6. package/package.json +1 -1
  7. package/src/History/PixelAccumulator.ts +27 -6
  8. package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +2 -0
  9. package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +5 -1
  10. package/src/History/PixelMutator/mutatorApplyMask.ts +1 -0
  11. package/src/History/PixelMutator/mutatorBlendAlphaMask.ts +1 -0
  12. package/src/History/PixelMutator/mutatorBlendBinaryMask.ts +1 -0
  13. package/src/History/PixelMutator/mutatorBlendColor.ts +2 -0
  14. package/src/History/PixelMutator/mutatorBlendColorPaintAlphaMask.ts +1 -0
  15. package/src/History/PixelMutator/mutatorBlendColorPaintBinaryMask.ts +1 -0
  16. package/src/History/PixelMutator/mutatorBlendColorPaintMask.ts +1 -0
  17. package/src/History/PixelMutator/mutatorBlendColorPaintRect.ts +2 -0
  18. package/src/History/PixelMutator/mutatorBlendMask.ts +1 -0
  19. package/src/History/PixelMutator/mutatorBlendPixel.ts +1 -0
  20. package/src/History/PixelMutator/mutatorBlendPixelData.ts +1 -0
  21. package/src/History/PixelMutator/mutatorClear.ts +2 -1
  22. package/src/History/PixelMutator/mutatorFill.ts +53 -37
  23. package/src/History/PixelMutator/mutatorFillBinaryMask.ts +2 -1
  24. package/src/History/PixelMutator/mutatorInvert.ts +3 -2
  25. package/src/History/PixelMutator.ts +1 -2
  26. package/src/Paint/PaintRect.ts +4 -1
  27. package/src/Paint/Render/PaintCursorRenderer.ts +40 -28
  28. package/src/Paint/_paint-types.ts +5 -0
  29. package/src/PixelData/_pixelData-types.ts +7 -0
  30. package/src/PixelData/cropPixelData.ts +36 -0
  31. package/src/PixelData/fillPixelData.ts +6 -6
  32. package/src/PixelData/trimPixelData.ts +49 -0
  33. package/src/index.ts +2 -0
@@ -71,6 +71,7 @@ __export(src_exports, {
71
71
  copyImageDataLike: () => copyImageDataLike,
72
72
  copyMask: () => copyMask,
73
73
  copyPixelData: () => copyPixelData,
74
+ cropPixelData: () => cropPixelData,
74
75
  darkenFast: () => darkenFast,
75
76
  darkenPerfect: () => darkenPerfect,
76
77
  darkerFast: () => darkerFast,
@@ -109,6 +110,7 @@ __export(src_exports, {
109
110
  getImageDataFromClipboard: () => getImageDataFromClipboard,
110
111
  getIndexedImageColor: () => getIndexedImageColor,
111
112
  getIndexedImageColorCounts: () => getIndexedImageColorCounts,
113
+ getPixelDataTransparentTrimmedBounds: () => getPixelDataTransparentTrimmedBounds,
112
114
  getRectsBounds: () => getRectsBounds,
113
115
  getSupportedPixelFormats: () => getSupportedPixelFormats,
114
116
  hardLightFast: () => hardLightFast,
@@ -204,7 +206,6 @@ __export(src_exports, {
204
206
  mutatorClear: () => mutatorClear,
205
207
  mutatorFill: () => mutatorFill,
206
208
  mutatorFillBinaryMask: () => mutatorFillBinaryMask,
207
- mutatorFillRect: () => mutatorFillRect,
208
209
  mutatorInvert: () => mutatorInvert,
209
210
  overlayFast: () => overlayFast,
210
211
  overlayPerfect: () => overlayPerfect,
@@ -248,6 +249,8 @@ __export(src_exports, {
248
249
  toBlendModeIndexAndName: () => toBlendModeIndexAndName,
249
250
  trimMaskRectBounds: () => trimMaskRectBounds,
250
251
  trimRectBounds: () => trimRectBounds,
252
+ trimTransparentPixelData: () => trimTransparentPixelData,
253
+ trimTransparentPixelDataInPlace: () => trimTransparentPixelDataInPlace,
251
254
  uInt32ArrayToImageData: () => uInt32ArrayToImageData,
252
255
  uInt32ArrayToImageDataLike: () => uInt32ArrayToImageDataLike,
253
256
  uInt32ArrayToPixelData: () => uInt32ArrayToPixelData,
@@ -2416,6 +2419,11 @@ var PixelAccumulator = class {
2416
2419
  storePixelBeforeState(x, y) {
2417
2420
  const shift = this.config.tileShift;
2418
2421
  const columns = this.config.targetColumns;
2422
+ const targetWidth = this.config.target.w;
2423
+ const targetHeight = this.config.target.h;
2424
+ if (x < 0 || x >= targetWidth || y < 0 || y >= targetHeight) {
2425
+ return null;
2426
+ }
2419
2427
  const tx = x >> shift;
2420
2428
  const ty = y >> shift;
2421
2429
  const id = ty * columns + tx;
@@ -2446,10 +2454,19 @@ var PixelAccumulator = class {
2446
2454
  storeRegionBeforeState(x, y, w, h) {
2447
2455
  const shift = this.config.tileShift;
2448
2456
  const columns = this.config.targetColumns;
2449
- const startX = x >> shift;
2450
- const startY = y >> shift;
2451
- const endX = x + w - 1 >> shift;
2452
- const endY = y + h - 1 >> shift;
2457
+ const targetWidth = this.config.target.w;
2458
+ const targetHeight = this.config.target.h;
2459
+ const clipX1 = Math.max(0, x);
2460
+ const clipY1 = Math.max(0, y);
2461
+ const clipX2 = Math.min(targetWidth - 1, x + w - 1);
2462
+ const clipY2 = Math.min(targetHeight - 1, y + h - 1);
2463
+ if (clipX2 < clipX1 || clipY2 < clipY1) {
2464
+ return null;
2465
+ }
2466
+ const startX = clipX1 >> shift;
2467
+ const startY = clipY1 >> shift;
2468
+ const endX = clipX2 >> shift;
2469
+ const endY = clipY2 >> shift;
2453
2470
  const startIndex = this.beforeTiles.length;
2454
2471
  for (let ty = startY; ty <= endY; ty++) {
2455
2472
  for (let tx = startX; tx <= endX; tx++) {
@@ -2920,6 +2937,7 @@ var mutatorApplyAlphaMask = ((writer, deps = defaults) => {
2920
2937
  const w = opts?.w ?? target.w;
2921
2938
  const h = opts?.h ?? target.h;
2922
2939
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
2940
+ if (!didChange) return false;
2923
2941
  return didChange(applyAlphaMaskToPixelData2(target, mask, opts));
2924
2942
  }
2925
2943
  };
@@ -3022,7 +3040,12 @@ var mutatorApplyBinaryMask = ((writer, deps = defaults2) => {
3022
3040
  const w = opts?.w ?? target.w;
3023
3041
  const h = opts?.h ?? target.h;
3024
3042
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3025
- return didChange(applyBinaryMaskToPixelData2(target, mask, opts));
3043
+ if (!didChange) return false;
3044
+ const b = applyBinaryMaskToPixelData2(target, mask, opts);
3045
+ console.log({
3046
+ b
3047
+ });
3048
+ return didChange(b);
3026
3049
  }
3027
3050
  };
3028
3051
  });
@@ -3045,6 +3068,7 @@ var mutatorApplyMask = ((writer, deps = defaults3) => {
3045
3068
  const w = opts?.w ?? target.w;
3046
3069
  const h = opts?.h ?? target.h;
3047
3070
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3071
+ if (!didChange) return false;
3048
3072
  if (mask.type === 1 /* BINARY */) {
3049
3073
  return didChange(applyBinaryMaskToPixelData2(target, mask, opts));
3050
3074
  } else {
@@ -3189,6 +3213,7 @@ var mutatorBlendAlphaMask = ((writer, deps = defaults4) => {
3189
3213
  const w = opts?.w ?? src.w;
3190
3214
  const h = opts?.h ?? src.h;
3191
3215
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3216
+ if (!didChange) return false;
3192
3217
  return didChange(blendPixelDataAlphaMask2(writer.config.target, src, mask, opts));
3193
3218
  }
3194
3219
  };
@@ -3316,6 +3341,7 @@ var mutatorBlendBinaryMask = ((writer, deps = defaults5) => {
3316
3341
  const w = opts?.w ?? src.w;
3317
3342
  const h = opts?.h ?? src.h;
3318
3343
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3344
+ if (!didChange) return false;
3319
3345
  return didChange(blendPixelDataBinaryMask2(writer.config.target, src, mask, opts));
3320
3346
  }
3321
3347
  };
@@ -3390,6 +3416,7 @@ var mutatorBlendColor = ((writer, deps = defaults6) => {
3390
3416
  const w = opts?.w ?? target.w;
3391
3417
  const h = opts?.h ?? target.h;
3392
3418
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3419
+ if (!didChange) return false;
3393
3420
  return didChange(blendColorPixelData2(target, color, opts));
3394
3421
  }
3395
3422
  };
@@ -3502,6 +3529,7 @@ var mutatorBlendColorPaintAlphaMask = ((writer, deps = defaults7) => {
3502
3529
  const tx = x + mask.centerOffsetX;
3503
3530
  const ty = y + mask.centerOffsetY;
3504
3531
  const didChange = writer.accumulator.storeRegionBeforeState(tx, ty, mask.w, mask.h);
3532
+ if (!didChange) return false;
3505
3533
  OPTS.x = tx;
3506
3534
  OPTS.y = ty;
3507
3535
  OPTS.alpha = alpha;
@@ -3598,6 +3626,7 @@ var mutatorBlendColorPaintBinaryMask = ((writer, deps = defaults8) => {
3598
3626
  const tx = x + mask.centerOffsetX;
3599
3627
  const ty = y + mask.centerOffsetY;
3600
3628
  const didChange = writer.accumulator.storeRegionBeforeState(tx, ty, mask.w, mask.h);
3629
+ if (!didChange) return false;
3601
3630
  OPTS.x = tx;
3602
3631
  OPTS.y = ty;
3603
3632
  OPTS.alpha = alpha;
@@ -3628,6 +3657,7 @@ var mutatorBlendColorPaintMask = ((writer, deps = defaults9) => {
3628
3657
  const tx = x + mask.centerOffsetX;
3629
3658
  const ty = y + mask.centerOffsetY;
3630
3659
  const didChange = writer.accumulator.storeRegionBeforeState(tx, ty, mask.w, mask.h);
3660
+ if (!didChange) return false;
3631
3661
  OPTS.x = tx;
3632
3662
  OPTS.y = ty;
3633
3663
  OPTS.alpha = alpha;
@@ -3669,6 +3699,7 @@ var mutatorBlendColorPaintRect = ((writer, deps = defaults10) => {
3669
3699
  OPTS.blendFn = blendFn;
3670
3700
  OPTS.alpha = alpha;
3671
3701
  const didChange = writer.accumulator.storeRegionBeforeState(topLeftX, topLeftY, brushWidth, brushHeight);
3702
+ if (!didChange) return false;
3672
3703
  return didChange(blendColorPixelData2(target, color, OPTS));
3673
3704
  }
3674
3705
  };
@@ -3691,6 +3722,7 @@ var mutatorBlendMask = ((writer, deps = defaults11) => {
3691
3722
  const w = opts?.w ?? src.w;
3692
3723
  const h = opts?.h ?? src.h;
3693
3724
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3725
+ if (!didChange) return false;
3694
3726
  if (mask.type === 1 /* BINARY */) {
3695
3727
  return didChange(blendPixelDataBinaryMask2(writer.config.target, src, mask, opts));
3696
3728
  } else {
@@ -3737,6 +3769,7 @@ var mutatorBlendPixel = ((writer, deps = defaults12) => {
3737
3769
  return {
3738
3770
  blendPixel(x, y, color, alpha, blendFn) {
3739
3771
  const didChange = writer.accumulator.storePixelBeforeState(x, y);
3772
+ if (!didChange) return false;
3740
3773
  return didChange(blendPixel2(writer.config.target, x, y, color, alpha, blendFn));
3741
3774
  }
3742
3775
  };
@@ -3844,6 +3877,7 @@ var mutatorBlendPixelData = ((writer, deps = defaults13) => {
3844
3877
  const w = opts?.w ?? src.w;
3845
3878
  const h = opts?.h ?? src.h;
3846
3879
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3880
+ if (!didChange) return false;
3847
3881
  return didChange(blendPixelData2(writer.config.target, src, opts));
3848
3882
  }
3849
3883
  };
@@ -3857,16 +3891,16 @@ function fillPixelData(dst, color, _x, _y, _w, _h) {
3857
3891
  let y;
3858
3892
  let w;
3859
3893
  let h;
3860
- if (typeof _x === "object") {
3861
- x = _x.x ?? 0;
3862
- y = _x.y ?? 0;
3863
- w = _x.w ?? dstW;
3864
- h = _x.h ?? dstH;
3865
- } else if (typeof _x === "number") {
3894
+ if (typeof _x === "number") {
3866
3895
  x = _x;
3867
3896
  y = _y;
3868
3897
  w = _w;
3869
3898
  h = _h;
3899
+ } else if (typeof _x === "object") {
3900
+ x = _x.x ?? 0;
3901
+ y = _x.y ?? 0;
3902
+ w = _x.w ?? dstW;
3903
+ h = _x.h ?? dstH;
3870
3904
  } else {
3871
3905
  x = 0;
3872
3906
  y = 0;
@@ -3931,6 +3965,7 @@ var mutatorClear = ((writer, deps = defaults14) => {
3931
3965
  const w = rect?.w ?? target.w;
3932
3966
  const h = rect?.h ?? target.h;
3933
3967
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3968
+ if (!didChange) return false;
3934
3969
  return didChange(fillPixelData2(target, 0, x, y, w, h));
3935
3970
  }
3936
3971
  };
@@ -3944,24 +3979,37 @@ var mutatorFill = ((writer, deps = defaults15) => {
3944
3979
  const {
3945
3980
  fillPixelData: fillPixelData2 = defaults15.fillPixelData
3946
3981
  } = deps;
3947
- return {
3948
- fill(color, x = 0, y = 0, w = writer.config.target.w, h = writer.config.target.h) {
3949
- const target = writer.config.target;
3950
- const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
3951
- return didChange(fillPixelData2(target, color, x, y, w, h));
3982
+ const config = writer.config;
3983
+ function fill(color, _x, _y, _w, _h) {
3984
+ const target = config.target;
3985
+ const dstW = target.w;
3986
+ const dstH = target.h;
3987
+ let x;
3988
+ let y;
3989
+ let w;
3990
+ let h;
3991
+ if (typeof _x === "number") {
3992
+ x = _x;
3993
+ y = _y;
3994
+ w = _w;
3995
+ h = _h;
3996
+ } else if (typeof _x === "object") {
3997
+ x = _x.x ?? 0;
3998
+ y = _x.y ?? 0;
3999
+ w = _x.w ?? dstW;
4000
+ h = _x.h ?? dstH;
4001
+ } else {
4002
+ x = 0;
4003
+ y = 0;
4004
+ w = dstW;
4005
+ h = dstH;
3952
4006
  }
3953
- };
3954
- });
3955
- var mutatorFillRect = ((writer, deps = defaults15) => {
3956
- const {
3957
- fillPixelData: fillPixelData2 = defaults15.fillPixelData
3958
- } = deps;
4007
+ const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
4008
+ if (!didChange) return false;
4009
+ return didChange(fillPixelData2(target, color, x, y, w, h));
4010
+ }
3959
4011
  return {
3960
- fillRect(color, rect) {
3961
- const target = writer.config.target;
3962
- const didChange = writer.accumulator.storeRegionBeforeState(rect.x, rect.y, rect.w, rect.h);
3963
- return didChange(fillPixelData2(target, color, rect.x, rect.y, rect.w, rect.h));
3964
- }
4012
+ fill
3965
4013
  };
3966
4014
  });
3967
4015
 
@@ -4023,6 +4071,7 @@ var mutatorFillBinaryMask = ((writer, deps = defaults16) => {
4023
4071
  return {
4024
4072
  fillBinaryMask(color, mask, x = 0, y = 0) {
4025
4073
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, mask.w, mask.h);
4074
+ if (!didChange) return false;
4026
4075
  return didChange(fillPixelDataBinaryMask2(writer.config.target, color, mask, x, y));
4027
4076
  }
4028
4077
  };
@@ -4107,7 +4156,8 @@ var mutatorInvert = ((writer, deps = defaults17) => {
4107
4156
  const w = opts?.w ?? target.w;
4108
4157
  const h = opts?.h ?? target.h;
4109
4158
  const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h);
4110
- return didChange(invertPixelData2(target, opts));
4159
+ if (!didChange) return false;
4160
+ return didChange?.(invertPixelData2(target, opts));
4111
4161
  }
4112
4162
  };
4113
4163
  });
@@ -4132,7 +4182,6 @@ function makeFullPixelMutator(writer) {
4132
4182
  ...mutatorClear(writer),
4133
4183
  ...mutatorFill(writer),
4134
4184
  ...mutatorFillBinaryMask(writer),
4135
- ...mutatorFillRect(writer),
4136
4185
  ...mutatorInvert(writer)
4137
4186
  };
4138
4187
  }
@@ -6163,6 +6212,9 @@ function makeRectFalloffPaintAlphaMask(width, height, fallOff = (d) => d) {
6163
6212
  // src/Paint/PaintRect.ts
6164
6213
  function makePaintRect(w, h) {
6165
6214
  return {
6215
+ type: null,
6216
+ outlineType: 2 /* RECT */,
6217
+ data: null,
6166
6218
  w,
6167
6219
  h,
6168
6220
  centerOffsetX: -(w - 1 >> 1),
@@ -6199,31 +6251,34 @@ function makePaintCursorRenderer(reusableCanvasFactory) {
6199
6251
  const getPixelData = makeReusablePixelData();
6200
6252
  let _color = packColor(0, 255, 255, 255);
6201
6253
  let _scale = 1;
6202
- let currentMask = {
6203
- type: 1 /* BINARY */,
6254
+ let currentBrush = {
6255
+ type: null,
6204
6256
  outlineType: 2 /* RECT */,
6205
6257
  w: 1,
6206
6258
  h: 1,
6207
6259
  centerOffsetX: -(10 - 1 >> 1),
6208
- centerOffsetY: -(10 - 1 >> 1)
6260
+ centerOffsetY: -(10 - 1 >> 1),
6261
+ data: null
6209
6262
  };
6210
6263
  let outline;
6211
6264
  function update(paintMask, scale, color, alphaThreshold = 127) {
6212
- currentMask = paintMask ?? currentMask;
6265
+ currentBrush = paintMask ?? currentBrush;
6213
6266
  _scale = scale ?? _scale;
6214
6267
  _color = color ?? _color;
6215
- updateBuffer(currentMask.w * _scale + 2 * _scale, currentMask.h * _scale + 2 * _scale);
6216
- if (currentMask.type === 1 /* BINARY */) {
6217
- if (currentMask.outlineType === 1 /* CIRCLE */) {
6218
- outline = makeCircleBinaryMaskOutline(currentMask.w, _scale);
6219
- } else if (currentMask.outlineType === 2 /* RECT */) {
6220
- outline = makeRectBinaryMaskOutline(currentMask.w, currentMask.h, _scale);
6221
- } else if (currentMask.outlineType === 0 /* MASKED */) {
6222
- outline = makeBinaryMaskOutline(currentMask, _scale);
6268
+ updateBuffer(currentBrush.w * _scale + 2 * _scale, currentBrush.h * _scale + 2 * _scale);
6269
+ if (currentBrush.type === 1 /* BINARY */) {
6270
+ if (currentBrush.outlineType === 1 /* CIRCLE */) {
6271
+ outline = makeCircleBinaryMaskOutline(currentBrush.w, _scale);
6272
+ } else if (currentBrush.outlineType === 2 /* RECT */) {
6273
+ outline = makeRectBinaryMaskOutline(currentBrush.w, currentBrush.h, _scale);
6274
+ } else if (currentBrush.outlineType === 0 /* MASKED */) {
6275
+ outline = makeBinaryMaskOutline(currentBrush, _scale);
6223
6276
  }
6224
- } else if (currentMask.type === 0 /* ALPHA */) {
6225
- const mask = makeBinaryMaskFromAlphaMask(currentMask, alphaThreshold);
6277
+ } else if (currentBrush.type === 0 /* ALPHA */) {
6278
+ const mask = makeBinaryMaskFromAlphaMask(currentBrush, alphaThreshold);
6226
6279
  outline = makeBinaryMaskOutline(mask, _scale);
6280
+ } else {
6281
+ outline = makeRectBinaryMaskOutline(currentBrush.w, currentBrush.h, _scale);
6227
6282
  }
6228
6283
  const pixelData = getPixelData(outline.w, outline.h);
6229
6284
  fillPixelDataBinaryMask(pixelData, _color, outline);
@@ -6236,10 +6291,10 @@ function makePaintCursorRenderer(reusableCanvasFactory) {
6236
6291
  h: 0
6237
6292
  };
6238
6293
  function getBounds(centerX, centerY) {
6239
- boundsScratch.x = centerX + currentMask.centerOffsetX;
6240
- boundsScratch.y = centerY + currentMask.centerOffsetY;
6241
- boundsScratch.w = currentMask.w;
6242
- boundsScratch.h = currentMask.h;
6294
+ boundsScratch.x = centerX + currentBrush.centerOffsetX;
6295
+ boundsScratch.y = centerY + currentBrush.centerOffsetY;
6296
+ boundsScratch.w = currentBrush.w;
6297
+ boundsScratch.h = currentBrush.h;
6243
6298
  return boundsScratch;
6244
6299
  }
6245
6300
  const boundsScaledScratch = {
@@ -6249,22 +6304,25 @@ function makePaintCursorRenderer(reusableCanvasFactory) {
6249
6304
  h: 0
6250
6305
  };
6251
6306
  function getOutlineBoundsScaled(centerX, centerY) {
6252
- boundsScaledScratch.x = centerX * _scale + currentMask.centerOffsetX * _scale - 1;
6253
- boundsScaledScratch.y = centerY * _scale + currentMask.centerOffsetY * _scale - 1;
6254
- boundsScaledScratch.w = currentMask.w * _scale;
6255
- boundsScaledScratch.h = currentMask.h * _scale;
6307
+ boundsScaledScratch.x = centerX * _scale + currentBrush.centerOffsetX * _scale - 1;
6308
+ boundsScaledScratch.y = centerY * _scale + currentBrush.centerOffsetY * _scale - 1;
6309
+ boundsScaledScratch.w = currentBrush.w * _scale;
6310
+ boundsScaledScratch.h = currentBrush.h * _scale;
6256
6311
  return boundsScaledScratch;
6257
6312
  }
6258
6313
  function draw(drawCtx, centerX, centerY) {
6259
- const dx = centerX * _scale + currentMask.centerOffsetX * _scale - 1;
6260
- const dy = centerY * _scale + currentMask.centerOffsetY * _scale - 1;
6314
+ const dx = centerX * _scale + currentBrush.centerOffsetX * _scale - 1;
6315
+ const dy = centerY * _scale + currentBrush.centerOffsetY * _scale - 1;
6261
6316
  drawCtx.drawImage(canvas, Math.floor(dx), Math.floor(dy));
6262
6317
  }
6318
+ function drawRaw(drawCtx, x, y) {
6319
+ drawCtx.drawImage(canvas, Math.floor(x * _scale), Math.floor(y * _scale));
6320
+ }
6263
6321
  function getSettings() {
6264
6322
  return {
6265
6323
  color: _color,
6266
6324
  scale: _scale,
6267
- currentMask
6325
+ currentBrush
6268
6326
  };
6269
6327
  }
6270
6328
  return {
@@ -6272,6 +6330,7 @@ function makePaintCursorRenderer(reusableCanvasFactory) {
6272
6330
  getBounds,
6273
6331
  getBoundsScaled: getOutlineBoundsScaled,
6274
6332
  draw,
6333
+ drawRaw,
6275
6334
  getSettings
6276
6335
  };
6277
6336
  }
@@ -6446,6 +6505,36 @@ function copyPixelData(target) {
6446
6505
  return makePixelData(new ImageData(buffer, target.w, target.h));
6447
6506
  }
6448
6507
 
6508
+ // src/PixelData/cropPixelData.ts
6509
+ function cropPixelData(src, x, y, w, h, out) {
6510
+ const cx = Math.max(x, 0);
6511
+ const cy = Math.max(y, 0);
6512
+ const cw = Math.min(x + w, src.w) - cx;
6513
+ const ch = Math.min(y + h, src.h) - cy;
6514
+ if (cw <= 0 || ch <= 0) {
6515
+ throw new Error(`Crop [${x},${y} ${w}x${h}] does not overlap PixelData [${src.w}x${src.h}]`);
6516
+ }
6517
+ const cropped = new ImageData(cw, ch);
6518
+ let dst32;
6519
+ if (out) {
6520
+ setPixelData(out, cropped);
6521
+ dst32 = out.data;
6522
+ } else {
6523
+ dst32 = new Uint32Array(cropped.data.buffer);
6524
+ }
6525
+ for (let row = 0; row < ch; row++) {
6526
+ const srcOffset = (cy + row) * src.w + cx;
6527
+ const dstOffset = row * cw;
6528
+ dst32.set(src.data.subarray(srcOffset, srcOffset + cw), dstOffset);
6529
+ }
6530
+ return out ?? {
6531
+ data: dst32,
6532
+ imageData: cropped,
6533
+ w: cw,
6534
+ h: ch
6535
+ };
6536
+ }
6537
+
6449
6538
  // src/PixelData/extractPixelDataBuffer.ts
6450
6539
  function extractPixelDataBuffer(source, _x, _y, _w, _h) {
6451
6540
  let x;
@@ -6661,6 +6750,46 @@ function rotateSquareInPlace(pixelData) {
6661
6750
  }
6662
6751
  }
6663
6752
 
6753
+ // src/PixelData/trimPixelData.ts
6754
+ function getPixelDataTransparentTrimmedBounds(target) {
6755
+ let minX = target.w;
6756
+ let minY = target.h;
6757
+ let maxX = -1;
6758
+ let maxY = -1;
6759
+ for (let y = 0; y < target.h; y++) {
6760
+ for (let x = 0; x < target.w; x++) {
6761
+ const alpha = target.data[y * target.w + x] >>> 24;
6762
+ if (alpha !== 0) {
6763
+ if (x < minX) minX = x;
6764
+ if (x > maxX) maxX = x;
6765
+ if (y < minY) minY = y;
6766
+ if (y > maxY) maxY = y;
6767
+ }
6768
+ }
6769
+ }
6770
+ if (maxX === -1) return null;
6771
+ return {
6772
+ x: minX,
6773
+ y: minY,
6774
+ w: maxX - minX + 1,
6775
+ h: maxY - minY + 1
6776
+ };
6777
+ }
6778
+ function trimTransparentPixelData(target) {
6779
+ const r = getPixelDataTransparentTrimmedBounds(target);
6780
+ if (!r) {
6781
+ throw new Error("PixelData is fully transparent \u2014 no crop bounds found");
6782
+ }
6783
+ return cropPixelData(target, r.x, r.y, r.w, r.h);
6784
+ }
6785
+ function trimTransparentPixelDataInPlace(target) {
6786
+ const r = getPixelDataTransparentTrimmedBounds(target);
6787
+ if (!r) {
6788
+ throw new Error("PixelData is fully transparent \u2014 no crop bounds found");
6789
+ }
6790
+ cropPixelData(target, r.x, r.y, r.w, r.h, target);
6791
+ }
6792
+
6664
6793
  // src/PixelData/uInt32ArrayToPixelData.ts
6665
6794
  function uInt32ArrayToPixelData(data, width, height) {
6666
6795
  const buffer = data.buffer;
@@ -6820,6 +6949,7 @@ function writePixelData(target, source, x = 0, y = 0) {
6820
6949
  copyImageDataLike,
6821
6950
  copyMask,
6822
6951
  copyPixelData,
6952
+ cropPixelData,
6823
6953
  darkenFast,
6824
6954
  darkenPerfect,
6825
6955
  darkerFast,
@@ -6858,6 +6988,7 @@ function writePixelData(target, source, x = 0, y = 0) {
6858
6988
  getImageDataFromClipboard,
6859
6989
  getIndexedImageColor,
6860
6990
  getIndexedImageColorCounts,
6991
+ getPixelDataTransparentTrimmedBounds,
6861
6992
  getRectsBounds,
6862
6993
  getSupportedPixelFormats,
6863
6994
  hardLightFast,
@@ -6953,7 +7084,6 @@ function writePixelData(target, source, x = 0, y = 0) {
6953
7084
  mutatorClear,
6954
7085
  mutatorFill,
6955
7086
  mutatorFillBinaryMask,
6956
- mutatorFillRect,
6957
7087
  mutatorInvert,
6958
7088
  overlayFast,
6959
7089
  overlayPerfect,
@@ -6997,6 +7127,8 @@ function writePixelData(target, source, x = 0, y = 0) {
6997
7127
  toBlendModeIndexAndName,
6998
7128
  trimMaskRectBounds,
6999
7129
  trimRectBounds,
7130
+ trimTransparentPixelData,
7131
+ trimTransparentPixelDataInPlace,
7000
7132
  uInt32ArrayToImageData,
7001
7133
  uInt32ArrayToImageDataLike,
7002
7134
  uInt32ArrayToPixelData,