pixel-data-js 0.20.0 → 0.22.2
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.dev.cjs +722 -357
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +709 -356
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +722 -357
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +283 -128
- package/dist/index.prod.js +709 -356
- package/dist/index.prod.js.map +1 -1
- package/package.json +1 -1
- package/src/Algorithm/floodFillSelection.ts +12 -14
- package/src/BlendModes/toBlendModeIndexAndName.ts +0 -7
- package/src/Clipboard/writeImgBlobToClipboard.ts +1 -1
- package/src/History/PixelMutator/mutatorApplyAlphaMask.ts +3 -0
- package/src/History/PixelMutator/mutatorApplyBinaryMask.ts +3 -0
- package/src/History/PixelMutator/mutatorApplyCircleBrush.ts +25 -6
- package/src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts +89 -46
- package/src/History/PixelMutator/mutatorApplyCirclePencil.ts +7 -7
- package/src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts +81 -41
- package/src/History/PixelMutator/mutatorApplyRectBrush.ts +3 -0
- package/src/History/PixelMutator/mutatorApplyRectBrushStroke.ts +18 -5
- package/src/History/PixelMutator/mutatorApplyRectPencil.ts +3 -0
- package/src/History/PixelMutator/mutatorApplyRectPencilStroke.ts +19 -4
- package/src/History/PixelMutator/mutatorBlendColor.ts +4 -0
- package/src/History/PixelMutator/mutatorBlendPixelData.ts +4 -0
- package/src/History/PixelMutator/mutatorClear.ts +11 -8
- package/src/History/PixelMutator/mutatorFill.ts +4 -0
- package/src/History/PixelMutator/mutatorFillBinaryMask.ts +28 -0
- package/src/History/PixelMutator/mutatorInvert.ts +3 -0
- package/src/ImageData/extractImageDataBuffer.ts +3 -3
- package/src/ImageData/{imageDataToAlphaMask.ts → imageDataToAlphaMaskBuffer.ts} +3 -4
- package/src/ImageData/resizeImageData.ts +3 -5
- package/src/ImageData/writeImageDataBuffer.ts +7 -7
- package/src/Mask/AlphaMask.ts +16 -0
- package/src/Mask/BinaryMask.ts +16 -0
- package/src/Mask/CircleBrushAlphaMask.ts +32 -0
- package/src/Mask/CircleBrushBinaryMask.ts +30 -0
- package/src/Mask/applyBinaryMaskToAlphaMask.ts +12 -9
- package/src/Mask/copyMask.ts +9 -3
- package/src/Mask/extractMask.ts +33 -31
- package/src/Mask/extractMaskBuffer.ts +87 -0
- package/src/Mask/invertMask.ts +6 -4
- package/src/Mask/mergeAlphaMasks.ts +11 -10
- package/src/Mask/mergeBinaryMasks.ts +10 -9
- package/src/Mask/setMaskData.ts +7 -0
- package/src/MaskRect/merge2BinaryMaskRects.ts +81 -0
- package/src/MaskRect/mergeBinaryMaskRects.ts +39 -0
- package/src/MaskRect/subtractBinaryMaskRects.ts +80 -0
- package/src/PixelData/applyAlphaMaskToPixelData.ts +8 -5
- package/src/PixelData/applyBinaryMaskToPixelData.ts +8 -9
- package/src/PixelData/applyCircleBrushToPixelData.ts +54 -62
- package/src/PixelData/blendColorPixelDataAlphaMask.ts +35 -25
- package/src/PixelData/blendColorPixelDataBinaryMask.ts +26 -19
- package/src/PixelData/blendPixelDataAlphaMask.ts +3 -3
- package/src/PixelData/blendPixelDataBinaryMask.ts +3 -3
- package/src/PixelData/clearPixelData.ts +2 -2
- package/src/PixelData/fillPixelData.ts +15 -42
- package/src/PixelData/fillPixelDataBinaryMask.ts +79 -0
- package/src/PixelData/invertPixelData.ts +3 -3
- package/src/PixelData/pixelDataToAlphaMask.ts +4 -2
- package/src/PixelData/writePixelDataBuffer.ts +2 -3
- package/src/Rect/getRectsBounds.ts +22 -0
- package/src/Rect/trimRectBounds.ts +20 -17
- package/src/_types.ts +55 -29
- package/src/index.ts +16 -1
package/dist/index.prod.js
CHANGED
|
@@ -196,8 +196,8 @@ function extractImageDataBuffer(imageData, _x, _y, _w, _h) {
|
|
|
196
196
|
return out;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
// src/Mask/
|
|
200
|
-
function
|
|
199
|
+
// src/Mask/extractMaskBuffer.ts
|
|
200
|
+
function extractMaskBuffer(maskBuffer, maskWidth, xOrRect, y, w, h) {
|
|
201
201
|
let finalX;
|
|
202
202
|
let finalY;
|
|
203
203
|
let finalW;
|
|
@@ -214,7 +214,7 @@ function extractMask(mask, maskWidth, xOrRect, y, w, h) {
|
|
|
214
214
|
finalH = h;
|
|
215
215
|
}
|
|
216
216
|
const out = new Uint8Array(finalW * finalH);
|
|
217
|
-
const srcH =
|
|
217
|
+
const srcH = maskBuffer.length / maskWidth;
|
|
218
218
|
for (let row = 0; row < finalH; row++) {
|
|
219
219
|
const currentSrcY = finalY + row;
|
|
220
220
|
if (currentSrcY < 0 || currentSrcY >= srcH) {
|
|
@@ -226,7 +226,7 @@ function extractMask(mask, maskWidth, xOrRect, y, w, h) {
|
|
|
226
226
|
const srcOffset = currentSrcY * maskWidth + start;
|
|
227
227
|
const dstOffset = row * finalW + (start - finalX);
|
|
228
228
|
const count = end - start;
|
|
229
|
-
out.set(
|
|
229
|
+
out.set(maskBuffer.subarray(srcOffset, srcOffset + count), dstOffset);
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
232
|
return out;
|
|
@@ -244,8 +244,8 @@ function trimRectBounds(target, bounds) {
|
|
|
244
244
|
if (intersectedMaxX <= intersectedX || intersectedMaxY <= intersectedY) {
|
|
245
245
|
target.w = 0;
|
|
246
246
|
target.h = 0;
|
|
247
|
-
if ("
|
|
248
|
-
target.
|
|
247
|
+
if ("data" in target && target.data) {
|
|
248
|
+
target.data = new Uint8Array(0);
|
|
249
249
|
}
|
|
250
250
|
return;
|
|
251
251
|
}
|
|
@@ -257,15 +257,15 @@ function trimRectBounds(target, bounds) {
|
|
|
257
257
|
target.y = intersectedY;
|
|
258
258
|
target.w = intersectedW;
|
|
259
259
|
target.h = intersectedH;
|
|
260
|
-
if ("
|
|
261
|
-
const
|
|
260
|
+
if ("data" in target && target.data) {
|
|
261
|
+
const currentMaskBuffer = extractMaskBuffer(target.data, originalW, offsetX, offsetY, intersectedW, intersectedH);
|
|
262
262
|
let minX = intersectedW;
|
|
263
263
|
let maxX = -1;
|
|
264
264
|
let minY = intersectedH;
|
|
265
265
|
let maxY = -1;
|
|
266
266
|
for (let y = 0; y < intersectedH; y++) {
|
|
267
267
|
for (let x = 0; x < intersectedW; x++) {
|
|
268
|
-
if (
|
|
268
|
+
if (currentMaskBuffer[y * intersectedW + x] !== 0) {
|
|
269
269
|
if (x < minX) minX = x;
|
|
270
270
|
if (x > maxX) maxX = x;
|
|
271
271
|
if (y < minY) minY = y;
|
|
@@ -276,19 +276,22 @@ function trimRectBounds(target, bounds) {
|
|
|
276
276
|
if (maxX === -1) {
|
|
277
277
|
target.w = 0;
|
|
278
278
|
target.h = 0;
|
|
279
|
-
target.
|
|
279
|
+
target.data = new Uint8Array(0);
|
|
280
280
|
return;
|
|
281
281
|
}
|
|
282
282
|
const finalW = maxX - minX + 1;
|
|
283
283
|
const finalH = maxY - minY + 1;
|
|
284
284
|
if (finalW !== intersectedW || finalH !== intersectedH) {
|
|
285
|
-
|
|
285
|
+
const newMaskBuffer = extractMaskBuffer(currentMaskBuffer, intersectedW, minX, minY, finalW, finalH);
|
|
286
286
|
target.x += minX;
|
|
287
287
|
target.y += minY;
|
|
288
288
|
target.w = finalW;
|
|
289
289
|
target.h = finalH;
|
|
290
|
+
target.data = newMaskBuffer;
|
|
290
291
|
} else {
|
|
291
|
-
target.
|
|
292
|
+
target.w = finalW;
|
|
293
|
+
target.h = finalH;
|
|
294
|
+
target.data = currentMaskBuffer;
|
|
292
295
|
}
|
|
293
296
|
}
|
|
294
297
|
}
|
|
@@ -398,17 +401,19 @@ function floodFillSelection(img, startX, startY, {
|
|
|
398
401
|
if (matchCount === 0) {
|
|
399
402
|
return null;
|
|
400
403
|
}
|
|
404
|
+
const w = maxX - minX + 1;
|
|
405
|
+
const h = maxY - minY + 1;
|
|
401
406
|
const selectionRect = {
|
|
402
407
|
x: minX,
|
|
403
408
|
y: minY,
|
|
404
|
-
w
|
|
405
|
-
h
|
|
406
|
-
|
|
407
|
-
|
|
409
|
+
w,
|
|
410
|
+
h,
|
|
411
|
+
data: new Uint8Array(w * h),
|
|
412
|
+
type: 1 /* BINARY */
|
|
408
413
|
};
|
|
409
414
|
const sw = selectionRect.w;
|
|
410
415
|
const sh = selectionRect.h;
|
|
411
|
-
const finalMask = selectionRect.
|
|
416
|
+
const finalMask = selectionRect.data;
|
|
412
417
|
for (let i = 0; i < matchCount; i++) {
|
|
413
418
|
const mx = matchX[i] - selectionRect.x;
|
|
414
419
|
const my = matchY[i] - selectionRect.y;
|
|
@@ -1483,16 +1488,7 @@ function toBlendModeIndexAndName(input) {
|
|
|
1483
1488
|
const num = Number(trimmed);
|
|
1484
1489
|
const isNumeric = trimmed !== "" && !Number.isNaN(num);
|
|
1485
1490
|
if (isNumeric && Number.isInteger(num)) {
|
|
1486
|
-
console.log({
|
|
1487
|
-
trimmed,
|
|
1488
|
-
num,
|
|
1489
|
-
isNumeric,
|
|
1490
|
-
isInt: Number.isInteger(num)
|
|
1491
|
-
});
|
|
1492
1491
|
const name = getKeyByValue(BaseBlendMode, num);
|
|
1493
|
-
console.log({
|
|
1494
|
-
name
|
|
1495
|
-
});
|
|
1496
1492
|
if (name === void 0) throw new Error(`Invalid index: ${num}`);
|
|
1497
1493
|
return {
|
|
1498
1494
|
blendIndex: num,
|
|
@@ -1866,7 +1862,6 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1866
1862
|
w: width = dst.width,
|
|
1867
1863
|
h: height = dst.height,
|
|
1868
1864
|
alpha: globalAlpha = 255,
|
|
1869
|
-
mw,
|
|
1870
1865
|
mx = 0,
|
|
1871
1866
|
my = 0,
|
|
1872
1867
|
invertMask = false
|
|
@@ -1888,15 +1883,14 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1888
1883
|
h = Math.min(h, dst.height - y);
|
|
1889
1884
|
if (w <= 0) return;
|
|
1890
1885
|
if (h <= 0) return;
|
|
1891
|
-
const mPitch =
|
|
1886
|
+
const mPitch = mask.w;
|
|
1892
1887
|
if (mPitch <= 0) return;
|
|
1893
|
-
const maskHeight = mask.length / mPitch | 0;
|
|
1894
1888
|
const startX = mx + (x - targetX);
|
|
1895
1889
|
const startY = my + (y - targetY);
|
|
1896
1890
|
const sX0 = Math.max(0, startX);
|
|
1897
1891
|
const sY0 = Math.max(0, startY);
|
|
1898
1892
|
const sX1 = Math.min(mPitch, startX + w);
|
|
1899
|
-
const sY1 = Math.min(
|
|
1893
|
+
const sY1 = Math.min(mask.h, startY + h);
|
|
1900
1894
|
const finalW = sX1 - sX0;
|
|
1901
1895
|
const finalH = sY1 - sY0;
|
|
1902
1896
|
if (finalW <= 0) return;
|
|
@@ -1907,11 +1901,12 @@ function applyAlphaMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1907
1901
|
const dw = dst.width;
|
|
1908
1902
|
const dStride = dw - finalW;
|
|
1909
1903
|
const mStride = mPitch - finalW;
|
|
1904
|
+
const maskData = mask.data;
|
|
1910
1905
|
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
1911
1906
|
let mIdx = sY0 * mPitch + sX0;
|
|
1912
1907
|
for (let iy = 0; iy < h; iy++) {
|
|
1913
1908
|
for (let ix = 0; ix < w; ix++) {
|
|
1914
|
-
const mVal =
|
|
1909
|
+
const mVal = maskData[mIdx];
|
|
1915
1910
|
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
1916
1911
|
let weight = 0;
|
|
1917
1912
|
if (effectiveM === 0) {
|
|
@@ -1971,13 +1966,12 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1971
1966
|
y: targetY = 0,
|
|
1972
1967
|
w: width = dst.width,
|
|
1973
1968
|
h: height = dst.height,
|
|
1974
|
-
alpha = 255,
|
|
1975
|
-
mw,
|
|
1969
|
+
alpha: globalAlpha = 255,
|
|
1976
1970
|
mx = 0,
|
|
1977
1971
|
my = 0,
|
|
1978
1972
|
invertMask = false
|
|
1979
1973
|
} = opts;
|
|
1980
|
-
if (
|
|
1974
|
+
if (globalAlpha === 0) return;
|
|
1981
1975
|
let x = targetX;
|
|
1982
1976
|
let y = targetY;
|
|
1983
1977
|
let w = width;
|
|
@@ -1994,15 +1988,14 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
1994
1988
|
h = Math.min(h, dst.height - y);
|
|
1995
1989
|
if (w <= 0) return;
|
|
1996
1990
|
if (h <= 0) return;
|
|
1997
|
-
const mPitch =
|
|
1991
|
+
const mPitch = mask.w;
|
|
1998
1992
|
if (mPitch <= 0) return;
|
|
1999
|
-
const maskHeight = mask.length / mPitch | 0;
|
|
2000
1993
|
const startX = mx + (x - targetX);
|
|
2001
1994
|
const startY = my + (y - targetY);
|
|
2002
1995
|
const sX0 = Math.max(0, startX);
|
|
2003
1996
|
const sY0 = Math.max(0, startY);
|
|
2004
1997
|
const sX1 = Math.min(mPitch, startX + w);
|
|
2005
|
-
const sY1 = Math.min(
|
|
1998
|
+
const sY1 = Math.min(mask.h, startY + h);
|
|
2006
1999
|
const finalW = sX1 - sX0;
|
|
2007
2000
|
const finalH = sY1 - sY0;
|
|
2008
2001
|
if (finalW <= 0) return;
|
|
@@ -2013,19 +2006,20 @@ function applyBinaryMaskToPixelData(dst, mask, opts = {}) {
|
|
|
2013
2006
|
const dw = dst.width;
|
|
2014
2007
|
const dStride = dw - finalW;
|
|
2015
2008
|
const mStride = mPitch - finalW;
|
|
2009
|
+
const maskData = mask.data;
|
|
2016
2010
|
let dIdx = (y + yShift) * dw + (x + xShift);
|
|
2017
2011
|
let mIdx = sY0 * mPitch + sX0;
|
|
2018
2012
|
for (let iy = 0; iy < h; iy++) {
|
|
2019
2013
|
for (let ix = 0; ix < w; ix++) {
|
|
2020
|
-
const mVal =
|
|
2014
|
+
const mVal = maskData[mIdx];
|
|
2021
2015
|
const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
|
|
2022
2016
|
if (isMaskedOut) {
|
|
2023
2017
|
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2024
|
-
} else if (
|
|
2018
|
+
} else if (globalAlpha !== 255) {
|
|
2025
2019
|
const d = dst32[dIdx];
|
|
2026
2020
|
const da = d >>> 24;
|
|
2027
2021
|
if (da !== 0) {
|
|
2028
|
-
const finalAlpha = da === 255 ?
|
|
2022
|
+
const finalAlpha = da === 255 ? globalAlpha : da * globalAlpha + 128 >> 8;
|
|
2029
2023
|
dst32[dIdx] = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2030
2024
|
}
|
|
2031
2025
|
}
|
|
@@ -2088,144 +2082,42 @@ function getCircleBrushOrPencilBounds(centerX, centerY, brushSize, targetWidth,
|
|
|
2088
2082
|
return res;
|
|
2089
2083
|
}
|
|
2090
2084
|
|
|
2091
|
-
// src/PixelData/applyCircleBrushToPixelData.ts
|
|
2092
|
-
function applyCircleBrushToPixelData(target, color, centerX, centerY, brushSize, alpha = 255, fallOff, blendFn = sourceOverPerfect, bounds) {
|
|
2093
|
-
const targetWidth = target.width;
|
|
2094
|
-
const targetHeight = target.height;
|
|
2095
|
-
const b = bounds ?? getCircleBrushOrPencilBounds(centerX, centerY, brushSize, targetWidth, targetHeight);
|
|
2096
|
-
if (b.w <= 0 || b.h <= 0) return;
|
|
2097
|
-
const data32 = target.data32;
|
|
2098
|
-
const r = brushSize / 2;
|
|
2099
|
-
const rSqr = r * r;
|
|
2100
|
-
const invR = 1 / r;
|
|
2101
|
-
const centerOffset = brushSize % 2 === 0 ? 0.5 : 0;
|
|
2102
|
-
const endX = b.x + b.w;
|
|
2103
|
-
const endY = b.y + b.h;
|
|
2104
|
-
const fCenterX = Math.floor(centerX);
|
|
2105
|
-
const fCenterY = Math.floor(centerY);
|
|
2106
|
-
const baseSrcAlpha = color >>> 24;
|
|
2107
|
-
const colorRGB = color & 16777215;
|
|
2108
|
-
const isOpaque = alpha === 255;
|
|
2109
|
-
const isOverwrite = blendFn.isOverwrite;
|
|
2110
|
-
for (let cy = b.y; cy < endY; cy++) {
|
|
2111
|
-
const relY = cy - fCenterY + centerOffset;
|
|
2112
|
-
const dySqr = relY * relY;
|
|
2113
|
-
const rowOffset = cy * targetWidth;
|
|
2114
|
-
for (let cx = b.x; cx < endX; cx++) {
|
|
2115
|
-
const relX = cx - fCenterX + centerOffset;
|
|
2116
|
-
const dSqr = relX * relX + dySqr;
|
|
2117
|
-
if (dSqr <= rSqr) {
|
|
2118
|
-
const idx = rowOffset + cx;
|
|
2119
|
-
let weight = alpha;
|
|
2120
|
-
const strength = fallOff(1 - Math.sqrt(dSqr) * invR);
|
|
2121
|
-
const maskVal = strength * 255 | 0;
|
|
2122
|
-
if (maskVal === 0) continue;
|
|
2123
|
-
if (isOpaque) {
|
|
2124
|
-
weight = maskVal;
|
|
2125
|
-
} else if (maskVal !== 255) {
|
|
2126
|
-
weight = maskVal * alpha + 128 >> 8;
|
|
2127
|
-
}
|
|
2128
|
-
let finalCol = color;
|
|
2129
|
-
if (weight < 255) {
|
|
2130
|
-
const a = baseSrcAlpha * weight + 128 >> 8;
|
|
2131
|
-
if (a === 0 && !isOverwrite) continue;
|
|
2132
|
-
finalCol = (colorRGB | a << 24) >>> 0;
|
|
2133
|
-
}
|
|
2134
|
-
data32[idx] = blendFn(finalCol, data32[idx]);
|
|
2135
|
-
}
|
|
2136
|
-
}
|
|
2137
|
-
}
|
|
2138
|
-
}
|
|
2139
|
-
|
|
2140
|
-
// src/History/PixelMutator/mutatorApplyCircleBrush.ts
|
|
2141
|
-
var defaults3 = {
|
|
2142
|
-
applyCircleBrushToPixelData,
|
|
2143
|
-
getCircleBrushOrPencilBounds
|
|
2144
|
-
};
|
|
2145
|
-
var mutatorApplyCircleBrush = ((writer, deps = defaults3) => {
|
|
2146
|
-
const {
|
|
2147
|
-
applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults3.applyCircleBrushToPixelData,
|
|
2148
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults3.getCircleBrushOrPencilBounds
|
|
2149
|
-
} = deps;
|
|
2150
|
-
const boundsOut = {
|
|
2151
|
-
x: 0,
|
|
2152
|
-
y: 0,
|
|
2153
|
-
w: 0,
|
|
2154
|
-
h: 0
|
|
2155
|
-
};
|
|
2156
|
-
return {
|
|
2157
|
-
applyCircleBrush(color, centerX, centerY, brushSize, alpha = 255, fallOff, blendFn) {
|
|
2158
|
-
const bounds = getCircleBrushOrPencilBounds2(centerX, centerY, brushSize, writer.target.width, writer.target.height, boundsOut);
|
|
2159
|
-
const {
|
|
2160
|
-
x,
|
|
2161
|
-
y,
|
|
2162
|
-
w,
|
|
2163
|
-
h
|
|
2164
|
-
} = bounds;
|
|
2165
|
-
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2166
|
-
applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brushSize, alpha, fallOff, blendFn, bounds);
|
|
2167
|
-
}
|
|
2168
|
-
};
|
|
2169
|
-
});
|
|
2170
|
-
|
|
2171
|
-
// src/Algorithm/forEachLinePoint.ts
|
|
2172
|
-
function forEachLinePoint(x0, y0, x1, y1, callback) {
|
|
2173
|
-
const dx = x1 - x0;
|
|
2174
|
-
const dy = y1 - y0;
|
|
2175
|
-
const steps = Math.max(Math.abs(dx), Math.abs(dy));
|
|
2176
|
-
if (steps === 0) {
|
|
2177
|
-
callback(x0, y0);
|
|
2178
|
-
return;
|
|
2179
|
-
}
|
|
2180
|
-
const xInc = dx / steps;
|
|
2181
|
-
const yInc = dy / steps;
|
|
2182
|
-
let curX = x0;
|
|
2183
|
-
let curY = y0;
|
|
2184
|
-
for (let i = 0; i <= steps; i++) {
|
|
2185
|
-
callback(curX, curY);
|
|
2186
|
-
curX += xInc;
|
|
2187
|
-
curY += yInc;
|
|
2188
|
-
}
|
|
2189
|
-
}
|
|
2190
|
-
|
|
2191
2085
|
// src/PixelData/blendColorPixelDataAlphaMask.ts
|
|
2192
|
-
function blendColorPixelDataAlphaMask(dst, color, mask, opts) {
|
|
2193
|
-
const
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
invertMask = false
|
|
2204
|
-
} = opts;
|
|
2205
|
-
if (globalAlpha === 0 || !mask) return;
|
|
2086
|
+
function blendColorPixelDataAlphaMask(dst, color, mask, opts = {}) {
|
|
2087
|
+
const targetX = opts.x ?? 0;
|
|
2088
|
+
const targetY = opts.y ?? 0;
|
|
2089
|
+
const w = opts.w ?? mask.w;
|
|
2090
|
+
const h = opts.h ?? mask.h;
|
|
2091
|
+
const globalAlpha = opts.alpha ?? 255;
|
|
2092
|
+
const blendFn = opts.blendFn ?? sourceOverPerfect;
|
|
2093
|
+
const mx = opts.mx ?? 0;
|
|
2094
|
+
const my = opts.my ?? 0;
|
|
2095
|
+
const invertMask = opts.invertMask ?? false;
|
|
2096
|
+
if (globalAlpha === 0) return;
|
|
2206
2097
|
const baseSrcAlpha = color >>> 24;
|
|
2207
2098
|
const isOverwrite = blendFn.isOverwrite || false;
|
|
2208
2099
|
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2209
2100
|
let x = targetX;
|
|
2210
2101
|
let y = targetY;
|
|
2211
|
-
let
|
|
2212
|
-
let
|
|
2102
|
+
let actualW = w;
|
|
2103
|
+
let actualH = h;
|
|
2213
2104
|
if (x < 0) {
|
|
2214
|
-
|
|
2105
|
+
actualW += x;
|
|
2215
2106
|
x = 0;
|
|
2216
2107
|
}
|
|
2217
2108
|
if (y < 0) {
|
|
2218
|
-
|
|
2109
|
+
actualH += y;
|
|
2219
2110
|
y = 0;
|
|
2220
2111
|
}
|
|
2221
|
-
|
|
2222
|
-
|
|
2112
|
+
actualW = Math.min(actualW, dst.width - x);
|
|
2113
|
+
actualH = Math.min(actualH, dst.height - y);
|
|
2223
2114
|
if (actualW <= 0 || actualH <= 0) return;
|
|
2224
2115
|
const dx = x - targetX | 0;
|
|
2225
2116
|
const dy = y - targetY | 0;
|
|
2226
2117
|
const dst32 = dst.data32;
|
|
2227
2118
|
const dw = dst.width;
|
|
2228
|
-
const mPitch =
|
|
2119
|
+
const mPitch = mask.w;
|
|
2120
|
+
const maskData = mask.data;
|
|
2229
2121
|
let dIdx = y * dw + x | 0;
|
|
2230
2122
|
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2231
2123
|
const dStride = dw - actualW | 0;
|
|
@@ -2234,7 +2126,7 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts) {
|
|
|
2234
2126
|
const colorRGB = color & 16777215;
|
|
2235
2127
|
for (let iy = 0; iy < actualH; iy++) {
|
|
2236
2128
|
for (let ix = 0; ix < actualW; ix++) {
|
|
2237
|
-
const mVal =
|
|
2129
|
+
const mVal = maskData[mIdx];
|
|
2238
2130
|
const effM = invertMask ? 255 - mVal : mVal;
|
|
2239
2131
|
if (effM === 0) {
|
|
2240
2132
|
dIdx++;
|
|
@@ -2271,6 +2163,155 @@ function blendColorPixelDataAlphaMask(dst, color, mask, opts) {
|
|
|
2271
2163
|
}
|
|
2272
2164
|
}
|
|
2273
2165
|
|
|
2166
|
+
// src/PixelData/blendColorPixelDataBinaryMask.ts
|
|
2167
|
+
function blendColorPixelDataBinaryMask(dst, color, mask, opts = {}) {
|
|
2168
|
+
const targetX = opts.x ?? 0;
|
|
2169
|
+
const targetY = opts.y ?? 0;
|
|
2170
|
+
let w = opts.w ?? mask.w;
|
|
2171
|
+
let h = opts.h ?? mask.h;
|
|
2172
|
+
const globalAlpha = opts.alpha ?? 255;
|
|
2173
|
+
const blendFn = opts.blendFn ?? sourceOverPerfect;
|
|
2174
|
+
const mx = opts.mx ?? 0;
|
|
2175
|
+
const my = opts.my ?? 0;
|
|
2176
|
+
const invertMask = opts.invertMask ?? false;
|
|
2177
|
+
if (globalAlpha === 0) return;
|
|
2178
|
+
const baseSrcAlpha = color >>> 24;
|
|
2179
|
+
const isOverwrite = blendFn.isOverwrite || false;
|
|
2180
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2181
|
+
let x = targetX;
|
|
2182
|
+
let y = targetY;
|
|
2183
|
+
if (x < 0) {
|
|
2184
|
+
w += x;
|
|
2185
|
+
x = 0;
|
|
2186
|
+
}
|
|
2187
|
+
if (y < 0) {
|
|
2188
|
+
h += y;
|
|
2189
|
+
y = 0;
|
|
2190
|
+
}
|
|
2191
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2192
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2193
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
2194
|
+
let baseColorWithGlobalAlpha = color;
|
|
2195
|
+
if (globalAlpha < 255) {
|
|
2196
|
+
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2197
|
+
if (a === 0 && !isOverwrite) return;
|
|
2198
|
+
baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
|
|
2199
|
+
}
|
|
2200
|
+
const dx = x - targetX | 0;
|
|
2201
|
+
const dy = y - targetY | 0;
|
|
2202
|
+
const dst32 = dst.data32;
|
|
2203
|
+
const dw = dst.width;
|
|
2204
|
+
const mPitch = mask.w;
|
|
2205
|
+
const maskData = mask.data;
|
|
2206
|
+
let dIdx = y * dw + x | 0;
|
|
2207
|
+
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2208
|
+
const dStride = dw - actualW | 0;
|
|
2209
|
+
const mStride = mPitch - actualW | 0;
|
|
2210
|
+
const skipVal = invertMask ? 1 : 0;
|
|
2211
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2212
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2213
|
+
if (maskData[mIdx] === skipVal) {
|
|
2214
|
+
dIdx++;
|
|
2215
|
+
mIdx++;
|
|
2216
|
+
continue;
|
|
2217
|
+
}
|
|
2218
|
+
dst32[dIdx] = blendFn(baseColorWithGlobalAlpha, dst32[dIdx]);
|
|
2219
|
+
dIdx++;
|
|
2220
|
+
mIdx++;
|
|
2221
|
+
}
|
|
2222
|
+
dIdx += dStride;
|
|
2223
|
+
mIdx += mStride;
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
// src/PixelData/applyCircleBrushToPixelData.ts
|
|
2228
|
+
function applyCircleBrushToPixelData(target, color, centerX, centerY, brush, alpha = 255, blendFn = sourceOverPerfect, scratchOptions = {}, bounds) {
|
|
2229
|
+
const b = bounds ?? getCircleBrushOrPencilBounds(centerX, centerY, brush.size, target.width, target.height);
|
|
2230
|
+
if (b.w <= 0 || b.h <= 0) return;
|
|
2231
|
+
const unclippedStartX = Math.floor(centerX + brush.minOffset);
|
|
2232
|
+
const unclippedStartY = Math.floor(centerY + brush.minOffset);
|
|
2233
|
+
const ix = Math.max(unclippedStartX, b.x);
|
|
2234
|
+
const iy = Math.max(unclippedStartY, b.y);
|
|
2235
|
+
const ir = Math.min(unclippedStartX + brush.w, b.x + b.w);
|
|
2236
|
+
const ib = Math.min(unclippedStartY + brush.h, b.y + b.h);
|
|
2237
|
+
const iw = ir - ix;
|
|
2238
|
+
const ih = ib - iy;
|
|
2239
|
+
if (iw <= 0 || ih <= 0) return;
|
|
2240
|
+
scratchOptions.x = ix;
|
|
2241
|
+
scratchOptions.y = iy;
|
|
2242
|
+
scratchOptions.w = iw;
|
|
2243
|
+
scratchOptions.h = ih;
|
|
2244
|
+
scratchOptions.mx = ix - unclippedStartX;
|
|
2245
|
+
scratchOptions.my = iy - unclippedStartY;
|
|
2246
|
+
scratchOptions.alpha = alpha;
|
|
2247
|
+
scratchOptions.blendFn = blendFn;
|
|
2248
|
+
if (brush.type === 0 /* ALPHA */) {
|
|
2249
|
+
blendColorPixelDataAlphaMask(target, color, brush, scratchOptions);
|
|
2250
|
+
}
|
|
2251
|
+
if (brush.type === 1 /* BINARY */) {
|
|
2252
|
+
blendColorPixelDataBinaryMask(target, color, brush, scratchOptions);
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
// src/History/PixelMutator/mutatorApplyCircleBrush.ts
|
|
2257
|
+
var defaults3 = {
|
|
2258
|
+
applyCircleBrushToPixelData,
|
|
2259
|
+
getCircleBrushOrPencilBounds
|
|
2260
|
+
};
|
|
2261
|
+
var mutatorApplyCircleBrush = ((writer, deps = defaults3) => {
|
|
2262
|
+
const {
|
|
2263
|
+
applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults3.applyCircleBrushToPixelData,
|
|
2264
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults3.getCircleBrushOrPencilBounds
|
|
2265
|
+
} = deps;
|
|
2266
|
+
const boundsOut = {
|
|
2267
|
+
x: 0,
|
|
2268
|
+
y: 0,
|
|
2269
|
+
w: 0,
|
|
2270
|
+
h: 0
|
|
2271
|
+
};
|
|
2272
|
+
const blendColorPixelOptions = {
|
|
2273
|
+
alpha: 255,
|
|
2274
|
+
blendFn: sourceOverPerfect,
|
|
2275
|
+
x: 0,
|
|
2276
|
+
y: 0,
|
|
2277
|
+
w: 0,
|
|
2278
|
+
h: 0
|
|
2279
|
+
};
|
|
2280
|
+
return {
|
|
2281
|
+
applyCircleBrush(color, centerX, centerY, brush, alpha = 255, blendFn) {
|
|
2282
|
+
const bounds = getCircleBrushOrPencilBounds2(centerX, centerY, brush.size, writer.target.width, writer.target.height, boundsOut);
|
|
2283
|
+
const {
|
|
2284
|
+
x,
|
|
2285
|
+
y,
|
|
2286
|
+
w,
|
|
2287
|
+
h
|
|
2288
|
+
} = bounds;
|
|
2289
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2290
|
+
applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brush, alpha, blendFn, blendColorPixelOptions, bounds);
|
|
2291
|
+
}
|
|
2292
|
+
};
|
|
2293
|
+
});
|
|
2294
|
+
|
|
2295
|
+
// src/Algorithm/forEachLinePoint.ts
|
|
2296
|
+
function forEachLinePoint(x0, y0, x1, y1, callback) {
|
|
2297
|
+
const dx = x1 - x0;
|
|
2298
|
+
const dy = y1 - y0;
|
|
2299
|
+
const steps = Math.max(Math.abs(dx), Math.abs(dy));
|
|
2300
|
+
if (steps === 0) {
|
|
2301
|
+
callback(x0, y0);
|
|
2302
|
+
return;
|
|
2303
|
+
}
|
|
2304
|
+
const xInc = dx / steps;
|
|
2305
|
+
const yInc = dy / steps;
|
|
2306
|
+
let curX = x0;
|
|
2307
|
+
let curY = y0;
|
|
2308
|
+
for (let i = 0; i <= steps; i++) {
|
|
2309
|
+
callback(curX, curY);
|
|
2310
|
+
curX += xInc;
|
|
2311
|
+
curY += yInc;
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2274
2315
|
// src/Rect/getCircleBrushOrPencilStrokeBounds.ts
|
|
2275
2316
|
function getCircleBrushOrPencilStrokeBounds(x0, y0, x1, y1, brushSize, result) {
|
|
2276
2317
|
const r = Math.ceil(brushSize / 2);
|
|
@@ -2319,8 +2360,15 @@ var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
|
|
|
2319
2360
|
w: 0,
|
|
2320
2361
|
h: 0
|
|
2321
2362
|
};
|
|
2363
|
+
const mask = {
|
|
2364
|
+
type: 0 /* ALPHA */,
|
|
2365
|
+
data: null,
|
|
2366
|
+
w: 0,
|
|
2367
|
+
h: 0
|
|
2368
|
+
};
|
|
2322
2369
|
return {
|
|
2323
|
-
applyCircleBrushStroke(color, x0, y0, x1, y1,
|
|
2370
|
+
applyCircleBrushStroke(color, x0, y0, x1, y1, brush, alpha = 255, blendFn = sourceOverPerfect) {
|
|
2371
|
+
const brushSize = brush.size;
|
|
2324
2372
|
const {
|
|
2325
2373
|
x: bx,
|
|
2326
2374
|
y: by,
|
|
@@ -2328,11 +2376,12 @@ var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
|
|
|
2328
2376
|
h: bh
|
|
2329
2377
|
} = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushSize, strokeBoundsOut);
|
|
2330
2378
|
if (bw <= 0 || bh <= 0) return;
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
const
|
|
2335
|
-
const
|
|
2379
|
+
mask.data = new Uint8Array(bw * bh);
|
|
2380
|
+
mask.w = bw;
|
|
2381
|
+
mask.h = bh;
|
|
2382
|
+
const maskData = mask.data;
|
|
2383
|
+
const brushData = brush.data;
|
|
2384
|
+
const minOffset = brush.minOffset;
|
|
2336
2385
|
const targetWidth = writer.target.width;
|
|
2337
2386
|
const targetHeight = writer.target.height;
|
|
2338
2387
|
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
@@ -2347,21 +2396,20 @@ var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
|
|
|
2347
2396
|
const startY = Math.max(by, cby);
|
|
2348
2397
|
const endX = Math.min(bx + bw, cbx + cbw);
|
|
2349
2398
|
const endY = Math.min(by + bh, cby + cbh);
|
|
2350
|
-
const
|
|
2351
|
-
const
|
|
2399
|
+
const unclippedStartX = Math.floor(px + minOffset);
|
|
2400
|
+
const unclippedStartY = Math.floor(py + minOffset);
|
|
2352
2401
|
for (let my = startY; my < endY; my++) {
|
|
2353
|
-
const
|
|
2354
|
-
const
|
|
2355
|
-
const
|
|
2402
|
+
const strokeMaskY = my - by;
|
|
2403
|
+
const strokeMaskRowOffset = strokeMaskY * bw;
|
|
2404
|
+
const brushY = my - unclippedStartY;
|
|
2405
|
+
const brushRowOffset = brushY * brushSize;
|
|
2356
2406
|
for (let mx = startX; mx < endX; mx++) {
|
|
2357
|
-
const
|
|
2358
|
-
const
|
|
2359
|
-
if (
|
|
2360
|
-
const
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
if (intensity > mask[maskIdx]) {
|
|
2364
|
-
mask[maskIdx] = intensity;
|
|
2407
|
+
const brushX = mx - unclippedStartX;
|
|
2408
|
+
const brushVal = brushData[brushRowOffset + brushX];
|
|
2409
|
+
if (brushVal > 0) {
|
|
2410
|
+
const strokeMaskIdx = strokeMaskRowOffset + (mx - bx);
|
|
2411
|
+
if (brushVal > maskData[strokeMaskIdx]) {
|
|
2412
|
+
maskData[strokeMaskIdx] = brushVal;
|
|
2365
2413
|
}
|
|
2366
2414
|
}
|
|
2367
2415
|
}
|
|
@@ -2378,71 +2426,6 @@ var mutatorApplyCircleBrushStroke = ((writer, deps = defaults4) => {
|
|
|
2378
2426
|
};
|
|
2379
2427
|
});
|
|
2380
2428
|
|
|
2381
|
-
// src/PixelData/blendColorPixelDataBinaryMask.ts
|
|
2382
|
-
function blendColorPixelDataBinaryMask(dst, color, mask, opts = {}) {
|
|
2383
|
-
const {
|
|
2384
|
-
x: targetX = 0,
|
|
2385
|
-
y: targetY = 0,
|
|
2386
|
-
w: width = dst.width,
|
|
2387
|
-
h: height = dst.height,
|
|
2388
|
-
alpha: globalAlpha = 255,
|
|
2389
|
-
blendFn = sourceOverPerfect,
|
|
2390
|
-
mw = width,
|
|
2391
|
-
mx = 0,
|
|
2392
|
-
my = 0,
|
|
2393
|
-
invertMask = false
|
|
2394
|
-
} = opts;
|
|
2395
|
-
if (globalAlpha === 0 || !mask) return;
|
|
2396
|
-
const baseSrcAlpha = color >>> 24;
|
|
2397
|
-
const isOverwrite = blendFn.isOverwrite || false;
|
|
2398
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2399
|
-
let x = targetX;
|
|
2400
|
-
let y = targetY;
|
|
2401
|
-
let w = width;
|
|
2402
|
-
let h = height;
|
|
2403
|
-
if (x < 0) {
|
|
2404
|
-
w += x;
|
|
2405
|
-
x = 0;
|
|
2406
|
-
}
|
|
2407
|
-
if (y < 0) {
|
|
2408
|
-
h += y;
|
|
2409
|
-
y = 0;
|
|
2410
|
-
}
|
|
2411
|
-
const actualW = Math.min(w, dst.width - x);
|
|
2412
|
-
const actualH = Math.min(h, dst.height - y);
|
|
2413
|
-
if (actualW <= 0 || actualH <= 0) return;
|
|
2414
|
-
let baseColorWithGlobalAlpha = color;
|
|
2415
|
-
if (globalAlpha < 255) {
|
|
2416
|
-
const a = baseSrcAlpha * globalAlpha + 128 >> 8;
|
|
2417
|
-
if (a === 0 && !isOverwrite) return;
|
|
2418
|
-
baseColorWithGlobalAlpha = (color & 16777215 | a << 24) >>> 0;
|
|
2419
|
-
}
|
|
2420
|
-
const dx = x - targetX | 0;
|
|
2421
|
-
const dy = y - targetY | 0;
|
|
2422
|
-
const dst32 = dst.data32;
|
|
2423
|
-
const dw = dst.width;
|
|
2424
|
-
const mPitch = mw;
|
|
2425
|
-
let dIdx = y * dw + x | 0;
|
|
2426
|
-
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
2427
|
-
const dStride = dw - actualW | 0;
|
|
2428
|
-
const mStride = mPitch - actualW | 0;
|
|
2429
|
-
const skipVal = invertMask ? 1 : 0;
|
|
2430
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
2431
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
2432
|
-
if (mask[mIdx] === skipVal) {
|
|
2433
|
-
dIdx++;
|
|
2434
|
-
mIdx++;
|
|
2435
|
-
continue;
|
|
2436
|
-
}
|
|
2437
|
-
dst32[dIdx] = blendFn(baseColorWithGlobalAlpha, dst32[dIdx]);
|
|
2438
|
-
dIdx++;
|
|
2439
|
-
mIdx++;
|
|
2440
|
-
}
|
|
2441
|
-
dIdx += dStride;
|
|
2442
|
-
mIdx += mStride;
|
|
2443
|
-
}
|
|
2444
|
-
}
|
|
2445
|
-
|
|
2446
2429
|
// src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts
|
|
2447
2430
|
var defaults5 = {
|
|
2448
2431
|
forEachLinePoint,
|
|
@@ -2477,19 +2460,25 @@ var mutatorApplyCirclePencilStroke = ((writer, deps = defaults5) => {
|
|
|
2477
2460
|
w: 0,
|
|
2478
2461
|
h: 0
|
|
2479
2462
|
};
|
|
2463
|
+
const mask = {
|
|
2464
|
+
type: 1 /* BINARY */,
|
|
2465
|
+
data: null,
|
|
2466
|
+
w: 0,
|
|
2467
|
+
h: 0
|
|
2468
|
+
};
|
|
2480
2469
|
return {
|
|
2481
|
-
applyCirclePencilStroke(color, x0, y0, x1, y1,
|
|
2470
|
+
applyCirclePencilStroke(color, x0, y0, x1, y1, brush, alpha = 255, blendFn = sourceOverPerfect) {
|
|
2482
2471
|
const {
|
|
2483
2472
|
x: bx,
|
|
2484
2473
|
y: by,
|
|
2485
2474
|
w: bw,
|
|
2486
2475
|
h: bh
|
|
2487
|
-
} = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1,
|
|
2476
|
+
} = getCircleBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brush.size, strokeBoundsOut);
|
|
2488
2477
|
if (bw <= 0 || bh <= 0) return;
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
const
|
|
2478
|
+
mask.data = new Uint8Array(bw * bh);
|
|
2479
|
+
mask.w = bw;
|
|
2480
|
+
mask.h = bh;
|
|
2481
|
+
const maskData = mask.data;
|
|
2493
2482
|
const targetWidth = writer.target.width;
|
|
2494
2483
|
const targetHeight = writer.target.height;
|
|
2495
2484
|
forEachLinePoint2(x0, y0, x1, y1, (px, py) => {
|
|
@@ -2498,24 +2487,24 @@ var mutatorApplyCirclePencilStroke = ((writer, deps = defaults5) => {
|
|
|
2498
2487
|
y: cby,
|
|
2499
2488
|
w: cbw,
|
|
2500
2489
|
h: cbh
|
|
2501
|
-
} = getCircleBrushOrPencilBounds2(px, py,
|
|
2490
|
+
} = getCircleBrushOrPencilBounds2(px, py, brush.size, targetWidth, targetHeight, circlePencilBounds);
|
|
2502
2491
|
writer.accumulator.storeRegionBeforeState(cbx, cby, cbw, cbh);
|
|
2503
|
-
const
|
|
2504
|
-
const
|
|
2505
|
-
const
|
|
2506
|
-
const
|
|
2507
|
-
const
|
|
2508
|
-
const
|
|
2492
|
+
const unclippedStartX = Math.floor(px + brush.minOffset);
|
|
2493
|
+
const unclippedStartY = Math.floor(py + brush.minOffset);
|
|
2494
|
+
const startX = Math.max(bx, unclippedStartX);
|
|
2495
|
+
const startY = Math.max(by, unclippedStartY);
|
|
2496
|
+
const endX = Math.min(bx + bw, unclippedStartX + brush.w);
|
|
2497
|
+
const endY = Math.min(by + bh, unclippedStartY + brush.h);
|
|
2509
2498
|
for (let my = startY; my < endY; my++) {
|
|
2510
|
-
const
|
|
2511
|
-
const dySqr = dy * dy;
|
|
2499
|
+
const brushY = my - unclippedStartY;
|
|
2512
2500
|
const maskRowOffset = (my - by) * bw;
|
|
2501
|
+
const brushRowOffset = brushY * brush.w;
|
|
2513
2502
|
for (let mx = startX; mx < endX; mx++) {
|
|
2514
|
-
const
|
|
2515
|
-
const
|
|
2516
|
-
if (
|
|
2503
|
+
const brushX = mx - unclippedStartX;
|
|
2504
|
+
const brushAlpha = brush.data[brushRowOffset + brushX];
|
|
2505
|
+
if (brushAlpha > 0) {
|
|
2517
2506
|
const maskIdx = maskRowOffset + (mx - bx);
|
|
2518
|
-
|
|
2507
|
+
maskData[maskIdx] = brushAlpha;
|
|
2519
2508
|
}
|
|
2520
2509
|
}
|
|
2521
2510
|
}
|
|
@@ -2682,6 +2671,12 @@ var mutatorApplyRectBrushStroke = ((writer, deps = defaults7) => {
|
|
|
2682
2671
|
w: 0,
|
|
2683
2672
|
h: 0
|
|
2684
2673
|
};
|
|
2674
|
+
const mask = {
|
|
2675
|
+
type: 0 /* ALPHA */,
|
|
2676
|
+
data: null,
|
|
2677
|
+
w: 0,
|
|
2678
|
+
h: 0
|
|
2679
|
+
};
|
|
2685
2680
|
return {
|
|
2686
2681
|
applyRectBrushStroke(color, x0, y0, x1, y1, brushWidth, brushHeight, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
|
|
2687
2682
|
const {
|
|
@@ -2691,7 +2686,10 @@ var mutatorApplyRectBrushStroke = ((writer, deps = defaults7) => {
|
|
|
2691
2686
|
h: bh
|
|
2692
2687
|
} = getRectBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushWidth, brushHeight, strokeBoundsOut);
|
|
2693
2688
|
if (bw <= 0 || bh <= 0) return;
|
|
2694
|
-
|
|
2689
|
+
mask.data = new Uint8Array(bw * bh);
|
|
2690
|
+
mask.w = bw;
|
|
2691
|
+
mask.h = bh;
|
|
2692
|
+
const maskData = mask.data;
|
|
2695
2693
|
const halfW = brushWidth / 2;
|
|
2696
2694
|
const halfH = brushHeight / 2;
|
|
2697
2695
|
const invHalfW = 1 / halfW;
|
|
@@ -2724,8 +2722,8 @@ var mutatorApplyRectBrushStroke = ((writer, deps = defaults7) => {
|
|
|
2724
2722
|
const strength = fallOff(dist);
|
|
2725
2723
|
if (strength > 0) {
|
|
2726
2724
|
const intensity = strength * 255 | 0;
|
|
2727
|
-
if (intensity >
|
|
2728
|
-
|
|
2725
|
+
if (intensity > maskData[maskIdx]) {
|
|
2726
|
+
maskData[maskIdx] = intensity;
|
|
2729
2727
|
}
|
|
2730
2728
|
}
|
|
2731
2729
|
}
|
|
@@ -2809,6 +2807,12 @@ var mutatorApplyRectPencilStroke = ((writer, deps = defaults9) => {
|
|
|
2809
2807
|
w: 0,
|
|
2810
2808
|
h: 0
|
|
2811
2809
|
};
|
|
2810
|
+
const mask = {
|
|
2811
|
+
type: 1 /* BINARY */,
|
|
2812
|
+
data: null,
|
|
2813
|
+
w: 0,
|
|
2814
|
+
h: 0
|
|
2815
|
+
};
|
|
2812
2816
|
return {
|
|
2813
2817
|
applyRectPencilStroke(color, x0, y0, x1, y1, brushWidth, brushHeight, alpha = 255, blendFn = sourceOverPerfect) {
|
|
2814
2818
|
const {
|
|
@@ -2818,7 +2822,10 @@ var mutatorApplyRectPencilStroke = ((writer, deps = defaults9) => {
|
|
|
2818
2822
|
h: bh
|
|
2819
2823
|
} = getRectBrushOrPencilStrokeBounds2(x0, y0, x1, y1, brushWidth, brushHeight, strokeBoundsOut);
|
|
2820
2824
|
if (bw <= 0 || bh <= 0) return;
|
|
2821
|
-
|
|
2825
|
+
mask.data = new Uint8Array(bw * bh);
|
|
2826
|
+
mask.w = bw;
|
|
2827
|
+
mask.h = bh;
|
|
2828
|
+
const maskData = mask.data;
|
|
2822
2829
|
const halfW = brushWidth / 2;
|
|
2823
2830
|
const halfH = brushHeight / 2;
|
|
2824
2831
|
const centerOffset = brushWidth % 2 === 0 ? 0.5 : 0;
|
|
@@ -2845,7 +2852,7 @@ var mutatorApplyRectPencilStroke = ((writer, deps = defaults9) => {
|
|
|
2845
2852
|
const dx = Math.abs(mx - fPx + centerOffset);
|
|
2846
2853
|
const maskIdx = maskRowOffset + (mx - bx);
|
|
2847
2854
|
if (dx <= halfW && dy <= halfH) {
|
|
2848
|
-
|
|
2855
|
+
maskData[maskIdx] = 1;
|
|
2849
2856
|
}
|
|
2850
2857
|
}
|
|
2851
2858
|
}
|
|
@@ -3056,24 +3063,21 @@ var mutatorBlendPixelData = ((writer, deps = defaults11) => {
|
|
|
3056
3063
|
|
|
3057
3064
|
// src/PixelData/fillPixelData.ts
|
|
3058
3065
|
var SCRATCH_RECT = makeClippedRect();
|
|
3059
|
-
function fillPixelData(dst, color, _x, _y, _w, _h
|
|
3066
|
+
function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
3060
3067
|
let x;
|
|
3061
3068
|
let y;
|
|
3062
3069
|
let w;
|
|
3063
3070
|
let h;
|
|
3064
|
-
let mask;
|
|
3065
3071
|
if (typeof _x === "object") {
|
|
3066
3072
|
x = _x.x ?? 0;
|
|
3067
3073
|
y = _x.y ?? 0;
|
|
3068
3074
|
w = _x.w ?? dst.width;
|
|
3069
3075
|
h = _x.h ?? dst.height;
|
|
3070
|
-
mask = _x.mask;
|
|
3071
3076
|
} else if (typeof _x === "number") {
|
|
3072
3077
|
x = _x;
|
|
3073
3078
|
y = _y;
|
|
3074
3079
|
w = _w;
|
|
3075
3080
|
h = _h;
|
|
3076
|
-
mask = _mask;
|
|
3077
3081
|
} else {
|
|
3078
3082
|
x = 0;
|
|
3079
3083
|
y = 0;
|
|
@@ -3094,28 +3098,10 @@ function fillPixelData(dst, color, _x, _y, _w, _h, _mask) {
|
|
|
3094
3098
|
dst32.fill(color);
|
|
3095
3099
|
return;
|
|
3096
3100
|
}
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
const maskOffset = maskY * w;
|
|
3102
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
3103
|
-
const currentX = finalX + ix;
|
|
3104
|
-
const maskX = currentX - x;
|
|
3105
|
-
const maskIndex = maskOffset + maskX;
|
|
3106
|
-
const isMasked = mask[maskIndex];
|
|
3107
|
-
if (isMasked) {
|
|
3108
|
-
const dstIndex = currentY * dw + currentX;
|
|
3109
|
-
dst32[dstIndex] = color;
|
|
3110
|
-
}
|
|
3111
|
-
}
|
|
3112
|
-
}
|
|
3113
|
-
} else {
|
|
3114
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
3115
|
-
const start = (finalY + iy) * dw + finalX;
|
|
3116
|
-
const end = start + actualW;
|
|
3117
|
-
dst32.fill(color, start, end);
|
|
3118
|
-
}
|
|
3101
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
3102
|
+
const start = (finalY + iy) * dw + finalX;
|
|
3103
|
+
const end = start + actualW;
|
|
3104
|
+
dst32.fill(color, start, end);
|
|
3119
3105
|
}
|
|
3120
3106
|
}
|
|
3121
3107
|
|
|
@@ -3129,12 +3115,10 @@ var mutatorClear = ((writer, deps = defaults12) => {
|
|
|
3129
3115
|
} = deps;
|
|
3130
3116
|
return {
|
|
3131
3117
|
clear(rect = {}) {
|
|
3132
|
-
const
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
h = writer.target.height
|
|
3137
|
-
} = rect;
|
|
3118
|
+
const x = rect.x ?? 0;
|
|
3119
|
+
const y = rect.y ?? 0;
|
|
3120
|
+
const w = rect.w ?? writer.target.width;
|
|
3121
|
+
const h = rect.h ?? writer.target.height;
|
|
3138
3122
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3139
3123
|
fillPixelData2(writer.target, 0, x, y, w, h);
|
|
3140
3124
|
}
|
|
@@ -3173,7 +3157,6 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
3173
3157
|
w: width = pixelData.width,
|
|
3174
3158
|
h: height = pixelData.height,
|
|
3175
3159
|
mask,
|
|
3176
|
-
mw,
|
|
3177
3160
|
mx = 0,
|
|
3178
3161
|
my = 0,
|
|
3179
3162
|
invertMask = false
|
|
@@ -3188,7 +3171,7 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
3188
3171
|
} = clip;
|
|
3189
3172
|
const dst32 = dst.data32;
|
|
3190
3173
|
const dw = dst.width;
|
|
3191
|
-
const mPitch =
|
|
3174
|
+
const mPitch = mask?.w ?? width;
|
|
3192
3175
|
const dx = x - targetX;
|
|
3193
3176
|
const dy = y - targetY;
|
|
3194
3177
|
let dIdx = y * dw + x;
|
|
@@ -3196,9 +3179,10 @@ function invertPixelData(pixelData, opts = {}) {
|
|
|
3196
3179
|
const dStride = dw - actualW;
|
|
3197
3180
|
const mStride = mPitch - actualW;
|
|
3198
3181
|
if (mask) {
|
|
3182
|
+
const maskData = mask.data;
|
|
3199
3183
|
for (let iy = 0; iy < actualH; iy++) {
|
|
3200
3184
|
for (let ix = 0; ix < actualW; ix++) {
|
|
3201
|
-
const mVal =
|
|
3185
|
+
const mVal = maskData[mIdx];
|
|
3202
3186
|
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
3203
3187
|
if (isHit) {
|
|
3204
3188
|
dst32[dIdx] = dst32[dIdx] ^ 16777215;
|
|
@@ -3309,14 +3293,12 @@ var PixelWriter = class {
|
|
|
3309
3293
|
// src/History/PixelMutator/mutatorApplyCirclePencil.ts
|
|
3310
3294
|
var defaults15 = {
|
|
3311
3295
|
applyCircleBrushToPixelData,
|
|
3312
|
-
getCircleBrushOrPencilBounds
|
|
3313
|
-
fallOff: () => 1
|
|
3296
|
+
getCircleBrushOrPencilBounds
|
|
3314
3297
|
};
|
|
3315
3298
|
var mutatorApplyCirclePencil = ((writer, deps = defaults15) => {
|
|
3316
3299
|
const {
|
|
3317
3300
|
applyCircleBrushToPixelData: applyCircleBrushToPixelData2 = defaults15.applyCircleBrushToPixelData,
|
|
3318
|
-
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults15.getCircleBrushOrPencilBounds
|
|
3319
|
-
fallOff = defaults15.fallOff
|
|
3301
|
+
getCircleBrushOrPencilBounds: getCircleBrushOrPencilBounds2 = defaults15.getCircleBrushOrPencilBounds
|
|
3320
3302
|
} = deps;
|
|
3321
3303
|
const boundsOut = {
|
|
3322
3304
|
x: 0,
|
|
@@ -3325,8 +3307,8 @@ var mutatorApplyCirclePencil = ((writer, deps = defaults15) => {
|
|
|
3325
3307
|
h: 0
|
|
3326
3308
|
};
|
|
3327
3309
|
return {
|
|
3328
|
-
applyCirclePencil(color, centerX, centerY,
|
|
3329
|
-
const bounds = getCircleBrushOrPencilBounds2(centerX, centerY,
|
|
3310
|
+
applyCirclePencil(color, centerX, centerY, brush, alpha = 255, blendFn) {
|
|
3311
|
+
const bounds = getCircleBrushOrPencilBounds2(centerX, centerY, brush.size, writer.target.width, writer.target.height, boundsOut);
|
|
3330
3312
|
const {
|
|
3331
3313
|
x,
|
|
3332
3314
|
y,
|
|
@@ -3334,7 +3316,63 @@ var mutatorApplyCirclePencil = ((writer, deps = defaults15) => {
|
|
|
3334
3316
|
h
|
|
3335
3317
|
} = bounds;
|
|
3336
3318
|
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
3337
|
-
applyCircleBrushToPixelData2(writer.target, color, centerX, centerY,
|
|
3319
|
+
applyCircleBrushToPixelData2(writer.target, color, centerX, centerY, brush, alpha, blendFn, bounds);
|
|
3320
|
+
}
|
|
3321
|
+
};
|
|
3322
|
+
});
|
|
3323
|
+
|
|
3324
|
+
// src/PixelData/fillPixelDataBinaryMask.ts
|
|
3325
|
+
var SCRATCH_RECT3 = makeClippedRect();
|
|
3326
|
+
function fillPixelDataBinaryMask(dst, color, mask, alpha = 255, x = 0, y = 0) {
|
|
3327
|
+
if (alpha === 0) return;
|
|
3328
|
+
const maskW = mask.w;
|
|
3329
|
+
const maskH = mask.h;
|
|
3330
|
+
const clip = resolveRectClipping(x, y, maskW, maskH, dst.width, dst.height, SCRATCH_RECT3);
|
|
3331
|
+
if (!clip.inBounds) return;
|
|
3332
|
+
const {
|
|
3333
|
+
x: finalX,
|
|
3334
|
+
y: finalY,
|
|
3335
|
+
w: actualW,
|
|
3336
|
+
h: actualH
|
|
3337
|
+
} = clip;
|
|
3338
|
+
const maskData = mask.data;
|
|
3339
|
+
const dst32 = dst.data32;
|
|
3340
|
+
const dw = dst.width;
|
|
3341
|
+
let finalCol = color;
|
|
3342
|
+
if (alpha < 255) {
|
|
3343
|
+
const baseSrcAlpha = color >>> 24;
|
|
3344
|
+
const colorRGB = color & 16777215;
|
|
3345
|
+
const a = baseSrcAlpha * alpha + 128 >> 8;
|
|
3346
|
+
finalCol = (colorRGB | a << 24) >>> 0;
|
|
3347
|
+
}
|
|
3348
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
3349
|
+
const currentY = finalY + iy;
|
|
3350
|
+
const maskY = currentY - y;
|
|
3351
|
+
const maskOffset = maskY * maskW;
|
|
3352
|
+
const dstRowOffset = currentY * dw;
|
|
3353
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
3354
|
+
const currentX = finalX + ix;
|
|
3355
|
+
const maskX = currentX - x;
|
|
3356
|
+
const maskIndex = maskOffset + maskX;
|
|
3357
|
+
if (maskData[maskIndex]) {
|
|
3358
|
+
dst32[dstRowOffset + currentX] = finalCol;
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
|
|
3364
|
+
// src/History/PixelMutator/mutatorFillBinaryMask.ts
|
|
3365
|
+
var defaults16 = {
|
|
3366
|
+
fillPixelDataBinaryMask
|
|
3367
|
+
};
|
|
3368
|
+
var mutatorFillBinaryMask = ((writer, deps = defaults16) => {
|
|
3369
|
+
const {
|
|
3370
|
+
fillPixelDataBinaryMask: fillPixelDataBinaryMask2 = defaults16.fillPixelDataBinaryMask
|
|
3371
|
+
} = deps;
|
|
3372
|
+
return {
|
|
3373
|
+
fillBinaryMask(color, mask, alpha = 255, x = 0, y = 0) {
|
|
3374
|
+
writer.accumulator.storeRegionBeforeState(x, y, mask.w, mask.h);
|
|
3375
|
+
fillPixelDataBinaryMask2(writer.target, color, mask, alpha, x, y);
|
|
3338
3376
|
}
|
|
3339
3377
|
};
|
|
3340
3378
|
});
|
|
@@ -3370,8 +3408,8 @@ function makeImageDataLike(width, height, data) {
|
|
|
3370
3408
|
};
|
|
3371
3409
|
}
|
|
3372
3410
|
|
|
3373
|
-
// src/ImageData/
|
|
3374
|
-
function
|
|
3411
|
+
// src/ImageData/imageDataToAlphaMaskBuffer.ts
|
|
3412
|
+
function imageDataToAlphaMaskBuffer(imageData) {
|
|
3375
3413
|
const {
|
|
3376
3414
|
width,
|
|
3377
3415
|
height,
|
|
@@ -3461,13 +3499,13 @@ function resampleImageData(source, factor) {
|
|
|
3461
3499
|
}
|
|
3462
3500
|
|
|
3463
3501
|
// src/ImageData/resizeImageData.ts
|
|
3464
|
-
function resizeImageData(
|
|
3502
|
+
function resizeImageData(target, newWidth, newHeight, offsetX = 0, offsetY = 0) {
|
|
3465
3503
|
const result = new ImageData(newWidth, newHeight);
|
|
3466
3504
|
const {
|
|
3467
3505
|
width: oldW,
|
|
3468
3506
|
height: oldH,
|
|
3469
3507
|
data: oldData
|
|
3470
|
-
} =
|
|
3508
|
+
} = target;
|
|
3471
3509
|
const newData = result.data;
|
|
3472
3510
|
const x0 = Math.max(0, offsetX);
|
|
3473
3511
|
const y0 = Math.max(0, offsetY);
|
|
@@ -3622,7 +3660,7 @@ function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width,
|
|
|
3622
3660
|
|
|
3623
3661
|
// src/ImageData/writeImageDataBuffer.ts
|
|
3624
3662
|
var SCRATCH_BLIT3 = makeClippedBlit();
|
|
3625
|
-
function writeImageDataBuffer(
|
|
3663
|
+
function writeImageDataBuffer(target, data, _x, _y, _w, _h) {
|
|
3626
3664
|
const {
|
|
3627
3665
|
x,
|
|
3628
3666
|
y,
|
|
@@ -3638,7 +3676,7 @@ function writeImageDataBuffer(imageData, data, _x, _y, _w, _h) {
|
|
|
3638
3676
|
width: dstW,
|
|
3639
3677
|
height: dstH,
|
|
3640
3678
|
data: dst
|
|
3641
|
-
} =
|
|
3679
|
+
} = target;
|
|
3642
3680
|
const clip = resolveBlitClipping(x, y, 0, 0, w, h, dstW, dstH, w, h, SCRATCH_BLIT3);
|
|
3643
3681
|
if (!clip.inBounds) return;
|
|
3644
3682
|
const {
|
|
@@ -3884,8 +3922,84 @@ async function getSupportedPixelFormats(rasterMimes = defaultRasterMimes) {
|
|
|
3884
3922
|
return formatsPromise;
|
|
3885
3923
|
}
|
|
3886
3924
|
|
|
3925
|
+
// src/Mask/AlphaMask.ts
|
|
3926
|
+
function makeAlphaMask(w, h, data) {
|
|
3927
|
+
return {
|
|
3928
|
+
type: 0 /* ALPHA */,
|
|
3929
|
+
data: data ?? new Uint8Array(w * h),
|
|
3930
|
+
w,
|
|
3931
|
+
h
|
|
3932
|
+
};
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3935
|
+
// src/Mask/BinaryMask.ts
|
|
3936
|
+
function makeBinaryMask(w, h, data) {
|
|
3937
|
+
return {
|
|
3938
|
+
type: 1 /* BINARY */,
|
|
3939
|
+
data: data ?? new Uint8Array(w * h),
|
|
3940
|
+
w,
|
|
3941
|
+
h
|
|
3942
|
+
};
|
|
3943
|
+
}
|
|
3944
|
+
|
|
3945
|
+
// src/Mask/CircleBrushAlphaMask.ts
|
|
3946
|
+
function makeCircleBrushAlphaMask(size, fallOff = () => 1) {
|
|
3947
|
+
const area = size * size;
|
|
3948
|
+
const data = new Uint8Array(area);
|
|
3949
|
+
const radius = size / 2;
|
|
3950
|
+
const invR = 1 / radius;
|
|
3951
|
+
const minOffset = -Math.ceil(radius - 0.5);
|
|
3952
|
+
for (let y = 0; y < size; y++) {
|
|
3953
|
+
for (let x = 0; x < size; x++) {
|
|
3954
|
+
const dx = x - radius + 0.5;
|
|
3955
|
+
const dy = y - radius + 0.5;
|
|
3956
|
+
const distSqr = dx * dx + dy * dy;
|
|
3957
|
+
if (distSqr <= radius * radius) {
|
|
3958
|
+
const dist = Math.sqrt(distSqr);
|
|
3959
|
+
data[y * size + x] = fallOff(1 - dist * invR) * 255 | 0;
|
|
3960
|
+
}
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
return {
|
|
3964
|
+
type: 0 /* ALPHA */,
|
|
3965
|
+
data,
|
|
3966
|
+
w: size,
|
|
3967
|
+
h: size,
|
|
3968
|
+
radius,
|
|
3969
|
+
size,
|
|
3970
|
+
minOffset
|
|
3971
|
+
};
|
|
3972
|
+
}
|
|
3973
|
+
|
|
3974
|
+
// src/Mask/CircleBrushBinaryMask.ts
|
|
3975
|
+
function makeCircleBrushBinaryMask(size) {
|
|
3976
|
+
const area = size * size;
|
|
3977
|
+
const data = new Uint8Array(area);
|
|
3978
|
+
const radius = size / 2;
|
|
3979
|
+
const minOffset = -Math.ceil(radius - 0.5);
|
|
3980
|
+
for (let y = 0; y < size; y++) {
|
|
3981
|
+
for (let x = 0; x < size; x++) {
|
|
3982
|
+
const dx = x - radius + 0.5;
|
|
3983
|
+
const dy = y - radius + 0.5;
|
|
3984
|
+
const distSqr = dx * dx + dy * dy;
|
|
3985
|
+
if (distSqr <= radius * radius) {
|
|
3986
|
+
data[y * size + x] = 1;
|
|
3987
|
+
}
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
return {
|
|
3991
|
+
type: 1 /* BINARY */,
|
|
3992
|
+
data,
|
|
3993
|
+
w: size,
|
|
3994
|
+
h: size,
|
|
3995
|
+
radius,
|
|
3996
|
+
size,
|
|
3997
|
+
minOffset
|
|
3998
|
+
};
|
|
3999
|
+
}
|
|
4000
|
+
|
|
3887
4001
|
// src/Mask/applyBinaryMaskToAlphaMask.ts
|
|
3888
|
-
function applyBinaryMaskToAlphaMask(alphaMaskDst,
|
|
4002
|
+
function applyBinaryMaskToAlphaMask(alphaMaskDst, binaryMaskSrc, opts = {}) {
|
|
3889
4003
|
const {
|
|
3890
4004
|
x: targetX = 0,
|
|
3891
4005
|
y: targetY = 0,
|
|
@@ -3895,11 +4009,13 @@ function applyBinaryMaskToAlphaMask(alphaMaskDst, dstWidth, binaryMaskSrc, srcWi
|
|
|
3895
4009
|
my = 0,
|
|
3896
4010
|
invertMask = false
|
|
3897
4011
|
} = opts;
|
|
4012
|
+
const dstWidth = alphaMaskDst.w;
|
|
3898
4013
|
if (dstWidth <= 0) return;
|
|
3899
|
-
if (binaryMaskSrc.length === 0) return;
|
|
4014
|
+
if (binaryMaskSrc.data.length === 0) return;
|
|
4015
|
+
const srcWidth = binaryMaskSrc.w;
|
|
3900
4016
|
if (srcWidth <= 0) return;
|
|
3901
|
-
const dstHeight = alphaMaskDst.length / dstWidth | 0;
|
|
3902
|
-
const srcHeight = binaryMaskSrc.length / srcWidth | 0;
|
|
4017
|
+
const dstHeight = alphaMaskDst.data.length / dstWidth | 0;
|
|
4018
|
+
const srcHeight = binaryMaskSrc.data.length / srcWidth | 0;
|
|
3903
4019
|
if (dstHeight <= 0) return;
|
|
3904
4020
|
if (srcHeight <= 0) return;
|
|
3905
4021
|
const dstX0 = Math.max(0, targetX);
|
|
@@ -3916,6 +4032,8 @@ function applyBinaryMaskToAlphaMask(alphaMaskDst, dstWidth, binaryMaskSrc, srcWi
|
|
|
3916
4032
|
if (srcY0 + (dstY1 - dstY0) <= 0) return;
|
|
3917
4033
|
const iterW = Math.min(dstX1 - dstX0, srcWidth - srcX0);
|
|
3918
4034
|
const iterH = Math.min(dstY1 - dstY0, srcHeight - srcY0);
|
|
4035
|
+
const srcData = binaryMaskSrc.data;
|
|
4036
|
+
const dstData = alphaMaskDst.data;
|
|
3919
4037
|
let dstIdx = dstY0 * dstWidth + dstX0;
|
|
3920
4038
|
let srcIdx = srcY0 * srcWidth + srcX0;
|
|
3921
4039
|
if (invertMask) {
|
|
@@ -3924,8 +4042,8 @@ function applyBinaryMaskToAlphaMask(alphaMaskDst, dstWidth, binaryMaskSrc, srcWi
|
|
|
3924
4042
|
let d = dstIdx;
|
|
3925
4043
|
let s = srcIdx;
|
|
3926
4044
|
while (d < dstEnd) {
|
|
3927
|
-
if (
|
|
3928
|
-
|
|
4045
|
+
if (srcData[s] !== 0) {
|
|
4046
|
+
dstData[d] = 0;
|
|
3929
4047
|
}
|
|
3930
4048
|
d++;
|
|
3931
4049
|
s++;
|
|
@@ -3939,8 +4057,8 @@ function applyBinaryMaskToAlphaMask(alphaMaskDst, dstWidth, binaryMaskSrc, srcWi
|
|
|
3939
4057
|
let d = dstIdx;
|
|
3940
4058
|
let s = srcIdx;
|
|
3941
4059
|
while (d < dstEnd) {
|
|
3942
|
-
if (
|
|
3943
|
-
|
|
4060
|
+
if (srcData[s] === 0) {
|
|
4061
|
+
dstData[d] = 0;
|
|
3944
4062
|
}
|
|
3945
4063
|
d++;
|
|
3946
4064
|
s++;
|
|
@@ -3953,25 +4071,72 @@ function applyBinaryMaskToAlphaMask(alphaMaskDst, dstWidth, binaryMaskSrc, srcWi
|
|
|
3953
4071
|
|
|
3954
4072
|
// src/Mask/copyMask.ts
|
|
3955
4073
|
function copyMask(src) {
|
|
3956
|
-
return
|
|
4074
|
+
return {
|
|
4075
|
+
type: src.type,
|
|
4076
|
+
data: src.data.slice(),
|
|
4077
|
+
w: src.w,
|
|
4078
|
+
h: src.h
|
|
4079
|
+
};
|
|
4080
|
+
}
|
|
4081
|
+
|
|
4082
|
+
// src/Mask/extractMask.ts
|
|
4083
|
+
function extractMask(mask, xOrRect, y, w, h) {
|
|
4084
|
+
let finalX;
|
|
4085
|
+
let finalY;
|
|
4086
|
+
let finalW;
|
|
4087
|
+
let finalH;
|
|
4088
|
+
if (typeof xOrRect === "object") {
|
|
4089
|
+
finalX = xOrRect.x;
|
|
4090
|
+
finalY = xOrRect.y;
|
|
4091
|
+
finalW = xOrRect.w;
|
|
4092
|
+
finalH = xOrRect.h;
|
|
4093
|
+
} else {
|
|
4094
|
+
finalX = xOrRect;
|
|
4095
|
+
finalY = y;
|
|
4096
|
+
finalW = w;
|
|
4097
|
+
finalH = h;
|
|
4098
|
+
}
|
|
4099
|
+
const out = {
|
|
4100
|
+
type: mask.type,
|
|
4101
|
+
w: finalW,
|
|
4102
|
+
h: finalH,
|
|
4103
|
+
data: new Uint8Array(finalW * finalH)
|
|
4104
|
+
};
|
|
4105
|
+
const srcH = mask.h;
|
|
4106
|
+
const stride = mask.w;
|
|
4107
|
+
for (let row = 0; row < finalH; row++) {
|
|
4108
|
+
const currentSrcY = finalY + row;
|
|
4109
|
+
if (currentSrcY < 0 || currentSrcY >= srcH) continue;
|
|
4110
|
+
const start = Math.max(0, finalX);
|
|
4111
|
+
const end = Math.min(stride, finalX + finalW);
|
|
4112
|
+
if (start < end) {
|
|
4113
|
+
const srcOffset = currentSrcY * stride + start;
|
|
4114
|
+
const dstOffset = row * finalW + (start - finalX);
|
|
4115
|
+
const count = end - start;
|
|
4116
|
+
out.data.set(mask.data.subarray(srcOffset, srcOffset + count), dstOffset);
|
|
4117
|
+
}
|
|
4118
|
+
}
|
|
4119
|
+
return out;
|
|
3957
4120
|
}
|
|
3958
4121
|
|
|
3959
4122
|
// src/Mask/invertMask.ts
|
|
3960
4123
|
function invertBinaryMask(dst) {
|
|
3961
|
-
const
|
|
4124
|
+
const data = dst.data;
|
|
4125
|
+
const len = data.length;
|
|
3962
4126
|
for (let i = 0; i < len; i++) {
|
|
3963
|
-
|
|
4127
|
+
data[i] = data[i] === 0 ? 1 : 0;
|
|
3964
4128
|
}
|
|
3965
4129
|
}
|
|
3966
4130
|
function invertAlphaMask(dst) {
|
|
3967
|
-
const
|
|
4131
|
+
const data = dst.data;
|
|
4132
|
+
const len = data.length;
|
|
3968
4133
|
for (let i = 0; i < len; i++) {
|
|
3969
|
-
|
|
4134
|
+
data[i] = 255 - data[i];
|
|
3970
4135
|
}
|
|
3971
4136
|
}
|
|
3972
4137
|
|
|
3973
4138
|
// src/Mask/mergeAlphaMasks.ts
|
|
3974
|
-
function mergeAlphaMasks(dst,
|
|
4139
|
+
function mergeAlphaMasks(dst, src, opts) {
|
|
3975
4140
|
const {
|
|
3976
4141
|
x: targetX = 0,
|
|
3977
4142
|
y: targetY = 0,
|
|
@@ -3982,15 +4147,17 @@ function mergeAlphaMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
|
3982
4147
|
my = 0,
|
|
3983
4148
|
invertMask = false
|
|
3984
4149
|
} = opts;
|
|
3985
|
-
const dstHeight = dst.length / dstWidth | 0;
|
|
3986
|
-
const srcHeight = src.length / srcWidth | 0;
|
|
3987
4150
|
if (width <= 0) return;
|
|
3988
4151
|
if (height <= 0) return;
|
|
3989
4152
|
if (globalAlpha === 0) return;
|
|
4153
|
+
const dstData = dst.data;
|
|
4154
|
+
const srcData = src.data;
|
|
4155
|
+
const srcWidth = src.w;
|
|
4156
|
+
const dstWidth = dst.w;
|
|
3990
4157
|
const startX = Math.max(0, -targetX, -mx);
|
|
3991
4158
|
const startY = Math.max(0, -targetY, -my);
|
|
3992
4159
|
const endX = Math.min(width, dstWidth - targetX, srcWidth - mx);
|
|
3993
|
-
const endY = Math.min(height,
|
|
4160
|
+
const endY = Math.min(height, dst.h - targetY, src.h - my);
|
|
3994
4161
|
if (startX >= endX) return;
|
|
3995
4162
|
if (startY >= endY) return;
|
|
3996
4163
|
for (let iy = startY; iy < endY; iy++) {
|
|
@@ -3999,7 +4166,7 @@ function mergeAlphaMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
|
3999
4166
|
let dIdx = dy * dstWidth + targetX + startX;
|
|
4000
4167
|
let sIdx = sy * srcWidth + mx + startX;
|
|
4001
4168
|
for (let ix = startX; ix < endX; ix++) {
|
|
4002
|
-
const rawM =
|
|
4169
|
+
const rawM = srcData[sIdx];
|
|
4003
4170
|
const effectiveM = invertMask ? 255 - rawM : rawM;
|
|
4004
4171
|
let weight = 0;
|
|
4005
4172
|
if (effectiveM === 0) {
|
|
@@ -4013,13 +4180,13 @@ function mergeAlphaMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
|
4013
4180
|
}
|
|
4014
4181
|
if (weight !== 255) {
|
|
4015
4182
|
if (weight === 0) {
|
|
4016
|
-
|
|
4183
|
+
dstData[dIdx] = 0;
|
|
4017
4184
|
} else {
|
|
4018
|
-
const da =
|
|
4185
|
+
const da = dstData[dIdx];
|
|
4019
4186
|
if (da === 255) {
|
|
4020
|
-
|
|
4187
|
+
dstData[dIdx] = weight;
|
|
4021
4188
|
} else if (da !== 0) {
|
|
4022
|
-
|
|
4189
|
+
dstData[dIdx] = da * weight + 128 >> 8;
|
|
4023
4190
|
}
|
|
4024
4191
|
}
|
|
4025
4192
|
}
|
|
@@ -4030,7 +4197,7 @@ function mergeAlphaMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
|
4030
4197
|
}
|
|
4031
4198
|
|
|
4032
4199
|
// src/Mask/mergeBinaryMasks.ts
|
|
4033
|
-
function mergeBinaryMasks(dst,
|
|
4200
|
+
function mergeBinaryMasks(dst, src, opts) {
|
|
4034
4201
|
const {
|
|
4035
4202
|
x: targetX = 0,
|
|
4036
4203
|
y: targetY = 0,
|
|
@@ -4040,10 +4207,12 @@ function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
|
4040
4207
|
my = 0,
|
|
4041
4208
|
invertMask = false
|
|
4042
4209
|
} = opts;
|
|
4210
|
+
const dstData = dst.data;
|
|
4211
|
+
const srcData = src.data;
|
|
4212
|
+
const srcWidth = src.w;
|
|
4213
|
+
const dstWidth = dst.w;
|
|
4043
4214
|
if (dstWidth <= 0) return;
|
|
4044
4215
|
if (srcWidth <= 0) return;
|
|
4045
|
-
const dstHeight = dst.length / dstWidth | 0;
|
|
4046
|
-
const srcHeight = src.length / srcWidth | 0;
|
|
4047
4216
|
let x = targetX;
|
|
4048
4217
|
let y = targetY;
|
|
4049
4218
|
let w = width;
|
|
@@ -4057,7 +4226,7 @@ function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
|
4057
4226
|
y = 0;
|
|
4058
4227
|
}
|
|
4059
4228
|
w = Math.min(w, dstWidth - x);
|
|
4060
|
-
h = Math.min(h,
|
|
4229
|
+
h = Math.min(h, dst.h - y);
|
|
4061
4230
|
if (w <= 0) return;
|
|
4062
4231
|
if (h <= 0) return;
|
|
4063
4232
|
const startX = mx + (x - targetX);
|
|
@@ -4065,7 +4234,7 @@ function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
|
4065
4234
|
const sX0 = Math.max(0, startX);
|
|
4066
4235
|
const sY0 = Math.max(0, startY);
|
|
4067
4236
|
const sX1 = Math.min(srcWidth, startX + w);
|
|
4068
|
-
const sY1 = Math.min(
|
|
4237
|
+
const sY1 = Math.min(src.h, startY + h);
|
|
4069
4238
|
const finalW = sX1 - sX0;
|
|
4070
4239
|
const finalH = sY1 - sY0;
|
|
4071
4240
|
if (finalW <= 0) return;
|
|
@@ -4078,10 +4247,10 @@ function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
|
4078
4247
|
let sIdx = sY0 * srcWidth + sX0;
|
|
4079
4248
|
for (let iy = 0; iy < finalH; iy++) {
|
|
4080
4249
|
for (let ix = 0; ix < finalW; ix++) {
|
|
4081
|
-
const mVal =
|
|
4250
|
+
const mVal = srcData[sIdx];
|
|
4082
4251
|
const isMaskedOut = invertMask ? mVal !== 0 : mVal === 0;
|
|
4083
4252
|
if (isMaskedOut) {
|
|
4084
|
-
|
|
4253
|
+
dstData[dIdx] = 0;
|
|
4085
4254
|
}
|
|
4086
4255
|
dIdx++;
|
|
4087
4256
|
sIdx++;
|
|
@@ -4091,6 +4260,177 @@ function mergeBinaryMasks(dst, dstWidth, src, srcWidth, opts) {
|
|
|
4091
4260
|
}
|
|
4092
4261
|
}
|
|
4093
4262
|
|
|
4263
|
+
// src/Mask/setMaskData.ts
|
|
4264
|
+
function setMaskData(mask, width, height, data) {
|
|
4265
|
+
;
|
|
4266
|
+
mask.w = width;
|
|
4267
|
+
mask.h = height;
|
|
4268
|
+
mask.data = data;
|
|
4269
|
+
}
|
|
4270
|
+
|
|
4271
|
+
// src/MaskRect/subtractBinaryMaskRects.ts
|
|
4272
|
+
function subtractBinaryMaskRects(current, subtracting) {
|
|
4273
|
+
let result = [...current];
|
|
4274
|
+
for (const sub of subtracting) {
|
|
4275
|
+
const next = [];
|
|
4276
|
+
for (const r of result) {
|
|
4277
|
+
const ix = Math.max(r.x, sub.x);
|
|
4278
|
+
const iy = Math.max(r.y, sub.y);
|
|
4279
|
+
const ix2 = Math.min(r.x + r.w, sub.x + sub.w);
|
|
4280
|
+
const iy2 = Math.min(r.y + r.h, sub.y + sub.h);
|
|
4281
|
+
if (ix >= ix2 || iy >= iy2) {
|
|
4282
|
+
next.push(r);
|
|
4283
|
+
continue;
|
|
4284
|
+
}
|
|
4285
|
+
if (r.y < iy) pushPiece(next, r, r.x, r.y, r.w, iy - r.y);
|
|
4286
|
+
if (iy2 < r.y + r.h) pushPiece(next, r, r.x, iy2, r.w, r.y + r.h - iy2);
|
|
4287
|
+
if (r.x < ix) pushPiece(next, r, r.x, iy, ix - r.x, iy2 - iy);
|
|
4288
|
+
if (ix2 < r.x + r.w) pushPiece(next, r, ix2, iy, r.x + r.w - ix2, iy2 - iy);
|
|
4289
|
+
}
|
|
4290
|
+
result = next;
|
|
4291
|
+
}
|
|
4292
|
+
return result;
|
|
4293
|
+
}
|
|
4294
|
+
function pushPiece(dest, r, x, y, w, h) {
|
|
4295
|
+
if (r.data === null || r.data === void 0) {
|
|
4296
|
+
dest.push({
|
|
4297
|
+
x,
|
|
4298
|
+
y,
|
|
4299
|
+
w,
|
|
4300
|
+
h,
|
|
4301
|
+
data: null,
|
|
4302
|
+
type: null
|
|
4303
|
+
});
|
|
4304
|
+
return;
|
|
4305
|
+
}
|
|
4306
|
+
const lx = x - r.x;
|
|
4307
|
+
const ly = y - r.y;
|
|
4308
|
+
const data = new Uint8Array(w * h);
|
|
4309
|
+
for (let row = 0; row < h; row++) {
|
|
4310
|
+
data.set(r.data.subarray((ly + row) * r.w + lx, (ly + row) * r.w + lx + w), row * w);
|
|
4311
|
+
}
|
|
4312
|
+
dest.push({
|
|
4313
|
+
x,
|
|
4314
|
+
y,
|
|
4315
|
+
w,
|
|
4316
|
+
h,
|
|
4317
|
+
data,
|
|
4318
|
+
type: 1 /* BINARY */
|
|
4319
|
+
});
|
|
4320
|
+
}
|
|
4321
|
+
|
|
4322
|
+
// src/Rect/getRectsBounds.ts
|
|
4323
|
+
function getRectsBounds(rects) {
|
|
4324
|
+
if (rects.length === 1) return {
|
|
4325
|
+
...rects[0]
|
|
4326
|
+
};
|
|
4327
|
+
let minX = Infinity, minY = Infinity;
|
|
4328
|
+
let maxX = -Infinity, maxY = -Infinity;
|
|
4329
|
+
for (let i = 0; i < rects.length; i++) {
|
|
4330
|
+
const r = rects[i];
|
|
4331
|
+
const x1 = r.x;
|
|
4332
|
+
const y1 = r.y;
|
|
4333
|
+
const x2 = x1 + r.w;
|
|
4334
|
+
const y2 = y1 + r.h;
|
|
4335
|
+
if (x1 < minX) minX = x1;
|
|
4336
|
+
if (y1 < minY) minY = y1;
|
|
4337
|
+
if (x2 > maxX) maxX = x2;
|
|
4338
|
+
if (y2 > maxY) maxY = y2;
|
|
4339
|
+
}
|
|
4340
|
+
return {
|
|
4341
|
+
x: minX,
|
|
4342
|
+
y: minY,
|
|
4343
|
+
w: maxX - minX,
|
|
4344
|
+
h: maxY - minY
|
|
4345
|
+
};
|
|
4346
|
+
}
|
|
4347
|
+
|
|
4348
|
+
// src/MaskRect/merge2BinaryMaskRects.ts
|
|
4349
|
+
function merge2BinaryMaskRects(a, b) {
|
|
4350
|
+
const bounds = getRectsBounds([a, b]);
|
|
4351
|
+
if ((a.data === null || a.data === void 0) && (b.data === null || b.data === void 0)) {
|
|
4352
|
+
const ix = Math.max(a.x, b.x);
|
|
4353
|
+
const iy = Math.max(a.y, b.y);
|
|
4354
|
+
const ir = Math.min(a.x + a.w, b.x + b.w);
|
|
4355
|
+
const ib = Math.min(a.y + a.h, b.y + b.h);
|
|
4356
|
+
const iw = Math.max(0, ir - ix);
|
|
4357
|
+
const ih = Math.max(0, ib - iy);
|
|
4358
|
+
const intersectionArea = iw * ih;
|
|
4359
|
+
const areaA = a.w * a.h;
|
|
4360
|
+
const areaB = b.w * b.h;
|
|
4361
|
+
const boundsArea = bounds.w * bounds.h;
|
|
4362
|
+
if (boundsArea === areaA + areaB - intersectionArea) {
|
|
4363
|
+
return {
|
|
4364
|
+
...bounds,
|
|
4365
|
+
data: null,
|
|
4366
|
+
type: null
|
|
4367
|
+
};
|
|
4368
|
+
}
|
|
4369
|
+
}
|
|
4370
|
+
const maskData = new Uint8Array(bounds.w * bounds.h);
|
|
4371
|
+
const aOffY = a.y - bounds.y;
|
|
4372
|
+
const aOffX = a.x - bounds.x;
|
|
4373
|
+
if (a.data === void 0 || a.data === null) {
|
|
4374
|
+
for (let ay = 0; ay < a.h; ay++) {
|
|
4375
|
+
const destRow = (aOffY + ay) * bounds.w + aOffX;
|
|
4376
|
+
maskData.fill(1, destRow, destRow + a.w);
|
|
4377
|
+
}
|
|
4378
|
+
} else {
|
|
4379
|
+
for (let ay = 0; ay < a.h; ay++) {
|
|
4380
|
+
const srcRow = ay * a.w;
|
|
4381
|
+
const destRow = (aOffY + ay) * bounds.w + aOffX;
|
|
4382
|
+
maskData.set(a.data.subarray(srcRow, srcRow + a.w), destRow);
|
|
4383
|
+
}
|
|
4384
|
+
}
|
|
4385
|
+
const bOffY = b.y - bounds.y;
|
|
4386
|
+
const bOffX = b.x - bounds.x;
|
|
4387
|
+
if (b.data === void 0 || b.data === null) {
|
|
4388
|
+
for (let by = 0; by < b.h; by++) {
|
|
4389
|
+
const destRow = (bOffY + by) * bounds.w + bOffX;
|
|
4390
|
+
maskData.fill(1, destRow, destRow + b.w);
|
|
4391
|
+
}
|
|
4392
|
+
} else {
|
|
4393
|
+
for (let by = 0; by < b.h; by++) {
|
|
4394
|
+
const srcRow = by * b.w;
|
|
4395
|
+
const destRow = (bOffY + by) * bounds.w + bOffX;
|
|
4396
|
+
for (let bx = 0; bx < b.w; bx++) {
|
|
4397
|
+
maskData[destRow + bx] |= b.data[srcRow + bx];
|
|
4398
|
+
}
|
|
4399
|
+
}
|
|
4400
|
+
}
|
|
4401
|
+
return {
|
|
4402
|
+
...bounds,
|
|
4403
|
+
data: maskData,
|
|
4404
|
+
type: 1 /* BINARY */
|
|
4405
|
+
};
|
|
4406
|
+
}
|
|
4407
|
+
|
|
4408
|
+
// src/MaskRect/mergeBinaryMaskRects.ts
|
|
4409
|
+
function mergeBinaryMaskRects(current, adding) {
|
|
4410
|
+
const rects = [...current, ...adding];
|
|
4411
|
+
let changed = true;
|
|
4412
|
+
while (changed) {
|
|
4413
|
+
changed = false;
|
|
4414
|
+
const next = [];
|
|
4415
|
+
for (const r of rects) {
|
|
4416
|
+
let merged = false;
|
|
4417
|
+
for (let i = 0; i < next.length; i++) {
|
|
4418
|
+
const n = next[i];
|
|
4419
|
+
const overlap = r.x <= n.x + n.w && r.x + r.w >= n.x && r.y <= n.y + n.h && r.y + r.h >= n.y;
|
|
4420
|
+
if (overlap) {
|
|
4421
|
+
next[i] = merge2BinaryMaskRects(n, r);
|
|
4422
|
+
merged = true;
|
|
4423
|
+
changed = true;
|
|
4424
|
+
break;
|
|
4425
|
+
}
|
|
4426
|
+
}
|
|
4427
|
+
if (!merged) next.push(r);
|
|
4428
|
+
}
|
|
4429
|
+
rects.splice(0, rects.length, ...next);
|
|
4430
|
+
}
|
|
4431
|
+
return rects;
|
|
4432
|
+
}
|
|
4433
|
+
|
|
4094
4434
|
// src/PixelData/PixelData.ts
|
|
4095
4435
|
var PixelData = class _PixelData {
|
|
4096
4436
|
data32;
|
|
@@ -4142,7 +4482,6 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
4142
4482
|
h: height = src.height,
|
|
4143
4483
|
alpha: globalAlpha = 255,
|
|
4144
4484
|
blendFn = sourceOverPerfect,
|
|
4145
|
-
mw = src.width,
|
|
4146
4485
|
mx = 0,
|
|
4147
4486
|
my = 0,
|
|
4148
4487
|
invertMask = false
|
|
@@ -4181,7 +4520,8 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
4181
4520
|
if (actualW <= 0 || actualH <= 0) return;
|
|
4182
4521
|
const dw = dst.width;
|
|
4183
4522
|
const sw = src.width;
|
|
4184
|
-
const mPitch =
|
|
4523
|
+
const mPitch = alphaMask.w;
|
|
4524
|
+
const maskData = alphaMask.data;
|
|
4185
4525
|
const dx = x - targetX | 0;
|
|
4186
4526
|
const dy = y - targetY | 0;
|
|
4187
4527
|
const dst32 = dst.data32;
|
|
@@ -4196,7 +4536,7 @@ function blendPixelDataAlphaMask(dst, src, alphaMask, opts = {}) {
|
|
|
4196
4536
|
const isOverwrite = blendFn.isOverwrite || false;
|
|
4197
4537
|
for (let iy = 0; iy < actualH; iy++) {
|
|
4198
4538
|
for (let ix = 0; ix < actualW; ix++) {
|
|
4199
|
-
const mVal =
|
|
4539
|
+
const mVal = maskData[mIdx];
|
|
4200
4540
|
const effM = invertMask ? 255 - mVal : mVal;
|
|
4201
4541
|
if (effM === 0) {
|
|
4202
4542
|
dIdx++;
|
|
@@ -4257,7 +4597,6 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts) {
|
|
|
4257
4597
|
h: height = src.height,
|
|
4258
4598
|
alpha: globalAlpha = 255,
|
|
4259
4599
|
blendFn = sourceOverPerfect,
|
|
4260
|
-
mw = src.width,
|
|
4261
4600
|
mx = 0,
|
|
4262
4601
|
my = 0,
|
|
4263
4602
|
invertMask = false
|
|
@@ -4300,7 +4639,8 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts) {
|
|
|
4300
4639
|
const src32 = src.data32;
|
|
4301
4640
|
const dw = dst.width;
|
|
4302
4641
|
const sw = src.width;
|
|
4303
|
-
const mPitch =
|
|
4642
|
+
const mPitch = binaryMask.w;
|
|
4643
|
+
const maskData = binaryMask.data;
|
|
4304
4644
|
let dIdx = y * dw + x | 0;
|
|
4305
4645
|
let sIdx = sy * sw + sx | 0;
|
|
4306
4646
|
let mIdx = (my + dy) * mPitch + (mx + dx) | 0;
|
|
@@ -4312,7 +4652,7 @@ function blendPixelDataBinaryMask(dst, src, binaryMask, opts) {
|
|
|
4312
4652
|
const isOverwrite = blendFn.isOverwrite || false;
|
|
4313
4653
|
for (let iy = 0; iy < actualH; iy++) {
|
|
4314
4654
|
for (let ix = 0; ix < actualW; ix++) {
|
|
4315
|
-
if (
|
|
4655
|
+
if (maskData[mIdx] === skipVal) {
|
|
4316
4656
|
dIdx++;
|
|
4317
4657
|
sIdx++;
|
|
4318
4658
|
mIdx++;
|
|
@@ -4440,10 +4780,11 @@ function pixelDataToAlphaMask(pixelData) {
|
|
|
4440
4780
|
height
|
|
4441
4781
|
} = pixelData;
|
|
4442
4782
|
const len = data32.length;
|
|
4443
|
-
const mask =
|
|
4783
|
+
const mask = makeAlphaMask(width, height);
|
|
4784
|
+
const maskData = mask.data;
|
|
4444
4785
|
for (let i = 0; i < len; i++) {
|
|
4445
4786
|
const val = data32[i];
|
|
4446
|
-
|
|
4787
|
+
maskData[i] = val >>> 24 & 255;
|
|
4447
4788
|
}
|
|
4448
4789
|
return mask;
|
|
4449
4790
|
}
|
|
@@ -4624,11 +4965,13 @@ export {
|
|
|
4624
4965
|
exclusionPerfect,
|
|
4625
4966
|
extractImageDataBuffer,
|
|
4626
4967
|
extractMask,
|
|
4968
|
+
extractMaskBuffer,
|
|
4627
4969
|
extractPixelData,
|
|
4628
4970
|
extractPixelDataBuffer,
|
|
4629
4971
|
fileInputChangeToImageData,
|
|
4630
4972
|
fileToImageData,
|
|
4631
4973
|
fillPixelData,
|
|
4974
|
+
fillPixelDataBinaryMask,
|
|
4632
4975
|
floodFillSelection,
|
|
4633
4976
|
forEachLinePoint,
|
|
4634
4977
|
getCircleBrushOrPencilBounds,
|
|
@@ -4637,12 +4980,13 @@ export {
|
|
|
4637
4980
|
getIndexedImageColorCounts,
|
|
4638
4981
|
getRectBrushOrPencilBounds,
|
|
4639
4982
|
getRectBrushOrPencilStrokeBounds,
|
|
4983
|
+
getRectsBounds,
|
|
4640
4984
|
getSupportedPixelFormats,
|
|
4641
4985
|
hardLightFast,
|
|
4642
4986
|
hardLightPerfect,
|
|
4643
4987
|
hardMixFast,
|
|
4644
4988
|
hardMixPerfect,
|
|
4645
|
-
|
|
4989
|
+
imageDataToAlphaMaskBuffer,
|
|
4646
4990
|
imageDataToDataUrl,
|
|
4647
4991
|
imageDataToImgBlob,
|
|
4648
4992
|
imageDataToUInt32Array,
|
|
@@ -4665,7 +5009,11 @@ export {
|
|
|
4665
5009
|
linearDodgePerfect,
|
|
4666
5010
|
linearLightFast,
|
|
4667
5011
|
linearLightPerfect,
|
|
5012
|
+
makeAlphaMask,
|
|
5013
|
+
makeBinaryMask,
|
|
4668
5014
|
makeBlendModeRegistry,
|
|
5015
|
+
makeCircleBrushAlphaMask,
|
|
5016
|
+
makeCircleBrushBinaryMask,
|
|
4669
5017
|
makeFastBlendModeRegistry,
|
|
4670
5018
|
makeFullPixelMutator,
|
|
4671
5019
|
makeImageDataLike,
|
|
@@ -4673,7 +5021,9 @@ export {
|
|
|
4673
5021
|
makePixelCanvas,
|
|
4674
5022
|
makeReusableCanvas,
|
|
4675
5023
|
makeReusableImageData,
|
|
5024
|
+
merge2BinaryMaskRects,
|
|
4676
5025
|
mergeAlphaMasks,
|
|
5026
|
+
mergeBinaryMaskRects,
|
|
4677
5027
|
mergeBinaryMasks,
|
|
4678
5028
|
multiplyFast,
|
|
4679
5029
|
multiplyPerfect,
|
|
@@ -4692,6 +5042,7 @@ export {
|
|
|
4692
5042
|
mutatorBlendPixelData,
|
|
4693
5043
|
mutatorClear,
|
|
4694
5044
|
mutatorFill,
|
|
5045
|
+
mutatorFillBinaryMask,
|
|
4695
5046
|
mutatorInvert,
|
|
4696
5047
|
overlayFast,
|
|
4697
5048
|
overlayPerfect,
|
|
@@ -4714,10 +5065,12 @@ export {
|
|
|
4714
5065
|
screenPerfect,
|
|
4715
5066
|
serializeImageData,
|
|
4716
5067
|
serializeNullableImageData,
|
|
5068
|
+
setMaskData,
|
|
4717
5069
|
softLightFast,
|
|
4718
5070
|
softLightPerfect,
|
|
4719
5071
|
sourceOverFast,
|
|
4720
5072
|
sourceOverPerfect,
|
|
5073
|
+
subtractBinaryMaskRects,
|
|
4721
5074
|
subtractFast,
|
|
4722
5075
|
subtractPerfect,
|
|
4723
5076
|
toBlendModeIndexAndName,
|