pixel-data-js 0.25.0 → 0.26.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 (63) hide show
  1. package/dist/index.prod.cjs +1832 -1606
  2. package/dist/index.prod.cjs.map +1 -1
  3. package/dist/index.prod.d.ts +458 -324
  4. package/dist/index.prod.js +1811 -1600
  5. package/dist/index.prod.js.map +1 -1
  6. package/package.json +8 -9
  7. package/src/Algorithm/floodFillSelection.ts +49 -80
  8. package/src/Canvas/PixelCanvas.ts +1 -1
  9. package/src/Canvas/ReusableCanvas.ts +1 -1
  10. package/src/History/HistoryAction.ts +6 -5
  11. package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +8 -10
  12. package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +8 -10
  13. package/src/History/PixelMutator/mutatorApplyMask.ts +39 -0
  14. package/src/History/PixelMutator/{mutatorBlendPixelDataAlphaMask.ts → mutatorBlendAlphaMask.ts} +9 -9
  15. package/src/History/PixelMutator/{mutatorBlendPixelDataBinaryMask.ts → mutatorBlendBinaryMask.ts} +9 -9
  16. package/src/History/PixelMutator/mutatorBlendColor.ts +8 -9
  17. package/src/History/PixelMutator/mutatorBlendColorPaintAlphaMask.ts +51 -0
  18. package/src/History/PixelMutator/mutatorBlendColorPaintBinaryMask.ts +51 -0
  19. package/src/History/PixelMutator/mutatorBlendColorPaintMask.ts +60 -0
  20. package/src/History/PixelMutator/mutatorBlendMask.ts +43 -0
  21. package/src/History/PixelMutator/mutatorBlendPaintRect.ts +55 -0
  22. package/src/History/PixelMutator/mutatorBlendPixel.ts +2 -2
  23. package/src/History/PixelMutator/mutatorBlendPixelData.ts +8 -9
  24. package/src/History/PixelMutator/mutatorClear.ts +13 -11
  25. package/src/History/PixelMutator/mutatorFill.ts +2 -2
  26. package/src/History/PixelMutator/mutatorFillBinaryMask.ts +3 -4
  27. package/src/History/PixelMutator/mutatorInvert.ts +8 -9
  28. package/src/History/PixelMutator.ts +20 -4
  29. package/src/History/PixelWriter.ts +11 -13
  30. package/src/Input/fileToImageData.ts +1 -1
  31. package/src/Internal/helpers.ts +4 -1
  32. package/src/Mask/applyBinaryMaskToAlphaMask.ts +8 -10
  33. package/src/Paint/PaintBuffer.ts +3 -3
  34. package/src/Paint/PaintBufferCanvasRenderer.ts +1 -1
  35. package/src/Paint/makePaintMask.ts +5 -5
  36. package/src/Paint/makeRectFalloffPaintAlphaMask.ts +3 -3
  37. package/src/PixelData/applyAlphaMaskToPixelData.ts +14 -16
  38. package/src/PixelData/applyBinaryMaskToPixelData.ts +14 -16
  39. package/src/PixelData/applyMaskToPixelData.ts +22 -0
  40. package/src/PixelData/blendColorPixelData.ts +12 -15
  41. package/src/PixelData/blendColorPixelDataAlphaMask.ts +16 -16
  42. package/src/PixelData/blendColorPixelDataBinaryMask.ts +16 -16
  43. package/src/PixelData/blendColorPixelDataMask.ts +16 -0
  44. package/src/PixelData/blendColorPixelDataPaintAlphaMask.ts +30 -0
  45. package/src/PixelData/blendColorPixelDataPaintBinaryMask.ts +30 -0
  46. package/src/PixelData/blendColorPixelDataPaintMask.ts +35 -0
  47. package/src/PixelData/blendPixelData.ts +14 -16
  48. package/src/PixelData/blendPixelDataAlphaMask.ts +17 -19
  49. package/src/PixelData/blendPixelDataBinaryMask.ts +17 -19
  50. package/src/PixelData/blendPixelDataMask.ts +16 -0
  51. package/src/PixelData/blendPixelDataPaintBuffer.ts +1 -1
  52. package/src/PixelData/{clearPixelData.ts → clearPixelDataFast.ts} +2 -2
  53. package/src/PixelData/fillPixelDataBinaryMask.ts +8 -22
  54. package/src/PixelData/fillPixelDataFast.ts +2 -2
  55. package/src/PixelData/invertPixelData.ts +13 -16
  56. package/src/_types.ts +8 -7
  57. package/src/index.ts +41 -29
  58. package/dist/index.dev.cjs +0 -5363
  59. package/dist/index.dev.cjs.map +0 -1
  60. package/dist/index.dev.js +0 -5154
  61. package/dist/index.dev.js.map +0 -1
  62. package/src/Canvas/_constants.ts +0 -2
  63. package/src/PixelData/PixelBuffer32.ts +0 -28
@@ -8,27 +8,27 @@ import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
8
8
  * If the width (`w`) or height (`h`) are omitted from the options, they will safely
9
9
  * default to the dimensions of the provided mask to prevent out-of-bounds memory access.
10
10
  *
11
- * @param dst - The destination {@link IPixelData32} buffer to modify.
11
+ * @param target - The destination {@link IPixelData32} buffer to modify.
12
12
  * @param color - The solid color to apply.
13
13
  * @param mask - The mask defining the per-pixel opacity of the target area.
14
14
  * @param opts - Configuration options including placement coordinates, bounds, global alpha, and mask offsets.
15
15
  * @returns true if any pixels were actually modified.
16
16
  */
17
17
  export function blendColorPixelDataAlphaMask(
18
- dst: IPixelData32,
18
+ target: IPixelData32,
19
19
  color: Color32,
20
20
  mask: AlphaMask,
21
- opts: ColorBlendMaskOptions = {},
21
+ opts?: ColorBlendMaskOptions,
22
22
  ): boolean {
23
- const targetX = opts.x ?? 0
24
- const targetY = opts.y ?? 0
25
- const w = opts.w ?? mask.w
26
- const h = opts.h ?? mask.h
27
- const globalAlpha = opts.alpha ?? 255
28
- const blendFn = opts.blendFn ?? sourceOverPerfect
29
- const mx = opts.mx ?? 0
30
- const my = opts.my ?? 0
31
- const invertMask = opts.invertMask ?? false
23
+ const targetX = opts?.x ?? 0
24
+ const targetY = opts?.y ?? 0
25
+ const w = opts?.w ?? mask.w
26
+ const h = opts?.h ?? mask.h
27
+ const globalAlpha = opts?.alpha ?? 255
28
+ const blendFn = opts?.blendFn ?? sourceOverPerfect
29
+ const mx = opts?.mx ?? 0
30
+ const my = opts?.my ?? 0
31
+ const invertMask = opts?.invertMask ?? false
32
32
 
33
33
  if (globalAlpha === 0) return false
34
34
 
@@ -52,16 +52,16 @@ export function blendColorPixelDataAlphaMask(
52
52
  y = 0
53
53
  }
54
54
 
55
- actualW = Math.min(actualW, dst.width - x)
56
- actualH = Math.min(actualH, dst.height - y)
55
+ actualW = Math.min(actualW, target.width - x)
56
+ actualH = Math.min(actualH, target.height - y)
57
57
 
58
58
  if (actualW <= 0 || actualH <= 0) return false
59
59
 
60
60
  const dx = (x - targetX) | 0
61
61
  const dy = (y - targetY) | 0
62
62
 
63
- const dst32 = dst.data32
64
- const dw = dst.width
63
+ const dst32 = target.data32
64
+ const dw = target.width
65
65
  const mPitch = mask.w
66
66
  const maskData = mask.data
67
67
 
@@ -8,27 +8,27 @@ import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
8
8
  * If the width (`w`) or height (`h`) are omitted from the options, they will safely
9
9
  * default to the dimensions of the provided mask to prevent out-of-bounds memory access.
10
10
  *
11
- * @param dst - The destination {@link IPixelData32} buffer to modify.
11
+ * @param target - The destination {@link IPixelData32} buffer to modify.
12
12
  * @param color - The solid color to apply.
13
13
  * @param mask - The mask defining the per-pixel opacity of the target area.
14
14
  * @param opts - Configuration options including placement coordinates, bounds, global alpha, and mask offsets.
15
15
  * @returns true if any pixels were actually modified.
16
16
  */
17
17
  export function blendColorPixelDataBinaryMask(
18
- dst: IPixelData32,
18
+ target: IPixelData32,
19
19
  color: Color32,
20
20
  mask: BinaryMask,
21
- opts: ColorBlendMaskOptions = {},
21
+ opts?: ColorBlendMaskOptions,
22
22
  ): boolean {
23
- const targetX = opts.x ?? 0
24
- const targetY = opts.y ?? 0
25
- let w = opts.w ?? mask.w
26
- let h = opts.h ?? mask.h
27
- const globalAlpha = opts.alpha ?? 255
28
- const blendFn = opts.blendFn ?? sourceOverPerfect
29
- const mx = opts.mx ?? 0
30
- const my = opts.my ?? 0
31
- const invertMask = opts.invertMask ?? false
23
+ const targetX = opts?.x ?? 0
24
+ const targetY = opts?.y ?? 0
25
+ let w = opts?.w ?? mask.w
26
+ let h = opts?.h ?? mask.h
27
+ const globalAlpha = opts?.alpha ?? 255
28
+ const blendFn = opts?.blendFn ?? sourceOverPerfect
29
+ const mx = opts?.mx ?? 0
30
+ const my = opts?.my ?? 0
31
+ const invertMask = opts?.invertMask ?? false
32
32
 
33
33
  if (globalAlpha === 0) return false
34
34
 
@@ -50,8 +50,8 @@ export function blendColorPixelDataBinaryMask(
50
50
  y = 0
51
51
  }
52
52
 
53
- const actualW = Math.min(w, dst.width - x)
54
- const actualH = Math.min(h, dst.height - y)
53
+ const actualW = Math.min(w, target.width - x)
54
+ const actualH = Math.min(h, target.height - y)
55
55
 
56
56
  if (actualW <= 0 || actualH <= 0) return false
57
57
 
@@ -65,8 +65,8 @@ export function blendColorPixelDataBinaryMask(
65
65
 
66
66
  const dx = (x - targetX) | 0
67
67
  const dy = (y - targetY) | 0
68
- const dst32 = dst.data32
69
- const dw = dst.width
68
+ const dst32 = target.data32
69
+ const dw = target.width
70
70
  const mPitch = mask.w
71
71
  const maskData = mask.data
72
72
  let dIdx = (y * dw + x) | 0
@@ -0,0 +1,16 @@
1
+ import { type Color32, type ColorBlendMaskOptions, type IPixelData32, type Mask, MaskType } from '../_types'
2
+ import { blendColorPixelDataAlphaMask } from './blendColorPixelDataAlphaMask'
3
+ import { blendColorPixelDataBinaryMask } from './blendColorPixelDataBinaryMask'
4
+
5
+ export function blendColorPixelDataMask(
6
+ dst: IPixelData32,
7
+ color: Color32,
8
+ mask: Mask,
9
+ opts?: ColorBlendMaskOptions,
10
+ ): boolean {
11
+ if (mask.type === MaskType.BINARY) {
12
+ return blendColorPixelDataBinaryMask(dst, color, mask, opts)
13
+ } else {
14
+ return blendColorPixelDataAlphaMask(dst, color, mask, opts)
15
+ }
16
+ }
@@ -0,0 +1,30 @@
1
+ import { type Color32, type IPixelData32, type PaintAlphaMask } from '../_types'
2
+ import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
3
+ import { blendColorPixelDataAlphaMask } from './blendColorPixelDataAlphaMask'
4
+
5
+ const SCRATCH_OPTS = {
6
+ x: 0,
7
+ y: 0,
8
+ alpha: 255,
9
+ blendFn: sourceOverPerfect,
10
+ }
11
+
12
+ export function blendColorPixelDataPaintAlphaMask(
13
+ dst: IPixelData32,
14
+ color: Color32,
15
+ mask: PaintAlphaMask,
16
+ x: number,
17
+ y: number,
18
+ alpha = 255,
19
+ blendFn = sourceOverPerfect,
20
+ ): boolean {
21
+ const tx = x + mask.centerOffsetX
22
+ const ty = y + mask.centerOffsetY
23
+
24
+ SCRATCH_OPTS.x = tx
25
+ SCRATCH_OPTS.y = ty
26
+ SCRATCH_OPTS.alpha = alpha
27
+ SCRATCH_OPTS.blendFn = blendFn
28
+
29
+ return blendColorPixelDataAlphaMask(dst, color, mask, SCRATCH_OPTS)
30
+ }
@@ -0,0 +1,30 @@
1
+ import { type Color32, type IPixelData32, type PaintBinaryMask } from '../_types'
2
+ import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
3
+ import { blendColorPixelDataBinaryMask } from './blendColorPixelDataBinaryMask'
4
+
5
+ const SCRATCH_OPTS = {
6
+ x: 0,
7
+ y: 0,
8
+ alpha: 255,
9
+ blendFn: sourceOverPerfect,
10
+ }
11
+
12
+ export function blendColorPixelDataPaintBinaryMask(
13
+ dst: IPixelData32,
14
+ color: Color32,
15
+ mask: PaintBinaryMask,
16
+ x: number,
17
+ y: number,
18
+ alpha = 255,
19
+ blendFn = sourceOverPerfect,
20
+ ): boolean {
21
+ const tx = x + mask.centerOffsetX
22
+ const ty = y + mask.centerOffsetY
23
+
24
+ SCRATCH_OPTS.x = tx
25
+ SCRATCH_OPTS.y = ty
26
+ SCRATCH_OPTS.alpha = alpha
27
+ SCRATCH_OPTS.blendFn = blendFn
28
+
29
+ return blendColorPixelDataBinaryMask(dst, color, mask, SCRATCH_OPTS)
30
+ }
@@ -0,0 +1,35 @@
1
+ import { type Color32, type IPixelData32, MaskType, type PaintMask } from '../_types'
2
+ import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
3
+ import { blendColorPixelDataAlphaMask } from './blendColorPixelDataAlphaMask'
4
+ import { blendColorPixelDataBinaryMask } from './blendColorPixelDataBinaryMask'
5
+
6
+ const SCRATCH_OPTS = {
7
+ x: 0,
8
+ y: 0,
9
+ alpha: 255,
10
+ blendFn: sourceOverPerfect,
11
+ }
12
+
13
+ export function blendColorPixelDataPaintMask(
14
+ dst: IPixelData32,
15
+ color: Color32,
16
+ mask: PaintMask,
17
+ x: number,
18
+ y: number,
19
+ alpha = 255,
20
+ blendFn = sourceOverPerfect,
21
+ ): boolean {
22
+ const tx = x + mask.centerOffsetX
23
+ const ty = y + mask.centerOffsetY
24
+
25
+ SCRATCH_OPTS.x = tx
26
+ SCRATCH_OPTS.y = ty
27
+ SCRATCH_OPTS.alpha = alpha
28
+ SCRATCH_OPTS.blendFn = blendFn
29
+
30
+ if (mask.type === MaskType.BINARY) {
31
+ return blendColorPixelDataBinaryMask(dst, color, mask, SCRATCH_OPTS)
32
+ } else {
33
+ return blendColorPixelDataAlphaMask(dst, color, mask, SCRATCH_OPTS)
34
+ }
35
+ }
@@ -16,20 +16,18 @@ import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
16
16
  * });
17
17
  */
18
18
  export function blendPixelData(
19
- dst: IPixelData32,
19
+ target: IPixelData32,
20
20
  src: IPixelData32,
21
- opts: PixelBlendOptions = {},
21
+ opts?: PixelBlendOptions,
22
22
  ): boolean {
23
- const {
24
- x: targetX = 0,
25
- y: targetY = 0,
26
- sx: sourceX = 0,
27
- sy: sourceY = 0,
28
- w: width = src.width,
29
- h: height = src.height,
30
- alpha: globalAlpha = 255,
31
- blendFn = sourceOverPerfect,
32
- } = opts
23
+ const targetX = opts?.x ?? 0
24
+ const targetY = opts?.y ?? 0
25
+ const sourceX = opts?.sx ?? 0
26
+ const sourceY = opts?.sy ?? 0
27
+ const width = opts?.w ?? src.width
28
+ const height = opts?.h ?? src.height
29
+ const globalAlpha = opts?.alpha ?? 255
30
+ const blendFn = opts?.blendFn ?? sourceOverPerfect
33
31
 
34
32
  if (globalAlpha === 0) return false
35
33
 
@@ -63,13 +61,13 @@ export function blendPixelData(
63
61
  y = 0
64
62
  }
65
63
 
66
- const actualW = Math.min(w, dst.width - x)
67
- const actualH = Math.min(h, dst.height - y)
64
+ const actualW = Math.min(w, target.width - x)
65
+ const actualH = Math.min(h, target.height - y)
68
66
  if (actualW <= 0 || actualH <= 0) return false
69
67
 
70
- const dst32 = dst.data32
68
+ const dst32 = target.data32
71
69
  const src32 = src.data32
72
- const dw = dst.width
70
+ const dw = target.width
73
71
  const sw = src.width
74
72
 
75
73
  let dIdx = (y * dw + x) | 0
@@ -2,24 +2,22 @@ import { type AlphaMask, type Color32, type IPixelData32, type PixelBlendMaskOpt
2
2
  import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
3
3
 
4
4
  export function blendPixelDataAlphaMask(
5
- dst: IPixelData32,
5
+ target: IPixelData32,
6
6
  src: IPixelData32,
7
7
  alphaMask: AlphaMask,
8
- opts: PixelBlendMaskOptions = {},
8
+ opts?: PixelBlendMaskOptions,
9
9
  ): boolean {
10
- const {
11
- x: targetX = 0,
12
- y: targetY = 0,
13
- sx: sourceX = 0,
14
- sy: sourceY = 0,
15
- w: width = src.width,
16
- h: height = src.height,
17
- alpha: globalAlpha = 255,
18
- blendFn = sourceOverPerfect,
19
- mx = 0,
20
- my = 0,
21
- invertMask = false,
22
- } = opts
10
+ const targetX = opts?.x ?? 0
11
+ const targetY = opts?.y ?? 0
12
+ const sourceX = opts?.sx ?? 0
13
+ const sourceY = opts?.sy ?? 0
14
+ const width = opts?.w ?? src.width
15
+ const height = opts?.h ?? src.height
16
+ const globalAlpha = opts?.alpha ?? 255
17
+ const blendFn = opts?.blendFn ?? sourceOverPerfect
18
+ const mx = opts?.mx ?? 0
19
+ const my = opts?.my ?? 0
20
+ const invertMask = opts?.invertMask ?? false
23
21
 
24
22
  if (globalAlpha === 0) return false
25
23
 
@@ -54,12 +52,12 @@ export function blendPixelDataAlphaMask(
54
52
  y = 0
55
53
  }
56
54
 
57
- const actualW = Math.min(w, dst.width - x)
58
- const actualH = Math.min(h, dst.height - y)
55
+ const actualW = Math.min(w, target.width - x)
56
+ const actualH = Math.min(h, target.height - y)
59
57
  if (actualW <= 0 || actualH <= 0) return false
60
58
 
61
59
  // 2. Index Setup
62
- const dw = dst.width
60
+ const dw = target.width
63
61
  const sw = src.width
64
62
  const mPitch = alphaMask.w
65
63
  const maskData = alphaMask.data
@@ -69,7 +67,7 @@ export function blendPixelDataAlphaMask(
69
67
  const dx = (x - targetX) | 0
70
68
  const dy = (y - targetY) | 0
71
69
 
72
- const dst32 = dst.data32
70
+ const dst32 = target.data32
73
71
  const src32 = src.data32
74
72
 
75
73
  let dIdx = (y * dw + x) | 0
@@ -2,24 +2,22 @@ import type { BinaryMask, Color32, IPixelData32, PixelBlendMaskOptions } from '.
2
2
  import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
3
3
 
4
4
  export function blendPixelDataBinaryMask(
5
- dst: IPixelData32,
5
+ target: IPixelData32,
6
6
  src: IPixelData32,
7
7
  binaryMask: BinaryMask,
8
- opts: PixelBlendMaskOptions = {},
8
+ opts?: PixelBlendMaskOptions,
9
9
  ): boolean {
10
- const {
11
- x: targetX = 0,
12
- y: targetY = 0,
13
- sx: sourceX = 0,
14
- sy: sourceY = 0,
15
- w: width = src.width,
16
- h: height = src.height,
17
- alpha: globalAlpha = 255,
18
- blendFn = sourceOverPerfect,
19
- mx = 0,
20
- my = 0,
21
- invertMask = false,
22
- } = opts
10
+ const targetX = opts?.x ?? 0
11
+ const targetY = opts?.y ?? 0
12
+ const sourceX = opts?.sx ?? 0
13
+ const sourceY = opts?.sy ?? 0
14
+ const width = opts?.w ?? src.width
15
+ const height = opts?.h ?? src.height
16
+ const globalAlpha = opts?.alpha ?? 255
17
+ const blendFn = opts?.blendFn ?? sourceOverPerfect
18
+ const mx = opts?.mx ?? 0
19
+ const my = opts?.my ?? 0
20
+ const invertMask = opts?.invertMask ?? false
23
21
 
24
22
  if (globalAlpha === 0) return false
25
23
 
@@ -56,8 +54,8 @@ export function blendPixelDataBinaryMask(
56
54
  y = 0
57
55
  }
58
56
 
59
- const actualW = Math.min(w, dst.width - x)
60
- const actualH = Math.min(h, dst.height - y)
57
+ const actualW = Math.min(w, target.width - x)
58
+ const actualH = Math.min(h, target.height - y)
61
59
 
62
60
  if (actualW <= 0 || actualH <= 0) return false
63
61
 
@@ -67,9 +65,9 @@ export function blendPixelDataBinaryMask(
67
65
  const dx = (x - targetX) | 0
68
66
  const dy = (y - targetY) | 0
69
67
 
70
- const dst32 = dst.data32
68
+ const dst32 = target.data32
71
69
  const src32 = src.data32
72
- const dw = dst.width
70
+ const dw = target.width
73
71
  const sw = src.width
74
72
  const mPitch = binaryMask.w
75
73
  const maskData = binaryMask.data
@@ -0,0 +1,16 @@
1
+ import { type IPixelData32, type Mask, MaskType, type PixelBlendMaskOptions } from '../_types'
2
+ import { blendPixelDataAlphaMask } from './blendPixelDataAlphaMask'
3
+ import { blendPixelDataBinaryMask } from './blendPixelDataBinaryMask'
4
+
5
+ export function blendPixelDataMask(
6
+ target: IPixelData32,
7
+ src: IPixelData32,
8
+ mask: Mask,
9
+ opts?: PixelBlendMaskOptions,
10
+ ): boolean {
11
+ if (mask.type === MaskType.BINARY) {
12
+ return blendPixelDataBinaryMask(target, src, mask, opts)
13
+ } else {
14
+ return blendPixelDataAlphaMask(target, src, mask, opts)
15
+ }
16
+ }
@@ -10,8 +10,8 @@ const SCRATCH_OPTS = {
10
10
  }
11
11
 
12
12
  export function blendPixelDataPaintBuffer(
13
- paintBuffer: PaintBuffer,
14
13
  target: IPixelData32,
14
+ paintBuffer: PaintBuffer,
15
15
  alpha = 255,
16
16
  blendFn?: BlendColor32,
17
17
  blendPixelDataFn = blendPixelData,
@@ -3,9 +3,9 @@ import { fillPixelDataFast } from './fillPixelDataFast'
3
3
 
4
4
  /**
5
5
  * Clears a region of the PixelData to transparent (0x00000000).
6
- * Internally uses the optimized fillPixelData.
6
+ * Internally uses the optimized fillPixelDataFast.
7
7
  */
8
- export function clearPixelData(
8
+ export function clearPixelDataFast(
9
9
  dst: IPixelData32,
10
10
  rect?: Partial<BinaryMaskRect>,
11
11
  ): void {
@@ -5,22 +5,19 @@ const SCRATCH_RECT = makeClippedRect()
5
5
 
6
6
  /**
7
7
  * Fills a region of the {@link IPixelData32} buffer with a solid color using a mask.
8
- * @param dst - The target to modify.
8
+ * @param target - The target to modify.
9
9
  * @param color - The color to apply.
10
10
  * @param mask - The mask defining the area to fill.
11
- * @param alpha - The overall opacity of the fill (0-255).
12
11
  * @param x - Starting horizontal coordinate for the mask placement.
13
12
  * @param y - Starting vertical coordinate for the mask placement.
14
13
  */
15
14
  export function fillPixelDataBinaryMask(
16
- dst: IPixelData32,
15
+ target: IPixelData32,
17
16
  color: Color32,
18
17
  mask: BinaryMask,
19
- alpha = 255,
20
18
  x = 0,
21
19
  y = 0,
22
20
  ): boolean {
23
- if (alpha === 0) return false
24
21
 
25
22
  const maskW = mask.w
26
23
  const maskH = mask.h
@@ -30,8 +27,8 @@ export function fillPixelDataBinaryMask(
30
27
  y,
31
28
  maskW,
32
29
  maskH,
33
- dst.width,
34
- dst.height,
30
+ target.width,
31
+ target.height,
35
32
  SCRATCH_RECT,
36
33
  )
37
34
 
@@ -45,19 +42,8 @@ export function fillPixelDataBinaryMask(
45
42
  } = clip
46
43
 
47
44
  const maskData = mask.data
48
- const dst32 = dst.data32
49
- const dw = dst.width
50
-
51
- // Pre-calculate the alpha-adjusted color once outside the loop
52
- let finalCol = color
53
-
54
- if (alpha < 255) {
55
- const baseSrcAlpha = color >>> 24
56
- const colorRGB = color & 0x00ffffff
57
- const a = (baseSrcAlpha * alpha + 128) >> 8
58
-
59
- finalCol = ((colorRGB | (a << 24)) >>> 0) as Color32
60
- }
45
+ const dst32 = target.data32
46
+ const dw = target.width
61
47
 
62
48
  let hasChanged = false
63
49
 
@@ -75,8 +61,8 @@ export function fillPixelDataBinaryMask(
75
61
 
76
62
  if (maskData[maskIndex]) {
77
63
  const current = dst32[dstRowOffset + currentX]
78
- if (current !== finalCol) {
79
- dst32[dstRowOffset + currentX] = finalCol
64
+ if (current !== color) {
65
+ dst32[dstRowOffset + currentX] = color
80
66
  hasChanged = true
81
67
  }
82
68
  }
@@ -8,13 +8,13 @@ const SCRATCH_RECT = makeClippedRect()
8
8
  * This function is faster than {@link fillPixelData} but does not
9
9
  * return a boolean value indicating changes were made.
10
10
  *
11
- * @param dst - The target to modify.
11
+ * @param target - The target to modify.
12
12
  * @param color - The color to apply.
13
13
  * @param rect - Defines the area to fill. If omitted, the entire
14
14
  * buffer is filled.
15
15
  */
16
16
  export function fillPixelDataFast(
17
- dst: IPixelData32,
17
+ target: IPixelData32,
18
18
  color: Color32,
19
19
  rect?: Partial<Rect>,
20
20
  ): void
@@ -4,22 +4,19 @@ import { makeClippedRect, resolveRectClipping } from '../Internal/resolveClippin
4
4
  const SCRATCH_RECT = makeClippedRect()
5
5
 
6
6
  export function invertPixelData(
7
- pixelData: IPixelData32,
8
- opts: PixelMutateOptions = {},
7
+ target: IPixelData32,
8
+ opts?: PixelMutateOptions,
9
9
  ): boolean {
10
- const dst = pixelData
11
- const {
12
- x: targetX = 0,
13
- y: targetY = 0,
14
- w: width = pixelData.width,
15
- h: height = pixelData.height,
16
- mask,
17
- mx = 0,
18
- my = 0,
19
- invertMask = false,
20
- } = opts
10
+ const mask = opts?.mask
11
+ const targetX = opts?.x ?? 0
12
+ const targetY = opts?.y ?? 0
13
+ const mx = opts?.mx ?? 0
14
+ const my = opts?.my ?? 0
15
+ const width = opts?.w ?? target.width
16
+ const height = opts?.h ?? target.height
17
+ const invertMask = opts?.invertMask ?? false
21
18
 
22
- const clip = resolveRectClipping(targetX, targetY, width, height, dst.width, dst.height, SCRATCH_RECT)
19
+ const clip = resolveRectClipping(targetX, targetY, width, height, target.width, target.height, SCRATCH_RECT)
23
20
 
24
21
  if (!clip.inBounds) return false
25
22
 
@@ -30,8 +27,8 @@ export function invertPixelData(
30
27
  h: actualH,
31
28
  } = clip
32
29
 
33
- const dst32 = dst.data32
34
- const dw = dst.width
30
+ const dst32 = target.data32
31
+ const dw = target.width
35
32
  const mPitch = mask?.w ?? width
36
33
 
37
34
  const dx = x - targetX
package/src/_types.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { PixelWriter, sourceOverPerfect } from './index'
2
-
3
1
  /** ALL values are 0-255 (including alpha which in CSS is 0-1) */
4
2
  export type RGBA = { r: number, g: number, b: number, a: number }
5
3
 
@@ -63,20 +61,22 @@ export enum MaskType {
63
61
  BINARY
64
62
  }
65
63
 
66
- export interface Mask {
64
+ export interface BaseMask {
67
65
  readonly type: MaskType
68
66
  readonly data: Uint8Array
69
67
  readonly w: number
70
68
  readonly h: number
71
69
  }
72
70
 
71
+ export type Mask = BinaryMask | AlphaMask
72
+
73
73
  /** Strictly 0 or 1 */
74
- export interface BinaryMask extends Mask {
74
+ export interface BinaryMask extends BaseMask {
75
75
  readonly type: MaskType.BINARY
76
76
  }
77
77
 
78
78
  /** Strictly 0-255 */
79
- export interface AlphaMask extends Mask {
79
+ export interface AlphaMask extends BaseMask {
80
80
  readonly type: MaskType.ALPHA
81
81
  }
82
82
 
@@ -210,6 +210,9 @@ export interface ColorBlendOptions extends PixelRect, Alpha {
210
210
  export interface ColorBlendMaskOptions extends ColorBlendOptions, MaskOffset, InvertMask {
211
211
  }
212
212
 
213
+ export interface ColorBlendPaintMaskOptions extends Omit<ColorBlendOptions, 'w' | 'h'> {
214
+ }
215
+
213
216
  export type MaskRect<T extends MaskType> = Rect & {
214
217
  type: T
215
218
  data: Uint8Array
@@ -235,8 +238,6 @@ export type NullableMaskRect = Rect & ({
235
238
  data?: null
236
239
  })
237
240
 
238
- export type HistoryMutator<T extends {}, D extends {}> = (writer: PixelWriter<any>, deps?: Partial<D>) => T
239
-
240
241
  export interface IPixelData32 {
241
242
  readonly data32: Uint32Array
242
243
  readonly width: number