pixel-data-js 0.11.0 → 0.12.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.
@@ -27,6 +27,7 @@ __export(src_exports, {
27
27
  FAST_BLEND_TO_INDEX: () => FAST_BLEND_TO_INDEX,
28
28
  INDEX_TO_FAST_BLEND: () => INDEX_TO_FAST_BLEND,
29
29
  INDEX_TO_PERFECT_BLEND: () => INDEX_TO_PERFECT_BLEND,
30
+ IndexedImage: () => IndexedImage,
30
31
  MaskType: () => MaskType,
31
32
  PERFECT_BLENDER_REGISTRY: () => PERFECT_BLENDER_REGISTRY,
32
33
  PERFECT_BLEND_MODES: () => PERFECT_BLEND_MODES,
@@ -81,6 +82,7 @@ __export(src_exports, {
81
82
  imageDataToImgBlob: () => imageDataToImgBlob,
82
83
  imgBlobToImageData: () => imgBlobToImageData,
83
84
  indexedImageToAverageColor: () => indexedImageToAverageColor,
85
+ indexedImageToImageData: () => indexedImageToImageData,
84
86
  invertAlphaMask: () => invertAlphaMask,
85
87
  invertBinaryMask: () => invertBinaryMask,
86
88
  invertImageData: () => invertImageData,
@@ -97,7 +99,6 @@ __export(src_exports, {
97
99
  linearDodgePerfect: () => linearDodgePerfect,
98
100
  linearLightFast: () => linearLightFast,
99
101
  linearLightPerfect: () => linearLightPerfect,
100
- makeIndexedImage: () => makeIndexedImage,
101
102
  makePixelCanvas: () => makePixelCanvas,
102
103
  makeReusableCanvas: () => makeReusableCanvas,
103
104
  mergeMasks: () => mergeMasks,
@@ -138,6 +139,7 @@ __export(src_exports, {
138
139
  unpackRed: () => unpackRed,
139
140
  vividLightFast: () => vividLightFast,
140
141
  vividLightPerfect: () => vividLightPerfect,
142
+ writeImageData: () => writeImageData,
141
143
  writeImageDataPixels: () => writeImageDataPixels,
142
144
  writeImageDataToClipboard: () => writeImageDataToClipboard,
143
145
  writeImgBlobToClipboard: () => writeImgBlobToClipboard
@@ -1710,7 +1712,9 @@ function resizeImageData(current, newWidth, newHeight, offsetX = 0, offsetY = 0)
1710
1712
 
1711
1713
  // src/ImageData/serialization.ts
1712
1714
  function base64EncodeArrayBuffer(buffer) {
1713
- const binary = String.fromCharCode(...new Uint8Array(buffer));
1715
+ const uint8 = new Uint8Array(buffer);
1716
+ const decoder = new TextDecoder("latin1");
1717
+ const binary = decoder.decode(uint8);
1714
1718
  return btoa(binary);
1715
1719
  }
1716
1720
  function base64DecodeArrayBuffer(encoded) {
@@ -1769,40 +1773,144 @@ function writeImageDataPixels(imageData, data, _x, _y, _w, _h) {
1769
1773
  }
1770
1774
  }
1771
1775
 
1772
- // src/IndexedImage/IndexedImage.ts
1773
- function makeIndexedImage(imageOrData, width, height) {
1774
- const isImageData = "width" in imageOrData;
1775
- const actualWidth = isImageData ? imageOrData.width : width;
1776
- const actualHeight = isImageData ? imageOrData.height : height;
1777
- const buffer = isImageData ? imageOrData.data.buffer : imageOrData.buffer;
1778
- const rawData = new Uint32Array(buffer);
1779
- const indexedData = new Int32Array(rawData.length);
1780
- const colorMap = /* @__PURE__ */ new Map();
1781
- const transparentColor = 0;
1782
- const transparentPalletIndex = 0;
1783
- colorMap.set(transparentColor, transparentPalletIndex);
1784
- for (let i = 0; i < rawData.length; i++) {
1785
- const pixel = rawData[i];
1786
- const alpha = pixel >>> 24 & 255;
1787
- const isTransparent = alpha === 0;
1788
- const colorKey = isTransparent ? transparentColor : pixel >>> 0;
1789
- let id = colorMap.get(colorKey);
1790
- if (id === void 0) {
1791
- id = colorMap.size;
1792
- colorMap.set(colorKey, id);
1776
+ // src/ImageData/writeImageData.ts
1777
+ function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width, sh = source.height, mask = null, maskType = 1 /* BINARY */) {
1778
+ const dstW = target.width;
1779
+ const dstH = target.height;
1780
+ const dstData = target.data;
1781
+ const srcW = source.width;
1782
+ const srcData = source.data;
1783
+ const x0 = Math.max(0, x);
1784
+ const y0 = Math.max(0, y);
1785
+ const x1 = Math.min(dstW, x + sw);
1786
+ const y1 = Math.min(dstH, y + sh);
1787
+ if (x1 <= x0 || y1 <= y0) {
1788
+ return;
1789
+ }
1790
+ const useMask = !!mask;
1791
+ const rowCount = y1 - y0;
1792
+ const rowLenPixels = x1 - x0;
1793
+ for (let row = 0; row < rowCount; row++) {
1794
+ const dstY = y0 + row;
1795
+ const srcY = sy + (dstY - y);
1796
+ const srcXBase = sx + (x0 - x);
1797
+ const dstStart = (dstY * dstW + x0) * 4;
1798
+ const srcStart = (srcY * srcW + srcXBase) * 4;
1799
+ if (useMask && mask) {
1800
+ for (let ix = 0; ix < rowLenPixels; ix++) {
1801
+ const mi = srcY * srcW + (srcXBase + ix);
1802
+ const alpha = mask[mi];
1803
+ if (alpha === 0) {
1804
+ continue;
1805
+ }
1806
+ const di = dstStart + ix * 4;
1807
+ const si = srcStart + ix * 4;
1808
+ if (maskType === 1 /* BINARY */ || alpha === 255) {
1809
+ dstData[di] = srcData[si];
1810
+ dstData[di + 1] = srcData[si + 1];
1811
+ dstData[di + 2] = srcData[si + 2];
1812
+ dstData[di + 3] = srcData[si + 3];
1813
+ } else {
1814
+ const a = alpha / 255;
1815
+ const invA = 1 - a;
1816
+ dstData[di] = srcData[si] * a + dstData[di] * invA;
1817
+ dstData[di + 1] = srcData[si + 1] * a + dstData[di + 1] * invA;
1818
+ dstData[di + 2] = srcData[si + 2] * a + dstData[di + 2] * invA;
1819
+ dstData[di + 3] = srcData[si + 3] * a + dstData[di + 3] * invA;
1820
+ }
1821
+ }
1822
+ } else {
1823
+ const byteLen = rowLenPixels * 4;
1824
+ const sub = srcData.subarray(srcStart, srcStart + byteLen);
1825
+ dstData.set(sub, dstStart);
1793
1826
  }
1794
- indexedData[i] = id;
1795
1827
  }
1796
- const palette = Uint32Array.from(colorMap.keys());
1797
- return {
1798
- width: actualWidth,
1799
- height: actualHeight,
1800
- data: indexedData,
1801
- transparentPalletIndex,
1802
- palette
1803
- };
1804
1828
  }
1805
1829
 
1830
+ // src/IndexedImage/IndexedImage.ts
1831
+ var IndexedImage = class _IndexedImage {
1832
+ /** The width of the image in pixels. */
1833
+ width;
1834
+ /** The height of the image in pixels. */
1835
+ height;
1836
+ /** Flat array of palette indices. Index = x + (y * width). */
1837
+ data;
1838
+ /** The palette of unique 32-bit colors (ABGR/RGBA packed) found in the image. */
1839
+ palette;
1840
+ /** The specific index in the palette reserved for fully transparent pixels. */
1841
+ transparentPalletIndex;
1842
+ /**
1843
+ * @param width - Image width.
1844
+ * @param height - Image height.
1845
+ * @param data - The indexed pixel data.
1846
+ * @param palette - The array of packed colors.
1847
+ * @param transparentPalletIndex - The index representing alpha 0.
1848
+ */
1849
+ constructor(width, height, data, palette, transparentPalletIndex) {
1850
+ this.width = width;
1851
+ this.height = height;
1852
+ this.data = data;
1853
+ this.palette = palette;
1854
+ this.transparentPalletIndex = transparentPalletIndex;
1855
+ }
1856
+ /**
1857
+ * Creates an IndexedImage from standard browser ImageData.
1858
+ * @param imageData - The source ImageData to convert.
1859
+ * @returns A new IndexedImage instance.
1860
+ */
1861
+ static fromImageData(imageData) {
1862
+ return _IndexedImage.fromRaw(imageData.data, imageData.width, imageData.height);
1863
+ }
1864
+ /**
1865
+ * Creates an IndexedImage from a raw byte buffer and dimensions.
1866
+ * Any pixel with an alpha channel of 0 is normalized to the transparent palette index.
1867
+ * @param data - Raw RGBA byte data.
1868
+ * @param width - Image width.
1869
+ * @param height - Image height.
1870
+ * @returns A new IndexedImage instance.
1871
+ */
1872
+ static fromRaw(data, width, height) {
1873
+ const buffer = data.buffer;
1874
+ const rawData = new Uint32Array(buffer);
1875
+ const indexedData = new Int32Array(rawData.length);
1876
+ const colorMap = /* @__PURE__ */ new Map();
1877
+ const transparentColor = 0;
1878
+ const transparentPalletIndex = 0;
1879
+ colorMap.set(transparentColor, transparentPalletIndex);
1880
+ for (let i = 0; i < rawData.length; i++) {
1881
+ const pixel = rawData[i];
1882
+ const alpha = pixel >>> 24 & 255;
1883
+ const isTransparent = alpha === 0;
1884
+ const colorKey = isTransparent ? transparentColor : pixel >>> 0;
1885
+ let id = colorMap.get(colorKey);
1886
+ if (id === void 0) {
1887
+ id = colorMap.size;
1888
+ colorMap.set(colorKey, id);
1889
+ }
1890
+ indexedData[i] = id;
1891
+ }
1892
+ const palette = Uint32Array.from(colorMap.keys());
1893
+ return new _IndexedImage(
1894
+ width,
1895
+ height,
1896
+ indexedData,
1897
+ palette,
1898
+ transparentPalletIndex
1899
+ );
1900
+ }
1901
+ /**
1902
+ * Retrieves the 32-bit packed color value at the given coordinates.
1903
+ * @param x - X coordinate.
1904
+ * @param y - Y coordinate.
1905
+ * @returns The packed color from the palette.
1906
+ */
1907
+ getColorAt(x, y) {
1908
+ const index = x + y * this.width;
1909
+ const paletteIndex = this.data[index];
1910
+ return this.palette[paletteIndex];
1911
+ }
1912
+ };
1913
+
1806
1914
  // src/IndexedImage/getIndexedImageColorCounts.ts
1807
1915
  function getIndexedImageColorCounts(indexedImage) {
1808
1916
  const data = indexedImage.data;
@@ -1865,13 +1973,26 @@ function resampleIndexedImage(source, factor) {
1865
1973
  source.height,
1866
1974
  factor
1867
1975
  );
1868
- return {
1976
+ return new IndexedImage(
1869
1977
  width,
1870
1978
  height,
1871
1979
  data,
1872
- palette: source.palette,
1873
- transparentPalletIndex: source.transparentPalletIndex
1874
- };
1980
+ source.palette,
1981
+ source.transparentPalletIndex
1982
+ );
1983
+ }
1984
+
1985
+ // src/IndexedImage/indexedImageToImageData.ts
1986
+ function indexedImageToImageData(indexedImage) {
1987
+ const { width, height, data, palette } = indexedImage;
1988
+ const result = new ImageData(width, height);
1989
+ const data32 = new Uint32Array(result.data.buffer);
1990
+ for (let i = 0; i < data.length; i++) {
1991
+ const paletteIndex = data[i];
1992
+ const color = palette[paletteIndex];
1993
+ data32[i] = color;
1994
+ }
1995
+ return result;
1875
1996
  }
1876
1997
 
1877
1998
  // src/Input/fileInputChangeToImageData.ts
@@ -2559,6 +2680,7 @@ function rotateSquareInPlace(pixelData) {
2559
2680
  FAST_BLEND_TO_INDEX,
2560
2681
  INDEX_TO_FAST_BLEND,
2561
2682
  INDEX_TO_PERFECT_BLEND,
2683
+ IndexedImage,
2562
2684
  MaskType,
2563
2685
  PERFECT_BLENDER_REGISTRY,
2564
2686
  PERFECT_BLEND_MODES,
@@ -2613,6 +2735,7 @@ function rotateSquareInPlace(pixelData) {
2613
2735
  imageDataToImgBlob,
2614
2736
  imgBlobToImageData,
2615
2737
  indexedImageToAverageColor,
2738
+ indexedImageToImageData,
2616
2739
  invertAlphaMask,
2617
2740
  invertBinaryMask,
2618
2741
  invertImageData,
@@ -2629,7 +2752,6 @@ function rotateSquareInPlace(pixelData) {
2629
2752
  linearDodgePerfect,
2630
2753
  linearLightFast,
2631
2754
  linearLightPerfect,
2632
- makeIndexedImage,
2633
2755
  makePixelCanvas,
2634
2756
  makeReusableCanvas,
2635
2757
  mergeMasks,
@@ -2670,6 +2792,7 @@ function rotateSquareInPlace(pixelData) {
2670
2792
  unpackRed,
2671
2793
  vividLightFast,
2672
2794
  vividLightPerfect,
2795
+ writeImageData,
2673
2796
  writeImageDataPixels,
2674
2797
  writeImageDataToClipboard,
2675
2798
  writeImgBlobToClipboard