pixel-data-js 0.12.0 → 0.14.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.
@@ -80,6 +80,7 @@ __export(src_exports, {
80
80
  imageDataToAlphaMask: () => imageDataToAlphaMask,
81
81
  imageDataToDataUrl: () => imageDataToDataUrl,
82
82
  imageDataToImgBlob: () => imageDataToImgBlob,
83
+ imageDataToUInt32Array: () => imageDataToUInt32Array,
83
84
  imgBlobToImageData: () => imgBlobToImageData,
84
85
  indexedImageToAverageColor: () => indexedImageToAverageColor,
85
86
  indexedImageToImageData: () => indexedImageToImageData,
@@ -101,6 +102,7 @@ __export(src_exports, {
101
102
  linearLightPerfect: () => linearLightPerfect,
102
103
  makePixelCanvas: () => makePixelCanvas,
103
104
  makeReusableCanvas: () => makeReusableCanvas,
105
+ makeReusableImageData: () => makeReusableImageData,
104
106
  mergeMasks: () => mergeMasks,
105
107
  multiplyFast: () => multiplyFast,
106
108
  multiplyPerfect: () => multiplyPerfect,
@@ -173,9 +175,11 @@ var BlendMode = /* @__PURE__ */ ((BlendMode2) => {
173
175
  BlendMode2[BlendMode2["divide"] = 22] = "divide";
174
176
  return BlendMode2;
175
177
  })(BlendMode || {});
178
+ var overwriteBase = (src, _dst) => src;
179
+ overwriteBase.isOverwrite = true;
176
180
 
177
181
  // src/BlendModes/blend-modes-fast.ts
178
- var overwriteFast = (src, _dst) => src;
182
+ var overwriteFast = overwriteBase;
179
183
  var sourceOverFast = (src, dst) => {
180
184
  const sa = src >>> 24 & 255;
181
185
  if (sa === 255) return src;
@@ -990,7 +994,7 @@ function floodFillSelection(img, startX, startY, {
990
994
  }
991
995
 
992
996
  // src/BlendModes/blend-modes-perfect.ts
993
- var overwritePerfect = (src, _dst) => src;
997
+ var overwritePerfect = overwriteBase;
994
998
  var sourceOverPerfect = (src, dst) => {
995
999
  const sa = src >>> 24 & 255;
996
1000
  if (sa === 255) return src;
@@ -1573,6 +1577,22 @@ async function writeImageDataToClipboard(imageData) {
1573
1577
  return writeImgBlobToClipboard(blob);
1574
1578
  }
1575
1579
 
1580
+ // src/ImageData/ReusableImageData.ts
1581
+ function makeReusableImageData() {
1582
+ let imageData = null;
1583
+ let buffer = null;
1584
+ return function getReusableImageData(width, height) {
1585
+ const hasInstance = !!imageData;
1586
+ const widthMatches = hasInstance && imageData.width === width;
1587
+ const heightMatches = hasInstance && imageData.height === height;
1588
+ if (!widthMatches || !heightMatches) {
1589
+ const buffer2 = new Uint8ClampedArray(width * height * 4);
1590
+ imageData = new ImageData(buffer2, width, height);
1591
+ }
1592
+ return imageData;
1593
+ };
1594
+ }
1595
+
1576
1596
  // src/ImageData/copyImageData.ts
1577
1597
  function copyImageData({ data, width, height }) {
1578
1598
  return new ImageData(data.slice(), width, height);
@@ -1631,6 +1651,16 @@ function imageDataToDataUrl(imageData) {
1631
1651
  }
1632
1652
  imageDataToDataUrl.reset = get.reset;
1633
1653
 
1654
+ // src/ImageData/imageDataToUInt32Array.ts
1655
+ function imageDataToUInt32Array(imageData) {
1656
+ return new Uint32Array(
1657
+ imageData.data.buffer,
1658
+ imageData.data.byteOffset,
1659
+ // Shift right by 2 is a fast bitwise division by 4.
1660
+ imageData.data.byteLength >> 2
1661
+ );
1662
+ }
1663
+
1634
1664
  // src/ImageData/invertImageData.ts
1635
1665
  function invertImageData(imageData) {
1636
1666
  const data = imageData.data;
@@ -1752,27 +1782,6 @@ function deserializeNullableImageData(serialized) {
1752
1782
  return deserializeImageData(serialized);
1753
1783
  }
1754
1784
 
1755
- // src/ImageData/writeImageDataPixels.ts
1756
- function writeImageDataPixels(imageData, data, _x, _y, _w, _h) {
1757
- const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
1758
- const { width: dstW, height: dstH, data: dst } = imageData;
1759
- const x0 = Math.max(0, x);
1760
- const y0 = Math.max(0, y);
1761
- const x1 = Math.min(dstW, x + w);
1762
- const y1 = Math.min(dstH, y + h);
1763
- if (x1 <= x0 || y1 <= y0) return;
1764
- const rowLen = (x1 - x0) * 4;
1765
- const srcCol = x0 - x;
1766
- const srcYOffset = y0 - y;
1767
- const actualH = y1 - y0;
1768
- for (let row = 0; row < actualH; row++) {
1769
- const dstStart = ((y0 + row) * dstW + x0) * 4;
1770
- const srcRow = srcYOffset + row;
1771
- const o = (srcRow * w + srcCol) * 4;
1772
- dst.set(data.subarray(o, o + rowLen), dstStart);
1773
- }
1774
- }
1775
-
1776
1785
  // src/ImageData/writeImageData.ts
1777
1786
  function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width, sh = source.height, mask = null, maskType = 1 /* BINARY */) {
1778
1787
  const dstW = target.width;
@@ -1827,6 +1836,27 @@ function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width,
1827
1836
  }
1828
1837
  }
1829
1838
 
1839
+ // src/ImageData/writeImageDataPixels.ts
1840
+ function writeImageDataPixels(imageData, data, _x, _y, _w, _h) {
1841
+ const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
1842
+ const { width: dstW, height: dstH, data: dst } = imageData;
1843
+ const x0 = Math.max(0, x);
1844
+ const y0 = Math.max(0, y);
1845
+ const x1 = Math.min(dstW, x + w);
1846
+ const y1 = Math.min(dstH, y + h);
1847
+ if (x1 <= x0 || y1 <= y0) return;
1848
+ const rowLen = (x1 - x0) * 4;
1849
+ const srcCol = x0 - x;
1850
+ const srcYOffset = y0 - y;
1851
+ const actualH = y1 - y0;
1852
+ for (let row = 0; row < actualH; row++) {
1853
+ const dstStart = ((y0 + row) * dstW + x0) * 4;
1854
+ const srcRow = srcYOffset + row;
1855
+ const o = (srcRow * w + srcCol) * 4;
1856
+ dst.set(data.subarray(o, o + rowLen), dstStart);
1857
+ }
1858
+ }
1859
+
1830
1860
  // src/IndexedImage/IndexedImage.ts
1831
1861
  var IndexedImage = class _IndexedImage {
1832
1862
  /** The width of the image in pixels. */
@@ -2166,28 +2196,34 @@ function mergeMasks(dst, dstWidth, src, opts) {
2166
2196
 
2167
2197
  // src/PixelData/PixelData.ts
2168
2198
  var PixelData = class _PixelData {
2199
+ data32;
2200
+ imageData;
2201
+ get width() {
2202
+ return this.imageData.width;
2203
+ }
2204
+ get height() {
2205
+ return this.imageData.height;
2206
+ }
2169
2207
  constructor(imageData) {
2208
+ this.data32 = imageDataToUInt32Array(imageData);
2170
2209
  this.imageData = imageData;
2171
- this.width = imageData.width;
2172
- this.height = imageData.height;
2173
- this.data32 = new Uint32Array(
2174
- imageData.data.buffer,
2175
- imageData.data.byteOffset,
2176
- // Shift right by 2 is a fast bitwise division by 4.
2177
- imageData.data.byteLength >> 2
2178
- );
2179
2210
  }
2180
- data32;
2181
- width;
2182
- height;
2211
+ set(imageData) {
2212
+ this.imageData = imageData;
2213
+ this.data32 = imageDataToUInt32Array(imageData);
2214
+ }
2215
+ /**
2216
+ * Creates a deep copy of the PixelData using the environment's ImageData constructor.
2217
+ */
2183
2218
  copy() {
2184
- const buffer = new Uint8ClampedArray(this.data32.buffer.slice(0));
2185
- const imageData = {
2186
- data: buffer,
2187
- width: this.width,
2188
- height: this.height
2189
- };
2190
- return new _PixelData(imageData);
2219
+ const buffer = new Uint8ClampedArray(this.imageData.data);
2220
+ const ImageConstructor = typeof ImageData !== "undefined" ? ImageData : this.imageData.constructor;
2221
+ const newImageData = new ImageConstructor(
2222
+ buffer,
2223
+ this.width,
2224
+ this.height
2225
+ );
2226
+ return new _PixelData(newImageData);
2191
2227
  }
2192
2228
  };
2193
2229
 
@@ -2279,14 +2315,14 @@ function applyMaskToPixelData(dst, mask, opts) {
2279
2315
  }
2280
2316
 
2281
2317
  // src/PixelData/blendColorPixelData.ts
2282
- function blendColorPixelData(dst, color, opts) {
2318
+ function blendColorPixelData(dst, color, opts = {}) {
2283
2319
  const {
2284
2320
  x: targetX = 0,
2285
2321
  y: targetY = 0,
2286
2322
  w: width = dst.width,
2287
2323
  h: height = dst.height,
2288
2324
  alpha: globalAlpha = 255,
2289
- blendFn = FAST_BLEND_MODES[1 /* sourceOver */],
2325
+ blendFn = sourceOverFast,
2290
2326
  mask,
2291
2327
  maskType = 0 /* ALPHA */,
2292
2328
  mw,
@@ -2295,6 +2331,9 @@ function blendColorPixelData(dst, color, opts) {
2295
2331
  invertMask = false
2296
2332
  } = opts;
2297
2333
  if (globalAlpha === 0) return;
2334
+ const baseSrcAlpha = color >>> 24;
2335
+ const isOverwrite = blendFn.isOverwrite;
2336
+ if (baseSrcAlpha === 0 && !isOverwrite) return;
2298
2337
  let x = targetX;
2299
2338
  let y = targetY;
2300
2339
  let w = width;
@@ -2320,15 +2359,8 @@ function blendColorPixelData(dst, color, opts) {
2320
2359
  let mIdx = (my + dy) * mPitch + (mx + dx);
2321
2360
  const dStride = dw - actualW;
2322
2361
  const mStride = mPitch - actualW;
2323
- const baseSrcColor = color;
2324
- const baseSrcAlpha = baseSrcColor >>> 24;
2325
2362
  for (let iy = 0; iy < actualH; iy++) {
2326
2363
  for (let ix = 0; ix < actualW; ix++) {
2327
- if (baseSrcAlpha === 0) {
2328
- dIdx++;
2329
- mIdx++;
2330
- continue;
2331
- }
2332
2364
  let weight = globalAlpha;
2333
2365
  if (mask) {
2334
2366
  const mVal = mask[mIdx];
@@ -2361,20 +2393,20 @@ function blendColorPixelData(dst, color, opts) {
2361
2393
  continue;
2362
2394
  }
2363
2395
  }
2364
- let currentSrcAlpha = baseSrcAlpha;
2365
- let currentSrcColor = baseSrcColor;
2396
+ let currentSrcColor = color;
2366
2397
  if (weight < 255) {
2398
+ let currentSrcAlpha = baseSrcAlpha;
2367
2399
  if (baseSrcAlpha === 255) {
2368
2400
  currentSrcAlpha = weight;
2369
2401
  } else {
2370
2402
  currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
2371
2403
  }
2372
- if (currentSrcAlpha === 0) {
2404
+ if (!isOverwrite && currentSrcAlpha === 0) {
2373
2405
  dIdx++;
2374
2406
  mIdx++;
2375
2407
  continue;
2376
2408
  }
2377
- currentSrcColor = (baseSrcColor & 16777215 | currentSrcAlpha << 24) >>> 0;
2409
+ currentSrcColor = (color & 16777215 | currentSrcAlpha << 24) >>> 0;
2378
2410
  }
2379
2411
  dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
2380
2412
  dIdx++;
@@ -2449,11 +2481,12 @@ function blendPixelData(dst, src, opts) {
2449
2481
  const dStride = dw - actualW;
2450
2482
  const sStride = sw - actualW;
2451
2483
  const mStride = mPitch - actualW;
2484
+ const isOverwrite = blendFn.isOverwrite;
2452
2485
  for (let iy = 0; iy < actualH; iy++) {
2453
2486
  for (let ix = 0; ix < actualW; ix++) {
2454
2487
  const baseSrcColor = src32[sIdx];
2455
2488
  const baseSrcAlpha = baseSrcColor >>> 24;
2456
- if (baseSrcAlpha === 0) {
2489
+ if (baseSrcAlpha === 0 && !isOverwrite) {
2457
2490
  dIdx++;
2458
2491
  sIdx++;
2459
2492
  mIdx++;
@@ -2494,15 +2527,15 @@ function blendPixelData(dst, src, opts) {
2494
2527
  continue;
2495
2528
  }
2496
2529
  }
2497
- let currentSrcAlpha = baseSrcAlpha;
2498
2530
  let currentSrcColor = baseSrcColor;
2499
2531
  if (weight < 255) {
2532
+ let currentSrcAlpha = baseSrcAlpha;
2500
2533
  if (baseSrcAlpha === 255) {
2501
2534
  currentSrcAlpha = weight;
2502
2535
  } else {
2503
2536
  currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
2504
2537
  }
2505
- if (currentSrcAlpha === 0) {
2538
+ if (!isOverwrite && currentSrcAlpha === 0) {
2506
2539
  dIdx++;
2507
2540
  sIdx++;
2508
2541
  mIdx++;
@@ -2622,11 +2655,11 @@ function reflectPixelDataVertical(pixelData) {
2622
2655
  // src/PixelData/resamplePixelData.ts
2623
2656
  function resamplePixelData(pixelData, factor) {
2624
2657
  const { data, width, height } = resample32(pixelData.data32, pixelData.width, pixelData.height, factor);
2625
- return new PixelData({
2658
+ return new PixelData(new ImageData(
2659
+ new Uint8ClampedArray(data.buffer),
2626
2660
  width,
2627
- height,
2628
- data: new Uint8ClampedArray(data.buffer)
2629
- });
2661
+ height
2662
+ ));
2630
2663
  }
2631
2664
 
2632
2665
  // src/PixelData/rotatePixelData.ts
@@ -2640,30 +2673,33 @@ function rotatePixelData(pixelData) {
2640
2673
  }
2641
2674
  const newWidth = height;
2642
2675
  const newHeight = width;
2643
- const newData = new Uint32Array(data.length);
2676
+ const newData32 = new Uint32Array(data.length);
2644
2677
  for (let y = 0; y < height; y++) {
2645
2678
  for (let x = 0; x < width; x++) {
2646
2679
  const oldIdx = y * width + x;
2647
2680
  const newX = height - 1 - y;
2648
2681
  const newY = x;
2649
2682
  const newIdx = newY * newWidth + newX;
2650
- newData[newIdx] = data[oldIdx];
2683
+ newData32[newIdx] = data[oldIdx];
2651
2684
  }
2652
2685
  }
2653
- pixelData.width = newWidth;
2654
- pixelData.height = newHeight;
2655
- pixelData.data32 = newData;
2686
+ const newImageData = new ImageData(
2687
+ new Uint8ClampedArray(newData32.buffer),
2688
+ newWidth,
2689
+ newHeight
2690
+ );
2691
+ pixelData.set(newImageData);
2656
2692
  }
2657
2693
  function rotateSquareInPlace(pixelData) {
2658
2694
  const n = pixelData.width;
2659
2695
  const data = pixelData.data32;
2660
2696
  for (let i = 0; i < n / 2; i++) {
2661
2697
  for (let j = i; j < n - i - 1; j++) {
2662
- const temp = data[i * n + j];
2663
2698
  const top = i * n + j;
2664
2699
  const right = j * n + (n - 1 - i);
2665
2700
  const bottom = (n - 1 - i) * n + (n - 1 - j);
2666
2701
  const left = (n - 1 - j) * n + i;
2702
+ const temp = data[top];
2667
2703
  data[top] = data[left];
2668
2704
  data[left] = data[bottom];
2669
2705
  data[bottom] = data[right];
@@ -2733,6 +2769,7 @@ function rotateSquareInPlace(pixelData) {
2733
2769
  imageDataToAlphaMask,
2734
2770
  imageDataToDataUrl,
2735
2771
  imageDataToImgBlob,
2772
+ imageDataToUInt32Array,
2736
2773
  imgBlobToImageData,
2737
2774
  indexedImageToAverageColor,
2738
2775
  indexedImageToImageData,
@@ -2754,6 +2791,7 @@ function rotateSquareInPlace(pixelData) {
2754
2791
  linearLightPerfect,
2755
2792
  makePixelCanvas,
2756
2793
  makeReusableCanvas,
2794
+ makeReusableImageData,
2757
2795
  mergeMasks,
2758
2796
  multiplyFast,
2759
2797
  multiplyPerfect,