pixel-data-js 0.26.0 → 0.28.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/README.md +12 -2
- package/dist/index.prod.cjs +2227 -1050
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +549 -424
- package/dist/index.prod.js +2171 -1028
- package/dist/index.prod.js.map +1 -1
- package/package.json +11 -11
- package/src/Algorithm/floodFillSelection.ts +8 -6
- package/src/Algorithm/forEachLinePoint.ts +6 -6
- package/src/{Internal/resample32.ts → Algorithm/resampleUint32Array.ts} +11 -21
- package/src/BlendModes/blend-modes-fast.ts +169 -0
- package/src/BlendModes/blend-modes-perfect.ts +207 -0
- package/src/BlendModes/blend-modes.ts +9 -0
- package/src/Canvas/CanvasFrameRenderer.ts +20 -28
- package/src/Canvas/CanvasPixelDataRenderer.ts +23 -0
- package/src/Canvas/PixelCanvas.ts +2 -7
- package/src/Canvas/ReusableCanvas.ts +4 -12
- package/src/Canvas/_canvas-types.ts +26 -0
- package/src/History/PixelAccumulator.ts +17 -17
- package/src/History/PixelEngineConfig.ts +3 -3
- package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +4 -3
- package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +4 -3
- package/src/History/PixelMutator/mutatorApplyMask.ts +4 -3
- package/src/History/PixelMutator/mutatorBlendAlphaMask.ts +6 -4
- package/src/History/PixelMutator/mutatorBlendBinaryMask.ts +6 -4
- package/src/History/PixelMutator/mutatorBlendColor.ts +2 -2
- package/src/History/PixelMutator/mutatorBlendColorPaintAlphaMask.ts +2 -1
- package/src/History/PixelMutator/mutatorBlendColorPaintBinaryMask.ts +2 -1
- package/src/History/PixelMutator/mutatorBlendColorPaintMask.ts +3 -1
- package/src/History/PixelMutator/{mutatorBlendPaintRect.ts → mutatorBlendColorPaintRect.ts} +5 -5
- package/src/History/PixelMutator/mutatorBlendMask.ts +6 -4
- package/src/History/PixelMutator/mutatorBlendPixelData.ts +5 -4
- package/src/History/PixelMutator/mutatorClear.ts +4 -3
- package/src/History/PixelMutator/mutatorFill.ts +5 -4
- package/src/History/PixelMutator/mutatorFillBinaryMask.ts +2 -1
- package/src/History/PixelMutator/mutatorInvert.ts +2 -2
- package/src/History/PixelMutator.ts +2 -2
- package/src/History/PixelPatchTiles.ts +7 -7
- package/src/History/PixelWriter.ts +12 -63
- package/src/ImageData/ImageDataLike.ts +1 -1
- package/src/ImageData/_ImageData-types.ts +13 -0
- package/src/ImageData/copyImageData.ts +1 -1
- package/src/ImageData/extractImageDataBuffer.ts +3 -2
- package/src/ImageData/imageDataToUint32Array.ts +18 -0
- package/src/ImageData/resampleImageData.ts +3 -3
- package/src/ImageData/resizeImageData.ts +1 -1
- package/src/ImageData/serialization.ts +1 -1
- package/src/ImageData/uInt32ArrayToImageData.ts +1 -1
- package/src/ImageData/writeImageData.ts +2 -2
- package/src/ImageData/writeImageDataBuffer.ts +2 -2
- package/src/IndexedImage/IndexedImage.ts +56 -98
- package/src/IndexedImage/_indexedImage-types.ts +18 -0
- package/src/IndexedImage/getIndexedImageColorCounts.ts +3 -3
- package/src/IndexedImage/indexedImageToAverageColor.ts +1 -1
- package/src/IndexedImage/indexedImageToImageData.ts +4 -6
- package/src/IndexedImage/resampleIndexedImage.ts +7 -15
- package/src/Input/fileToImageData.ts +1 -1
- package/src/Internal/_errors.ts +2 -0
- package/src/Internal/macros.ts +14 -0
- package/src/Mask/AlphaMask.ts +1 -1
- package/src/Mask/BinaryMask/makeBinaryMaskFromAlphaMask.ts +23 -0
- package/src/Mask/BinaryMask/makeBinaryMaskOutline.ts +88 -0
- package/src/Mask/BinaryMask/makeCircleBinaryMaskOutline.ts +104 -0
- package/src/Mask/BinaryMask/makeRectBinaryMaskOutline.ts +34 -0
- package/src/Mask/BinaryMask.ts +1 -1
- package/src/Mask/_mask-types.ts +73 -0
- package/src/Mask/applyBinaryMaskToAlphaMask.ts +2 -1
- package/src/Mask/copyMask.ts +1 -1
- package/src/Mask/extractMask.ts +2 -1
- package/src/Mask/extractMaskBuffer.ts +1 -1
- package/src/Mask/mergeAlphaMasks.ts +6 -3
- package/src/Mask/mergeBinaryMasks.ts +2 -1
- package/src/Mask/setMaskData.ts +1 -1
- package/src/MaskRect/merge2BinaryMaskRects.ts +2 -2
- package/src/MaskRect/mergeBinaryMaskRects.ts +1 -1
- package/src/MaskRect/subtractBinaryMaskRects.ts +1 -1
- package/src/Paint/AlphaMaskPaintBuffer.ts +339 -0
- package/src/Paint/AlphaMaskPaintBufferCanvasRenderer.ts +78 -0
- package/src/Paint/BinaryMaskPaintBuffer.ts +254 -0
- package/src/Paint/BinaryMaskPaintBufferCanvasRenderer.ts +67 -0
- package/src/Paint/{PaintBuffer.ts → ColorPaintBuffer.ts} +148 -77
- package/src/Paint/{PaintBufferCanvasRenderer.ts → ColorPaintBufferCanvasRenderer.ts} +6 -5
- package/src/Paint/PaintCursorRenderer.ts +117 -0
- package/src/Paint/_paint-types.ts +22 -0
- package/src/Paint/eachTileInBounds.ts +45 -0
- package/src/Paint/makeCirclePaintMask.ts +74 -0
- package/src/Paint/makePaintMask.ts +5 -2
- package/src/Paint/makeRectFalloffPaintAlphaMask.ts +4 -2
- package/src/PixelData/PixelData.ts +15 -19
- package/src/PixelData/ReusablePixelData.ts +36 -0
- package/src/PixelData/_pixelData-types.ts +17 -0
- package/src/PixelData/applyAlphaMaskToPixelData.ts +80 -43
- package/src/PixelData/applyBinaryMaskToPixelData.ts +10 -8
- package/src/PixelData/applyMaskToPixelData.ts +4 -9
- package/src/PixelData/blendColorPixelData.ts +9 -8
- package/src/PixelData/blendColorPixelDataAlphaMask.ts +9 -7
- package/src/PixelData/blendColorPixelDataBinaryMask.ts +9 -7
- package/src/PixelData/blendColorPixelDataMask.ts +4 -2
- package/src/PixelData/blendColorPixelDataPaintAlphaMask.ts +4 -2
- package/src/PixelData/blendColorPixelDataPaintBinaryMask.ts +4 -2
- package/src/PixelData/blendColorPixelDataPaintMask.ts +5 -2
- package/src/PixelData/blendPixel.ts +6 -5
- package/src/PixelData/blendPixelData.ts +14 -13
- package/src/PixelData/blendPixelDataAlphaMask.ts +15 -13
- package/src/PixelData/blendPixelDataBinaryMask.ts +15 -13
- package/src/PixelData/blendPixelDataMask.ts +5 -3
- package/src/PixelData/blendPixelDataPaintBuffer.ts +5 -4
- package/src/PixelData/clearPixelDataFast.ts +4 -2
- package/src/PixelData/copyPixelData.ts +14 -0
- package/src/PixelData/extractPixelData.ts +8 -7
- package/src/PixelData/extractPixelDataBuffer.ts +9 -8
- package/src/PixelData/fillPixelData.ts +16 -14
- package/src/PixelData/fillPixelDataBinaryMask.ts +10 -8
- package/src/PixelData/fillPixelDataFast.ts +16 -14
- package/src/PixelData/invertPixelData.ts +9 -8
- package/src/PixelData/pixelDataToAlphaMask.ts +9 -8
- package/src/PixelData/reflectPixelData.ts +9 -9
- package/src/PixelData/resamplePixelData.ts +20 -9
- package/src/PixelData/rotatePixelData.ts +8 -7
- package/src/PixelData/uInt32ArrayToPixelData.ts +15 -0
- package/src/PixelData/writePaintBufferToPixelData.ts +5 -5
- package/src/PixelData/writePixelDataBuffer.ts +10 -9
- package/src/Rect/_rect-types.ts +7 -0
- package/src/Rect/getRectsBounds.ts +1 -1
- package/src/Rect/trimMaskRectBounds.ts +2 -1
- package/src/Rect/trimRectBounds.ts +1 -1
- package/src/Tile/MaskTile.ts +40 -0
- package/src/Tile/PixelTile.ts +23 -0
- package/src/{PixelTile/PixelTilePool.ts → Tile/TilePool.ts} +9 -9
- package/src/Tile/_tile-types.ts +33 -0
- package/src/_errors.ts +1 -0
- package/src/_types.ts +2 -118
- package/src/index.ts +47 -22
- package/src/ImageData/imageDataToUInt32Array.ts +0 -13
- package/src/Internal/helpers.ts +0 -5
- package/src/Paint/makeCirclePaintAlphaMask.ts +0 -41
- package/src/Paint/makeCirclePaintBinaryMask.ts +0 -29
- package/src/PixelTile/PixelTile.ts +0 -21
- /package/src/{Internal → Rect}/resolveClipping.ts +0 -0
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
import type { ImageDataLike
|
|
2
|
-
import {
|
|
1
|
+
import type { ImageDataLike } from '../ImageData/_ImageData-types'
|
|
2
|
+
import { _macro_imageDataToUint32Array } from '../ImageData/imageDataToUint32Array'
|
|
3
|
+
import type { PixelData } from './_pixelData-types'
|
|
3
4
|
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
constructor(imageData: T) {
|
|
11
|
-
this.data32 = imageDataToUInt32Array(imageData)
|
|
12
|
-
this.imageData = imageData
|
|
13
|
-
this.width = imageData.width
|
|
14
|
-
this.height = imageData.height
|
|
5
|
+
export function makePixelData<T extends ImageDataLike = ImageData>(imageData: T): PixelData<T> {
|
|
6
|
+
return {
|
|
7
|
+
data: _macro_imageDataToUint32Array(imageData),
|
|
8
|
+
imageData,
|
|
9
|
+
w: imageData.width,
|
|
10
|
+
h: imageData.height,
|
|
15
11
|
}
|
|
12
|
+
}
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
14
|
+
export function setPixelData(target: PixelData, imageData: ImageData) {
|
|
15
|
+
;(target as any).data = _macro_imageDataToUint32Array(imageData)
|
|
16
|
+
;(target as any).imageData = imageData
|
|
17
|
+
;(target as any).w = imageData.width
|
|
18
|
+
;(target as any).h = imageData.height
|
|
23
19
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { PixelData } from './_pixelData-types'
|
|
2
|
+
import { setPixelData } from './PixelData'
|
|
3
|
+
|
|
4
|
+
export type ReusablePixelData = ReturnType<typeof makeReusablePixelData>
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Creates a factory function that manages a single, reusable PixelData instance.
|
|
8
|
+
* This is used to minimize garbage collection overhead by recycling the
|
|
9
|
+
* underlying pixel buffer across multiple operations.
|
|
10
|
+
* @returns A function that takes width and height and returns a pooled PixelData instance.
|
|
11
|
+
*/
|
|
12
|
+
export function makeReusablePixelData() {
|
|
13
|
+
const pixelData = {
|
|
14
|
+
w: 0,
|
|
15
|
+
h: 0,
|
|
16
|
+
data: null as unknown as Uint32Array,
|
|
17
|
+
imageData: null as unknown as ImageData,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Retrieves a PixelData instance of the requested dimensions.
|
|
22
|
+
* If the requested dimensions differ from the cached instance, a new one is allocated.
|
|
23
|
+
* @param width - The desired width in pixels.
|
|
24
|
+
* @param height - The desired height in pixels.
|
|
25
|
+
* @returns The cached PixelData object.
|
|
26
|
+
*/
|
|
27
|
+
return function getReusablePixelData(width: number, height: number): PixelData {
|
|
28
|
+
if (pixelData.w !== width || pixelData.h !== height) {
|
|
29
|
+
setPixelData(pixelData, new ImageData(width, height))
|
|
30
|
+
} else {
|
|
31
|
+
pixelData.data.fill(0)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return pixelData
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ImageDataLike } from '../ImageData/_ImageData-types'
|
|
2
|
+
|
|
3
|
+
export interface PixelData32 {
|
|
4
|
+
readonly data: Uint32Array
|
|
5
|
+
readonly w: number
|
|
6
|
+
readonly h: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface MutablePixelData32 {
|
|
10
|
+
data: Uint32Array
|
|
11
|
+
w: number
|
|
12
|
+
h: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface PixelData<T extends ImageDataLike = ImageData> extends PixelData32 {
|
|
16
|
+
readonly imageData: T
|
|
17
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ApplyMaskToPixelDataOptions } from '../_types'
|
|
2
|
+
import type { AlphaMask } from '../Mask/_mask-types'
|
|
3
|
+
import type { PixelData32 } from './_pixelData-types'
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Directly applies a mask to a region of PixelData,
|
|
@@ -6,14 +8,14 @@ import { type AlphaMask, type ApplyMaskToPixelDataOptions, type Color32, type IP
|
|
|
6
8
|
* @returns true if any pixels were actually modified.
|
|
7
9
|
*/
|
|
8
10
|
export function applyAlphaMaskToPixelData(
|
|
9
|
-
target:
|
|
11
|
+
target: PixelData32,
|
|
10
12
|
mask: AlphaMask,
|
|
11
13
|
opts?: ApplyMaskToPixelDataOptions,
|
|
12
14
|
): boolean {
|
|
13
15
|
const targetX = opts?.x ?? 0
|
|
14
16
|
const targetY = opts?.y ?? 0
|
|
15
|
-
const width = opts?.w ?? target.
|
|
16
|
-
const height = opts?.h ?? target.
|
|
17
|
+
const width = opts?.w ?? target.w
|
|
18
|
+
const height = opts?.h ?? target.h
|
|
17
19
|
const globalAlpha = opts?.alpha ?? 255
|
|
18
20
|
const mx = opts?.mx ?? 0
|
|
19
21
|
const my = opts?.my ?? 0
|
|
@@ -37,8 +39,8 @@ export function applyAlphaMaskToPixelData(
|
|
|
37
39
|
y = 0
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
w = Math.min(w, target.
|
|
41
|
-
h = Math.min(h, target.
|
|
42
|
+
w = Math.min(w, target.w - x)
|
|
43
|
+
h = Math.min(h, target.h - y)
|
|
42
44
|
|
|
43
45
|
if (w <= 0) return false
|
|
44
46
|
if (h <= 0) return false
|
|
@@ -70,8 +72,8 @@ export function applyAlphaMaskToPixelData(
|
|
|
70
72
|
const xShift = sX0 - startX
|
|
71
73
|
const yShift = sY0 - startY
|
|
72
74
|
|
|
73
|
-
const dst32 = target.
|
|
74
|
-
const dw = target.
|
|
75
|
+
const dst32 = target.data
|
|
76
|
+
const dw = target.w
|
|
75
77
|
const dStride = dw - finalW
|
|
76
78
|
const mStride = mPitch - finalW
|
|
77
79
|
const maskData = mask.data
|
|
@@ -80,51 +82,86 @@ export function applyAlphaMaskToPixelData(
|
|
|
80
82
|
let mIdx = sY0 * mPitch + sX0
|
|
81
83
|
|
|
82
84
|
let didChange = false
|
|
83
|
-
|
|
84
|
-
for (let
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const effectiveM = invertMask ? 255 - mVal : mVal
|
|
88
|
-
|
|
89
|
-
let weight = 0
|
|
90
|
-
|
|
91
|
-
if (effectiveM === 0) {
|
|
92
|
-
weight = 0
|
|
93
|
-
} else if (effectiveM === 255) {
|
|
94
|
-
weight = globalAlpha
|
|
95
|
-
} else if (globalAlpha === 255) {
|
|
96
|
-
weight = effectiveM
|
|
97
|
-
} else {
|
|
98
|
-
weight = (effectiveM * globalAlpha + 128) >> 8
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (weight === 0) {
|
|
102
|
-
// Clear alpha channel
|
|
103
|
-
dst32[dIdx] = (dst32[dIdx] & 0x00ffffff) >>> 0
|
|
104
|
-
didChange = true
|
|
105
|
-
} else if (weight !== 255) {
|
|
106
|
-
// Merge alpha channel
|
|
107
|
-
const d = dst32[dIdx]
|
|
108
|
-
const da = d >>> 24
|
|
85
|
+
if (invertMask) {
|
|
86
|
+
for (let iy = 0; iy < finalH; iy++) {
|
|
87
|
+
for (let ix = 0; ix < finalW; ix++) {
|
|
88
|
+
const effectiveM = 255 - maskData[mIdx]
|
|
109
89
|
|
|
110
|
-
if (
|
|
111
|
-
const
|
|
90
|
+
if (effectiveM === 0) {
|
|
91
|
+
const current = dst32[dIdx]
|
|
92
|
+
const next = (current & 0x00ffffff) >>> 0
|
|
112
93
|
|
|
113
|
-
const current = dst32[dIdx] as Color32
|
|
114
|
-
const next = ((d & 0x00ffffff) | (finalAlpha << 24)) >>> 0
|
|
115
94
|
if (current !== next) {
|
|
116
95
|
dst32[dIdx] = next
|
|
117
96
|
didChange = true
|
|
118
97
|
}
|
|
98
|
+
} else {
|
|
99
|
+
const t1 = effectiveM * globalAlpha + 128
|
|
100
|
+
const weight = (t1 + (t1 >> 8)) >> 8
|
|
101
|
+
|
|
102
|
+
if (weight < 255) {
|
|
103
|
+
const current = dst32[dIdx]
|
|
104
|
+
const da = current >>> 24
|
|
105
|
+
|
|
106
|
+
if (da !== 0) {
|
|
107
|
+
const t2 = da * weight + 128
|
|
108
|
+
const finalAlpha = (t2 + (t2 >> 8)) >> 8
|
|
109
|
+
const next = ((current & 0x00ffffff) | (finalAlpha << 24)) >>> 0
|
|
110
|
+
|
|
111
|
+
if (current !== next) {
|
|
112
|
+
dst32[dIdx] = next
|
|
113
|
+
didChange = true
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
119
117
|
}
|
|
120
|
-
}
|
|
121
118
|
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
dIdx++
|
|
120
|
+
mIdx++
|
|
121
|
+
}
|
|
122
|
+
dIdx += dStride
|
|
123
|
+
mIdx += mStride
|
|
124
124
|
}
|
|
125
|
+
} else {
|
|
126
|
+
for (let iy = 0; iy < finalH; iy++) {
|
|
127
|
+
for (let ix = 0; ix < finalW; ix++) {
|
|
128
|
+
const effectiveM = maskData[mIdx]
|
|
129
|
+
|
|
130
|
+
if (effectiveM === 0) {
|
|
131
|
+
const current = dst32[dIdx]
|
|
132
|
+
const next = (current & 0x00ffffff) >>> 0
|
|
125
133
|
|
|
126
|
-
|
|
127
|
-
|
|
134
|
+
if (current !== next) {
|
|
135
|
+
dst32[dIdx] = next
|
|
136
|
+
didChange = true
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
const t1 = effectiveM * globalAlpha + 128
|
|
140
|
+
const weight = (t1 + (t1 >> 8)) >> 8
|
|
141
|
+
|
|
142
|
+
if (weight < 255) {
|
|
143
|
+
const current = dst32[dIdx]
|
|
144
|
+
const da = current >>> 24
|
|
145
|
+
|
|
146
|
+
if (da !== 0) {
|
|
147
|
+
const t2 = da * weight + 128
|
|
148
|
+
const finalAlpha = (t2 + (t2 >> 8)) >> 8
|
|
149
|
+
const next = ((current & 0x00ffffff) | (finalAlpha << 24)) >>> 0
|
|
150
|
+
|
|
151
|
+
if (current !== next) {
|
|
152
|
+
dst32[dIdx] = next
|
|
153
|
+
didChange = true
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
dIdx++
|
|
160
|
+
mIdx++
|
|
161
|
+
}
|
|
162
|
+
dIdx += dStride
|
|
163
|
+
mIdx += mStride
|
|
164
|
+
}
|
|
128
165
|
}
|
|
129
166
|
return didChange
|
|
130
167
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { type ApplyMaskToPixelDataOptions
|
|
1
|
+
import { type ApplyMaskToPixelDataOptions } from '../_types'
|
|
2
|
+
import type { BinaryMask } from '../Mask/_mask-types'
|
|
3
|
+
import type { PixelData32 } from './_pixelData-types'
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Directly applies a mask to a region of PixelData,
|
|
@@ -6,14 +8,14 @@ import { type ApplyMaskToPixelDataOptions, type BinaryMask, type IPixelData32 }
|
|
|
6
8
|
* @returns true if any pixels were actually modified.
|
|
7
9
|
*/
|
|
8
10
|
export function applyBinaryMaskToPixelData(
|
|
9
|
-
target:
|
|
11
|
+
target: PixelData32,
|
|
10
12
|
mask: BinaryMask,
|
|
11
13
|
opts?: ApplyMaskToPixelDataOptions,
|
|
12
14
|
): boolean {
|
|
13
15
|
const targetX = opts?.x ?? 0
|
|
14
16
|
const targetY = opts?.y ?? 0
|
|
15
|
-
const width = opts?.w ?? target.
|
|
16
|
-
const height = opts?.h ?? target.
|
|
17
|
+
const width = opts?.w ?? target.w
|
|
18
|
+
const height = opts?.h ?? target.h
|
|
17
19
|
const globalAlpha = opts?.alpha ?? 255
|
|
18
20
|
const mx = opts?.mx ?? 0
|
|
19
21
|
const my = opts?.my ?? 0
|
|
@@ -36,8 +38,8 @@ export function applyBinaryMaskToPixelData(
|
|
|
36
38
|
y = 0
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
w = Math.min(w, target.
|
|
40
|
-
h = Math.min(h, target.
|
|
41
|
+
w = Math.min(w, target.w - x)
|
|
42
|
+
h = Math.min(h, target.h - y)
|
|
41
43
|
|
|
42
44
|
if (w <= 0 || h <= 0) return false
|
|
43
45
|
|
|
@@ -67,8 +69,8 @@ export function applyBinaryMaskToPixelData(
|
|
|
67
69
|
const xShift = sX0 - startX
|
|
68
70
|
const yShift = sY0 - startY
|
|
69
71
|
|
|
70
|
-
const dst32 = target.
|
|
71
|
-
const dw = target.
|
|
72
|
+
const dst32 = target.data
|
|
73
|
+
const dw = target.w
|
|
72
74
|
const dStride = dw - finalW
|
|
73
75
|
const mStride = mPitch - finalW
|
|
74
76
|
const maskData = mask.data
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type BinaryMask,
|
|
5
|
-
type IPixelData32,
|
|
6
|
-
type Mask,
|
|
7
|
-
MaskType,
|
|
8
|
-
} from '../_types'
|
|
1
|
+
import { type ApplyMaskToPixelDataOptions } from '../_types'
|
|
2
|
+
import { type AlphaMask, type BinaryMask, type Mask, MaskType } from '../Mask/_mask-types'
|
|
3
|
+
import type { PixelData32 } from './_pixelData-types'
|
|
9
4
|
import { applyAlphaMaskToPixelData } from './applyAlphaMaskToPixelData'
|
|
10
5
|
import { applyBinaryMaskToPixelData } from './applyBinaryMaskToPixelData'
|
|
11
6
|
|
|
12
7
|
export function applyMaskToPixelData(
|
|
13
|
-
dst:
|
|
8
|
+
dst: PixelData32,
|
|
14
9
|
mask: Mask,
|
|
15
10
|
opts?: ApplyMaskToPixelDataOptions,
|
|
16
11
|
): boolean {
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import { type Color32, type ColorBlendOptions
|
|
1
|
+
import { type Color32, type ColorBlendOptions } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { PixelData32 } from './_pixelData-types'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Blends a solid color into a target pixel buffer.
|
|
6
7
|
* @returns true if any pixels were actually modified.
|
|
7
8
|
*/
|
|
8
9
|
export function blendColorPixelData(
|
|
9
|
-
target:
|
|
10
|
+
target: PixelData32,
|
|
10
11
|
color: Color32,
|
|
11
12
|
opts?: ColorBlendOptions,
|
|
12
13
|
): boolean {
|
|
13
14
|
const targetX = opts?.x ?? 0
|
|
14
15
|
const targetY = opts?.y ?? 0
|
|
15
|
-
const width = opts?.w ?? target.
|
|
16
|
-
const height = opts?.h ?? target.
|
|
16
|
+
const width = opts?.w ?? target.w
|
|
17
|
+
const height = opts?.h ?? target.h
|
|
17
18
|
const globalAlpha = opts?.alpha ?? 255
|
|
18
19
|
const blendFn = opts?.blendFn ?? sourceOverPerfect
|
|
19
20
|
if (globalAlpha === 0) return false
|
|
@@ -39,8 +40,8 @@ export function blendColorPixelData(
|
|
|
39
40
|
y = 0
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
const actualW = Math.min(w, target.
|
|
43
|
-
const actualH = Math.min(h, target.
|
|
43
|
+
const actualW = Math.min(w, target.w - x)
|
|
44
|
+
const actualH = Math.min(h, target.h - y)
|
|
44
45
|
|
|
45
46
|
if (actualW <= 0 || actualH <= 0) return false
|
|
46
47
|
|
|
@@ -53,8 +54,8 @@ export function blendColorPixelData(
|
|
|
53
54
|
finalSrcColor = ((color & 0x00ffffff) | (a << 24)) >>> 0 as Color32
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
const dst32 = target.
|
|
57
|
-
const dw = target.
|
|
57
|
+
const dst32 = target.data
|
|
58
|
+
const dw = target.w
|
|
58
59
|
let dIdx = (y * dw + x) | 0
|
|
59
60
|
const dStride = (dw - actualW) | 0
|
|
60
61
|
let didChange = false
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Color32, ColorBlendMaskOptions } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { AlphaMask } from '../Mask/_mask-types'
|
|
4
|
+
import type { PixelData32 } from './_pixelData-types'
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Blends a solid color into a target pixel buffer using an alpha mask.
|
|
@@ -8,14 +10,14 @@ import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
|
8
10
|
* If the width (`w`) or height (`h`) are omitted from the options, they will safely
|
|
9
11
|
* default to the dimensions of the provided mask to prevent out-of-bounds memory access.
|
|
10
12
|
*
|
|
11
|
-
* @param target - The destination {@link
|
|
13
|
+
* @param target - The destination {@link PixelData32} buffer to modify.
|
|
12
14
|
* @param color - The solid color to apply.
|
|
13
15
|
* @param mask - The mask defining the per-pixel opacity of the target area.
|
|
14
16
|
* @param opts - Configuration options including placement coordinates, bounds, global alpha, and mask offsets.
|
|
15
17
|
* @returns true if any pixels were actually modified.
|
|
16
18
|
*/
|
|
17
19
|
export function blendColorPixelDataAlphaMask(
|
|
18
|
-
target:
|
|
20
|
+
target: PixelData32,
|
|
19
21
|
color: Color32,
|
|
20
22
|
mask: AlphaMask,
|
|
21
23
|
opts?: ColorBlendMaskOptions,
|
|
@@ -52,16 +54,16 @@ export function blendColorPixelDataAlphaMask(
|
|
|
52
54
|
y = 0
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
actualW = Math.min(actualW, target.
|
|
56
|
-
actualH = Math.min(actualH, target.
|
|
57
|
+
actualW = Math.min(actualW, target.w - x)
|
|
58
|
+
actualH = Math.min(actualH, target.h - y)
|
|
57
59
|
|
|
58
60
|
if (actualW <= 0 || actualH <= 0) return false
|
|
59
61
|
|
|
60
62
|
const dx = (x - targetX) | 0
|
|
61
63
|
const dy = (y - targetY) | 0
|
|
62
64
|
|
|
63
|
-
const dst32 = target.
|
|
64
|
-
const dw = target.
|
|
65
|
+
const dst32 = target.data
|
|
66
|
+
const dw = target.w
|
|
65
67
|
const mPitch = mask.w
|
|
66
68
|
const maskData = mask.data
|
|
67
69
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Color32, ColorBlendMaskOptions } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { BinaryMask } from '../Mask/_mask-types'
|
|
4
|
+
import type { PixelData32 } from './_pixelData-types'
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Blends a solid color into a target pixel buffer using a binary mask.
|
|
@@ -8,14 +10,14 @@ import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
|
8
10
|
* If the width (`w`) or height (`h`) are omitted from the options, they will safely
|
|
9
11
|
* default to the dimensions of the provided mask to prevent out-of-bounds memory access.
|
|
10
12
|
*
|
|
11
|
-
* @param target - The destination {@link
|
|
13
|
+
* @param target - The destination {@link PixelData32} buffer to modify.
|
|
12
14
|
* @param color - The solid color to apply.
|
|
13
15
|
* @param mask - The mask defining the per-pixel opacity of the target area.
|
|
14
16
|
* @param opts - Configuration options including placement coordinates, bounds, global alpha, and mask offsets.
|
|
15
17
|
* @returns true if any pixels were actually modified.
|
|
16
18
|
*/
|
|
17
19
|
export function blendColorPixelDataBinaryMask(
|
|
18
|
-
target:
|
|
20
|
+
target: PixelData32,
|
|
19
21
|
color: Color32,
|
|
20
22
|
mask: BinaryMask,
|
|
21
23
|
opts?: ColorBlendMaskOptions,
|
|
@@ -50,8 +52,8 @@ export function blendColorPixelDataBinaryMask(
|
|
|
50
52
|
y = 0
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
const actualW = Math.min(w, target.
|
|
54
|
-
const actualH = Math.min(h, target.
|
|
55
|
+
const actualW = Math.min(w, target.w - x)
|
|
56
|
+
const actualH = Math.min(h, target.h - y)
|
|
55
57
|
|
|
56
58
|
if (actualW <= 0 || actualH <= 0) return false
|
|
57
59
|
|
|
@@ -65,8 +67,8 @@ export function blendColorPixelDataBinaryMask(
|
|
|
65
67
|
|
|
66
68
|
const dx = (x - targetX) | 0
|
|
67
69
|
const dy = (y - targetY) | 0
|
|
68
|
-
const dst32 = target.
|
|
69
|
-
const dw = target.
|
|
70
|
+
const dst32 = target.data
|
|
71
|
+
const dw = target.w
|
|
70
72
|
const mPitch = mask.w
|
|
71
73
|
const maskData = mask.data
|
|
72
74
|
let dIdx = (y * dw + x) | 0
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { type Color32, type ColorBlendMaskOptions
|
|
1
|
+
import { type Color32, type ColorBlendMaskOptions } from '../_types'
|
|
2
|
+
import { type Mask, MaskType } from '../Mask/_mask-types'
|
|
3
|
+
import type { PixelData32 } from './_pixelData-types'
|
|
2
4
|
import { blendColorPixelDataAlphaMask } from './blendColorPixelDataAlphaMask'
|
|
3
5
|
import { blendColorPixelDataBinaryMask } from './blendColorPixelDataBinaryMask'
|
|
4
6
|
|
|
5
7
|
export function blendColorPixelDataMask(
|
|
6
|
-
dst:
|
|
8
|
+
dst: PixelData32,
|
|
7
9
|
color: Color32,
|
|
8
10
|
mask: Mask,
|
|
9
11
|
opts?: ColorBlendMaskOptions,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { type Color32
|
|
1
|
+
import { type Color32 } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { PaintAlphaMask } from '../Paint/_paint-types'
|
|
4
|
+
import type { PixelData32 } from './_pixelData-types'
|
|
3
5
|
import { blendColorPixelDataAlphaMask } from './blendColorPixelDataAlphaMask'
|
|
4
6
|
|
|
5
7
|
const SCRATCH_OPTS = {
|
|
@@ -10,7 +12,7 @@ const SCRATCH_OPTS = {
|
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export function blendColorPixelDataPaintAlphaMask(
|
|
13
|
-
dst:
|
|
15
|
+
dst: PixelData32,
|
|
14
16
|
color: Color32,
|
|
15
17
|
mask: PaintAlphaMask,
|
|
16
18
|
x: number,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { type Color32
|
|
1
|
+
import { type Color32 } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { PaintBinaryMask } from '../Paint/_paint-types'
|
|
4
|
+
import type { PixelData32 } from './_pixelData-types'
|
|
3
5
|
import { blendColorPixelDataBinaryMask } from './blendColorPixelDataBinaryMask'
|
|
4
6
|
|
|
5
7
|
const SCRATCH_OPTS = {
|
|
@@ -10,7 +12,7 @@ const SCRATCH_OPTS = {
|
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export function blendColorPixelDataPaintBinaryMask(
|
|
13
|
-
dst:
|
|
15
|
+
dst: PixelData32,
|
|
14
16
|
color: Color32,
|
|
15
17
|
mask: PaintBinaryMask,
|
|
16
18
|
x: number,
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { type Color32
|
|
1
|
+
import { type Color32 } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import { MaskType } from '../Mask/_mask-types'
|
|
4
|
+
import type { PaintMask } from '../Paint/_paint-types'
|
|
5
|
+
import type { PixelData32 } from './_pixelData-types'
|
|
3
6
|
import { blendColorPixelDataAlphaMask } from './blendColorPixelDataAlphaMask'
|
|
4
7
|
import { blendColorPixelDataBinaryMask } from './blendColorPixelDataBinaryMask'
|
|
5
8
|
|
|
@@ -11,7 +14,7 @@ const SCRATCH_OPTS = {
|
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
export function blendColorPixelDataPaintMask(
|
|
14
|
-
dst:
|
|
17
|
+
dst: PixelData32,
|
|
15
18
|
color: Color32,
|
|
16
19
|
mask: PaintMask,
|
|
17
20
|
x: number,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { BlendColor32, Color32
|
|
1
|
+
import type { BlendColor32, Color32 } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { PixelData32 } from './_pixelData-types'
|
|
3
4
|
|
|
4
5
|
export function blendPixel(
|
|
5
|
-
target:
|
|
6
|
+
target: PixelData32,
|
|
6
7
|
x: number,
|
|
7
8
|
y: number,
|
|
8
9
|
color: Color32,
|
|
@@ -11,8 +12,8 @@ export function blendPixel(
|
|
|
11
12
|
): boolean {
|
|
12
13
|
if (alpha === 0) return false
|
|
13
14
|
|
|
14
|
-
let width = target.
|
|
15
|
-
let height = target.
|
|
15
|
+
let width = target.w
|
|
16
|
+
let height = target.h
|
|
16
17
|
|
|
17
18
|
if (x < 0 || x >= width || y < 0 || y >= height) return false
|
|
18
19
|
|
|
@@ -22,7 +23,7 @@ export function blendPixel(
|
|
|
22
23
|
// Early exit for transparent source unless we are in an overwrite mode
|
|
23
24
|
if (srcAlpha === 0 && !isOverwrite) return false
|
|
24
25
|
|
|
25
|
-
let dst32 = target.
|
|
26
|
+
let dst32 = target.data
|
|
26
27
|
let index = y * width + x
|
|
27
28
|
let finalColor = color
|
|
28
29
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type Color32, type
|
|
1
|
+
import { type Color32, type PixelBlendOptions } from '../_types'
|
|
2
2
|
import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
3
|
+
import type { PixelData32 } from './_pixelData-types'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Blits source PixelData into a destination PixelData using 32-bit integer bitwise blending.
|
|
@@ -16,16 +17,16 @@ import { sourceOverPerfect } from '../BlendModes/blend-modes-perfect'
|
|
|
16
17
|
* });
|
|
17
18
|
*/
|
|
18
19
|
export function blendPixelData(
|
|
19
|
-
target:
|
|
20
|
-
src:
|
|
20
|
+
target: PixelData32,
|
|
21
|
+
src: PixelData32,
|
|
21
22
|
opts?: PixelBlendOptions,
|
|
22
23
|
): boolean {
|
|
23
24
|
const targetX = opts?.x ?? 0
|
|
24
25
|
const targetY = opts?.y ?? 0
|
|
25
26
|
const sourceX = opts?.sx ?? 0
|
|
26
27
|
const sourceY = opts?.sy ?? 0
|
|
27
|
-
const width = opts?.w ?? src.
|
|
28
|
-
const height = opts?.h ?? src.
|
|
28
|
+
const width = opts?.w ?? src.w
|
|
29
|
+
const height = opts?.h ?? src.h
|
|
29
30
|
const globalAlpha = opts?.alpha ?? 255
|
|
30
31
|
const blendFn = opts?.blendFn ?? sourceOverPerfect
|
|
31
32
|
|
|
@@ -48,8 +49,8 @@ export function blendPixelData(
|
|
|
48
49
|
h += sy
|
|
49
50
|
sy = 0
|
|
50
51
|
}
|
|
51
|
-
w = Math.min(w, src.
|
|
52
|
-
h = Math.min(h, src.
|
|
52
|
+
w = Math.min(w, src.w - sx)
|
|
53
|
+
h = Math.min(h, src.h - sy)
|
|
53
54
|
if (x < 0) {
|
|
54
55
|
sx -= x
|
|
55
56
|
w += x
|
|
@@ -61,14 +62,14 @@ export function blendPixelData(
|
|
|
61
62
|
y = 0
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
const actualW = Math.min(w, target.
|
|
65
|
-
const actualH = Math.min(h, target.
|
|
65
|
+
const actualW = Math.min(w, target.w - x)
|
|
66
|
+
const actualH = Math.min(h, target.h - y)
|
|
66
67
|
if (actualW <= 0 || actualH <= 0) return false
|
|
67
68
|
|
|
68
|
-
const dst32 = target.
|
|
69
|
-
const src32 = src.
|
|
70
|
-
const dw = target.
|
|
71
|
-
const sw = src.
|
|
69
|
+
const dst32 = target.data
|
|
70
|
+
const src32 = src.data
|
|
71
|
+
const dw = target.w
|
|
72
|
+
const sw = src.w
|
|
72
73
|
|
|
73
74
|
let dIdx = (y * dw + x) | 0
|
|
74
75
|
let sIdx = (sy * sw + sx) | 0
|