pixel-data-js 0.25.2 → 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.
- package/dist/index.prod.cjs +1696 -1526
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +414 -311
- package/dist/index.prod.js +1676 -1519
- package/dist/index.prod.js.map +1 -1
- package/package.json +8 -9
- package/src/Algorithm/floodFillSelection.ts +49 -80
- package/src/Canvas/PixelCanvas.ts +1 -1
- package/src/Canvas/ReusableCanvas.ts +1 -1
- package/src/History/HistoryAction.ts +6 -5
- package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +8 -10
- package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +8 -10
- package/src/History/PixelMutator/mutatorApplyMask.ts +39 -0
- package/src/History/PixelMutator/{mutatorBlendPixelDataAlphaMask.ts → mutatorBlendAlphaMask.ts} +9 -9
- package/src/History/PixelMutator/{mutatorBlendPixelDataBinaryMask.ts → mutatorBlendBinaryMask.ts} +9 -9
- package/src/History/PixelMutator/mutatorBlendColor.ts +8 -9
- package/src/History/PixelMutator/mutatorBlendColorPaintAlphaMask.ts +51 -0
- package/src/History/PixelMutator/mutatorBlendColorPaintBinaryMask.ts +51 -0
- package/src/History/PixelMutator/{mutatorBlendPaintMask.ts → mutatorBlendColorPaintMask.ts} +3 -3
- package/src/History/PixelMutator/mutatorBlendMask.ts +43 -0
- package/src/History/PixelMutator/mutatorBlendPaintRect.ts +55 -0
- package/src/History/PixelMutator/mutatorBlendPixel.ts +2 -2
- package/src/History/PixelMutator/mutatorBlendPixelData.ts +8 -9
- package/src/History/PixelMutator/mutatorClear.ts +13 -11
- package/src/History/PixelMutator/mutatorFill.ts +2 -2
- package/src/History/PixelMutator/mutatorFillBinaryMask.ts +3 -4
- package/src/History/PixelMutator/mutatorInvert.ts +8 -9
- package/src/History/PixelMutator.ts +20 -4
- package/src/History/PixelWriter.ts +11 -13
- package/src/Input/fileToImageData.ts +1 -1
- package/src/Internal/helpers.ts +4 -1
- package/src/Mask/applyBinaryMaskToAlphaMask.ts +8 -10
- package/src/Paint/PaintBuffer.ts +3 -3
- package/src/Paint/PaintBufferCanvasRenderer.ts +1 -1
- package/src/Paint/makePaintMask.ts +5 -5
- package/src/Paint/makeRectFalloffPaintAlphaMask.ts +3 -3
- package/src/PixelData/applyAlphaMaskToPixelData.ts +14 -16
- package/src/PixelData/applyBinaryMaskToPixelData.ts +14 -16
- package/src/PixelData/applyMaskToPixelData.ts +22 -0
- package/src/PixelData/blendColorPixelData.ts +12 -15
- package/src/PixelData/blendColorPixelDataAlphaMask.ts +16 -16
- package/src/PixelData/blendColorPixelDataBinaryMask.ts +16 -16
- package/src/PixelData/blendColorPixelDataMask.ts +16 -0
- package/src/PixelData/blendColorPixelDataPaintAlphaMask.ts +30 -0
- package/src/PixelData/blendColorPixelDataPaintBinaryMask.ts +30 -0
- package/src/PixelData/blendColorPixelDataPaintMask.ts +35 -0
- package/src/PixelData/blendPixelData.ts +14 -16
- package/src/PixelData/blendPixelDataAlphaMask.ts +17 -19
- package/src/PixelData/blendPixelDataBinaryMask.ts +17 -19
- package/src/PixelData/blendPixelDataMask.ts +16 -0
- package/src/PixelData/blendPixelDataPaintBuffer.ts +1 -1
- package/src/PixelData/{clearPixelData.ts → clearPixelDataFast.ts} +2 -2
- package/src/PixelData/fillPixelDataBinaryMask.ts +8 -22
- package/src/PixelData/fillPixelDataFast.ts +2 -2
- package/src/PixelData/invertPixelData.ts +13 -16
- package/src/_types.ts +8 -7
- package/src/index.ts +41 -31
- package/dist/index.dev.cjs +0 -5419
- package/dist/index.dev.cjs.map +0 -1
- package/dist/index.dev.js +0 -5208
- package/dist/index.dev.js.map +0 -1
- package/src/Canvas/_constants.ts +0 -2
- package/src/PixelData/PixelBuffer32.ts +0 -28
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixel-data-js",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"packageManager": "pnpm@10.
|
|
4
|
+
"version": "0.26.0",
|
|
5
|
+
"packageManager": "pnpm@10.33.0",
|
|
6
6
|
"description": "JS Pixel and ImageData operations",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Carl Olsen",
|
|
@@ -27,10 +27,6 @@
|
|
|
27
27
|
".": {
|
|
28
28
|
"types": "./dist/index.prod.d.ts",
|
|
29
29
|
"source": "./src/index.ts",
|
|
30
|
-
"development": {
|
|
31
|
-
"require": "./dist/index.dev.cjs",
|
|
32
|
-
"import": "./dist/index.dev.js"
|
|
33
|
-
},
|
|
34
30
|
"production": {
|
|
35
31
|
"require": "./dist/index.prod.cjs",
|
|
36
32
|
"import": "./dist/index.prod.js"
|
|
@@ -49,6 +45,8 @@
|
|
|
49
45
|
"scripts": {
|
|
50
46
|
"build": "tsup",
|
|
51
47
|
"test": "vitest --coverage --project unit",
|
|
48
|
+
"re-index": "tsx _scripts/re-index.ts",
|
|
49
|
+
"check": "npm run check-circ && npm run re-index && npm run sort && npm run typecheck",
|
|
52
50
|
"test:build": "pnpm build && vitest run --project dist",
|
|
53
51
|
"check-circ": "tsx _scripts/check-circular.ts",
|
|
54
52
|
"test:mutation": "stryker run",
|
|
@@ -63,7 +61,7 @@
|
|
|
63
61
|
"devDependencies": {
|
|
64
62
|
"@clack/prompts": "^1.1.0",
|
|
65
63
|
"@mitata/counters": "^0.0.8",
|
|
66
|
-
"@napi-rs/canvas": "^0.1.
|
|
64
|
+
"@napi-rs/canvas": "^0.1.97",
|
|
67
65
|
"@stryker-mutator/core": "^9.5.1",
|
|
68
66
|
"@stryker-mutator/typescript-checker": "^9.5.1",
|
|
69
67
|
"@stryker-mutator/vitest-runner": "^9.5.1",
|
|
@@ -83,13 +81,14 @@
|
|
|
83
81
|
"sanitize-filename": "^1.6.3",
|
|
84
82
|
"sharp": "^0.34.5",
|
|
85
83
|
"simple-git": "^3.33.0",
|
|
84
|
+
"source-map": "^0.7.6",
|
|
86
85
|
"tsup": "^8.5.1",
|
|
87
86
|
"tsx": "^4.21.0",
|
|
88
|
-
"typedoc": "^0.28.
|
|
87
|
+
"typedoc": "^0.28.18",
|
|
89
88
|
"typedoc-plugin-mdn-links": "^5.1.1",
|
|
90
89
|
"typedoc-rhineai-theme": "^1.2.0",
|
|
91
90
|
"typescript": "^5.9.3",
|
|
92
|
-
"unplugin-inline": "^1.
|
|
91
|
+
"unplugin-inline": "^1.14.0",
|
|
93
92
|
"vite-tsconfig-paths": "^6.1.1",
|
|
94
93
|
"vitest": "3.2.4"
|
|
95
94
|
},
|
|
@@ -1,19 +1,12 @@
|
|
|
1
|
-
import { type BinaryMaskRect, type Color32,
|
|
1
|
+
import { type BinaryMaskRect, type Color32, MaskType, type Rect } from '../_types'
|
|
2
2
|
import { colorDistance } from '../color'
|
|
3
3
|
import { extractImageDataBuffer } from '../ImageData/extractImageDataBuffer'
|
|
4
4
|
import type { PixelData } from '../PixelData/PixelData'
|
|
5
5
|
import { trimMaskRectBounds } from '../Rect/trimMaskRectBounds'
|
|
6
6
|
|
|
7
|
-
export type
|
|
8
|
-
contiguous?: boolean
|
|
9
|
-
tolerance?: number
|
|
10
|
-
bounds?: Rect
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export type FloodFillResult = {
|
|
7
|
+
export type FloodFillResult = BinaryMaskRect & {
|
|
14
8
|
startX: number
|
|
15
9
|
startY: number
|
|
16
|
-
selectionRect: BinaryMaskRect
|
|
17
10
|
pixels: Uint8ClampedArray
|
|
18
11
|
}
|
|
19
12
|
|
|
@@ -23,16 +16,15 @@ export type FloodFillResult = {
|
|
|
23
16
|
* color tolerance. It can operate in "contiguous" mode (classic bucket fill) or
|
|
24
17
|
* "non-contiguous" mode (selects all matching pixels in the buffer).
|
|
25
18
|
*
|
|
26
|
-
* @param
|
|
19
|
+
* @param target - The source image data to process.
|
|
27
20
|
* @param startX - The starting horizontal coordinate.
|
|
28
21
|
* @param startY - The starting vertical coordinate.
|
|
29
|
-
* @param
|
|
30
|
-
* @param options.contiguous - If true, only connected pixels are
|
|
22
|
+
* @param contiguous - If true, only connected pixels are
|
|
31
23
|
* selected. If false, all pixels within tolerance are selected regardless of position.
|
|
32
|
-
* @param
|
|
24
|
+
* @param tolerance - The maximum allowed difference in color
|
|
33
25
|
* distance (0-255) for a pixel to be included.
|
|
34
|
-
* @param
|
|
35
|
-
*
|
|
26
|
+
* @param bounds - Optional bounding box to restrict the search area.
|
|
27
|
+
* @param out output object
|
|
36
28
|
* @returns A {@link FloodFillResult} containing the mask and bounds of the selection,
|
|
37
29
|
* or `null` if the starting coordinates are out of bounds.
|
|
38
30
|
*
|
|
@@ -50,49 +42,33 @@ export type FloodFillResult = {
|
|
|
50
42
|
* ```
|
|
51
43
|
*/
|
|
52
44
|
export function floodFillSelection(
|
|
53
|
-
|
|
45
|
+
target: PixelData,
|
|
54
46
|
startX: number,
|
|
55
47
|
startY: number,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}: FloodFillImageDataOptions = {},
|
|
48
|
+
contiguous = true,
|
|
49
|
+
tolerance = 0,
|
|
50
|
+
bounds?: Rect,
|
|
51
|
+
out?: FloodFillResult,
|
|
61
52
|
): FloodFillResult | null {
|
|
62
53
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
img.data.byteOffset,
|
|
72
|
-
img.data.byteLength >> 2,
|
|
73
|
-
)
|
|
74
|
-
imageData = img
|
|
75
|
-
}
|
|
76
|
-
const {
|
|
77
|
-
width,
|
|
78
|
-
height,
|
|
79
|
-
} = img
|
|
80
|
-
|
|
81
|
-
const limit = bounds || {
|
|
82
|
-
x: 0,
|
|
83
|
-
y: 0,
|
|
84
|
-
w: width,
|
|
85
|
-
h: height,
|
|
86
|
-
}
|
|
54
|
+
const data32 = target.data32
|
|
55
|
+
const width = target.width
|
|
56
|
+
const height = target.height
|
|
57
|
+
|
|
58
|
+
const lx = bounds?.x ?? 0
|
|
59
|
+
const ly = bounds?.y ?? 0
|
|
60
|
+
const lw = bounds?.w ?? width
|
|
61
|
+
const lh = bounds?.h ?? height
|
|
87
62
|
|
|
88
|
-
const xMin = Math.max(0,
|
|
89
|
-
const xMax = Math.min(width - 1,
|
|
90
|
-
const yMin = Math.max(0,
|
|
91
|
-
const yMax = Math.min(height - 1,
|
|
63
|
+
const xMin = Math.max(0, lx)
|
|
64
|
+
const xMax = Math.min(width - 1, lx + lw - 1)
|
|
65
|
+
const yMin = Math.max(0, ly)
|
|
66
|
+
const yMax = Math.min(height - 1, ly + lh - 1)
|
|
92
67
|
|
|
93
68
|
if (startX < xMin || startX > xMax || startY < yMin || startY > yMax) {
|
|
94
69
|
return null
|
|
95
70
|
}
|
|
71
|
+
out = out ?? {} as FloodFillResult
|
|
96
72
|
|
|
97
73
|
const baseColor = data32[startY * width + startX] as Color32
|
|
98
74
|
|
|
@@ -178,50 +154,43 @@ export function floodFillSelection(
|
|
|
178
154
|
}
|
|
179
155
|
}
|
|
180
156
|
|
|
181
|
-
if (matchCount === 0)
|
|
182
|
-
|
|
183
|
-
}
|
|
157
|
+
if (matchCount === 0) return null
|
|
158
|
+
|
|
184
159
|
const w = maxX - minX + 1
|
|
185
160
|
const h = maxY - minY + 1
|
|
186
|
-
const selectionRect: BinaryMaskRect = {
|
|
187
|
-
x: minX,
|
|
188
|
-
y: minY,
|
|
189
|
-
w,
|
|
190
|
-
h,
|
|
191
|
-
data: new Uint8Array(w * h),
|
|
192
|
-
type: MaskType.BINARY,
|
|
193
|
-
}
|
|
194
161
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
162
|
+
out.startX = startX
|
|
163
|
+
out.startY = startY
|
|
164
|
+
out.x = minX
|
|
165
|
+
out.y = minY
|
|
166
|
+
out.w = w
|
|
167
|
+
out.h = h
|
|
168
|
+
out.data = new Uint8Array(w * h)
|
|
169
|
+
out.type = MaskType.BINARY
|
|
170
|
+
|
|
171
|
+
const finalMask = out.data
|
|
198
172
|
|
|
199
173
|
for (let i = 0; i < matchCount; i++) {
|
|
200
|
-
const mx = matchX[i] -
|
|
201
|
-
const my = matchY[i] -
|
|
174
|
+
const mx = matchX[i] - minX
|
|
175
|
+
const my = matchY[i] - minY
|
|
202
176
|
|
|
203
|
-
if (mx >= 0 && mx <
|
|
204
|
-
finalMask[my *
|
|
177
|
+
if (mx >= 0 && mx < w && my >= 0 && my < h) {
|
|
178
|
+
finalMask[my * w + mx] = 1
|
|
205
179
|
}
|
|
206
180
|
}
|
|
207
181
|
|
|
208
182
|
trimMaskRectBounds(
|
|
209
|
-
|
|
183
|
+
out,
|
|
210
184
|
{ x: 0, y: 0, w: width, h: height },
|
|
211
185
|
)
|
|
212
186
|
|
|
213
|
-
|
|
214
|
-
imageData,
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
187
|
+
out.pixels = extractImageDataBuffer(
|
|
188
|
+
target.imageData,
|
|
189
|
+
out.x,
|
|
190
|
+
out.y,
|
|
191
|
+
out.w,
|
|
192
|
+
out.h,
|
|
219
193
|
)
|
|
220
194
|
|
|
221
|
-
return
|
|
222
|
-
startX,
|
|
223
|
-
startY,
|
|
224
|
-
selectionRect,
|
|
225
|
-
pixels: extracted,
|
|
226
|
-
}
|
|
195
|
+
return out
|
|
227
196
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { PixelAccumulator } from './PixelAccumulator'
|
|
2
|
+
import type { PixelEngineConfig } from './PixelEngineConfig'
|
|
1
3
|
import { applyPatchTiles, type PixelPatchTiles } from './PixelPatchTiles'
|
|
2
|
-
import type { PixelWriter } from './PixelWriter'
|
|
3
4
|
|
|
4
5
|
export interface HistoryAction {
|
|
5
6
|
undo: () => void
|
|
@@ -10,7 +11,8 @@ export interface HistoryAction {
|
|
|
10
11
|
export type HistoryActionFactory = typeof makeHistoryAction
|
|
11
12
|
|
|
12
13
|
export function makeHistoryAction(
|
|
13
|
-
|
|
14
|
+
config: PixelEngineConfig,
|
|
15
|
+
accumulator: PixelAccumulator,
|
|
14
16
|
patch: PixelPatchTiles,
|
|
15
17
|
after?: () => void,
|
|
16
18
|
afterUndo?: () => void,
|
|
@@ -18,9 +20,8 @@ export function makeHistoryAction(
|
|
|
18
20
|
applyPatchTilesFn = applyPatchTiles,
|
|
19
21
|
): HistoryAction {
|
|
20
22
|
|
|
21
|
-
const target =
|
|
22
|
-
const tileSize =
|
|
23
|
-
const accumulator = writer.accumulator
|
|
23
|
+
const target = config.target
|
|
24
|
+
const tileSize = config.tileSize
|
|
24
25
|
|
|
25
26
|
return {
|
|
26
27
|
undo: () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type AlphaMask, type ApplyMaskToPixelDataOptions
|
|
1
|
+
import { type AlphaMask, type ApplyMaskToPixelDataOptions } from '../../_types'
|
|
2
2
|
import { applyAlphaMaskToPixelData } from '../../PixelData/applyAlphaMaskToPixelData'
|
|
3
|
-
import { PixelWriter } from '../PixelWriter'
|
|
3
|
+
import { type HistoryMutator, PixelWriter } from '../PixelWriter'
|
|
4
4
|
|
|
5
5
|
const defaults = {
|
|
6
6
|
applyAlphaMaskToPixelData,
|
|
@@ -17,14 +17,12 @@ export const mutatorApplyAlphaMask = ((writer: PixelWriter<any>, deps: Deps = de
|
|
|
17
17
|
} = deps
|
|
18
18
|
|
|
19
19
|
return {
|
|
20
|
-
applyAlphaMask(mask: AlphaMask, opts
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
h = target.height,
|
|
27
|
-
} = opts
|
|
20
|
+
applyAlphaMask(mask: AlphaMask, opts?: ApplyMaskToPixelDataOptions): boolean {
|
|
21
|
+
const target = writer.config.target
|
|
22
|
+
const x = opts?.x ?? 0
|
|
23
|
+
const y = opts?.y ?? 0
|
|
24
|
+
const w = opts?.w ?? target.width
|
|
25
|
+
const h = opts?.h ?? target.height
|
|
28
26
|
|
|
29
27
|
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h)
|
|
30
28
|
return didChange(applyAlphaMaskToPixelData(target, mask, opts))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type ApplyMaskToPixelDataOptions, type BinaryMask
|
|
1
|
+
import { type ApplyMaskToPixelDataOptions, type BinaryMask } from '../../_types'
|
|
2
2
|
import { applyBinaryMaskToPixelData } from '../../PixelData/applyBinaryMaskToPixelData'
|
|
3
|
-
import { PixelWriter } from '../PixelWriter'
|
|
3
|
+
import { type HistoryMutator, PixelWriter } from '../PixelWriter'
|
|
4
4
|
|
|
5
5
|
const defaults = {
|
|
6
6
|
applyBinaryMaskToPixelData,
|
|
@@ -17,14 +17,12 @@ export const mutatorApplyBinaryMask = ((writer: PixelWriter<any>, deps: Deps = d
|
|
|
17
17
|
} = deps
|
|
18
18
|
|
|
19
19
|
return {
|
|
20
|
-
applyBinaryMask(mask: BinaryMask, opts
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
h = target.height,
|
|
27
|
-
} = opts
|
|
20
|
+
applyBinaryMask(mask: BinaryMask, opts?: ApplyMaskToPixelDataOptions): boolean {
|
|
21
|
+
const target = writer.config.target
|
|
22
|
+
const x = opts?.x ?? 0
|
|
23
|
+
const y = opts?.y ?? 0
|
|
24
|
+
const w = opts?.w ?? target.width
|
|
25
|
+
const h = opts?.h ?? target.height
|
|
28
26
|
|
|
29
27
|
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h)
|
|
30
28
|
return didChange(applyBinaryMaskToPixelData(target, mask, opts))
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ApplyMaskToPixelDataOptions, type Mask, MaskType } from '../../_types'
|
|
2
|
+
import { applyAlphaMaskToPixelData } from '../../PixelData/applyAlphaMaskToPixelData'
|
|
3
|
+
import { applyBinaryMaskToPixelData } from '../../PixelData/applyBinaryMaskToPixelData'
|
|
4
|
+
import { type HistoryMutator, PixelWriter } from '../PixelWriter'
|
|
5
|
+
|
|
6
|
+
const defaults = {
|
|
7
|
+
applyBinaryMaskToPixelData,
|
|
8
|
+
applyAlphaMaskToPixelData,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type Deps = Partial<typeof defaults>
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param deps - @hidden
|
|
15
|
+
*/
|
|
16
|
+
export const mutatorApplyMask = ((writer: PixelWriter<any>, deps: Deps = defaults) => {
|
|
17
|
+
const {
|
|
18
|
+
applyBinaryMaskToPixelData = defaults.applyBinaryMaskToPixelData,
|
|
19
|
+
applyAlphaMaskToPixelData = defaults.applyAlphaMaskToPixelData,
|
|
20
|
+
} = deps
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
applyMask(mask: Mask, opts?: ApplyMaskToPixelDataOptions): boolean {
|
|
24
|
+
const target = writer.config.target
|
|
25
|
+
const x = opts?.x ?? 0
|
|
26
|
+
const y = opts?.y ?? 0
|
|
27
|
+
const w = opts?.w ?? target.width
|
|
28
|
+
const h = opts?.h ?? target.height
|
|
29
|
+
|
|
30
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h)
|
|
31
|
+
|
|
32
|
+
if (mask.type === MaskType.BINARY) {
|
|
33
|
+
return didChange(applyBinaryMaskToPixelData(target, mask, opts))
|
|
34
|
+
} else {
|
|
35
|
+
return didChange(applyAlphaMaskToPixelData(target, mask, opts))
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
}) satisfies HistoryMutator<any, Deps>
|
package/src/History/PixelMutator/{mutatorBlendPixelDataAlphaMask.ts → mutatorBlendAlphaMask.ts}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { AlphaMask,
|
|
1
|
+
import type { AlphaMask, IPixelData32, PixelBlendMaskOptions } from '../../_types'
|
|
2
2
|
import { blendPixelDataAlphaMask } from '../../PixelData/blendPixelDataAlphaMask'
|
|
3
|
-
import { PixelWriter } from '../PixelWriter'
|
|
3
|
+
import { type HistoryMutator, PixelWriter } from '../PixelWriter'
|
|
4
4
|
|
|
5
5
|
const defaults = { blendPixelDataAlphaMask }
|
|
6
6
|
type Deps = Partial<typeof defaults>
|
|
@@ -8,21 +8,21 @@ type Deps = Partial<typeof defaults>
|
|
|
8
8
|
/**
|
|
9
9
|
* @param deps - @hidden
|
|
10
10
|
*/
|
|
11
|
-
export const
|
|
11
|
+
export const mutatorBlendAlphaMask = ((writer: PixelWriter<any>, deps: Partial<Deps> = defaults) => {
|
|
12
12
|
const {
|
|
13
13
|
blendPixelDataAlphaMask = defaults.blendPixelDataAlphaMask,
|
|
14
14
|
} = deps
|
|
15
15
|
|
|
16
16
|
return {
|
|
17
|
-
|
|
17
|
+
blendAlphaMask(
|
|
18
18
|
src: IPixelData32,
|
|
19
19
|
mask: AlphaMask,
|
|
20
|
-
opts
|
|
20
|
+
opts?: PixelBlendMaskOptions,
|
|
21
21
|
): boolean {
|
|
22
|
-
const x = opts
|
|
23
|
-
const y = opts
|
|
24
|
-
const w = opts
|
|
25
|
-
const h = opts
|
|
22
|
+
const x = opts?.x ?? 0
|
|
23
|
+
const y = opts?.y ?? 0
|
|
24
|
+
const w = opts?.w ?? src.width
|
|
25
|
+
const h = opts?.h ?? src.height
|
|
26
26
|
|
|
27
27
|
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h)
|
|
28
28
|
|
package/src/History/PixelMutator/{mutatorBlendPixelDataBinaryMask.ts → mutatorBlendBinaryMask.ts}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { BinaryMask,
|
|
1
|
+
import type { BinaryMask, IPixelData32, PixelBlendMaskOptions } from '../../_types'
|
|
2
2
|
import { blendPixelDataBinaryMask } from '../../PixelData/blendPixelDataBinaryMask'
|
|
3
|
-
import { PixelWriter } from '../PixelWriter'
|
|
3
|
+
import { type HistoryMutator, PixelWriter } from '../PixelWriter'
|
|
4
4
|
|
|
5
5
|
const defaults = { blendPixelDataBinaryMask }
|
|
6
6
|
type Deps = Partial<typeof defaults>
|
|
@@ -8,21 +8,21 @@ type Deps = Partial<typeof defaults>
|
|
|
8
8
|
/**
|
|
9
9
|
* @param deps - @hidden
|
|
10
10
|
*/
|
|
11
|
-
export const
|
|
11
|
+
export const mutatorBlendBinaryMask = ((writer: PixelWriter<any>, deps: Partial<Deps> = defaults) => {
|
|
12
12
|
const {
|
|
13
13
|
blendPixelDataBinaryMask = defaults.blendPixelDataBinaryMask,
|
|
14
14
|
} = deps
|
|
15
15
|
|
|
16
16
|
return {
|
|
17
|
-
|
|
17
|
+
blendBinaryMask(
|
|
18
18
|
src: IPixelData32,
|
|
19
19
|
mask: BinaryMask,
|
|
20
|
-
opts
|
|
20
|
+
opts?: PixelBlendMaskOptions,
|
|
21
21
|
): boolean {
|
|
22
|
-
const x = opts
|
|
23
|
-
const y = opts
|
|
24
|
-
const w = opts
|
|
25
|
-
const h = opts
|
|
22
|
+
const x = opts?.x ?? 0
|
|
23
|
+
const y = opts?.y ?? 0
|
|
24
|
+
const w = opts?.w ?? src.width
|
|
25
|
+
const h = opts?.h ?? src.height
|
|
26
26
|
|
|
27
27
|
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h)
|
|
28
28
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Color32, ColorBlendOptions
|
|
1
|
+
import type { Color32, ColorBlendOptions } from '../../_types'
|
|
2
2
|
import { blendColorPixelData } from '../../PixelData/blendColorPixelData'
|
|
3
|
-
import { PixelWriter } from '../PixelWriter'
|
|
3
|
+
import { type HistoryMutator, PixelWriter } from '../PixelWriter'
|
|
4
4
|
|
|
5
5
|
const defaults = { blendColorPixelData }
|
|
6
6
|
type Deps = Partial<typeof defaults>
|
|
@@ -16,15 +16,14 @@ export const mutatorBlendColor = ((writer: PixelWriter<any>, deps: Deps = defaul
|
|
|
16
16
|
return {
|
|
17
17
|
blendColor(
|
|
18
18
|
color: Color32,
|
|
19
|
-
opts
|
|
19
|
+
opts?: ColorBlendOptions,
|
|
20
20
|
): boolean {
|
|
21
21
|
const target = writer.config.target
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
} = opts
|
|
22
|
+
const x = opts?.x ?? 0
|
|
23
|
+
const y = opts?.y ?? 0
|
|
24
|
+
const w = opts?.w ?? target.width
|
|
25
|
+
const h = opts?.h ?? target.height
|
|
26
|
+
|
|
28
27
|
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h)
|
|
29
28
|
return didChange(
|
|
30
29
|
blendColorPixelData(target, color, opts),
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type Color32, type PaintAlphaMask } from '../../_types'
|
|
2
|
+
import { sourceOverPerfect } from '../../BlendModes/blend-modes-perfect'
|
|
3
|
+
import { blendColorPixelDataAlphaMask } from '../../PixelData/blendColorPixelDataAlphaMask'
|
|
4
|
+
import { type HistoryMutator, PixelWriter } from '../PixelWriter'
|
|
5
|
+
|
|
6
|
+
const defaults = {
|
|
7
|
+
blendColorPixelDataAlphaMask,
|
|
8
|
+
}
|
|
9
|
+
type Deps = Partial<typeof defaults>
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param deps - @hidden
|
|
13
|
+
*/
|
|
14
|
+
export const mutatorBlendColorPaintAlphaMask = ((writer: PixelWriter<any>, deps: Partial<Deps> = defaults) => {
|
|
15
|
+
const {
|
|
16
|
+
blendColorPixelDataAlphaMask = defaults.blendColorPixelDataAlphaMask,
|
|
17
|
+
} = deps
|
|
18
|
+
|
|
19
|
+
const OPTS = {
|
|
20
|
+
x: 0,
|
|
21
|
+
y: 0,
|
|
22
|
+
blendFn: sourceOverPerfect,
|
|
23
|
+
alpha: 255,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
blendColorPaintAlphaMask(
|
|
28
|
+
color: Color32,
|
|
29
|
+
mask: PaintAlphaMask,
|
|
30
|
+
x: number,
|
|
31
|
+
y: number,
|
|
32
|
+
alpha = 255,
|
|
33
|
+
blendFn = sourceOverPerfect,
|
|
34
|
+
): boolean {
|
|
35
|
+
const tx = x + mask.centerOffsetX
|
|
36
|
+
const ty = y + mask.centerOffsetY
|
|
37
|
+
|
|
38
|
+
const didChange = writer.accumulator.storeRegionBeforeState(tx, ty, mask.w, mask.h)
|
|
39
|
+
|
|
40
|
+
OPTS.x = tx
|
|
41
|
+
OPTS.y = ty
|
|
42
|
+
OPTS.alpha = alpha
|
|
43
|
+
OPTS.blendFn = blendFn
|
|
44
|
+
|
|
45
|
+
return didChange(
|
|
46
|
+
blendColorPixelDataAlphaMask(writer.config.target, color, mask, OPTS),
|
|
47
|
+
)
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
}) satisfies HistoryMutator<any, Deps>
|
|
51
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type Color32, type PaintBinaryMask } from '../../_types'
|
|
2
|
+
import { sourceOverPerfect } from '../../BlendModes/blend-modes-perfect'
|
|
3
|
+
import { blendColorPixelDataBinaryMask } from '../../PixelData/blendColorPixelDataBinaryMask'
|
|
4
|
+
import { type HistoryMutator, PixelWriter } from '../PixelWriter'
|
|
5
|
+
|
|
6
|
+
const defaults = {
|
|
7
|
+
blendColorPixelDataBinaryMask,
|
|
8
|
+
}
|
|
9
|
+
type Deps = Partial<typeof defaults>
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param deps - @hidden
|
|
13
|
+
*/
|
|
14
|
+
export const mutatorBlendColorPaintBinaryMask = ((writer: PixelWriter<any>, deps: Partial<Deps> = defaults) => {
|
|
15
|
+
const {
|
|
16
|
+
blendColorPixelDataBinaryMask = defaults.blendColorPixelDataBinaryMask,
|
|
17
|
+
} = deps
|
|
18
|
+
|
|
19
|
+
const OPTS = {
|
|
20
|
+
x: 0,
|
|
21
|
+
y: 0,
|
|
22
|
+
blendFn: sourceOverPerfect,
|
|
23
|
+
alpha: 255,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
blendColorPaintBinaryMask(
|
|
28
|
+
color: Color32,
|
|
29
|
+
mask: PaintBinaryMask,
|
|
30
|
+
x: number,
|
|
31
|
+
y: number,
|
|
32
|
+
alpha = 255,
|
|
33
|
+
blendFn = sourceOverPerfect,
|
|
34
|
+
): boolean {
|
|
35
|
+
const tx = x + mask.centerOffsetX
|
|
36
|
+
const ty = y + mask.centerOffsetY
|
|
37
|
+
|
|
38
|
+
const didChange = writer.accumulator.storeRegionBeforeState(tx, ty, mask.w, mask.h)
|
|
39
|
+
|
|
40
|
+
OPTS.x = tx
|
|
41
|
+
OPTS.y = ty
|
|
42
|
+
OPTS.alpha = alpha
|
|
43
|
+
OPTS.blendFn = blendFn
|
|
44
|
+
|
|
45
|
+
return didChange(
|
|
46
|
+
blendColorPixelDataBinaryMask(writer.config.target, color, mask, OPTS),
|
|
47
|
+
)
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
}) satisfies HistoryMutator<any, Deps>
|
|
51
|
+
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { type Color32,
|
|
1
|
+
import { type Color32, MaskType, type PaintMask } from '../../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../../BlendModes/blend-modes-perfect'
|
|
3
3
|
import { blendColorPixelDataAlphaMask } from '../../PixelData/blendColorPixelDataAlphaMask'
|
|
4
4
|
import { blendColorPixelDataBinaryMask } from '../../PixelData/blendColorPixelDataBinaryMask'
|
|
5
|
-
import { PixelWriter } from '../PixelWriter'
|
|
5
|
+
import { type HistoryMutator, PixelWriter } from '../PixelWriter'
|
|
6
6
|
|
|
7
7
|
const defaults = {
|
|
8
8
|
blendColorPixelDataAlphaMask,
|
|
@@ -13,7 +13,7 @@ type Deps = Partial<typeof defaults>
|
|
|
13
13
|
/**
|
|
14
14
|
* @param deps - @hidden
|
|
15
15
|
*/
|
|
16
|
-
export const
|
|
16
|
+
export const mutatorBlendColorPaintMask = ((writer: PixelWriter<any>, deps: Partial<Deps> = defaults) => {
|
|
17
17
|
const {
|
|
18
18
|
blendColorPixelDataBinaryMask = defaults.blendColorPixelDataBinaryMask,
|
|
19
19
|
blendColorPixelDataAlphaMask = defaults.blendColorPixelDataAlphaMask,
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type IPixelData32, type Mask, MaskType, type PixelBlendMaskOptions } from '../../_types'
|
|
2
|
+
import { blendPixelDataAlphaMask } from '../../PixelData/blendPixelDataAlphaMask'
|
|
3
|
+
import { blendPixelDataBinaryMask } from '../../PixelData/blendPixelDataBinaryMask'
|
|
4
|
+
import { type HistoryMutator, PixelWriter } from '../PixelWriter'
|
|
5
|
+
|
|
6
|
+
const defaults = { blendPixelDataAlphaMask, blendPixelDataBinaryMask }
|
|
7
|
+
type Deps = Partial<typeof defaults>
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param deps - @hidden
|
|
11
|
+
*/
|
|
12
|
+
export const mutatorBlendMask = ((writer: PixelWriter<any>, deps: Partial<Deps> = defaults) => {
|
|
13
|
+
const {
|
|
14
|
+
blendPixelDataAlphaMask = defaults.blendPixelDataAlphaMask,
|
|
15
|
+
blendPixelDataBinaryMask = defaults.blendPixelDataBinaryMask,
|
|
16
|
+
} = deps
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
blendMask(
|
|
20
|
+
src: IPixelData32,
|
|
21
|
+
mask: Mask,
|
|
22
|
+
opts?: PixelBlendMaskOptions,
|
|
23
|
+
): boolean {
|
|
24
|
+
const x = opts?.x ?? 0
|
|
25
|
+
const y = opts?.y ?? 0
|
|
26
|
+
const w = opts?.w ?? src.width
|
|
27
|
+
const h = opts?.h ?? src.height
|
|
28
|
+
|
|
29
|
+
const didChange = writer.accumulator.storeRegionBeforeState(x, y, w, h)
|
|
30
|
+
|
|
31
|
+
if (mask.type === MaskType.BINARY) {
|
|
32
|
+
return didChange(
|
|
33
|
+
blendPixelDataBinaryMask(writer.config.target, src, mask, opts),
|
|
34
|
+
)
|
|
35
|
+
} else {
|
|
36
|
+
return didChange(
|
|
37
|
+
blendPixelDataAlphaMask(writer.config.target, src, mask, opts),
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
}) satisfies HistoryMutator<any, Deps>
|
|
43
|
+
|