pixel-data-js 0.27.0 → 0.29.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 (148) hide show
  1. package/README.md +12 -2
  2. package/dist/index.prod.cjs +2355 -1124
  3. package/dist/index.prod.cjs.map +1 -1
  4. package/dist/index.prod.d.ts +558 -424
  5. package/dist/index.prod.js +2304 -1115
  6. package/dist/index.prod.js.map +1 -1
  7. package/package.json +11 -11
  8. package/src/Algorithm/floodFillSelection.ts +8 -6
  9. package/src/Algorithm/forEachLinePoint.ts +6 -6
  10. package/src/{Internal/resample32.ts → Algorithm/resampleUint32Array.ts} +11 -21
  11. package/src/BlendModes/blend-modes-fast.ts +169 -0
  12. package/src/BlendModes/blend-modes-perfect.ts +207 -0
  13. package/src/BlendModes/blend-modes.ts +9 -0
  14. package/src/Canvas/CanvasFrameRenderer.ts +20 -28
  15. package/src/Canvas/CanvasPixelDataRenderer.ts +23 -0
  16. package/src/Canvas/PixelCanvas.ts +2 -7
  17. package/src/Canvas/ReusableCanvas.ts +4 -12
  18. package/src/Canvas/_canvas-types.ts +26 -0
  19. package/src/History/PixelAccumulator.ts +17 -17
  20. package/src/History/PixelEngineConfig.ts +3 -3
  21. package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +4 -3
  22. package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +4 -3
  23. package/src/History/PixelMutator/mutatorApplyMask.ts +4 -3
  24. package/src/History/PixelMutator/mutatorBlendAlphaMask.ts +6 -4
  25. package/src/History/PixelMutator/mutatorBlendBinaryMask.ts +6 -4
  26. package/src/History/PixelMutator/mutatorBlendColor.ts +2 -2
  27. package/src/History/PixelMutator/mutatorBlendColorPaintAlphaMask.ts +2 -1
  28. package/src/History/PixelMutator/mutatorBlendColorPaintBinaryMask.ts +2 -1
  29. package/src/History/PixelMutator/mutatorBlendColorPaintMask.ts +3 -1
  30. package/src/History/PixelMutator/mutatorBlendColorPaintRect.ts +3 -3
  31. package/src/History/PixelMutator/mutatorBlendMask.ts +6 -4
  32. package/src/History/PixelMutator/mutatorBlendPixelData.ts +5 -4
  33. package/src/History/PixelMutator/mutatorClear.ts +4 -3
  34. package/src/History/PixelMutator/mutatorFill.ts +5 -4
  35. package/src/History/PixelMutator/mutatorFillBinaryMask.ts +2 -1
  36. package/src/History/PixelMutator/mutatorInvert.ts +2 -2
  37. package/src/History/PixelMutator.ts +1 -1
  38. package/src/History/PixelPatchTiles.ts +7 -7
  39. package/src/History/PixelWriter.ts +12 -63
  40. package/src/ImageData/ImageDataLike.ts +1 -1
  41. package/src/ImageData/_ImageData-types.ts +13 -0
  42. package/src/ImageData/copyImageData.ts +1 -1
  43. package/src/ImageData/extractImageDataBuffer.ts +3 -2
  44. package/src/ImageData/imageDataToUint32Array.ts +18 -0
  45. package/src/ImageData/resampleImageData.ts +3 -3
  46. package/src/ImageData/resizeImageData.ts +1 -1
  47. package/src/ImageData/serialization.ts +1 -1
  48. package/src/ImageData/uInt32ArrayToImageData.ts +1 -1
  49. package/src/ImageData/writeImageData.ts +2 -2
  50. package/src/ImageData/writeImageDataBuffer.ts +2 -2
  51. package/src/IndexedImage/IndexedImage.ts +56 -98
  52. package/src/IndexedImage/_indexedImage-types.ts +18 -0
  53. package/src/IndexedImage/getIndexedImageColorCounts.ts +3 -3
  54. package/src/IndexedImage/indexedImageToAverageColor.ts +1 -1
  55. package/src/IndexedImage/indexedImageToImageData.ts +4 -6
  56. package/src/IndexedImage/resampleIndexedImage.ts +7 -15
  57. package/src/Input/fileToImageData.ts +1 -1
  58. package/src/Internal/_constants.ts +3 -0
  59. package/src/Internal/_errors.ts +2 -0
  60. package/src/Internal/macros.ts +14 -0
  61. package/src/Mask/AlphaMask.ts +1 -1
  62. package/src/Mask/BinaryMask/makeBinaryMaskFromAlphaMask.ts +23 -0
  63. package/src/Mask/BinaryMask/makeBinaryMaskOutline.ts +88 -0
  64. package/src/Mask/BinaryMask/makeCircleBinaryMaskOutline.ts +104 -0
  65. package/src/Mask/BinaryMask/makeRectBinaryMaskOutline.ts +34 -0
  66. package/src/Mask/BinaryMask.ts +1 -1
  67. package/src/Mask/_mask-types.ts +73 -0
  68. package/src/Mask/applyBinaryMaskToAlphaMask.ts +2 -1
  69. package/src/Mask/copyMask.ts +1 -1
  70. package/src/Mask/extractMask.ts +2 -1
  71. package/src/Mask/extractMaskBuffer.ts +1 -1
  72. package/src/Mask/mergeAlphaMasks.ts +6 -3
  73. package/src/Mask/mergeBinaryMasks.ts +2 -1
  74. package/src/Mask/setMaskData.ts +1 -1
  75. package/src/MaskRect/merge2BinaryMaskRects.ts +2 -2
  76. package/src/MaskRect/mergeBinaryMaskRects.ts +1 -1
  77. package/src/MaskRect/subtractBinaryMaskRects.ts +1 -1
  78. package/src/Paint/AlphaMaskPaintBuffer.ts +283 -0
  79. package/src/Paint/BinaryMaskPaintBuffer.ts +198 -0
  80. package/src/Paint/{PaintBuffer.ts → ColorPaintBuffer.ts} +95 -77
  81. package/src/Paint/Commit/AlphaMaskPaintBufferCommitter.ts +26 -0
  82. package/src/Paint/Commit/AlphaMaskPaintBufferManager.ts +34 -0
  83. package/src/Paint/Commit/BinaryMaskPaintBufferCommitter.ts +26 -0
  84. package/src/Paint/Commit/BinaryMaskPaintBufferManager.ts +31 -0
  85. package/src/Paint/Commit/ColorPaintBufferCommitter.ts +23 -0
  86. package/src/Paint/Commit/ColorPaintBufferManager.ts +34 -0
  87. package/src/Paint/Commit/commitColorPaintBuffer.ts +55 -0
  88. package/src/Paint/Commit/commitMaskPaintBuffer.ts +78 -0
  89. package/src/Paint/Render/AlphaMaskPaintBufferCanvasRenderer.ts +78 -0
  90. package/src/Paint/Render/BinaryMaskPaintBufferCanvasRenderer.ts +67 -0
  91. package/src/Paint/{PaintBufferCanvasRenderer.ts → Render/ColorPaintBufferCanvasRenderer.ts} +13 -14
  92. package/src/Paint/Render/PaintCursorRenderer.ts +118 -0
  93. package/src/Paint/_paint-types.ts +22 -0
  94. package/src/Paint/eachTileInBounds.ts +45 -0
  95. package/src/Paint/makeCirclePaintMask.ts +74 -0
  96. package/src/Paint/makePaintMask.ts +5 -2
  97. package/src/Paint/makeRectFalloffPaintAlphaMask.ts +4 -2
  98. package/src/PixelData/PixelData.ts +15 -19
  99. package/src/PixelData/ReusablePixelData.ts +36 -0
  100. package/src/PixelData/_pixelData-types.ts +17 -0
  101. package/src/PixelData/applyAlphaMaskToPixelData.ts +80 -43
  102. package/src/PixelData/applyBinaryMaskToPixelData.ts +10 -8
  103. package/src/PixelData/applyMaskToPixelData.ts +4 -9
  104. package/src/PixelData/blendColorPixelData.ts +9 -8
  105. package/src/PixelData/blendColorPixelDataAlphaMask.ts +9 -7
  106. package/src/PixelData/blendColorPixelDataBinaryMask.ts +9 -7
  107. package/src/PixelData/blendColorPixelDataMask.ts +4 -2
  108. package/src/PixelData/blendColorPixelDataPaintAlphaMask.ts +4 -2
  109. package/src/PixelData/blendColorPixelDataPaintBinaryMask.ts +4 -2
  110. package/src/PixelData/blendColorPixelDataPaintMask.ts +5 -2
  111. package/src/PixelData/blendPixel.ts +6 -5
  112. package/src/PixelData/blendPixelData.ts +14 -13
  113. package/src/PixelData/blendPixelDataAlphaMask.ts +15 -13
  114. package/src/PixelData/blendPixelDataBinaryMask.ts +15 -13
  115. package/src/PixelData/blendPixelDataMask.ts +5 -3
  116. package/src/PixelData/blendPixelDataPaintBuffer.ts +5 -4
  117. package/src/PixelData/clearPixelDataFast.ts +4 -2
  118. package/src/PixelData/copyPixelData.ts +14 -0
  119. package/src/PixelData/extractPixelData.ts +8 -7
  120. package/src/PixelData/extractPixelDataBuffer.ts +9 -8
  121. package/src/PixelData/fillPixelData.ts +16 -14
  122. package/src/PixelData/fillPixelDataBinaryMask.ts +10 -8
  123. package/src/PixelData/fillPixelDataFast.ts +16 -14
  124. package/src/PixelData/invertPixelData.ts +9 -8
  125. package/src/PixelData/pixelDataToAlphaMask.ts +9 -8
  126. package/src/PixelData/reflectPixelData.ts +9 -9
  127. package/src/PixelData/resamplePixelData.ts +20 -9
  128. package/src/PixelData/rotatePixelData.ts +8 -7
  129. package/src/PixelData/uInt32ArrayToPixelData.ts +15 -0
  130. package/src/PixelData/writePaintBufferToPixelData.ts +5 -5
  131. package/src/PixelData/writePixelDataBuffer.ts +10 -9
  132. package/src/Rect/_rect-types.ts +7 -0
  133. package/src/Rect/getRectsBounds.ts +1 -1
  134. package/src/Rect/trimMaskRectBounds.ts +2 -1
  135. package/src/Rect/trimRectBounds.ts +1 -1
  136. package/src/Tile/MaskTile.ts +40 -0
  137. package/src/Tile/PixelTile.ts +23 -0
  138. package/src/{PixelTile/PixelTilePool.ts → Tile/TilePool.ts} +9 -9
  139. package/src/Tile/_tile-types.ts +33 -0
  140. package/src/_errors.ts +1 -0
  141. package/src/_types.ts +2 -118
  142. package/src/index.ts +57 -21
  143. package/src/ImageData/imageDataToUInt32Array.ts +0 -13
  144. package/src/Internal/helpers.ts +0 -5
  145. package/src/Paint/makeCirclePaintAlphaMask.ts +0 -41
  146. package/src/Paint/makeCirclePaintBinaryMask.ts +0 -29
  147. package/src/PixelTile/PixelTile.ts +0 -21
  148. /package/src/{Internal → Rect}/resolveClipping.ts +0 -0
@@ -1,10 +1,12 @@
1
- import type { Color32, IPixelData32, Rect } from '../_types'
2
- import { makeClippedRect, resolveRectClipping } from '../Internal/resolveClipping'
1
+ import type { Color32 } from '../_types'
2
+ import type { Rect } from '../Rect/_rect-types'
3
+ import { makeClippedRect, resolveRectClipping } from '../Rect/resolveClipping'
4
+ import type { PixelData32 } from './_pixelData-types'
3
5
 
4
6
  const SCRATCH_RECT = makeClippedRect()
5
7
 
6
8
  /**
7
- * Fills a region or the {@link IPixelData32} buffer with a solid color.
9
+ * Fills a region or the {@link PixelData32} buffer with a solid color.
8
10
  *
9
11
  * @param dst - The target to modify.
10
12
  * @param color - The color to apply.
@@ -12,7 +14,7 @@ const SCRATCH_RECT = makeClippedRect()
12
14
  * @returns true if any pixels were actually modified.
13
15
  */
14
16
  export function fillPixelData(
15
- dst: IPixelData32,
17
+ dst: PixelData32,
16
18
  color: Color32,
17
19
  rect?: Partial<Rect>,
18
20
  ): boolean
@@ -25,7 +27,7 @@ export function fillPixelData(
25
27
  * @param h - Height of the fill area.
26
28
  */
27
29
  export function fillPixelData(
28
- dst: IPixelData32,
30
+ dst: PixelData32,
29
31
  color: Color32,
30
32
  x: number,
31
33
  y: number,
@@ -33,7 +35,7 @@ export function fillPixelData(
33
35
  h: number,
34
36
  ): boolean
35
37
  export function fillPixelData(
36
- dst: IPixelData32,
38
+ dst: PixelData32,
37
39
  color: Color32,
38
40
  _x?: Partial<Rect> | number,
39
41
  _y?: number,
@@ -48,8 +50,8 @@ export function fillPixelData(
48
50
  if (typeof _x === 'object') {
49
51
  x = _x.x ?? 0
50
52
  y = _x.y ?? 0
51
- w = _x.w ?? dst.width
52
- h = _x.h ?? dst.height
53
+ w = _x.w ?? dst.w
54
+ h = _x.h ?? dst.h
53
55
  } else if (typeof _x === 'number') {
54
56
  x = _x
55
57
  y = _y!
@@ -58,8 +60,8 @@ export function fillPixelData(
58
60
  } else {
59
61
  x = 0
60
62
  y = 0
61
- w = dst.width
62
- h = dst.height
63
+ w = dst.w
64
+ h = dst.h
63
65
  }
64
66
 
65
67
  const clip = resolveRectClipping(
@@ -67,8 +69,8 @@ export function fillPixelData(
67
69
  y,
68
70
  w,
69
71
  h,
70
- dst.width,
71
- dst.height,
72
+ dst.w,
73
+ dst.h,
72
74
  SCRATCH_RECT,
73
75
  )
74
76
 
@@ -81,8 +83,8 @@ export function fillPixelData(
81
83
  h: actualH,
82
84
  } = clip
83
85
 
84
- const dst32 = dst.data32
85
- const dw = dst.width
86
+ const dst32 = dst.data
87
+ const dw = dst.w
86
88
  let hasChanged = false
87
89
 
88
90
  for (let iy = 0; iy < actualH; iy++) {
@@ -1,10 +1,12 @@
1
- import type { BinaryMask, Color32, IPixelData32 } from '../_types'
2
- import { makeClippedRect, resolveRectClipping } from '../Internal/resolveClipping'
1
+ import type { Color32 } from '../_types'
2
+ import type { BinaryMask } from '../Mask/_mask-types'
3
+ import { makeClippedRect, resolveRectClipping } from '../Rect/resolveClipping'
4
+ import type { PixelData32 } from './_pixelData-types'
3
5
 
4
6
  const SCRATCH_RECT = makeClippedRect()
5
7
 
6
8
  /**
7
- * Fills a region of the {@link IPixelData32} buffer with a solid color using a mask.
9
+ * Fills a region of the {@link PixelData32} buffer with a solid color using a mask.
8
10
  * @param target - The target to modify.
9
11
  * @param color - The color to apply.
10
12
  * @param mask - The mask defining the area to fill.
@@ -12,7 +14,7 @@ const SCRATCH_RECT = makeClippedRect()
12
14
  * @param y - Starting vertical coordinate for the mask placement.
13
15
  */
14
16
  export function fillPixelDataBinaryMask(
15
- target: IPixelData32,
17
+ target: PixelData32,
16
18
  color: Color32,
17
19
  mask: BinaryMask,
18
20
  x = 0,
@@ -27,8 +29,8 @@ export function fillPixelDataBinaryMask(
27
29
  y,
28
30
  maskW,
29
31
  maskH,
30
- target.width,
31
- target.height,
32
+ target.w,
33
+ target.h,
32
34
  SCRATCH_RECT,
33
35
  )
34
36
 
@@ -42,8 +44,8 @@ export function fillPixelDataBinaryMask(
42
44
  } = clip
43
45
 
44
46
  const maskData = mask.data
45
- const dst32 = target.data32
46
- const dw = target.width
47
+ const dst32 = target.data
48
+ const dw = target.w
47
49
 
48
50
  let hasChanged = false
49
51
 
@@ -1,10 +1,12 @@
1
- import type { Color32, IPixelData32, Rect } from '../_types'
2
- import { makeClippedRect, resolveRectClipping } from '../Internal/resolveClipping'
1
+ import type { Color32 } from '../_types'
2
+ import type { Rect } from '../Rect/_rect-types'
3
+ import { makeClippedRect, resolveRectClipping } from '../Rect/resolveClipping'
4
+ import type { PixelData32 } from './_pixelData-types'
3
5
 
4
6
  const SCRATCH_RECT = makeClippedRect()
5
7
 
6
8
  /**
7
- * Fills a region or the {@link IPixelData32} buffer with a solid color.
9
+ * Fills a region or the {@link PixelData32} buffer with a solid color.
8
10
  * This function is faster than {@link fillPixelData} but does not
9
11
  * return a boolean value indicating changes were made.
10
12
  *
@@ -14,7 +16,7 @@ const SCRATCH_RECT = makeClippedRect()
14
16
  * buffer is filled.
15
17
  */
16
18
  export function fillPixelDataFast(
17
- target: IPixelData32,
19
+ target: PixelData32,
18
20
  color: Color32,
19
21
  rect?: Partial<Rect>,
20
22
  ): void
@@ -27,7 +29,7 @@ export function fillPixelDataFast(
27
29
  * @param h - Height of the fill area.
28
30
  */
29
31
  export function fillPixelDataFast(
30
- dst: IPixelData32,
32
+ dst: PixelData32,
31
33
  color: Color32,
32
34
  x: number,
33
35
  y: number,
@@ -35,7 +37,7 @@ export function fillPixelDataFast(
35
37
  h: number,
36
38
  ): void
37
39
  export function fillPixelDataFast(
38
- dst: IPixelData32,
40
+ dst: PixelData32,
39
41
  color: Color32,
40
42
  _x?: Partial<Rect> | number,
41
43
  _y?: number,
@@ -50,8 +52,8 @@ export function fillPixelDataFast(
50
52
  if (typeof _x === 'object') {
51
53
  x = _x.x ?? 0
52
54
  y = _x.y ?? 0
53
- w = _x.w ?? dst.width
54
- h = _x.h ?? dst.height
55
+ w = _x.w ?? dst.w
56
+ h = _x.h ?? dst.h
55
57
  } else if (typeof _x === 'number') {
56
58
  x = _x
57
59
  y = _y!
@@ -60,11 +62,11 @@ export function fillPixelDataFast(
60
62
  } else {
61
63
  x = 0
62
64
  y = 0
63
- w = dst.width
64
- h = dst.height
65
+ w = dst.w
66
+ h = dst.h
65
67
  }
66
68
 
67
- const clip = resolveRectClipping(x, y, w, h, dst.width, dst.height, SCRATCH_RECT)
69
+ const clip = resolveRectClipping(x, y, w, h, dst.w, dst.h, SCRATCH_RECT)
68
70
 
69
71
  if (!clip.inBounds) return
70
72
 
@@ -76,11 +78,11 @@ export function fillPixelDataFast(
76
78
  h: actualH,
77
79
  } = clip
78
80
 
79
- const dst32 = dst.data32
80
- const dw = dst.width
81
+ const dst32 = dst.data
82
+ const dw = dst.w
81
83
 
82
84
  // Optimization: If filling the entire buffer, use the native .fill()
83
- if (actualW === dw && actualH === dst.height && finalX === 0 && finalY === 0) {
85
+ if (actualW === dw && actualH === dst.h && finalX === 0 && finalY === 0) {
84
86
  dst32.fill(color)
85
87
  return
86
88
  }
@@ -1,10 +1,11 @@
1
- import { type IPixelData32, type PixelMutateOptions } from '../_types'
2
- import { makeClippedRect, resolveRectClipping } from '../Internal/resolveClipping'
1
+ import { type PixelMutateOptions } from '../_types'
2
+ import { makeClippedRect, resolveRectClipping } from '../Rect/resolveClipping'
3
+ import type { PixelData32 } from './_pixelData-types'
3
4
 
4
5
  const SCRATCH_RECT = makeClippedRect()
5
6
 
6
7
  export function invertPixelData(
7
- target: IPixelData32,
8
+ target: PixelData32,
8
9
  opts?: PixelMutateOptions,
9
10
  ): boolean {
10
11
  const mask = opts?.mask
@@ -12,11 +13,11 @@ export function invertPixelData(
12
13
  const targetY = opts?.y ?? 0
13
14
  const mx = opts?.mx ?? 0
14
15
  const my = opts?.my ?? 0
15
- const width = opts?.w ?? target.width
16
- const height = opts?.h ?? target.height
16
+ const width = opts?.w ?? target.w
17
+ const height = opts?.h ?? target.h
17
18
  const invertMask = opts?.invertMask ?? false
18
19
 
19
- const clip = resolveRectClipping(targetX, targetY, width, height, target.width, target.height, SCRATCH_RECT)
20
+ const clip = resolveRectClipping(targetX, targetY, width, height, target.w, target.h, SCRATCH_RECT)
20
21
 
21
22
  if (!clip.inBounds) return false
22
23
 
@@ -27,8 +28,8 @@ export function invertPixelData(
27
28
  h: actualH,
28
29
  } = clip
29
30
 
30
- const dst32 = target.data32
31
- const dw = target.width
31
+ const dst32 = target.data
32
+ const dw = target.w
32
33
  const mPitch = mask?.w ?? width
33
34
 
34
35
  const dx = x - targetX
@@ -1,24 +1,25 @@
1
- import type { AlphaMask, IPixelData32 } from '../_types'
1
+ import type { AlphaMask } from '../Mask/_mask-types'
2
2
  import { makeAlphaMask } from '../Mask/AlphaMask'
3
+ import type { PixelData32 } from './_pixelData-types'
3
4
 
4
5
  /**
5
6
  * Extracts the alpha channel from PixelData into a single-channel mask.
6
7
  * Returns a Uint8Array branded as AlphaMask.
7
8
  */
8
9
  export function pixelDataToAlphaMask(
9
- pixelData: IPixelData32,
10
+ pixelData: PixelData32,
10
11
  ): AlphaMask {
11
12
  const {
12
- data32,
13
- width,
14
- height,
13
+ data,
14
+ w,
15
+ h,
15
16
  } = pixelData
16
- const len = data32.length
17
- const mask = makeAlphaMask(width, height)
17
+ const len = data.length
18
+ const mask = makeAlphaMask(w, h)
18
19
  const maskData = mask.data
19
20
 
20
21
  for (let i = 0; i < len; i++) {
21
- const val = data32[i]
22
+ const val = data[i]
22
23
 
23
24
  // Extract the Alpha byte (top 8 bits in ABGR / Little-Endian)
24
25
  // Shift right by 24 moves the 4th byte to the 1st position
@@ -1,9 +1,9 @@
1
- import type { IPixelData32 } from '../_types'
1
+ import type { PixelData32 } from './_pixelData-types'
2
2
 
3
- export function reflectPixelDataHorizontal(pixelData: IPixelData32): void {
4
- const width = pixelData.width
5
- const height = pixelData.height
6
- const data = pixelData.data32
3
+ export function reflectPixelDataHorizontal(pixelData: PixelData32): void {
4
+ const width = pixelData.w
5
+ const height = pixelData.h
6
+ const data = pixelData.data
7
7
  const halfWidth = Math.floor(width / 2)
8
8
 
9
9
  for (let y = 0; y < height; y++) {
@@ -20,10 +20,10 @@ export function reflectPixelDataHorizontal(pixelData: IPixelData32): void {
20
20
  }
21
21
  }
22
22
 
23
- export function reflectPixelDataVertical(pixelData: IPixelData32): void {
24
- const width = pixelData.width
25
- const height = pixelData.height
26
- const data = pixelData.data32
23
+ export function reflectPixelDataVertical(pixelData: PixelData32): void {
24
+ const width = pixelData.w
25
+ const height = pixelData.h
26
+ const data = pixelData.data
27
27
  const halfHeight = Math.floor(height / 2)
28
28
 
29
29
  for (let y = 0; y < halfHeight; y++) {
@@ -1,19 +1,30 @@
1
- import { type IPixelData32, PixelData } from '../index'
2
- import { resample32 } from '../Internal/resample32'
1
+ import { resampleUint32Array } from '../Algorithm/resampleUint32Array'
2
+ import { type MutablePixelData32, type PixelData, type PixelData32, uInt32ArrayToImageData } from '../index'
3
3
 
4
4
  /**
5
5
  * Resamples PixelData by a specific factor using nearest neighbor.
6
6
  * Factor > 1 upscales, Factor < 1 downscales.
7
7
  */
8
8
  export function resamplePixelData(
9
- pixelData: IPixelData32,
9
+ pixelData: PixelData32,
10
10
  factor: number,
11
11
  ): PixelData {
12
- const { data, width, height } = resample32(pixelData.data32, pixelData.width, pixelData.height, factor)
13
12
 
14
- return new PixelData(new ImageData(
15
- new Uint8ClampedArray(data.buffer) as ImageDataArray,
16
- width,
17
- height,
18
- ))
13
+ const output = {} as MutablePixelData32
14
+
15
+ const resampled = resampleUint32Array(pixelData.data, pixelData.w, pixelData.h, factor, output) as PixelData
16
+
17
+ (resampled as any).imageData = uInt32ArrayToImageData(resampled.data, resampled.w, resampled.h)
18
+
19
+ return resampled
20
+ }
21
+
22
+ export function resamplePixelDataInPlace(
23
+ pixelData: PixelData32,
24
+ factor: number,
25
+ ): void {
26
+
27
+ const resampled = resampleUint32Array(pixelData.data, pixelData.w, pixelData.h, factor, pixelData) as PixelData
28
+
29
+ (resampled as any).imageData = uInt32ArrayToImageData(resampled.data, resampled.w, resampled.h)
19
30
  }
@@ -1,4 +1,5 @@
1
- import { PixelData } from './PixelData'
1
+ import type { PixelData } from './_pixelData-types'
2
+ import { setPixelData } from './PixelData'
2
3
 
3
4
  /**
4
5
  * Rotates pixel data 90 degrees clockwise.
@@ -6,9 +7,9 @@ import { PixelData } from './PixelData'
6
7
  * If rectangular, it replaces the internal ImageData with a new rotated version.
7
8
  */
8
9
  export function rotatePixelData(pixelData: PixelData): void {
9
- const width = pixelData.width
10
- const height = pixelData.height
11
- const data = pixelData.data32
10
+ const width = pixelData.w
11
+ const height = pixelData.h
12
+ const data = pixelData.data
12
13
 
13
14
  if (width === height) {
14
15
  rotateSquareInPlace(pixelData)
@@ -38,12 +39,12 @@ export function rotatePixelData(pixelData: PixelData): void {
38
39
  newHeight,
39
40
  )
40
41
 
41
- pixelData.set(newImageData)
42
+ setPixelData(pixelData, newImageData)
42
43
  }
43
44
 
44
45
  function rotateSquareInPlace(pixelData: PixelData): void {
45
- const n = pixelData.width
46
- const data = pixelData.data32
46
+ const n = pixelData.w
47
+ const data = pixelData.data
47
48
 
48
49
  for (let i = 0; i < n / 2; i++) {
49
50
  for (let j = i; j < n - i - 1; j++) {
@@ -0,0 +1,15 @@
1
+ import { makePixelData, type PixelData } from '../index'
2
+
3
+ export function uInt32ArrayToPixelData(
4
+ data: Uint32Array,
5
+ width: number,
6
+ height: number,
7
+ ): PixelData {
8
+ const buffer = data.buffer as ArrayBuffer
9
+ const byteOffset = data.byteOffset
10
+ const byteLength = data.byteLength
11
+ const clampedArray = new Uint8ClampedArray(buffer, byteOffset, byteLength)
12
+ const imageData = new ImageData(clampedArray, width, height)
13
+
14
+ return makePixelData(imageData)
15
+ }
@@ -1,13 +1,13 @@
1
- import type { IPixelData } from '../_types'
2
- import type { PaintBuffer } from '../Paint/PaintBuffer'
1
+ import type { ColorPaintBuffer } from '../Paint/ColorPaintBuffer'
2
+ import type { PixelData } from './_pixelData-types'
3
3
  import { writePixelDataBuffer } from './writePixelDataBuffer'
4
4
 
5
5
  /**
6
6
  * @param writePixelDataBufferFn - @hidden
7
7
  */
8
8
  export function writePaintBufferToPixelData(
9
- target: IPixelData,
10
- paintBuffer: PaintBuffer,
9
+ target: PixelData,
10
+ paintBuffer: ColorPaintBuffer,
11
11
  writePixelDataBufferFn = writePixelDataBuffer,
12
12
  ) {
13
13
  const tileShift = paintBuffer.config.tileShift
@@ -20,7 +20,7 @@ export function writePaintBufferToPixelData(
20
20
  const dx = tile.tx << tileShift
21
21
  const dy = tile.ty << tileShift
22
22
 
23
- writePixelDataBufferFn(target, tile.data32, dx, dy, tile.width, tile.height)
23
+ writePixelDataBufferFn(target, tile.data, dx, dy, tile.w, tile.h)
24
24
  }
25
25
  }
26
26
  }
@@ -1,21 +1,22 @@
1
- import { type IPixelData32, type Rect } from '../_types'
2
- import { makeClippedBlit, resolveBlitClipping } from '../Internal/resolveClipping'
1
+ import type { Rect } from '../Rect/_rect-types'
2
+ import { makeClippedBlit, resolveBlitClipping } from '../Rect/resolveClipping'
3
+ import type { PixelData32 } from './_pixelData-types'
3
4
 
4
5
  const SCRATCH_BLIT = makeClippedBlit()
5
6
 
6
7
  /**
7
- * Copies a pixel buffer into a specific region of a {@link IPixelData32} object.
8
+ * Copies a pixel buffer into a specific region of a {@link PixelData32} object.
8
9
  *
9
10
  * This function performs a direct memory copy from a {@link Uint32Array}
10
11
  * into the target buffer.
11
12
  */
12
13
  export function writePixelDataBuffer(
13
- target: IPixelData32,
14
+ target: PixelData32,
14
15
  data: Uint32Array,
15
16
  rect: Rect,
16
17
  ): void
17
18
  export function writePixelDataBuffer(
18
- target: IPixelData32,
19
+ target: PixelData32,
19
20
  data: Uint32Array,
20
21
  x: number,
21
22
  y: number,
@@ -23,7 +24,7 @@ export function writePixelDataBuffer(
23
24
  h: number,
24
25
  ): void
25
26
  export function writePixelDataBuffer(
26
- target: IPixelData32,
27
+ target: PixelData32,
27
28
  data: Uint32Array,
28
29
  _x: Rect | number,
29
30
  _y?: number,
@@ -39,9 +40,9 @@ export function writePixelDataBuffer(
39
40
  h: _h!,
40
41
  }
41
42
 
42
- const dstW = target.width
43
- const dstH = target.height
44
- const dstData = target.data32
43
+ const dstW = target.w
44
+ const dstH = target.h
45
+ const dstData = target.data
45
46
 
46
47
  // treat the source buffer as a Source Image starting at 0,0 with size w,h
47
48
  const clip = resolveBlitClipping(
@@ -0,0 +1,7 @@
1
+ /** Rectangle definition */
2
+ export type Rect = {
3
+ x: number
4
+ y: number
5
+ w: number
6
+ h: number
7
+ }
@@ -1,4 +1,4 @@
1
- import type { Rect } from '../_types'
1
+ import type { Rect } from './_rect-types'
2
2
 
3
3
  export function getRectsBounds<T extends Rect>(rects: T[]): T {
4
4
  if (rects.length === 1) return { ...rects[0] }
@@ -1,5 +1,6 @@
1
- import type { NullableMaskRect, Rect } from '../_types'
1
+ import type { NullableMaskRect } from '../Mask/_mask-types'
2
2
  import { extractMaskBuffer } from '../Mask/extractMaskBuffer'
3
+ import type { Rect } from './_rect-types'
3
4
 
4
5
  /**
5
6
  * Intersects a target rectangle with a boundary, trimming dimensions and masks in-place.
@@ -1,4 +1,4 @@
1
- import { type Rect } from '../_types'
1
+ import type { Rect } from './_rect-types'
2
2
 
3
3
  export function trimRectBounds(
4
4
  x: number,
@@ -0,0 +1,40 @@
1
+ import { MaskType } from '../Mask/_mask-types'
2
+ import { type AlphaMaskTile, type BinaryMaskTile, type TileFactory, TileType } from './_tile-types'
3
+
4
+ export const makeAlphaMaskTile: TileFactory<AlphaMaskTile> = (
5
+ id: number,
6
+ tx: number,
7
+ ty: number,
8
+ tileSize: number,
9
+ tileArea: number,
10
+ ) => {
11
+ return {
12
+ tileType: TileType.MASK,
13
+ type: MaskType.ALPHA,
14
+ data: new Uint8Array(tileArea),
15
+ w: tileSize,
16
+ h: tileSize,
17
+ id,
18
+ tx,
19
+ ty,
20
+ }
21
+ }
22
+
23
+ export const makeBinaryMaskTile: TileFactory<BinaryMaskTile> = (
24
+ id: number,
25
+ tx: number,
26
+ ty: number,
27
+ tileSize: number,
28
+ tileArea: number,
29
+ ) => {
30
+ return {
31
+ tileType: TileType.MASK,
32
+ type: MaskType.BINARY,
33
+ data: new Uint8Array(tileArea),
34
+ w: tileSize,
35
+ h: tileSize,
36
+ id,
37
+ tx,
38
+ ty,
39
+ }
40
+ }
@@ -0,0 +1,23 @@
1
+ import { type PixelTile, TileType } from './_tile-types'
2
+
3
+ export function makePixelTile(
4
+ id: number,
5
+ tx: number,
6
+ ty: number,
7
+ tileSize: number,
8
+ tileArea: number,
9
+ ): PixelTile {
10
+ const data32 = new Uint32Array(tileArea)
11
+ const data8 = new Uint8ClampedArray(data32.buffer) as Uint8ClampedArray<ArrayBuffer>
12
+
13
+ return {
14
+ tileType: TileType.PIXEL,
15
+ id,
16
+ tx,
17
+ ty,
18
+ w: tileSize,
19
+ h: tileSize,
20
+ data: data32,
21
+ imageData: new ImageData(data8, tileSize, tileSize),
22
+ }
23
+ }
@@ -1,15 +1,15 @@
1
1
  import type { PixelEngineConfig } from '../History/PixelEngineConfig'
2
+ import type { Tile, TileFactory } from './_tile-types'
2
3
 
3
- import { PixelTile } from './PixelTile'
4
-
5
- export class PixelTilePool {
6
- public pool: PixelTile[]
4
+ export class TilePool<T extends Tile> {
5
+ public pool: T[]
7
6
 
8
7
  private tileSize: number
9
8
  private tileArea: number
10
9
 
11
10
  constructor(
12
11
  config: PixelEngineConfig,
12
+ private tileFactory: TileFactory<T>,
13
13
  ) {
14
14
  this.pool = []
15
15
  this.tileSize = config.tileSize
@@ -20,7 +20,7 @@ export class PixelTilePool {
20
20
  id: number,
21
21
  tx: number,
22
22
  ty: number,
23
- ): PixelTile {
23
+ ): T {
24
24
  let tile = this.pool.pop()
25
25
 
26
26
  if (tile) {
@@ -29,12 +29,12 @@ export class PixelTilePool {
29
29
  tile.ty = ty
30
30
 
31
31
  // Wipe dirty memory from previous uses before handing it out
32
- tile.data32.fill(0)
32
+ tile.data.fill(0)
33
33
 
34
34
  return tile
35
35
  }
36
36
 
37
- return new PixelTile(
37
+ return this.tileFactory(
38
38
  id,
39
39
  tx,
40
40
  ty,
@@ -43,11 +43,11 @@ export class PixelTilePool {
43
43
  )
44
44
  }
45
45
 
46
- releaseTile(tile: PixelTile): void {
46
+ releaseTile(tile: T): void {
47
47
  this.pool.push(tile)
48
48
  }
49
49
 
50
- releaseTiles(tiles: (PixelTile | undefined)[]): void {
50
+ releaseTiles(tiles: (T | undefined)[]): void {
51
51
  let length = tiles.length
52
52
 
53
53
  for (let i = 0; i < length; i++) {
@@ -0,0 +1,33 @@
1
+ import type { AlphaMask, BinaryMask } from '../Mask/_mask-types'
2
+ import type { PixelData } from '../PixelData/_pixelData-types'
3
+
4
+ export const enum TileType {
5
+ PIXEL,
6
+ MASK,
7
+ }
8
+
9
+ interface BaseTile {
10
+ tileType: TileType,
11
+ id: number
12
+ tx: number
13
+ ty: number
14
+ }
15
+
16
+ export interface PixelTile extends PixelData, BaseTile {
17
+ }
18
+
19
+ export interface AlphaMaskTile extends AlphaMask, BaseTile {
20
+ }
21
+
22
+ export interface BinaryMaskTile extends BinaryMask, BaseTile {
23
+ }
24
+
25
+ export type Tile = PixelTile | AlphaMaskTile | BinaryMaskTile
26
+
27
+ export type TileFactory<T extends Tile> = (
28
+ id: number,
29
+ tx: number,
30
+ ty: number,
31
+ tileSize: number,
32
+ tileArea: number,
33
+ ) => T