pixel-data-js 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.dev.cjs +1648 -908
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +1629 -906
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +1648 -908
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +287 -67
- package/dist/index.prod.js +1629 -906
- package/dist/index.prod.js.map +1 -1
- package/package.json +1 -1
- package/src/BlendModes/BlendModeRegistry.ts +34 -50
- package/src/BlendModes/blend-modes-perfect.ts +313 -136
- package/src/BlendModes/blend-modes.ts +6 -0
- package/src/History/HistoryManager.ts +83 -0
- package/src/History/PixelAccumulator.ts +191 -0
- package/src/History/PixelEngineConfig.ts +18 -0
- package/src/History/PixelMutator/mutatorApplyMask.ts +20 -0
- package/src/History/PixelMutator/mutatorBlendColor.ts +22 -0
- package/src/History/PixelMutator/mutatorBlendPixel.ts +37 -0
- package/src/History/PixelMutator/mutatorBlendPixelData.ts +24 -0
- package/src/History/PixelMutator/mutatorFillPixelData.ts +21 -0
- package/src/History/PixelMutator/mutatorInvert.ts +18 -0
- package/src/History/PixelMutator.ts +18 -0
- package/src/History/PixelPatchTiles.ts +52 -0
- package/src/History/PixelWriter.ts +79 -0
- package/src/ImageData/{writeImageDataPixels.ts → writeImageDataBuffer.ts} +3 -3
- package/src/PixelData/applyCircleBrushToPixelData.ts +69 -0
- package/src/PixelData/applyMaskToPixelData.ts +1 -1
- package/src/PixelData/applyRectBrushToPixelData.ts +102 -0
- package/src/PixelData/invertPixelData.ts +74 -7
- package/src/PixelData/writePixelDataBuffer.ts +65 -0
- package/src/_types.ts +31 -11
- package/src/index.ts +18 -1
package/dist/index.dev.cjs
CHANGED
|
@@ -23,11 +23,19 @@ __export(src_exports, {
|
|
|
23
23
|
BASE_FAST_BLEND_MODE_FUNCTIONS: () => BASE_FAST_BLEND_MODE_FUNCTIONS,
|
|
24
24
|
BASE_PERFECT_BLEND_MODE_FUNCTIONS: () => BASE_PERFECT_BLEND_MODE_FUNCTIONS,
|
|
25
25
|
BaseBlendMode: () => BaseBlendMode,
|
|
26
|
+
HistoryManager: () => HistoryManager,
|
|
26
27
|
IndexedImage: () => IndexedImage,
|
|
27
28
|
MaskType: () => MaskType,
|
|
29
|
+
PixelAccumulator: () => PixelAccumulator,
|
|
28
30
|
PixelData: () => PixelData,
|
|
31
|
+
PixelEngineConfig: () => PixelEngineConfig,
|
|
32
|
+
PixelTile: () => PixelTile,
|
|
33
|
+
PixelWriter: () => PixelWriter,
|
|
29
34
|
UnsupportedFormatError: () => UnsupportedFormatError,
|
|
35
|
+
applyCircleBrushToPixelData: () => applyCircleBrushToPixelData,
|
|
30
36
|
applyMaskToPixelData: () => applyMaskToPixelData,
|
|
37
|
+
applyPatchTiles: () => applyPatchTiles,
|
|
38
|
+
applyRectBrushToPixelData: () => applyRectBrushToPixelData,
|
|
31
39
|
base64DecodeArrayBuffer: () => base64DecodeArrayBuffer,
|
|
32
40
|
base64EncodeArrayBuffer: () => base64EncodeArrayBuffer,
|
|
33
41
|
blendColorPixelData: () => blendColorPixelData,
|
|
@@ -66,6 +74,7 @@ __export(src_exports, {
|
|
|
66
74
|
floodFillSelection: () => floodFillSelection,
|
|
67
75
|
getImageDataFromClipboard: () => getImageDataFromClipboard,
|
|
68
76
|
getIndexedImageColorCounts: () => getIndexedImageColorCounts,
|
|
77
|
+
getRectBrushBounds: () => getRectBrushBounds,
|
|
69
78
|
getSupportedPixelFormats: () => getSupportedPixelFormats,
|
|
70
79
|
hardLightFast: () => hardLightFast,
|
|
71
80
|
hardLightPerfect: () => hardLightPerfect,
|
|
@@ -96,6 +105,7 @@ __export(src_exports, {
|
|
|
96
105
|
linearLightPerfect: () => linearLightPerfect,
|
|
97
106
|
makeBlendModeRegistry: () => makeBlendModeRegistry,
|
|
98
107
|
makeFastBlendModeRegistry: () => makeFastBlendModeRegistry,
|
|
108
|
+
makeFullPixelMutator: () => makeFullPixelMutator,
|
|
99
109
|
makePerfectBlendModeRegistry: () => makePerfectBlendModeRegistry,
|
|
100
110
|
makePixelCanvas: () => makePixelCanvas,
|
|
101
111
|
makeReusableCanvas: () => makeReusableCanvas,
|
|
@@ -103,6 +113,12 @@ __export(src_exports, {
|
|
|
103
113
|
mergeMasks: () => mergeMasks,
|
|
104
114
|
multiplyFast: () => multiplyFast,
|
|
105
115
|
multiplyPerfect: () => multiplyPerfect,
|
|
116
|
+
mutatorApplyMask: () => mutatorApplyMask,
|
|
117
|
+
mutatorBlendColor: () => mutatorBlendColor,
|
|
118
|
+
mutatorBlendPixel: () => mutatorBlendPixel,
|
|
119
|
+
mutatorBlendPixelData: () => mutatorBlendPixelData,
|
|
120
|
+
mutatorFill: () => mutatorFill,
|
|
121
|
+
mutatorInvert: () => mutatorInvert,
|
|
106
122
|
overlayFast: () => overlayFast,
|
|
107
123
|
overlayPerfect: () => overlayPerfect,
|
|
108
124
|
overwriteBase: () => overwriteBase,
|
|
@@ -140,9 +156,10 @@ __export(src_exports, {
|
|
|
140
156
|
vividLightFast: () => vividLightFast,
|
|
141
157
|
vividLightPerfect: () => vividLightPerfect,
|
|
142
158
|
writeImageData: () => writeImageData,
|
|
143
|
-
|
|
159
|
+
writeImageDataBuffer: () => writeImageDataBuffer,
|
|
144
160
|
writeImageDataToClipboard: () => writeImageDataToClipboard,
|
|
145
|
-
writeImgBlobToClipboard: () => writeImgBlobToClipboard
|
|
161
|
+
writeImgBlobToClipboard: () => writeImgBlobToClipboard,
|
|
162
|
+
writePixelDataBuffer: () => writePixelDataBuffer
|
|
146
163
|
});
|
|
147
164
|
module.exports = __toCommonJS(src_exports);
|
|
148
165
|
|
|
@@ -177,33 +194,37 @@ overwriteBase.isOverwrite = true;
|
|
|
177
194
|
|
|
178
195
|
// src/BlendModes/BlendModeRegistry.ts
|
|
179
196
|
function makeBlendModeRegistry(blendModes, initialEntries) {
|
|
180
|
-
const
|
|
181
|
-
const
|
|
182
|
-
const
|
|
183
|
-
const
|
|
197
|
+
const blendToName = /* @__PURE__ */ new Map();
|
|
198
|
+
const blendToIndex = /* @__PURE__ */ new Map();
|
|
199
|
+
const indexToName = [];
|
|
200
|
+
const indexToBlend = [];
|
|
201
|
+
const nameToBlend = {};
|
|
202
|
+
const nameToIndex = {};
|
|
184
203
|
const add = (name, index, blendFn) => {
|
|
185
|
-
if (
|
|
186
|
-
throw new Error(`
|
|
204
|
+
if (!Number.isFinite(index)) {
|
|
205
|
+
throw new Error(`Index "${index}" is not a number. Attempting to add name: "${name}", index: "${index}"`);
|
|
187
206
|
}
|
|
188
|
-
if (
|
|
189
|
-
throw new Error(`Blend Mode name: "${name}"
|
|
207
|
+
if (indexToBlend[index]) {
|
|
208
|
+
throw new Error(`Blend Mode index: ${index} is already used. Attempting to add name: "${name}", index: "${index}"`);
|
|
190
209
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
210
|
+
indexToName[index] = name;
|
|
211
|
+
indexToBlend[index] = blendFn;
|
|
212
|
+
blendToIndex.set(blendFn, index);
|
|
213
|
+
blendToName.set(blendFn, name);
|
|
214
|
+
nameToBlend[name] = blendFn;
|
|
215
|
+
nameToIndex[name] = index;
|
|
196
216
|
};
|
|
197
217
|
for (const [name, index] of Object.entries(blendModes)) {
|
|
198
218
|
const blend = initialEntries[index];
|
|
199
219
|
add(name, index, blend);
|
|
200
220
|
}
|
|
201
221
|
return {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
222
|
+
nameToBlend,
|
|
223
|
+
nameToIndex,
|
|
224
|
+
blendToIndex,
|
|
225
|
+
blendToName,
|
|
226
|
+
indexToBlend,
|
|
227
|
+
indexToName,
|
|
207
228
|
indexType: null,
|
|
208
229
|
nameType: null
|
|
209
230
|
};
|
|
@@ -988,14 +1009,18 @@ var sourceOverPerfect = (src, dst) => {
|
|
|
988
1009
|
const sa = src >>> 24 & 255;
|
|
989
1010
|
if (sa === 255) return src;
|
|
990
1011
|
if (sa === 0) return dst;
|
|
1012
|
+
const invA = 255 - sa;
|
|
991
1013
|
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
992
1014
|
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
993
1015
|
const da = dst >>> 24 & 255;
|
|
994
|
-
const
|
|
995
|
-
const r =
|
|
996
|
-
const
|
|
997
|
-
const
|
|
998
|
-
const
|
|
1016
|
+
const tR = sr * sa + dr * invA;
|
|
1017
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1018
|
+
const tG = sg * sa + dg * invA;
|
|
1019
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1020
|
+
const tB = sb * sa + db * invA;
|
|
1021
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1022
|
+
const tA = 255 * sa + da * invA;
|
|
1023
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
999
1024
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1000
1025
|
};
|
|
1001
1026
|
var darkenPerfect = (src, dst) => {
|
|
@@ -1008,44 +1033,71 @@ var darkenPerfect = (src, dst) => {
|
|
|
1008
1033
|
const bb = sb < db ? sb : db;
|
|
1009
1034
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1010
1035
|
const invA = 255 - sa;
|
|
1011
|
-
const
|
|
1012
|
-
const
|
|
1013
|
-
const
|
|
1014
|
-
const
|
|
1036
|
+
const da = dst >>> 24 & 255;
|
|
1037
|
+
const tR = br * sa + dr * invA;
|
|
1038
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1039
|
+
const tG = bg * sa + dg * invA;
|
|
1040
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1041
|
+
const tB = bb * sa + db * invA;
|
|
1042
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1043
|
+
const tA = 255 * sa + da * invA;
|
|
1044
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1015
1045
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1016
1046
|
};
|
|
1017
1047
|
var multiplyPerfect = (src, dst) => {
|
|
1018
1048
|
const sa = src >>> 24 & 255;
|
|
1019
1049
|
if (sa === 0) return dst;
|
|
1020
|
-
const
|
|
1021
|
-
const
|
|
1022
|
-
const
|
|
1023
|
-
const
|
|
1024
|
-
const
|
|
1050
|
+
const dr = dst & 255;
|
|
1051
|
+
const dg = dst >>> 8 & 255;
|
|
1052
|
+
const db = dst >>> 16 & 255;
|
|
1053
|
+
const da = dst >>> 24 & 255;
|
|
1054
|
+
const sr = src & 255;
|
|
1055
|
+
const sg = src >>> 8 & 255;
|
|
1056
|
+
const sb = src >>> 16 & 255;
|
|
1057
|
+
const mR = sr * dr;
|
|
1058
|
+
const br = mR + 1 + (mR >> 8) >> 8;
|
|
1059
|
+
const mG = sg * dg;
|
|
1060
|
+
const bg = mG + 1 + (mG >> 8) >> 8;
|
|
1061
|
+
const mB = sb * db;
|
|
1062
|
+
const bb = mB + 1 + (mB >> 8) >> 8;
|
|
1025
1063
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1026
1064
|
const invA = 255 - sa;
|
|
1027
|
-
const
|
|
1028
|
-
const r =
|
|
1029
|
-
const
|
|
1030
|
-
const
|
|
1031
|
-
const
|
|
1065
|
+
const tR = br * sa + dr * invA;
|
|
1066
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1067
|
+
const tG = bg * sa + dg * invA;
|
|
1068
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1069
|
+
const tB = bb * sa + db * invA;
|
|
1070
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1071
|
+
const tA = 255 * sa + da * invA;
|
|
1072
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1032
1073
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1033
1074
|
};
|
|
1034
1075
|
var colorBurnPerfect = (src, dst) => {
|
|
1035
1076
|
const sa = src >>> 24 & 255;
|
|
1036
1077
|
if (sa === 0) return dst;
|
|
1037
|
-
const
|
|
1038
|
-
const
|
|
1039
|
-
const
|
|
1040
|
-
const
|
|
1041
|
-
const
|
|
1078
|
+
const dr = dst & 255;
|
|
1079
|
+
const dg = dst >>> 8 & 255;
|
|
1080
|
+
const db = dst >>> 16 & 255;
|
|
1081
|
+
const sr = src & 255;
|
|
1082
|
+
const sg = src >>> 8 & 255;
|
|
1083
|
+
const sb = src >>> 16 & 255;
|
|
1084
|
+
const resR = dr === 255 ? 255 : sr === 0 ? 0 : 255 - ((255 - dr) * 255 / sr | 0);
|
|
1085
|
+
const br = resR < 0 ? 0 : resR;
|
|
1086
|
+
const resG = dg === 255 ? 255 : sg === 0 ? 0 : 255 - ((255 - dg) * 255 / sg | 0);
|
|
1087
|
+
const bg = resG < 0 ? 0 : resG;
|
|
1088
|
+
const resB = db === 255 ? 255 : sb === 0 ? 0 : 255 - ((255 - db) * 255 / sb | 0);
|
|
1089
|
+
const bb = resB < 0 ? 0 : resB;
|
|
1042
1090
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1043
1091
|
const invA = 255 - sa;
|
|
1044
1092
|
const da = dst >>> 24 & 255;
|
|
1045
|
-
const
|
|
1046
|
-
const
|
|
1047
|
-
const
|
|
1048
|
-
const
|
|
1093
|
+
const tR = br * sa + dr * invA;
|
|
1094
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1095
|
+
const tG = bg * sa + dg * invA;
|
|
1096
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1097
|
+
const tB = bb * sa + db * invA;
|
|
1098
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1099
|
+
const tA = 255 * sa + da * invA;
|
|
1100
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1049
1101
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1050
1102
|
};
|
|
1051
1103
|
var linearBurnPerfect = (src, dst) => {
|
|
@@ -1061,10 +1113,15 @@ var linearBurnPerfect = (src, dst) => {
|
|
|
1061
1113
|
const bb = bbU < 0 ? 0 : bbU;
|
|
1062
1114
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1063
1115
|
const invA = 255 - sa;
|
|
1064
|
-
const
|
|
1065
|
-
const
|
|
1066
|
-
const
|
|
1067
|
-
const
|
|
1116
|
+
const da = dst >>> 24 & 255;
|
|
1117
|
+
const tR = br * sa + dr * invA;
|
|
1118
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1119
|
+
const tG = bg * sa + dg * invA;
|
|
1120
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1121
|
+
const tB = bb * sa + db * invA;
|
|
1122
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1123
|
+
const tA = 255 * sa + da * invA;
|
|
1124
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1068
1125
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1069
1126
|
};
|
|
1070
1127
|
var darkerPerfect = (src, dst) => {
|
|
@@ -1086,10 +1143,15 @@ var darkerPerfect = (src, dst) => {
|
|
|
1086
1143
|
}
|
|
1087
1144
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1088
1145
|
const invA = 255 - sa;
|
|
1089
|
-
const
|
|
1090
|
-
const
|
|
1091
|
-
const
|
|
1092
|
-
const
|
|
1146
|
+
const da = dst >>> 24 & 255;
|
|
1147
|
+
const tR = br * sa + dr * invA;
|
|
1148
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1149
|
+
const tG = bg * sa + dg * invA;
|
|
1150
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1151
|
+
const tB = bb * sa + db * invA;
|
|
1152
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1153
|
+
const tA = 255 * sa + da * invA;
|
|
1154
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1093
1155
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1094
1156
|
};
|
|
1095
1157
|
var lightenPerfect = (src, dst) => {
|
|
@@ -1101,10 +1163,15 @@ var lightenPerfect = (src, dst) => {
|
|
|
1101
1163
|
const bb = (src >>> 16 & 255) > db ? src >>> 16 & 255 : db;
|
|
1102
1164
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1103
1165
|
const invA = 255 - sa;
|
|
1104
|
-
const
|
|
1105
|
-
const
|
|
1106
|
-
const
|
|
1107
|
-
const
|
|
1166
|
+
const da = dst >>> 24 & 255;
|
|
1167
|
+
const tR = br * sa + dr * invA;
|
|
1168
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1169
|
+
const tG = bg * sa + dg * invA;
|
|
1170
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1171
|
+
const tB = bb * sa + db * invA;
|
|
1172
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1173
|
+
const tA = 255 * sa + da * invA;
|
|
1174
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1108
1175
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1109
1176
|
};
|
|
1110
1177
|
var screenPerfect = (src, dst) => {
|
|
@@ -1116,26 +1183,43 @@ var screenPerfect = (src, dst) => {
|
|
|
1116
1183
|
const bb = 255 - ((255 - (src >>> 16 & 255)) * (255 - db) / 255 | 0);
|
|
1117
1184
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1118
1185
|
const invA = 255 - sa;
|
|
1119
|
-
const
|
|
1120
|
-
const
|
|
1121
|
-
const
|
|
1122
|
-
const
|
|
1186
|
+
const da = dst >>> 24 & 255;
|
|
1187
|
+
const tR = br * sa + dr * invA;
|
|
1188
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1189
|
+
const tG = bg * sa + dg * invA;
|
|
1190
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1191
|
+
const tB = bb * sa + db * invA;
|
|
1192
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1193
|
+
const tA = 255 * sa + da * invA;
|
|
1194
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1123
1195
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1124
1196
|
};
|
|
1125
1197
|
var colorDodgePerfect = (src, dst) => {
|
|
1126
1198
|
const sa = src >>> 24 & 255;
|
|
1127
1199
|
if (sa === 0) return dst;
|
|
1128
|
-
const dr = dst & 255
|
|
1129
|
-
const
|
|
1130
|
-
const
|
|
1131
|
-
const
|
|
1132
|
-
const
|
|
1200
|
+
const dr = dst & 255;
|
|
1201
|
+
const dg = dst >>> 8 & 255;
|
|
1202
|
+
const db = dst >>> 16 & 255;
|
|
1203
|
+
const sr = src & 255;
|
|
1204
|
+
const sg = src >>> 8 & 255;
|
|
1205
|
+
const sb = src >>> 16 & 255;
|
|
1206
|
+
const resR = sr === 255 ? 255 : dr * 255 / (255 - sr) | 0;
|
|
1207
|
+
const br = resR > 255 ? 255 : resR;
|
|
1208
|
+
const resG = sg === 255 ? 255 : dg * 255 / (255 - sg) | 0;
|
|
1209
|
+
const bg = resG > 255 ? 255 : resG;
|
|
1210
|
+
const resB = sb === 255 ? 255 : db * 255 / (255 - sb) | 0;
|
|
1211
|
+
const bb = resB > 255 ? 255 : resB;
|
|
1133
1212
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1134
1213
|
const invA = 255 - sa;
|
|
1135
|
-
const
|
|
1136
|
-
const
|
|
1137
|
-
const
|
|
1138
|
-
const
|
|
1214
|
+
const da = dst >>> 24 & 255;
|
|
1215
|
+
const tR = br * sa + dr * invA;
|
|
1216
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1217
|
+
const tG = bg * sa + dg * invA;
|
|
1218
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1219
|
+
const tB = bb * sa + db * invA;
|
|
1220
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1221
|
+
const tA = 255 * sa + da * invA;
|
|
1222
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1139
1223
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1140
1224
|
};
|
|
1141
1225
|
var linearDodgePerfect = (src, dst) => {
|
|
@@ -1150,10 +1234,15 @@ var linearDodgePerfect = (src, dst) => {
|
|
|
1150
1234
|
const bb = bbU > 255 ? 255 : bbU;
|
|
1151
1235
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1152
1236
|
const invA = 255 - sa;
|
|
1153
|
-
const
|
|
1154
|
-
const
|
|
1155
|
-
const
|
|
1156
|
-
const
|
|
1237
|
+
const da = dst >>> 24 & 255;
|
|
1238
|
+
const tR = br * sa + dr * invA;
|
|
1239
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1240
|
+
const tG = bg * sa + dg * invA;
|
|
1241
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1242
|
+
const tB = bb * sa + db * invA;
|
|
1243
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1244
|
+
const tA = 255 * sa + da * invA;
|
|
1245
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1157
1246
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1158
1247
|
};
|
|
1159
1248
|
var lighterPerfect = (src, dst) => {
|
|
@@ -1175,10 +1264,15 @@ var lighterPerfect = (src, dst) => {
|
|
|
1175
1264
|
}
|
|
1176
1265
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1177
1266
|
const invA = 255 - sa;
|
|
1178
|
-
const
|
|
1179
|
-
const
|
|
1180
|
-
const
|
|
1181
|
-
const
|
|
1267
|
+
const da = dst >>> 24 & 255;
|
|
1268
|
+
const tR = br * sa + dr * invA;
|
|
1269
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1270
|
+
const tG = bg * sa + dg * invA;
|
|
1271
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1272
|
+
const tB = bb * sa + db * invA;
|
|
1273
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1274
|
+
const tA = 255 * sa + da * invA;
|
|
1275
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1182
1276
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1183
1277
|
};
|
|
1184
1278
|
var overlayPerfect = (src, dst) => {
|
|
@@ -1191,10 +1285,15 @@ var overlayPerfect = (src, dst) => {
|
|
|
1191
1285
|
const bb = db < 128 ? 2 * sb * db / 255 | 0 : 255 - (2 * (255 - sb) * (255 - db) / 255 | 0);
|
|
1192
1286
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1193
1287
|
const invA = 255 - sa;
|
|
1194
|
-
const
|
|
1195
|
-
const
|
|
1196
|
-
const
|
|
1197
|
-
const
|
|
1288
|
+
const da = dst >>> 24 & 255;
|
|
1289
|
+
const tR = br * sa + dr * invA;
|
|
1290
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1291
|
+
const tG = bg * sa + dg * invA;
|
|
1292
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1293
|
+
const tB = bb * sa + db * invA;
|
|
1294
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1295
|
+
const tA = 255 * sa + da * invA;
|
|
1296
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1198
1297
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1199
1298
|
};
|
|
1200
1299
|
var softLightPerfect = (src, dst) => {
|
|
@@ -1202,15 +1301,26 @@ var softLightPerfect = (src, dst) => {
|
|
|
1202
1301
|
if (sa === 0) return dst;
|
|
1203
1302
|
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
1204
1303
|
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
1205
|
-
const
|
|
1206
|
-
const
|
|
1207
|
-
const
|
|
1304
|
+
const mR = sr * dr;
|
|
1305
|
+
const scR = (255 - sr) * (255 - dr);
|
|
1306
|
+
const br = (255 - dr) * (mR + 1 + (mR >> 8) >> 8) + dr * (255 - (scR + 1 + (scR >> 8) >> 8)) + 1 + ((255 - dr) * (mR + 1 + (mR >> 8) >> 8) + dr * (255 - (scR + 1 + (scR >> 8) >> 8)) >> 8) >> 8;
|
|
1307
|
+
const mG = sg * dg;
|
|
1308
|
+
const scG = (255 - sg) * (255 - dg);
|
|
1309
|
+
const bg = (255 - dg) * (mG + 1 + (mG >> 8) >> 8) + dg * (255 - (scG + 1 + (scG >> 8) >> 8)) + 1 + ((255 - dg) * (mG + 1 + (mG >> 8) >> 8) + dg * (255 - (scG + 1 + (scG >> 8) >> 8)) >> 8) >> 8;
|
|
1310
|
+
const mB = sb * db;
|
|
1311
|
+
const scB = (255 - sb) * (255 - db);
|
|
1312
|
+
const bb = (255 - db) * (mB + 1 + (mB >> 8) >> 8) + db * (255 - (scB + 1 + (scB >> 8) >> 8)) + 1 + ((255 - db) * (mB + 1 + (mB >> 8) >> 8) + db * (255 - (scB + 1 + (scB >> 8) >> 8)) >> 8) >> 8;
|
|
1208
1313
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1209
1314
|
const invA = 255 - sa;
|
|
1210
|
-
const
|
|
1211
|
-
const
|
|
1212
|
-
const
|
|
1213
|
-
const
|
|
1315
|
+
const da = dst >>> 24 & 255;
|
|
1316
|
+
const tR = br * sa + dr * invA;
|
|
1317
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1318
|
+
const tG = bg * sa + dg * invA;
|
|
1319
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1320
|
+
const tB = bb * sa + db * invA;
|
|
1321
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1322
|
+
const tA = 255 * sa + da * invA;
|
|
1323
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1214
1324
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1215
1325
|
};
|
|
1216
1326
|
var hardLightPerfect = (src, dst) => {
|
|
@@ -1223,10 +1333,15 @@ var hardLightPerfect = (src, dst) => {
|
|
|
1223
1333
|
const bb = sb < 128 ? 2 * sb * db / 255 | 0 : 255 - (2 * (255 - sb) * (255 - db) / 255 | 0);
|
|
1224
1334
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1225
1335
|
const invA = 255 - sa;
|
|
1226
|
-
const
|
|
1227
|
-
const
|
|
1228
|
-
const
|
|
1229
|
-
const
|
|
1336
|
+
const da = dst >>> 24 & 255;
|
|
1337
|
+
const tR = br * sa + dr * invA;
|
|
1338
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1339
|
+
const tG = bg * sa + dg * invA;
|
|
1340
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1341
|
+
const tB = bb * sa + db * invA;
|
|
1342
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1343
|
+
const tA = 255 * sa + da * invA;
|
|
1344
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1230
1345
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1231
1346
|
};
|
|
1232
1347
|
var vividLightPerfect = (src, dst) => {
|
|
@@ -1239,10 +1354,15 @@ var vividLightPerfect = (src, dst) => {
|
|
|
1239
1354
|
const bb = sb < 128 ? sb === 0 ? 0 : Math.max(0, 255 - ((255 - db) * 255 / (2 * sb) | 0)) : sb === 255 ? 255 : Math.min(255, db * 255 / (2 * (255 - sb)) | 0);
|
|
1240
1355
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1241
1356
|
const invA = 255 - sa;
|
|
1242
|
-
const
|
|
1243
|
-
const
|
|
1244
|
-
const
|
|
1245
|
-
const
|
|
1357
|
+
const da = dst >>> 24 & 255;
|
|
1358
|
+
const tR = br * sa + dr * invA;
|
|
1359
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1360
|
+
const tG = bg * sa + dg * invA;
|
|
1361
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1362
|
+
const tB = bb * sa + db * invA;
|
|
1363
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1364
|
+
const tA = 255 * sa + da * invA;
|
|
1365
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1246
1366
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1247
1367
|
};
|
|
1248
1368
|
var linearLightPerfect = (src, dst) => {
|
|
@@ -1258,10 +1378,15 @@ var linearLightPerfect = (src, dst) => {
|
|
|
1258
1378
|
const bb = bbU < 0 ? 0 : bbU > 255 ? 255 : bbU;
|
|
1259
1379
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1260
1380
|
const invA = 255 - sa;
|
|
1261
|
-
const
|
|
1262
|
-
const
|
|
1263
|
-
const
|
|
1264
|
-
const
|
|
1381
|
+
const da = dst >>> 24 & 255;
|
|
1382
|
+
const tR = br * sa + dr * invA;
|
|
1383
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1384
|
+
const tG = bg * sa + dg * invA;
|
|
1385
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1386
|
+
const tB = bb * sa + db * invA;
|
|
1387
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1388
|
+
const tA = 255 * sa + da * invA;
|
|
1389
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1265
1390
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1266
1391
|
};
|
|
1267
1392
|
var pinLightPerfect = (src, dst) => {
|
|
@@ -1279,10 +1404,14 @@ var pinLightPerfect = (src, dst) => {
|
|
|
1279
1404
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1280
1405
|
const invA = 255 - sa;
|
|
1281
1406
|
const da = dst >>> 24 & 255;
|
|
1282
|
-
const
|
|
1283
|
-
const
|
|
1284
|
-
const
|
|
1285
|
-
const
|
|
1407
|
+
const tR = br * sa + dr * invA;
|
|
1408
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1409
|
+
const tG = bg * sa + dg * invA;
|
|
1410
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1411
|
+
const tB = bb * sa + db * invA;
|
|
1412
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1413
|
+
const tA = 255 * sa + da * invA;
|
|
1414
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1286
1415
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1287
1416
|
};
|
|
1288
1417
|
var hardMixPerfect = (src, dst) => {
|
|
@@ -1295,33 +1424,36 @@ var hardMixPerfect = (src, dst) => {
|
|
|
1295
1424
|
const bb = (sb < 128 ? sb === 0 ? 0 : Math.max(0, 255 - ((255 - db) * 255 / (2 * sb) | 0)) : sb === 255 ? 255 : Math.min(255, db * 255 / (2 * (255 - sb)) | 0)) < 128 ? 0 : 255;
|
|
1296
1425
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1297
1426
|
const invA = 255 - sa;
|
|
1298
|
-
const
|
|
1299
|
-
const
|
|
1300
|
-
const
|
|
1301
|
-
const
|
|
1427
|
+
const da = dst >>> 24 & 255;
|
|
1428
|
+
const tR = br * sa + dr * invA;
|
|
1429
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1430
|
+
const tG = bg * sa + dg * invA;
|
|
1431
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1432
|
+
const tB = bb * sa + db * invA;
|
|
1433
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1434
|
+
const tA = 255 * sa + da * invA;
|
|
1435
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1302
1436
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1303
1437
|
};
|
|
1304
1438
|
var differencePerfect = (src, dst) => {
|
|
1305
1439
|
const sa = src >>> 24 & 255;
|
|
1306
1440
|
if (sa === 0) return dst;
|
|
1307
|
-
const dr = dst & 255;
|
|
1308
|
-
const
|
|
1309
|
-
const
|
|
1310
|
-
const
|
|
1311
|
-
const
|
|
1312
|
-
|
|
1313
|
-
const br = Math.abs(dr - sr);
|
|
1314
|
-
const bg = Math.abs(dg - sg);
|
|
1315
|
-
const bb = Math.abs(db - sb);
|
|
1316
|
-
if (sa === 255) {
|
|
1317
|
-
return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1318
|
-
}
|
|
1441
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
1442
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
1443
|
+
const br = dr > sr ? dr - sr : sr - dr;
|
|
1444
|
+
const bg = dg > sg ? dg - sg : sg - dg;
|
|
1445
|
+
const bb = db > sb ? db - sb : sb - db;
|
|
1446
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1319
1447
|
const invA = 255 - sa;
|
|
1320
1448
|
const da = dst >>> 24 & 255;
|
|
1321
|
-
const
|
|
1322
|
-
const
|
|
1323
|
-
const
|
|
1324
|
-
const
|
|
1449
|
+
const tR = br * sa + dr * invA;
|
|
1450
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1451
|
+
const tG = bg * sa + dg * invA;
|
|
1452
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1453
|
+
const tB = bb * sa + db * invA;
|
|
1454
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1455
|
+
const tA = 255 * sa + da * invA;
|
|
1456
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1325
1457
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1326
1458
|
};
|
|
1327
1459
|
var exclusionPerfect = (src, dst) => {
|
|
@@ -1333,18 +1465,23 @@ var exclusionPerfect = (src, dst) => {
|
|
|
1333
1465
|
const sr = src & 255;
|
|
1334
1466
|
const sg = src >>> 8 & 255;
|
|
1335
1467
|
const sb = src >>> 16 & 255;
|
|
1336
|
-
const
|
|
1337
|
-
const
|
|
1338
|
-
const
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1468
|
+
const r2 = dr * sr;
|
|
1469
|
+
const br = dr + sr - (r2 + r2 + 1 + (r2 + r2 >> 8) >> 8);
|
|
1470
|
+
const g2 = dg * sg;
|
|
1471
|
+
const bg = dg + sg - (g2 + g2 + 1 + (g2 + g2 >> 8) >> 8);
|
|
1472
|
+
const b2 = db * sb;
|
|
1473
|
+
const bb = db + sb - (b2 + b2 + 1 + (b2 + b2 >> 8) >> 8);
|
|
1474
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1342
1475
|
const invA = 255 - sa;
|
|
1343
1476
|
const da = dst >>> 24 & 255;
|
|
1344
|
-
const
|
|
1345
|
-
const
|
|
1346
|
-
const
|
|
1347
|
-
const
|
|
1477
|
+
const tR = br * sa + dr * invA;
|
|
1478
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1479
|
+
const tG = bg * sa + dg * invA;
|
|
1480
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1481
|
+
const tB = bb * sa + db * invA;
|
|
1482
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1483
|
+
const tA = 255 * sa + da * invA;
|
|
1484
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1348
1485
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1349
1486
|
};
|
|
1350
1487
|
var subtractPerfect = (src, dst) => {
|
|
@@ -1360,10 +1497,15 @@ var subtractPerfect = (src, dst) => {
|
|
|
1360
1497
|
const bb = bbU < 0 ? 0 : bbU;
|
|
1361
1498
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1362
1499
|
const invA = 255 - sa;
|
|
1363
|
-
const
|
|
1364
|
-
const
|
|
1365
|
-
const
|
|
1366
|
-
const
|
|
1500
|
+
const da = dst >>> 24 & 255;
|
|
1501
|
+
const tR = br * sa + dr * invA;
|
|
1502
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1503
|
+
const tG = bg * sa + dg * invA;
|
|
1504
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1505
|
+
const tB = bb * sa + db * invA;
|
|
1506
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1507
|
+
const tA = 255 * sa + da * invA;
|
|
1508
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1367
1509
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1368
1510
|
};
|
|
1369
1511
|
var dividePerfect = (src, dst) => {
|
|
@@ -1376,10 +1518,15 @@ var dividePerfect = (src, dst) => {
|
|
|
1376
1518
|
const bb = sb === 0 ? 255 : Math.min(255, db * 255 / sb | 0);
|
|
1377
1519
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1378
1520
|
const invA = 255 - sa;
|
|
1379
|
-
const
|
|
1380
|
-
const
|
|
1381
|
-
const
|
|
1382
|
-
const
|
|
1521
|
+
const da = dst >>> 24 & 255;
|
|
1522
|
+
const tR = br * sa + dr * invA;
|
|
1523
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1524
|
+
const tG = bg * sa + dg * invA;
|
|
1525
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1526
|
+
const tB = bb * sa + db * invA;
|
|
1527
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1528
|
+
const tA = 255 * sa + da * invA;
|
|
1529
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1383
1530
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1384
1531
|
};
|
|
1385
1532
|
var BASE_PERFECT_BLEND_MODE_FUNCTIONS = {
|
|
@@ -1524,279 +1671,1126 @@ async function writeImageDataToClipboard(imageData) {
|
|
|
1524
1671
|
return writeImgBlobToClipboard(blob);
|
|
1525
1672
|
}
|
|
1526
1673
|
|
|
1527
|
-
// src/
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1674
|
+
// src/History/PixelPatchTiles.ts
|
|
1675
|
+
var PixelTile = class {
|
|
1676
|
+
constructor(id, tx, ty, tileArea) {
|
|
1677
|
+
this.id = id;
|
|
1678
|
+
this.tx = tx;
|
|
1679
|
+
this.ty = ty;
|
|
1680
|
+
this.data32 = new Uint32Array(tileArea);
|
|
1681
|
+
}
|
|
1682
|
+
data32;
|
|
1683
|
+
};
|
|
1684
|
+
function applyPatchTiles(target, tiles, tileSize = 256) {
|
|
1685
|
+
for (let i = 0; i < tiles.length; i++) {
|
|
1686
|
+
const tile = tiles[i];
|
|
1687
|
+
if (!tile) continue;
|
|
1688
|
+
const dst = target.data32;
|
|
1689
|
+
const src = tile.data32;
|
|
1690
|
+
const dstWidth = target.width;
|
|
1691
|
+
const dstHeight = target.height;
|
|
1692
|
+
const startX = tile.tx * tileSize;
|
|
1693
|
+
const startY = tile.ty * tileSize;
|
|
1694
|
+
const copyWidth = Math.max(0, Math.min(tileSize, dstWidth - startX));
|
|
1695
|
+
if (copyWidth <= 0) return;
|
|
1696
|
+
for (let ly = 0; ly < tileSize; ly++) {
|
|
1697
|
+
const globalY = startY + ly;
|
|
1698
|
+
if (globalY >= dstHeight) break;
|
|
1699
|
+
const dstIndex = globalY * dstWidth + startX;
|
|
1700
|
+
const srcIndex = ly * tileSize;
|
|
1701
|
+
const rowData = src.subarray(srcIndex, srcIndex + copyWidth);
|
|
1702
|
+
dst.set(rowData, dstIndex);
|
|
1538
1703
|
}
|
|
1539
|
-
return imageData;
|
|
1540
|
-
};
|
|
1541
|
-
}
|
|
1542
|
-
|
|
1543
|
-
// src/ImageData/copyImageData.ts
|
|
1544
|
-
function copyImageData({ data, width, height }) {
|
|
1545
|
-
return new ImageData(data.slice(), width, height);
|
|
1546
|
-
}
|
|
1547
|
-
function copyImageDataLike({ data, width, height }) {
|
|
1548
|
-
return {
|
|
1549
|
-
data: data.slice(),
|
|
1550
|
-
width,
|
|
1551
|
-
height
|
|
1552
|
-
};
|
|
1553
|
-
}
|
|
1554
|
-
|
|
1555
|
-
// src/PixelData/pixelDataToAlphaMask.ts
|
|
1556
|
-
function pixelDataToAlphaMask(pixelData) {
|
|
1557
|
-
const {
|
|
1558
|
-
data32,
|
|
1559
|
-
width,
|
|
1560
|
-
height
|
|
1561
|
-
} = pixelData;
|
|
1562
|
-
const len = data32.length;
|
|
1563
|
-
const mask = new Uint8Array(width * height);
|
|
1564
|
-
for (let i = 0; i < len; i++) {
|
|
1565
|
-
const val = data32[i];
|
|
1566
|
-
mask[i] = val >>> 24 & 255;
|
|
1567
1704
|
}
|
|
1568
|
-
return mask;
|
|
1569
1705
|
}
|
|
1570
1706
|
|
|
1571
|
-
// src/
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1707
|
+
// src/History/PixelAccumulator.ts
|
|
1708
|
+
var PixelAccumulator = class {
|
|
1709
|
+
constructor(target, config) {
|
|
1710
|
+
this.target = target;
|
|
1711
|
+
this.config = config;
|
|
1712
|
+
this.lookup = [];
|
|
1713
|
+
this.beforeTiles = [];
|
|
1714
|
+
this.pool = [];
|
|
1715
|
+
}
|
|
1716
|
+
lookup;
|
|
1717
|
+
beforeTiles;
|
|
1718
|
+
pool;
|
|
1719
|
+
getTile(id, tx, ty) {
|
|
1720
|
+
let tile = this.pool.pop();
|
|
1721
|
+
if (tile) {
|
|
1722
|
+
tile.id = id;
|
|
1723
|
+
tile.tx = tx;
|
|
1724
|
+
tile.ty = ty;
|
|
1725
|
+
return tile;
|
|
1726
|
+
}
|
|
1727
|
+
return new PixelTile(
|
|
1728
|
+
id,
|
|
1729
|
+
tx,
|
|
1730
|
+
ty,
|
|
1731
|
+
this.config.tileArea
|
|
1732
|
+
);
|
|
1588
1733
|
}
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1734
|
+
recyclePatch(patch) {
|
|
1735
|
+
const before = patch.beforeTiles;
|
|
1736
|
+
for (let i = 0; i < before.length; i++) {
|
|
1737
|
+
let tile = before[i];
|
|
1738
|
+
if (tile) {
|
|
1739
|
+
this.pool.push(tile);
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
const after = patch.afterTiles;
|
|
1743
|
+
for (let i = 0; i < after.length; i++) {
|
|
1744
|
+
let tile = after[i];
|
|
1745
|
+
if (tile) {
|
|
1746
|
+
this.pool.push(tile);
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
/**
|
|
1751
|
+
* @param x pixel x coordinate
|
|
1752
|
+
* @param y pixel y coordinate
|
|
1753
|
+
*/
|
|
1754
|
+
storeTileBeforeState(x, y) {
|
|
1755
|
+
let target = this.target;
|
|
1756
|
+
let shift = this.config.tileShift;
|
|
1757
|
+
let columns = target.width + this.config.tileMask >> shift;
|
|
1758
|
+
let tx = x >> shift;
|
|
1759
|
+
let ty = y >> shift;
|
|
1760
|
+
let id = ty * columns + tx;
|
|
1761
|
+
let tile = this.lookup[id];
|
|
1762
|
+
if (!tile) {
|
|
1763
|
+
tile = this.getTile(
|
|
1764
|
+
id,
|
|
1765
|
+
tx,
|
|
1766
|
+
ty
|
|
1767
|
+
);
|
|
1768
|
+
this.extractState(tile);
|
|
1769
|
+
this.lookup[id] = tile;
|
|
1770
|
+
this.beforeTiles.push(tile);
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
/**
|
|
1774
|
+
*
|
|
1775
|
+
* @param x pixel x coordinate
|
|
1776
|
+
* @param y pixel y coordinate
|
|
1777
|
+
* @param w pixel width
|
|
1778
|
+
* @param h pixel height
|
|
1779
|
+
*/
|
|
1780
|
+
storeRegionBeforeState(x, y, w, h) {
|
|
1781
|
+
let target = this.target;
|
|
1782
|
+
let shift = this.config.tileShift;
|
|
1783
|
+
let columns = target.width + this.config.tileMask >> shift;
|
|
1784
|
+
let startX = x >> shift;
|
|
1785
|
+
let startY = y >> shift;
|
|
1786
|
+
let endX = x + w - 1 >> shift;
|
|
1787
|
+
let endY = y + h - 1 >> shift;
|
|
1788
|
+
for (let ty = startY; ty <= endY; ty++) {
|
|
1789
|
+
for (let tx = startX; tx <= endX; tx++) {
|
|
1790
|
+
let id = ty * columns + tx;
|
|
1791
|
+
let tile = this.lookup[id];
|
|
1792
|
+
if (!tile) {
|
|
1793
|
+
tile = this.getTile(
|
|
1794
|
+
id,
|
|
1795
|
+
tx,
|
|
1796
|
+
ty
|
|
1797
|
+
);
|
|
1798
|
+
this.extractState(tile);
|
|
1799
|
+
this.lookup[id] = tile;
|
|
1800
|
+
this.beforeTiles.push(tile);
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
extractState(tile) {
|
|
1806
|
+
let target = this.target;
|
|
1807
|
+
let TILE_SIZE = this.config.tileSize;
|
|
1808
|
+
let dst = tile.data32;
|
|
1809
|
+
let src = target.data32;
|
|
1810
|
+
let startX = tile.tx * TILE_SIZE;
|
|
1811
|
+
let startY = tile.ty * TILE_SIZE;
|
|
1812
|
+
let targetWidth = target.width;
|
|
1813
|
+
let targetHeight = target.height;
|
|
1814
|
+
let copyWidth = Math.max(0, Math.min(TILE_SIZE, targetWidth - startX));
|
|
1815
|
+
for (let ly = 0; ly < TILE_SIZE; ly++) {
|
|
1816
|
+
let globalY = startY + ly;
|
|
1817
|
+
let dstIndex = ly * TILE_SIZE;
|
|
1818
|
+
if (globalY < 0 || globalY >= targetHeight || copyWidth === 0) {
|
|
1819
|
+
dst.fill(0, dstIndex, dstIndex + TILE_SIZE);
|
|
1820
|
+
continue;
|
|
1821
|
+
}
|
|
1822
|
+
let srcIndex = globalY * targetWidth + startX;
|
|
1823
|
+
let rowData = src.subarray(srcIndex, srcIndex + copyWidth);
|
|
1824
|
+
dst.set(rowData, dstIndex);
|
|
1825
|
+
if (copyWidth < TILE_SIZE) {
|
|
1826
|
+
dst.fill(0, dstIndex + copyWidth, dstIndex + TILE_SIZE);
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
extractAfterTiles() {
|
|
1831
|
+
let afterTiles = [];
|
|
1832
|
+
let length = this.beforeTiles.length;
|
|
1833
|
+
for (let i = 0; i < length; i++) {
|
|
1834
|
+
let beforeTile = this.beforeTiles[i];
|
|
1835
|
+
if (beforeTile) {
|
|
1836
|
+
let afterTile = this.getTile(
|
|
1837
|
+
beforeTile.id,
|
|
1838
|
+
beforeTile.tx,
|
|
1839
|
+
beforeTile.ty
|
|
1840
|
+
);
|
|
1841
|
+
this.extractState(afterTile);
|
|
1842
|
+
afterTiles.push(afterTile);
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
return afterTiles;
|
|
1846
|
+
}
|
|
1847
|
+
reset() {
|
|
1848
|
+
this.lookup = [];
|
|
1849
|
+
this.beforeTiles = [];
|
|
1619
1850
|
}
|
|
1620
|
-
return imageData;
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
// src/Internal/resample32.ts
|
|
1624
|
-
var resample32Scratch = {
|
|
1625
|
-
data: null,
|
|
1626
|
-
width: 0,
|
|
1627
|
-
height: 0
|
|
1628
1851
|
};
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1852
|
+
|
|
1853
|
+
// src/History/HistoryManager.ts
|
|
1854
|
+
var HistoryManager = class {
|
|
1855
|
+
constructor(maxSteps = 50) {
|
|
1856
|
+
this.maxSteps = maxSteps;
|
|
1857
|
+
this.undoStack = [];
|
|
1858
|
+
this.redoStack = [];
|
|
1859
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
1860
|
+
}
|
|
1861
|
+
undoStack;
|
|
1862
|
+
redoStack;
|
|
1863
|
+
listeners;
|
|
1864
|
+
get canUndo() {
|
|
1865
|
+
return this.undoStack.length > 0;
|
|
1866
|
+
}
|
|
1867
|
+
get canRedo() {
|
|
1868
|
+
return this.redoStack.length > 0;
|
|
1869
|
+
}
|
|
1870
|
+
subscribe(fn) {
|
|
1871
|
+
this.listeners.add(fn);
|
|
1872
|
+
return () => this.listeners.delete(fn);
|
|
1873
|
+
}
|
|
1874
|
+
notify() {
|
|
1875
|
+
this.listeners.forEach((fn) => fn());
|
|
1876
|
+
}
|
|
1877
|
+
commit(action) {
|
|
1878
|
+
this.undoStack.push(action);
|
|
1879
|
+
this.clearRedoStack();
|
|
1880
|
+
if (this.undoStack.length > this.maxSteps) {
|
|
1881
|
+
this.undoStack.shift()?.dispose?.();
|
|
1882
|
+
}
|
|
1883
|
+
this.notify();
|
|
1884
|
+
}
|
|
1885
|
+
undo() {
|
|
1886
|
+
let action = this.undoStack.pop();
|
|
1887
|
+
if (!action) return;
|
|
1888
|
+
this.redoStack.push(action);
|
|
1889
|
+
action.undo();
|
|
1890
|
+
this.notify();
|
|
1891
|
+
}
|
|
1892
|
+
redo() {
|
|
1893
|
+
let action = this.redoStack.pop();
|
|
1894
|
+
if (!action) return;
|
|
1895
|
+
this.undoStack.push(action);
|
|
1896
|
+
action.redo();
|
|
1897
|
+
this.notify();
|
|
1898
|
+
}
|
|
1899
|
+
clearRedoStack() {
|
|
1900
|
+
let length = this.redoStack.length;
|
|
1901
|
+
for (let i = 0; i < length; i++) {
|
|
1902
|
+
let action = this.redoStack[i];
|
|
1903
|
+
if (action) {
|
|
1904
|
+
action.dispose?.();
|
|
1905
|
+
}
|
|
1642
1906
|
}
|
|
1907
|
+
this.redoStack.length = 0;
|
|
1643
1908
|
}
|
|
1644
|
-
|
|
1645
|
-
resample32Scratch.width = dstW;
|
|
1646
|
-
resample32Scratch.height = dstH;
|
|
1647
|
-
return resample32Scratch;
|
|
1648
|
-
}
|
|
1909
|
+
};
|
|
1649
1910
|
|
|
1650
|
-
// src/
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1911
|
+
// src/History/PixelEngineConfig.ts
|
|
1912
|
+
var PixelEngineConfig = class {
|
|
1913
|
+
tileSize;
|
|
1914
|
+
tileShift;
|
|
1915
|
+
tileMask;
|
|
1916
|
+
tileArea;
|
|
1917
|
+
constructor(tileSize = 256) {
|
|
1918
|
+
if ((tileSize & tileSize - 1) !== 0) {
|
|
1919
|
+
throw new Error("tileSize must be a power of 2");
|
|
1920
|
+
}
|
|
1921
|
+
this.tileSize = tileSize;
|
|
1922
|
+
this.tileShift = Math.log2(tileSize);
|
|
1923
|
+
this.tileMask = tileSize - 1;
|
|
1924
|
+
this.tileArea = tileSize * tileSize;
|
|
1925
|
+
}
|
|
1926
|
+
};
|
|
1657
1927
|
|
|
1658
|
-
// src/
|
|
1659
|
-
function
|
|
1660
|
-
const result = new ImageData(newWidth, newHeight);
|
|
1928
|
+
// src/PixelData/applyMaskToPixelData.ts
|
|
1929
|
+
function applyMaskToPixelData(dst, mask, opts = {}) {
|
|
1661
1930
|
const {
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1931
|
+
x: targetX = 0,
|
|
1932
|
+
y: targetY = 0,
|
|
1933
|
+
w: width = dst.width,
|
|
1934
|
+
h: height = dst.height,
|
|
1935
|
+
alpha: globalAlpha = 255,
|
|
1936
|
+
maskType = 0 /* ALPHA */,
|
|
1937
|
+
mw,
|
|
1938
|
+
mx = 0,
|
|
1939
|
+
my = 0,
|
|
1940
|
+
invertMask = false
|
|
1941
|
+
} = opts;
|
|
1942
|
+
let x = targetX;
|
|
1943
|
+
let y = targetY;
|
|
1944
|
+
let w = width;
|
|
1945
|
+
let h = height;
|
|
1946
|
+
if (x < 0) {
|
|
1947
|
+
w += x;
|
|
1948
|
+
x = 0;
|
|
1673
1949
|
}
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1950
|
+
if (y < 0) {
|
|
1951
|
+
h += y;
|
|
1952
|
+
y = 0;
|
|
1953
|
+
}
|
|
1954
|
+
const actualW = Math.min(w, dst.width - x);
|
|
1955
|
+
const actualH = Math.min(h, dst.height - y);
|
|
1956
|
+
if (actualW <= 0 || actualH <= 0 || globalAlpha === 0) {
|
|
1957
|
+
return;
|
|
1958
|
+
}
|
|
1959
|
+
const dst32 = dst.data32;
|
|
1960
|
+
const dw = dst.width;
|
|
1961
|
+
const mPitch = mw ?? width;
|
|
1962
|
+
const isAlpha = maskType === 0 /* ALPHA */;
|
|
1963
|
+
const dx = x - targetX;
|
|
1964
|
+
const dy = y - targetY;
|
|
1965
|
+
let dIdx = y * dw + x;
|
|
1966
|
+
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
1967
|
+
const dStride = dw - actualW;
|
|
1968
|
+
const mStride = mPitch - actualW;
|
|
1969
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
1970
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
1971
|
+
const mVal = mask[mIdx];
|
|
1972
|
+
let weight = globalAlpha;
|
|
1973
|
+
if (isAlpha) {
|
|
1974
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
1975
|
+
if (effectiveM === 0) {
|
|
1976
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
1977
|
+
dIdx++;
|
|
1978
|
+
mIdx++;
|
|
1979
|
+
continue;
|
|
1980
|
+
}
|
|
1981
|
+
weight = globalAlpha === 255 ? effectiveM : effectiveM * globalAlpha + 128 >> 8;
|
|
1982
|
+
} else {
|
|
1983
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
1984
|
+
if (!isHit) {
|
|
1985
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
1986
|
+
dIdx++;
|
|
1987
|
+
mIdx++;
|
|
1988
|
+
continue;
|
|
1989
|
+
}
|
|
1990
|
+
weight = globalAlpha;
|
|
1991
|
+
}
|
|
1992
|
+
if (weight === 0) {
|
|
1993
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
1994
|
+
} else {
|
|
1995
|
+
const d = dst32[dIdx];
|
|
1996
|
+
const da = d >>> 24;
|
|
1997
|
+
let finalAlpha = da;
|
|
1998
|
+
if (da === 0) {
|
|
1999
|
+
} else if (weight === 255) {
|
|
2000
|
+
} else if (da === 255) {
|
|
2001
|
+
finalAlpha = weight;
|
|
2002
|
+
} else {
|
|
2003
|
+
finalAlpha = da * weight + 128 >> 8;
|
|
2004
|
+
}
|
|
2005
|
+
dst32[dIdx] = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
2006
|
+
}
|
|
2007
|
+
dIdx++;
|
|
2008
|
+
mIdx++;
|
|
2009
|
+
}
|
|
2010
|
+
dIdx += dStride;
|
|
2011
|
+
mIdx += mStride;
|
|
1686
2012
|
}
|
|
1687
|
-
return result;
|
|
1688
2013
|
}
|
|
1689
2014
|
|
|
1690
|
-
// src/
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
2015
|
+
// src/History/PixelWriter.ts
|
|
2016
|
+
var PixelWriter = class {
|
|
2017
|
+
target;
|
|
2018
|
+
historyManager;
|
|
2019
|
+
accumulator;
|
|
2020
|
+
config;
|
|
2021
|
+
mutator;
|
|
2022
|
+
constructor(target, mutatorFactory, {
|
|
2023
|
+
tileSize = 256,
|
|
2024
|
+
maxHistorySteps = 50,
|
|
2025
|
+
historyManager = new HistoryManager(maxHistorySteps)
|
|
2026
|
+
} = {}) {
|
|
2027
|
+
this.target = target;
|
|
2028
|
+
this.config = new PixelEngineConfig(tileSize);
|
|
2029
|
+
this.historyManager = historyManager;
|
|
2030
|
+
this.accumulator = new PixelAccumulator(target, this.config);
|
|
2031
|
+
this.mutator = mutatorFactory(this);
|
|
2032
|
+
}
|
|
2033
|
+
withHistory(cb) {
|
|
2034
|
+
cb(this.mutator);
|
|
2035
|
+
const beforeTiles = this.accumulator.beforeTiles;
|
|
2036
|
+
if (beforeTiles.length === 0) return;
|
|
2037
|
+
const afterTiles = this.accumulator.extractAfterTiles();
|
|
2038
|
+
const patch = {
|
|
2039
|
+
beforeTiles,
|
|
2040
|
+
afterTiles
|
|
2041
|
+
};
|
|
2042
|
+
const target = this.target;
|
|
2043
|
+
const tileSize = this.config.tileSize;
|
|
2044
|
+
const accumulator = this.accumulator;
|
|
2045
|
+
const action = {
|
|
2046
|
+
undo: () => applyPatchTiles(target, patch.beforeTiles, tileSize),
|
|
2047
|
+
redo: () => applyPatchTiles(target, patch.afterTiles, tileSize),
|
|
2048
|
+
dispose: () => accumulator.recyclePatch(patch)
|
|
2049
|
+
};
|
|
2050
|
+
this.historyManager.commit(action);
|
|
2051
|
+
this.accumulator.reset();
|
|
1702
2052
|
}
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
width: imageData.width,
|
|
1708
|
-
height: imageData.height,
|
|
1709
|
-
data: base64EncodeArrayBuffer(imageData.data.buffer)
|
|
1710
|
-
};
|
|
1711
|
-
}
|
|
1712
|
-
function serializeNullableImageData(imageData) {
|
|
1713
|
-
if (!imageData) return null;
|
|
1714
|
-
return serializeImageData(imageData);
|
|
1715
|
-
}
|
|
1716
|
-
function deserializeRawImageData(serialized) {
|
|
2053
|
+
};
|
|
2054
|
+
|
|
2055
|
+
// src/History/PixelMutator/mutatorApplyMask.ts
|
|
2056
|
+
function mutatorApplyMask(writer) {
|
|
1717
2057
|
return {
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
2058
|
+
applyMask: (mask, opts = {}) => {
|
|
2059
|
+
let target = writer.target;
|
|
2060
|
+
const {
|
|
2061
|
+
x = 0,
|
|
2062
|
+
y = 0,
|
|
2063
|
+
w = writer.target.width,
|
|
2064
|
+
h = writer.target.height
|
|
2065
|
+
} = opts;
|
|
2066
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2067
|
+
applyMaskToPixelData(target, mask, opts);
|
|
2068
|
+
}
|
|
1721
2069
|
};
|
|
1722
2070
|
}
|
|
1723
|
-
function deserializeImageData(serialized) {
|
|
1724
|
-
const data = base64DecodeArrayBuffer(serialized.data);
|
|
1725
|
-
return new ImageData(data, serialized.width, serialized.height);
|
|
1726
|
-
}
|
|
1727
|
-
function deserializeNullableImageData(serialized) {
|
|
1728
|
-
if (!serialized) return null;
|
|
1729
|
-
return deserializeImageData(serialized);
|
|
1730
|
-
}
|
|
1731
2071
|
|
|
1732
|
-
// src/
|
|
1733
|
-
function
|
|
1734
|
-
const
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
2072
|
+
// src/PixelData/blendColorPixelData.ts
|
|
2073
|
+
function blendColorPixelData(dst, color, opts = {}) {
|
|
2074
|
+
const {
|
|
2075
|
+
x: targetX = 0,
|
|
2076
|
+
y: targetY = 0,
|
|
2077
|
+
w: width = dst.width,
|
|
2078
|
+
h: height = dst.height,
|
|
2079
|
+
alpha: globalAlpha = 255,
|
|
2080
|
+
blendFn = sourceOverFast,
|
|
2081
|
+
mask,
|
|
2082
|
+
maskType = 0 /* ALPHA */,
|
|
2083
|
+
mw,
|
|
2084
|
+
mx = 0,
|
|
2085
|
+
my = 0,
|
|
2086
|
+
invertMask = false
|
|
2087
|
+
} = opts;
|
|
2088
|
+
if (globalAlpha === 0) return;
|
|
2089
|
+
const baseSrcAlpha = color >>> 24;
|
|
2090
|
+
const isOverwrite = blendFn.isOverwrite;
|
|
2091
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2092
|
+
let x = targetX;
|
|
2093
|
+
let y = targetY;
|
|
2094
|
+
let w = width;
|
|
2095
|
+
let h = height;
|
|
2096
|
+
if (x < 0) {
|
|
2097
|
+
w += x;
|
|
2098
|
+
x = 0;
|
|
1745
2099
|
}
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
2100
|
+
if (y < 0) {
|
|
2101
|
+
h += y;
|
|
2102
|
+
y = 0;
|
|
2103
|
+
}
|
|
2104
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2105
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2106
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
2107
|
+
const dst32 = dst.data32;
|
|
2108
|
+
const dw = dst.width;
|
|
2109
|
+
const mPitch = mw ?? width;
|
|
2110
|
+
const isAlphaMask = maskType === 0 /* ALPHA */;
|
|
2111
|
+
const dx = x - targetX;
|
|
2112
|
+
const dy = y - targetY;
|
|
2113
|
+
let dIdx = y * dw + x;
|
|
2114
|
+
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2115
|
+
const dStride = dw - actualW;
|
|
2116
|
+
const mStride = mPitch - actualW;
|
|
2117
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2118
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2119
|
+
let weight = globalAlpha;
|
|
2120
|
+
if (mask) {
|
|
2121
|
+
const mVal = mask[mIdx];
|
|
2122
|
+
if (isAlphaMask) {
|
|
2123
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2124
|
+
if (effectiveM === 0) {
|
|
2125
|
+
dIdx++;
|
|
2126
|
+
mIdx++;
|
|
2127
|
+
continue;
|
|
2128
|
+
}
|
|
2129
|
+
if (globalAlpha === 255) {
|
|
2130
|
+
weight = effectiveM;
|
|
2131
|
+
} else if (effectiveM === 255) {
|
|
2132
|
+
weight = globalAlpha;
|
|
2133
|
+
} else {
|
|
2134
|
+
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2135
|
+
}
|
|
2136
|
+
} else {
|
|
2137
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2138
|
+
if (!isHit) {
|
|
2139
|
+
dIdx++;
|
|
2140
|
+
mIdx++;
|
|
2141
|
+
continue;
|
|
2142
|
+
}
|
|
2143
|
+
weight = globalAlpha;
|
|
2144
|
+
}
|
|
2145
|
+
if (weight === 0) {
|
|
2146
|
+
dIdx++;
|
|
2147
|
+
mIdx++;
|
|
1760
2148
|
continue;
|
|
1761
2149
|
}
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
dstData[di + 3] = srcData[si + 3];
|
|
2150
|
+
}
|
|
2151
|
+
let currentSrcColor = color;
|
|
2152
|
+
if (weight < 255) {
|
|
2153
|
+
let currentSrcAlpha = baseSrcAlpha;
|
|
2154
|
+
if (baseSrcAlpha === 255) {
|
|
2155
|
+
currentSrcAlpha = weight;
|
|
1769
2156
|
} else {
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
2157
|
+
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2158
|
+
}
|
|
2159
|
+
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
2160
|
+
dIdx++;
|
|
2161
|
+
mIdx++;
|
|
2162
|
+
continue;
|
|
1776
2163
|
}
|
|
2164
|
+
currentSrcColor = (color & 16777215 | currentSrcAlpha << 24) >>> 0;
|
|
1777
2165
|
}
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
dstData.set(sub, dstStart);
|
|
2166
|
+
dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
|
|
2167
|
+
dIdx++;
|
|
2168
|
+
mIdx++;
|
|
1782
2169
|
}
|
|
2170
|
+
dIdx += dStride;
|
|
2171
|
+
mIdx += mStride;
|
|
1783
2172
|
}
|
|
1784
2173
|
}
|
|
1785
2174
|
|
|
1786
|
-
// src/
|
|
1787
|
-
function
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
2175
|
+
// src/History/PixelMutator/mutatorBlendColor.ts
|
|
2176
|
+
function mutatorBlendColor(writer) {
|
|
2177
|
+
return {
|
|
2178
|
+
blendColor(color, opts = {}) {
|
|
2179
|
+
const {
|
|
2180
|
+
x = 0,
|
|
2181
|
+
y = 0,
|
|
2182
|
+
w = writer.target.width,
|
|
2183
|
+
h = writer.target.height
|
|
2184
|
+
} = opts;
|
|
2185
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2186
|
+
blendColorPixelData(writer.target, color, opts);
|
|
2187
|
+
}
|
|
2188
|
+
};
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
// src/History/PixelMutator/mutatorBlendPixel.ts
|
|
2192
|
+
function mutatorBlendPixel(writer) {
|
|
2193
|
+
return {
|
|
2194
|
+
blendPixel(x, y, color, alpha = 255, blendFn = overwriteFast) {
|
|
2195
|
+
let target = writer.target;
|
|
2196
|
+
let width = target.width;
|
|
2197
|
+
let height = target.height;
|
|
2198
|
+
if (x < 0 || x >= width || y < 0 || y >= height) return;
|
|
2199
|
+
writer.accumulator.storeTileBeforeState(x, y);
|
|
2200
|
+
let index = y * width + x;
|
|
2201
|
+
let bg = target.data32[index];
|
|
2202
|
+
let finalColor = color;
|
|
2203
|
+
if (alpha < 255) {
|
|
2204
|
+
let baseSrcAlpha = color >>> 24;
|
|
2205
|
+
let finalAlpha = baseSrcAlpha * alpha + 128 >> 8;
|
|
2206
|
+
finalColor = (color & 16777215 | finalAlpha << 24) >>> 0;
|
|
2207
|
+
}
|
|
2208
|
+
target.data32[index] = blendFn(finalColor, bg);
|
|
2209
|
+
}
|
|
2210
|
+
};
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
// src/PixelData/blendPixelData.ts
|
|
2214
|
+
function blendPixelData(dst, src, opts) {
|
|
2215
|
+
const {
|
|
2216
|
+
x: targetX = 0,
|
|
2217
|
+
y: targetY = 0,
|
|
2218
|
+
sx: sourceX = 0,
|
|
2219
|
+
sy: sourceY = 0,
|
|
2220
|
+
w: width = src.width,
|
|
2221
|
+
h: height = src.height,
|
|
2222
|
+
alpha: globalAlpha = 255,
|
|
2223
|
+
blendFn = sourceOverFast,
|
|
2224
|
+
mask,
|
|
2225
|
+
maskType = 0 /* ALPHA */,
|
|
2226
|
+
mw,
|
|
2227
|
+
mx = 0,
|
|
2228
|
+
my = 0,
|
|
2229
|
+
invertMask = false
|
|
2230
|
+
} = opts;
|
|
2231
|
+
if (globalAlpha === 0) return;
|
|
2232
|
+
let x = targetX;
|
|
2233
|
+
let y = targetY;
|
|
2234
|
+
let sx = sourceX;
|
|
2235
|
+
let sy = sourceY;
|
|
2236
|
+
let w = width;
|
|
2237
|
+
let h = height;
|
|
2238
|
+
if (sx < 0) {
|
|
2239
|
+
x -= sx;
|
|
2240
|
+
w += sx;
|
|
2241
|
+
sx = 0;
|
|
2242
|
+
}
|
|
2243
|
+
if (sy < 0) {
|
|
2244
|
+
y -= sy;
|
|
2245
|
+
h += sy;
|
|
2246
|
+
sy = 0;
|
|
2247
|
+
}
|
|
2248
|
+
w = Math.min(w, src.width - sx);
|
|
2249
|
+
h = Math.min(h, src.height - sy);
|
|
2250
|
+
if (x < 0) {
|
|
2251
|
+
sx -= x;
|
|
2252
|
+
w += x;
|
|
2253
|
+
x = 0;
|
|
2254
|
+
}
|
|
2255
|
+
if (y < 0) {
|
|
2256
|
+
sy -= y;
|
|
2257
|
+
h += y;
|
|
2258
|
+
y = 0;
|
|
2259
|
+
}
|
|
2260
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2261
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2262
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
2263
|
+
const dst32 = dst.data32;
|
|
2264
|
+
const src32 = src.data32;
|
|
2265
|
+
const dw = dst.width;
|
|
2266
|
+
const sw = src.width;
|
|
2267
|
+
const mPitch = mw ?? width;
|
|
2268
|
+
const isAlphaMask = maskType === 0 /* ALPHA */;
|
|
2269
|
+
const dx = x - targetX;
|
|
2270
|
+
const dy = y - targetY;
|
|
2271
|
+
let dIdx = y * dw + x;
|
|
2272
|
+
let sIdx = sy * sw + sx;
|
|
2273
|
+
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2274
|
+
const dStride = dw - actualW;
|
|
2275
|
+
const sStride = sw - actualW;
|
|
2276
|
+
const mStride = mPitch - actualW;
|
|
2277
|
+
const isOverwrite = blendFn.isOverwrite;
|
|
2278
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2279
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2280
|
+
const baseSrcColor = src32[sIdx];
|
|
2281
|
+
const baseSrcAlpha = baseSrcColor >>> 24;
|
|
2282
|
+
if (baseSrcAlpha === 0 && !isOverwrite) {
|
|
2283
|
+
dIdx++;
|
|
2284
|
+
sIdx++;
|
|
2285
|
+
mIdx++;
|
|
2286
|
+
continue;
|
|
2287
|
+
}
|
|
2288
|
+
let weight = globalAlpha;
|
|
2289
|
+
if (mask) {
|
|
2290
|
+
const mVal = mask[mIdx];
|
|
2291
|
+
if (isAlphaMask) {
|
|
2292
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2293
|
+
if (effectiveM === 0) {
|
|
2294
|
+
dIdx++;
|
|
2295
|
+
sIdx++;
|
|
2296
|
+
mIdx++;
|
|
2297
|
+
continue;
|
|
2298
|
+
}
|
|
2299
|
+
if (globalAlpha === 255) {
|
|
2300
|
+
weight = effectiveM;
|
|
2301
|
+
} else if (effectiveM === 255) {
|
|
2302
|
+
weight = globalAlpha;
|
|
2303
|
+
} else {
|
|
2304
|
+
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2305
|
+
}
|
|
2306
|
+
} else {
|
|
2307
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2308
|
+
if (!isHit) {
|
|
2309
|
+
dIdx++;
|
|
2310
|
+
sIdx++;
|
|
2311
|
+
mIdx++;
|
|
2312
|
+
continue;
|
|
2313
|
+
}
|
|
2314
|
+
weight = globalAlpha;
|
|
2315
|
+
}
|
|
2316
|
+
if (weight === 0) {
|
|
2317
|
+
dIdx++;
|
|
2318
|
+
sIdx++;
|
|
2319
|
+
mIdx++;
|
|
2320
|
+
continue;
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
let currentSrcColor = baseSrcColor;
|
|
2324
|
+
if (weight < 255) {
|
|
2325
|
+
let currentSrcAlpha = baseSrcAlpha;
|
|
2326
|
+
if (baseSrcAlpha === 255) {
|
|
2327
|
+
currentSrcAlpha = weight;
|
|
2328
|
+
} else {
|
|
2329
|
+
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2330
|
+
}
|
|
2331
|
+
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
2332
|
+
dIdx++;
|
|
2333
|
+
sIdx++;
|
|
2334
|
+
mIdx++;
|
|
2335
|
+
continue;
|
|
2336
|
+
}
|
|
2337
|
+
currentSrcColor = (baseSrcColor & 16777215 | currentSrcAlpha << 24) >>> 0;
|
|
2338
|
+
}
|
|
2339
|
+
dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
|
|
2340
|
+
dIdx++;
|
|
2341
|
+
sIdx++;
|
|
2342
|
+
mIdx++;
|
|
2343
|
+
}
|
|
2344
|
+
dIdx += dStride;
|
|
2345
|
+
sIdx += sStride;
|
|
2346
|
+
mIdx += mStride;
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
|
|
2350
|
+
// src/History/PixelMutator/mutatorBlendPixelData.ts
|
|
2351
|
+
function mutatorBlendPixelData(writer) {
|
|
2352
|
+
return {
|
|
2353
|
+
blendPixelData(src, opts) {
|
|
2354
|
+
const {
|
|
2355
|
+
x = 0,
|
|
2356
|
+
y = 0,
|
|
2357
|
+
w = src.width,
|
|
2358
|
+
h = src.height
|
|
2359
|
+
} = opts;
|
|
2360
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2361
|
+
blendPixelData(writer.target, src, opts);
|
|
2362
|
+
}
|
|
2363
|
+
};
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
// src/PixelData/fillPixelData.ts
|
|
2367
|
+
function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
2368
|
+
let x;
|
|
2369
|
+
let y;
|
|
2370
|
+
let w;
|
|
2371
|
+
let h;
|
|
2372
|
+
if (typeof _x === "object") {
|
|
2373
|
+
x = _x.x ?? 0;
|
|
2374
|
+
y = _x.y ?? 0;
|
|
2375
|
+
w = _x.w ?? dst.width;
|
|
2376
|
+
h = _x.h ?? dst.height;
|
|
2377
|
+
} else if (typeof _x === "number") {
|
|
2378
|
+
x = _x;
|
|
2379
|
+
y = _y;
|
|
2380
|
+
w = _w;
|
|
2381
|
+
h = _h;
|
|
2382
|
+
} else {
|
|
2383
|
+
x = 0;
|
|
2384
|
+
y = 0;
|
|
2385
|
+
w = dst.width;
|
|
2386
|
+
h = dst.height;
|
|
2387
|
+
}
|
|
2388
|
+
if (x < 0) {
|
|
2389
|
+
w += x;
|
|
2390
|
+
x = 0;
|
|
2391
|
+
}
|
|
2392
|
+
if (y < 0) {
|
|
2393
|
+
h += y;
|
|
2394
|
+
y = 0;
|
|
2395
|
+
}
|
|
2396
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2397
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2398
|
+
if (actualW <= 0 || actualH <= 0) {
|
|
2399
|
+
return;
|
|
2400
|
+
}
|
|
2401
|
+
const dst32 = dst.data32;
|
|
2402
|
+
const dw = dst.width;
|
|
2403
|
+
if (actualW === dw && actualH === dst.height && x === 0 && y === 0) {
|
|
2404
|
+
dst32.fill(color);
|
|
2405
|
+
return;
|
|
2406
|
+
}
|
|
2407
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2408
|
+
const start = (y + iy) * dw + x;
|
|
2409
|
+
const end = start + actualW;
|
|
2410
|
+
dst32.fill(color, start, end);
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
|
|
2414
|
+
// src/History/PixelMutator/mutatorFillPixelData.ts
|
|
2415
|
+
function mutatorFill(writer) {
|
|
2416
|
+
return {
|
|
2417
|
+
fill(color, rect = {}) {
|
|
2418
|
+
const {
|
|
2419
|
+
x = 0,
|
|
2420
|
+
y = 0,
|
|
2421
|
+
w = writer.target.width,
|
|
2422
|
+
h = writer.target.height
|
|
2423
|
+
} = rect;
|
|
2424
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2425
|
+
fillPixelData(writer.target, color, x, y, w, h);
|
|
2426
|
+
}
|
|
2427
|
+
};
|
|
2428
|
+
}
|
|
2429
|
+
|
|
2430
|
+
// src/PixelData/invertPixelData.ts
|
|
2431
|
+
function invertPixelData(pixelData, opts = {}) {
|
|
2432
|
+
const dst = pixelData;
|
|
2433
|
+
const {
|
|
2434
|
+
x: targetX = 0,
|
|
2435
|
+
y: targetY = 0,
|
|
2436
|
+
w: width = pixelData.width,
|
|
2437
|
+
h: height = pixelData.height,
|
|
2438
|
+
mask,
|
|
2439
|
+
mw,
|
|
2440
|
+
mx = 0,
|
|
2441
|
+
my = 0,
|
|
2442
|
+
invertMask = false
|
|
2443
|
+
} = opts;
|
|
2444
|
+
let x = targetX;
|
|
2445
|
+
let y = targetY;
|
|
2446
|
+
let w = width;
|
|
2447
|
+
let h = height;
|
|
2448
|
+
if (x < 0) {
|
|
2449
|
+
w += x;
|
|
2450
|
+
x = 0;
|
|
2451
|
+
}
|
|
2452
|
+
if (y < 0) {
|
|
2453
|
+
h += y;
|
|
2454
|
+
y = 0;
|
|
2455
|
+
}
|
|
2456
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2457
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2458
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
2459
|
+
const dst32 = dst.data32;
|
|
2460
|
+
const dw = dst.width;
|
|
2461
|
+
const mPitch = mw ?? width;
|
|
2462
|
+
const dx = x - targetX;
|
|
2463
|
+
const dy = y - targetY;
|
|
2464
|
+
let dIdx = y * dw + x;
|
|
2465
|
+
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2466
|
+
const dStride = dw - actualW;
|
|
2467
|
+
const mStride = mPitch - actualW;
|
|
2468
|
+
if (mask) {
|
|
2469
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2470
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2471
|
+
const mVal = mask[mIdx];
|
|
2472
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2473
|
+
if (isHit) {
|
|
2474
|
+
dst32[dIdx] = dst32[dIdx] ^ 16777215;
|
|
2475
|
+
}
|
|
2476
|
+
dIdx++;
|
|
2477
|
+
mIdx++;
|
|
2478
|
+
}
|
|
2479
|
+
dIdx += dStride;
|
|
2480
|
+
mIdx += mStride;
|
|
2481
|
+
}
|
|
2482
|
+
} else {
|
|
2483
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2484
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2485
|
+
dst32[dIdx] = dst32[dIdx] ^ 16777215;
|
|
2486
|
+
dIdx++;
|
|
2487
|
+
}
|
|
2488
|
+
dIdx += dStride;
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2493
|
+
// src/History/PixelMutator/mutatorInvert.ts
|
|
2494
|
+
function mutatorInvert(writer) {
|
|
2495
|
+
return {
|
|
2496
|
+
invert(opts = {}) {
|
|
2497
|
+
const {
|
|
2498
|
+
x = 0,
|
|
2499
|
+
y = 0,
|
|
2500
|
+
w = writer.target.width,
|
|
2501
|
+
h = writer.target.height
|
|
2502
|
+
} = opts;
|
|
2503
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2504
|
+
invertPixelData(writer.target, opts);
|
|
2505
|
+
}
|
|
2506
|
+
};
|
|
2507
|
+
}
|
|
2508
|
+
|
|
2509
|
+
// src/History/PixelMutator.ts
|
|
2510
|
+
function makeFullPixelMutator(writer) {
|
|
2511
|
+
return {
|
|
2512
|
+
...mutatorApplyMask(writer),
|
|
2513
|
+
...mutatorBlendPixelData(writer),
|
|
2514
|
+
...mutatorBlendColor(writer),
|
|
2515
|
+
...mutatorBlendPixel(writer),
|
|
2516
|
+
...mutatorFill(writer),
|
|
2517
|
+
...mutatorInvert(writer)
|
|
2518
|
+
};
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
// src/ImageData/ReusableImageData.ts
|
|
2522
|
+
function makeReusableImageData() {
|
|
2523
|
+
let imageData = null;
|
|
2524
|
+
let buffer = null;
|
|
2525
|
+
return function getReusableImageData(width, height) {
|
|
2526
|
+
const hasInstance = !!imageData;
|
|
2527
|
+
const widthMatches = hasInstance && imageData.width === width;
|
|
2528
|
+
const heightMatches = hasInstance && imageData.height === height;
|
|
2529
|
+
if (!widthMatches || !heightMatches) {
|
|
2530
|
+
const buffer2 = new Uint8ClampedArray(width * height * 4);
|
|
2531
|
+
imageData = new ImageData(buffer2, width, height);
|
|
2532
|
+
}
|
|
2533
|
+
return imageData;
|
|
2534
|
+
};
|
|
2535
|
+
}
|
|
2536
|
+
|
|
2537
|
+
// src/ImageData/copyImageData.ts
|
|
2538
|
+
function copyImageData({ data, width, height }) {
|
|
2539
|
+
return new ImageData(data.slice(), width, height);
|
|
2540
|
+
}
|
|
2541
|
+
function copyImageDataLike({ data, width, height }) {
|
|
2542
|
+
return {
|
|
2543
|
+
data: data.slice(),
|
|
2544
|
+
width,
|
|
2545
|
+
height
|
|
2546
|
+
};
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2549
|
+
// src/PixelData/pixelDataToAlphaMask.ts
|
|
2550
|
+
function pixelDataToAlphaMask(pixelData) {
|
|
2551
|
+
const {
|
|
2552
|
+
data32,
|
|
2553
|
+
width,
|
|
2554
|
+
height
|
|
2555
|
+
} = pixelData;
|
|
2556
|
+
const len = data32.length;
|
|
2557
|
+
const mask = new Uint8Array(width * height);
|
|
2558
|
+
for (let i = 0; i < len; i++) {
|
|
2559
|
+
const val = data32[i];
|
|
2560
|
+
mask[i] = val >>> 24 & 255;
|
|
2561
|
+
}
|
|
2562
|
+
return mask;
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2565
|
+
// src/ImageData/imageDataToAlphaMask.ts
|
|
2566
|
+
function imageDataToAlphaMask(imageData) {
|
|
2567
|
+
const {
|
|
2568
|
+
width,
|
|
2569
|
+
height,
|
|
2570
|
+
data
|
|
2571
|
+
} = imageData;
|
|
2572
|
+
const data32 = new Uint32Array(
|
|
2573
|
+
data.buffer,
|
|
2574
|
+
data.byteOffset,
|
|
2575
|
+
data.byteLength >> 2
|
|
2576
|
+
);
|
|
2577
|
+
const len = data32.length;
|
|
2578
|
+
const mask = new Uint8Array(width * height);
|
|
2579
|
+
for (let i = 0; i < len; i++) {
|
|
2580
|
+
const val = data32[i];
|
|
2581
|
+
mask[i] = val >>> 24 & 255;
|
|
2582
|
+
}
|
|
2583
|
+
return mask;
|
|
2584
|
+
}
|
|
2585
|
+
|
|
2586
|
+
// src/ImageData/imageDataToDataUrl.ts
|
|
2587
|
+
var get = makeReusableCanvas();
|
|
2588
|
+
function imageDataToDataUrl(imageData) {
|
|
2589
|
+
const { canvas, ctx } = get(imageData.width, imageData.height);
|
|
2590
|
+
ctx.putImageData(imageData, 0, 0);
|
|
2591
|
+
return canvas.toDataURL();
|
|
2592
|
+
}
|
|
2593
|
+
imageDataToDataUrl.reset = get.reset;
|
|
2594
|
+
|
|
2595
|
+
// src/ImageData/imageDataToUInt32Array.ts
|
|
2596
|
+
function imageDataToUInt32Array(imageData) {
|
|
2597
|
+
return new Uint32Array(
|
|
2598
|
+
imageData.data.buffer,
|
|
2599
|
+
imageData.data.byteOffset,
|
|
2600
|
+
// Shift right by 2 is a fast bitwise division by 4.
|
|
2601
|
+
imageData.data.byteLength >> 2
|
|
2602
|
+
);
|
|
2603
|
+
}
|
|
2604
|
+
|
|
2605
|
+
// src/ImageData/invertImageData.ts
|
|
2606
|
+
function invertImageData(imageData) {
|
|
2607
|
+
const data = imageData.data;
|
|
2608
|
+
let length = data.length;
|
|
2609
|
+
for (let i = 0; i < length; i += 4) {
|
|
2610
|
+
data[i] = 255 - data[i];
|
|
2611
|
+
data[i + 1] = 255 - data[i + 1];
|
|
2612
|
+
data[i + 2] = 255 - data[i + 2];
|
|
2613
|
+
}
|
|
2614
|
+
return imageData;
|
|
2615
|
+
}
|
|
2616
|
+
|
|
2617
|
+
// src/Internal/resample32.ts
|
|
2618
|
+
var resample32Scratch = {
|
|
2619
|
+
data: null,
|
|
2620
|
+
width: 0,
|
|
2621
|
+
height: 0
|
|
2622
|
+
};
|
|
2623
|
+
function resample32(srcData32, srcW, srcH, factor) {
|
|
2624
|
+
const dstW = Math.max(1, srcW * factor | 0);
|
|
2625
|
+
const dstH = Math.max(1, srcH * factor | 0);
|
|
2626
|
+
const dstData = new Int32Array(dstW * dstH);
|
|
2627
|
+
const scaleX = srcW / dstW;
|
|
2628
|
+
const scaleY = srcH / dstH;
|
|
2629
|
+
for (let y = 0; y < dstH; y++) {
|
|
2630
|
+
const srcY = Math.min(srcH - 1, y * scaleY | 0);
|
|
2631
|
+
const srcRowOffset = srcY * srcW;
|
|
2632
|
+
const dstRowOffset = y * dstW;
|
|
2633
|
+
for (let x = 0; x < dstW; x++) {
|
|
2634
|
+
const srcX = Math.min(srcW - 1, x * scaleX | 0);
|
|
2635
|
+
dstData[dstRowOffset + x] = srcData32[srcRowOffset + srcX];
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
resample32Scratch.data = dstData;
|
|
2639
|
+
resample32Scratch.width = dstW;
|
|
2640
|
+
resample32Scratch.height = dstH;
|
|
2641
|
+
return resample32Scratch;
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
// src/ImageData/resampleImageData.ts
|
|
2645
|
+
function resampleImageData(source, factor) {
|
|
2646
|
+
const src32 = new Uint32Array(source.data.buffer);
|
|
2647
|
+
const { data, width, height } = resample32(src32, source.width, source.height, factor);
|
|
2648
|
+
const uint8ClampedArray = new Uint8ClampedArray(data.buffer);
|
|
2649
|
+
return new ImageData(uint8ClampedArray, width, height);
|
|
2650
|
+
}
|
|
2651
|
+
|
|
2652
|
+
// src/ImageData/resizeImageData.ts
|
|
2653
|
+
function resizeImageData(current, newWidth, newHeight, offsetX = 0, offsetY = 0) {
|
|
2654
|
+
const result = new ImageData(newWidth, newHeight);
|
|
2655
|
+
const {
|
|
2656
|
+
width: oldW,
|
|
2657
|
+
height: oldH,
|
|
2658
|
+
data: oldData
|
|
2659
|
+
} = current;
|
|
2660
|
+
const newData = result.data;
|
|
2661
|
+
const x0 = Math.max(0, offsetX);
|
|
2662
|
+
const y0 = Math.max(0, offsetY);
|
|
2663
|
+
const x1 = Math.min(newWidth, offsetX + oldW);
|
|
2664
|
+
const y1 = Math.min(newHeight, offsetY + oldH);
|
|
2665
|
+
if (x1 <= x0 || y1 <= y0) {
|
|
2666
|
+
return result;
|
|
2667
|
+
}
|
|
2668
|
+
const rowCount = y1 - y0;
|
|
2669
|
+
const rowLen = (x1 - x0) * 4;
|
|
2670
|
+
for (let row = 0; row < rowCount; row++) {
|
|
2671
|
+
const dstY = y0 + row;
|
|
2672
|
+
const srcY = dstY - offsetY;
|
|
2673
|
+
const srcX = x0 - offsetX;
|
|
2674
|
+
const dstStart = (dstY * newWidth + x0) * 4;
|
|
2675
|
+
const srcStart = (srcY * oldW + srcX) * 4;
|
|
2676
|
+
newData.set(
|
|
2677
|
+
oldData.subarray(srcStart, srcStart + rowLen),
|
|
2678
|
+
dstStart
|
|
2679
|
+
);
|
|
2680
|
+
}
|
|
2681
|
+
return result;
|
|
2682
|
+
}
|
|
2683
|
+
|
|
2684
|
+
// src/ImageData/serialization.ts
|
|
2685
|
+
function base64EncodeArrayBuffer(buffer) {
|
|
2686
|
+
const uint8 = new Uint8Array(buffer);
|
|
2687
|
+
const decoder = new TextDecoder("latin1");
|
|
2688
|
+
const binary = decoder.decode(uint8);
|
|
2689
|
+
return btoa(binary);
|
|
2690
|
+
}
|
|
2691
|
+
function base64DecodeArrayBuffer(encoded) {
|
|
2692
|
+
const binary = atob(encoded);
|
|
2693
|
+
const bytes = new Uint8ClampedArray(binary.length);
|
|
2694
|
+
for (let i = 0; i < binary.length; i++) {
|
|
2695
|
+
bytes[i] = binary.charCodeAt(i);
|
|
2696
|
+
}
|
|
2697
|
+
return bytes;
|
|
2698
|
+
}
|
|
2699
|
+
function serializeImageData(imageData) {
|
|
2700
|
+
return {
|
|
2701
|
+
width: imageData.width,
|
|
2702
|
+
height: imageData.height,
|
|
2703
|
+
data: base64EncodeArrayBuffer(imageData.data.buffer)
|
|
2704
|
+
};
|
|
2705
|
+
}
|
|
2706
|
+
function serializeNullableImageData(imageData) {
|
|
2707
|
+
if (!imageData) return null;
|
|
2708
|
+
return serializeImageData(imageData);
|
|
2709
|
+
}
|
|
2710
|
+
function deserializeRawImageData(serialized) {
|
|
2711
|
+
return {
|
|
2712
|
+
width: serialized.width,
|
|
2713
|
+
height: serialized.height,
|
|
2714
|
+
data: base64DecodeArrayBuffer(serialized.data)
|
|
2715
|
+
};
|
|
2716
|
+
}
|
|
2717
|
+
function deserializeImageData(serialized) {
|
|
2718
|
+
const data = base64DecodeArrayBuffer(serialized.data);
|
|
2719
|
+
return new ImageData(data, serialized.width, serialized.height);
|
|
2720
|
+
}
|
|
2721
|
+
function deserializeNullableImageData(serialized) {
|
|
2722
|
+
if (!serialized) return null;
|
|
2723
|
+
return deserializeImageData(serialized);
|
|
2724
|
+
}
|
|
2725
|
+
|
|
2726
|
+
// src/ImageData/writeImageData.ts
|
|
2727
|
+
function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width, sh = source.height, mask = null, maskType = 1 /* BINARY */) {
|
|
2728
|
+
const dstW = target.width;
|
|
2729
|
+
const dstH = target.height;
|
|
2730
|
+
const dstData = target.data;
|
|
2731
|
+
const srcW = source.width;
|
|
2732
|
+
const srcData = source.data;
|
|
2733
|
+
const x0 = Math.max(0, x);
|
|
2734
|
+
const y0 = Math.max(0, y);
|
|
2735
|
+
const x1 = Math.min(dstW, x + sw);
|
|
2736
|
+
const y1 = Math.min(dstH, y + sh);
|
|
2737
|
+
if (x1 <= x0 || y1 <= y0) {
|
|
2738
|
+
return;
|
|
2739
|
+
}
|
|
2740
|
+
const useMask = !!mask;
|
|
2741
|
+
const rowCount = y1 - y0;
|
|
2742
|
+
const rowLenPixels = x1 - x0;
|
|
2743
|
+
for (let row = 0; row < rowCount; row++) {
|
|
2744
|
+
const dstY = y0 + row;
|
|
2745
|
+
const srcY = sy + (dstY - y);
|
|
2746
|
+
const srcXBase = sx + (x0 - x);
|
|
2747
|
+
const dstStart = (dstY * dstW + x0) * 4;
|
|
2748
|
+
const srcStart = (srcY * srcW + srcXBase) * 4;
|
|
2749
|
+
if (useMask && mask) {
|
|
2750
|
+
for (let ix = 0; ix < rowLenPixels; ix++) {
|
|
2751
|
+
const mi = srcY * srcW + (srcXBase + ix);
|
|
2752
|
+
const alpha = mask[mi];
|
|
2753
|
+
if (alpha === 0) {
|
|
2754
|
+
continue;
|
|
2755
|
+
}
|
|
2756
|
+
const di = dstStart + ix * 4;
|
|
2757
|
+
const si = srcStart + ix * 4;
|
|
2758
|
+
if (maskType === 1 /* BINARY */ || alpha === 255) {
|
|
2759
|
+
dstData[di] = srcData[si];
|
|
2760
|
+
dstData[di + 1] = srcData[si + 1];
|
|
2761
|
+
dstData[di + 2] = srcData[si + 2];
|
|
2762
|
+
dstData[di + 3] = srcData[si + 3];
|
|
2763
|
+
} else {
|
|
2764
|
+
const a = alpha / 255;
|
|
2765
|
+
const invA = 1 - a;
|
|
2766
|
+
dstData[di] = srcData[si] * a + dstData[di] * invA;
|
|
2767
|
+
dstData[di + 1] = srcData[si + 1] * a + dstData[di + 1] * invA;
|
|
2768
|
+
dstData[di + 2] = srcData[si + 2] * a + dstData[di + 2] * invA;
|
|
2769
|
+
dstData[di + 3] = srcData[si + 3] * a + dstData[di + 3] * invA;
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
} else {
|
|
2773
|
+
const byteLen = rowLenPixels * 4;
|
|
2774
|
+
const sub = srcData.subarray(srcStart, srcStart + byteLen);
|
|
2775
|
+
dstData.set(sub, dstStart);
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
// src/ImageData/writeImageDataBuffer.ts
|
|
2781
|
+
function writeImageDataBuffer(imageData, data, _x, _y, _w, _h) {
|
|
2782
|
+
const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
|
|
2783
|
+
const { width: dstW, height: dstH, data: dst } = imageData;
|
|
2784
|
+
const x0 = Math.max(0, x);
|
|
2785
|
+
const y0 = Math.max(0, y);
|
|
2786
|
+
const x1 = Math.min(dstW, x + w);
|
|
2787
|
+
const y1 = Math.min(dstH, y + h);
|
|
2788
|
+
if (x1 <= x0 || y1 <= y0) return;
|
|
2789
|
+
const rowLen = (x1 - x0) * 4;
|
|
2790
|
+
const srcCol = x0 - x;
|
|
2791
|
+
const srcYOffset = y0 - y;
|
|
2792
|
+
const actualH = y1 - y0;
|
|
2793
|
+
for (let row = 0; row < actualH; row++) {
|
|
1800
2794
|
const dstStart = ((y0 + row) * dstW + x0) * 4;
|
|
1801
2795
|
const srcRow = srcYOffset + row;
|
|
1802
2796
|
const o = (srcRow * w + srcCol) * 4;
|
|
@@ -2001,553 +2995,262 @@ async function fileToImageData(file) {
|
|
|
2001
2995
|
);
|
|
2002
2996
|
const ctx = canvas.getContext("2d");
|
|
2003
2997
|
if (!ctx) throw new Error(OFFSCREEN_CANVAS_CTX_FAILED);
|
|
2004
|
-
ctx.drawImage(
|
|
2005
|
-
bitmap,
|
|
2006
|
-
0,
|
|
2007
|
-
0
|
|
2008
|
-
);
|
|
2009
|
-
return ctx.getImageData(
|
|
2010
|
-
0,
|
|
2011
|
-
0,
|
|
2012
|
-
bitmap.width,
|
|
2013
|
-
bitmap.height
|
|
2014
|
-
);
|
|
2015
|
-
} finally {
|
|
2016
|
-
bitmap?.close();
|
|
2017
|
-
}
|
|
2018
|
-
}
|
|
2019
|
-
|
|
2020
|
-
// src/Input/getSupportedRasterFormats.ts
|
|
2021
|
-
var formatsPromise = null;
|
|
2022
|
-
var defaultRasterMimes = [
|
|
2023
|
-
"image/png",
|
|
2024
|
-
"image/jpeg",
|
|
2025
|
-
"image/webp",
|
|
2026
|
-
"image/avif",
|
|
2027
|
-
"image/gif",
|
|
2028
|
-
"image/bmp"
|
|
2029
|
-
];
|
|
2030
|
-
async function getSupportedPixelFormats(rasterMimes = defaultRasterMimes) {
|
|
2031
|
-
if (formatsPromise) {
|
|
2032
|
-
return formatsPromise;
|
|
2033
|
-
}
|
|
2034
|
-
const probeCanvas = async () => {
|
|
2035
|
-
const canvas = new OffscreenCanvas(1, 1);
|
|
2036
|
-
const results = await Promise.all(
|
|
2037
|
-
rasterMimes.map(async (mime) => {
|
|
2038
|
-
try {
|
|
2039
|
-
const blob = await canvas.convertToBlob({
|
|
2040
|
-
type: mime
|
|
2041
|
-
});
|
|
2042
|
-
return blob.type === mime ? mime : null;
|
|
2043
|
-
} catch {
|
|
2044
|
-
return null;
|
|
2045
|
-
}
|
|
2046
|
-
})
|
|
2047
|
-
);
|
|
2048
|
-
return results.filter((type) => {
|
|
2049
|
-
return type !== null;
|
|
2050
|
-
});
|
|
2051
|
-
};
|
|
2052
|
-
formatsPromise = probeCanvas().catch((error) => {
|
|
2053
|
-
formatsPromise = null;
|
|
2054
|
-
throw error;
|
|
2055
|
-
});
|
|
2056
|
-
return formatsPromise;
|
|
2057
|
-
}
|
|
2058
|
-
|
|
2059
|
-
// src/Mask/copyMask.ts
|
|
2060
|
-
function copyMask(src) {
|
|
2061
|
-
return src.slice();
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2064
|
-
// src/Mask/invertMask.ts
|
|
2065
|
-
function invertBinaryMask(dst) {
|
|
2066
|
-
const len = dst.length;
|
|
2067
|
-
for (let i = 0; i < len; i++) {
|
|
2068
|
-
dst[i] = dst[i] === 0 ? 1 : 0;
|
|
2069
|
-
}
|
|
2070
|
-
}
|
|
2071
|
-
function invertAlphaMask(dst) {
|
|
2072
|
-
const len = dst.length;
|
|
2073
|
-
for (let i = 0; i < len; i++) {
|
|
2074
|
-
dst[i] = 255 - dst[i];
|
|
2075
|
-
}
|
|
2076
|
-
}
|
|
2077
|
-
|
|
2078
|
-
// src/Mask/mergeMasks.ts
|
|
2079
|
-
function mergeMasks(dst, dstWidth, src, opts) {
|
|
2080
|
-
const {
|
|
2081
|
-
x: targetX = 0,
|
|
2082
|
-
y: targetY = 0,
|
|
2083
|
-
w: width = 0,
|
|
2084
|
-
h: height = 0,
|
|
2085
|
-
alpha: globalAlpha = 255,
|
|
2086
|
-
maskType = 0 /* ALPHA */,
|
|
2087
|
-
mw,
|
|
2088
|
-
mx = 0,
|
|
2089
|
-
my = 0,
|
|
2090
|
-
invertMask = false
|
|
2091
|
-
} = opts;
|
|
2092
|
-
if (width <= 0 || height <= 0 || globalAlpha === 0) {
|
|
2093
|
-
return;
|
|
2094
|
-
}
|
|
2095
|
-
const sPitch = mw ?? width;
|
|
2096
|
-
const isAlpha = maskType === 0 /* ALPHA */;
|
|
2097
|
-
for (let iy = 0; iy < height; iy++) {
|
|
2098
|
-
const dy = targetY + iy;
|
|
2099
|
-
const sy = my + iy;
|
|
2100
|
-
if (dy < 0 || sy < 0) {
|
|
2101
|
-
continue;
|
|
2102
|
-
}
|
|
2103
|
-
for (let ix = 0; ix < width; ix++) {
|
|
2104
|
-
const dx = targetX + ix;
|
|
2105
|
-
const sx = mx + ix;
|
|
2106
|
-
if (dx < 0 || dx >= dstWidth || sx < 0 || sx >= sPitch) {
|
|
2107
|
-
continue;
|
|
2108
|
-
}
|
|
2109
|
-
const dIdx = dy * dstWidth + dx;
|
|
2110
|
-
const sIdx = sy * sPitch + sx;
|
|
2111
|
-
const mVal = src[sIdx];
|
|
2112
|
-
let weight = globalAlpha;
|
|
2113
|
-
if (isAlpha) {
|
|
2114
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2115
|
-
if (effectiveM === 0) {
|
|
2116
|
-
dst[dIdx] = 0;
|
|
2117
|
-
continue;
|
|
2118
|
-
}
|
|
2119
|
-
weight = globalAlpha === 255 ? effectiveM : effectiveM * globalAlpha + 128 >> 8;
|
|
2120
|
-
} else {
|
|
2121
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2122
|
-
if (!isHit) {
|
|
2123
|
-
dst[dIdx] = 0;
|
|
2124
|
-
continue;
|
|
2125
|
-
}
|
|
2126
|
-
weight = globalAlpha;
|
|
2127
|
-
}
|
|
2128
|
-
if (weight === 0) {
|
|
2129
|
-
dst[dIdx] = 0;
|
|
2130
|
-
continue;
|
|
2131
|
-
}
|
|
2132
|
-
const da = dst[dIdx];
|
|
2133
|
-
if (da === 0) {
|
|
2134
|
-
} else if (weight === 255) {
|
|
2135
|
-
} else if (da === 255) {
|
|
2136
|
-
dst[dIdx] = weight;
|
|
2137
|
-
} else {
|
|
2138
|
-
dst[dIdx] = da * weight + 128 >> 8;
|
|
2139
|
-
}
|
|
2140
|
-
}
|
|
2141
|
-
}
|
|
2142
|
-
}
|
|
2143
|
-
|
|
2144
|
-
// src/PixelData/PixelData.ts
|
|
2145
|
-
var PixelData = class _PixelData {
|
|
2146
|
-
data32;
|
|
2147
|
-
imageData;
|
|
2148
|
-
get width() {
|
|
2149
|
-
return this.imageData.width;
|
|
2150
|
-
}
|
|
2151
|
-
get height() {
|
|
2152
|
-
return this.imageData.height;
|
|
2153
|
-
}
|
|
2154
|
-
constructor(imageData) {
|
|
2155
|
-
this.data32 = imageDataToUInt32Array(imageData);
|
|
2156
|
-
this.imageData = imageData;
|
|
2157
|
-
}
|
|
2158
|
-
set(imageData) {
|
|
2159
|
-
this.imageData = imageData;
|
|
2160
|
-
this.data32 = imageDataToUInt32Array(imageData);
|
|
2161
|
-
}
|
|
2162
|
-
/**
|
|
2163
|
-
* Creates a deep copy of the PixelData using the environment's ImageData constructor.
|
|
2164
|
-
*/
|
|
2165
|
-
copy() {
|
|
2166
|
-
const buffer = new Uint8ClampedArray(this.imageData.data);
|
|
2167
|
-
const ImageConstructor = typeof ImageData !== "undefined" ? ImageData : this.imageData.constructor;
|
|
2168
|
-
const newImageData = new ImageConstructor(
|
|
2169
|
-
buffer,
|
|
2170
|
-
this.width,
|
|
2171
|
-
this.height
|
|
2998
|
+
ctx.drawImage(
|
|
2999
|
+
bitmap,
|
|
3000
|
+
0,
|
|
3001
|
+
0
|
|
2172
3002
|
);
|
|
2173
|
-
return
|
|
3003
|
+
return ctx.getImageData(
|
|
3004
|
+
0,
|
|
3005
|
+
0,
|
|
3006
|
+
bitmap.width,
|
|
3007
|
+
bitmap.height
|
|
3008
|
+
);
|
|
3009
|
+
} finally {
|
|
3010
|
+
bitmap?.close();
|
|
2174
3011
|
}
|
|
2175
|
-
}
|
|
3012
|
+
}
|
|
2176
3013
|
|
|
2177
|
-
// src/
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
} = opts;
|
|
2191
|
-
let x = targetX;
|
|
2192
|
-
let y = targetY;
|
|
2193
|
-
let w = width;
|
|
2194
|
-
let h = height;
|
|
2195
|
-
if (x < 0) {
|
|
2196
|
-
w += x;
|
|
2197
|
-
x = 0;
|
|
2198
|
-
}
|
|
2199
|
-
if (y < 0) {
|
|
2200
|
-
h += y;
|
|
2201
|
-
y = 0;
|
|
2202
|
-
}
|
|
2203
|
-
const actualW = Math.min(w, dst.width - x);
|
|
2204
|
-
const actualH = Math.min(h, dst.height - y);
|
|
2205
|
-
if (actualW <= 0 || actualH <= 0 || globalAlpha === 0) {
|
|
2206
|
-
return;
|
|
3014
|
+
// src/Input/getSupportedRasterFormats.ts
|
|
3015
|
+
var formatsPromise = null;
|
|
3016
|
+
var defaultRasterMimes = [
|
|
3017
|
+
"image/png",
|
|
3018
|
+
"image/jpeg",
|
|
3019
|
+
"image/webp",
|
|
3020
|
+
"image/avif",
|
|
3021
|
+
"image/gif",
|
|
3022
|
+
"image/bmp"
|
|
3023
|
+
];
|
|
3024
|
+
async function getSupportedPixelFormats(rasterMimes = defaultRasterMimes) {
|
|
3025
|
+
if (formatsPromise) {
|
|
3026
|
+
return formatsPromise;
|
|
2207
3027
|
}
|
|
2208
|
-
const
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
2220
|
-
const mVal = mask[mIdx];
|
|
2221
|
-
let weight = globalAlpha;
|
|
2222
|
-
if (isAlpha) {
|
|
2223
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2224
|
-
if (effectiveM === 0) {
|
|
2225
|
-
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2226
|
-
dIdx++;
|
|
2227
|
-
mIdx++;
|
|
2228
|
-
continue;
|
|
2229
|
-
}
|
|
2230
|
-
weight = globalAlpha === 255 ? effectiveM : effectiveM * globalAlpha + 128 >> 8;
|
|
2231
|
-
} else {
|
|
2232
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2233
|
-
if (!isHit) {
|
|
2234
|
-
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2235
|
-
dIdx++;
|
|
2236
|
-
mIdx++;
|
|
2237
|
-
continue;
|
|
2238
|
-
}
|
|
2239
|
-
weight = globalAlpha;
|
|
2240
|
-
}
|
|
2241
|
-
if (weight === 0) {
|
|
2242
|
-
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2243
|
-
} else {
|
|
2244
|
-
const d = dst32[dIdx];
|
|
2245
|
-
const da = d >>> 24;
|
|
2246
|
-
let finalAlpha = da;
|
|
2247
|
-
if (da === 0) {
|
|
2248
|
-
} else if (weight === 255) {
|
|
2249
|
-
} else if (da === 255) {
|
|
2250
|
-
finalAlpha = weight;
|
|
2251
|
-
} else {
|
|
2252
|
-
finalAlpha = da * weight + 128 >> 8;
|
|
3028
|
+
const probeCanvas = async () => {
|
|
3029
|
+
const canvas = new OffscreenCanvas(1, 1);
|
|
3030
|
+
const results = await Promise.all(
|
|
3031
|
+
rasterMimes.map(async (mime) => {
|
|
3032
|
+
try {
|
|
3033
|
+
const blob = await canvas.convertToBlob({
|
|
3034
|
+
type: mime
|
|
3035
|
+
});
|
|
3036
|
+
return blob.type === mime ? mime : null;
|
|
3037
|
+
} catch {
|
|
3038
|
+
return null;
|
|
2253
3039
|
}
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
}
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
3040
|
+
})
|
|
3041
|
+
);
|
|
3042
|
+
return results.filter((type) => {
|
|
3043
|
+
return type !== null;
|
|
3044
|
+
});
|
|
3045
|
+
};
|
|
3046
|
+
formatsPromise = probeCanvas().catch((error) => {
|
|
3047
|
+
formatsPromise = null;
|
|
3048
|
+
throw error;
|
|
3049
|
+
});
|
|
3050
|
+
return formatsPromise;
|
|
2262
3051
|
}
|
|
2263
3052
|
|
|
2264
|
-
// src/
|
|
2265
|
-
function
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
maskType = 0 /* ALPHA */,
|
|
2275
|
-
mw,
|
|
2276
|
-
mx = 0,
|
|
2277
|
-
my = 0,
|
|
2278
|
-
invertMask = false
|
|
2279
|
-
} = opts;
|
|
2280
|
-
if (globalAlpha === 0) return;
|
|
2281
|
-
const baseSrcAlpha = color >>> 24;
|
|
2282
|
-
const isOverwrite = blendFn.isOverwrite;
|
|
2283
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2284
|
-
let x = targetX;
|
|
2285
|
-
let y = targetY;
|
|
2286
|
-
let w = width;
|
|
2287
|
-
let h = height;
|
|
2288
|
-
if (x < 0) {
|
|
2289
|
-
w += x;
|
|
2290
|
-
x = 0;
|
|
2291
|
-
}
|
|
2292
|
-
if (y < 0) {
|
|
2293
|
-
h += y;
|
|
2294
|
-
y = 0;
|
|
3053
|
+
// src/Mask/copyMask.ts
|
|
3054
|
+
function copyMask(src) {
|
|
3055
|
+
return src.slice();
|
|
3056
|
+
}
|
|
3057
|
+
|
|
3058
|
+
// src/Mask/invertMask.ts
|
|
3059
|
+
function invertBinaryMask(dst) {
|
|
3060
|
+
const len = dst.length;
|
|
3061
|
+
for (let i = 0; i < len; i++) {
|
|
3062
|
+
dst[i] = dst[i] === 0 ? 1 : 0;
|
|
2295
3063
|
}
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
const mPitch = mw ?? width;
|
|
2302
|
-
const isAlphaMask = maskType === 0 /* ALPHA */;
|
|
2303
|
-
const dx = x - targetX;
|
|
2304
|
-
const dy = y - targetY;
|
|
2305
|
-
let dIdx = y * dw + x;
|
|
2306
|
-
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2307
|
-
const dStride = dw - actualW;
|
|
2308
|
-
const mStride = mPitch - actualW;
|
|
2309
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
2310
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
2311
|
-
let weight = globalAlpha;
|
|
2312
|
-
if (mask) {
|
|
2313
|
-
const mVal = mask[mIdx];
|
|
2314
|
-
if (isAlphaMask) {
|
|
2315
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2316
|
-
if (effectiveM === 0) {
|
|
2317
|
-
dIdx++;
|
|
2318
|
-
mIdx++;
|
|
2319
|
-
continue;
|
|
2320
|
-
}
|
|
2321
|
-
if (globalAlpha === 255) {
|
|
2322
|
-
weight = effectiveM;
|
|
2323
|
-
} else if (effectiveM === 255) {
|
|
2324
|
-
weight = globalAlpha;
|
|
2325
|
-
} else {
|
|
2326
|
-
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2327
|
-
}
|
|
2328
|
-
} else {
|
|
2329
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2330
|
-
if (!isHit) {
|
|
2331
|
-
dIdx++;
|
|
2332
|
-
mIdx++;
|
|
2333
|
-
continue;
|
|
2334
|
-
}
|
|
2335
|
-
weight = globalAlpha;
|
|
2336
|
-
}
|
|
2337
|
-
if (weight === 0) {
|
|
2338
|
-
dIdx++;
|
|
2339
|
-
mIdx++;
|
|
2340
|
-
continue;
|
|
2341
|
-
}
|
|
2342
|
-
}
|
|
2343
|
-
let currentSrcColor = color;
|
|
2344
|
-
if (weight < 255) {
|
|
2345
|
-
let currentSrcAlpha = baseSrcAlpha;
|
|
2346
|
-
if (baseSrcAlpha === 255) {
|
|
2347
|
-
currentSrcAlpha = weight;
|
|
2348
|
-
} else {
|
|
2349
|
-
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2350
|
-
}
|
|
2351
|
-
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
2352
|
-
dIdx++;
|
|
2353
|
-
mIdx++;
|
|
2354
|
-
continue;
|
|
2355
|
-
}
|
|
2356
|
-
currentSrcColor = (color & 16777215 | currentSrcAlpha << 24) >>> 0;
|
|
2357
|
-
}
|
|
2358
|
-
dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
|
|
2359
|
-
dIdx++;
|
|
2360
|
-
mIdx++;
|
|
2361
|
-
}
|
|
2362
|
-
dIdx += dStride;
|
|
2363
|
-
mIdx += mStride;
|
|
3064
|
+
}
|
|
3065
|
+
function invertAlphaMask(dst) {
|
|
3066
|
+
const len = dst.length;
|
|
3067
|
+
for (let i = 0; i < len; i++) {
|
|
3068
|
+
dst[i] = 255 - dst[i];
|
|
2364
3069
|
}
|
|
2365
3070
|
}
|
|
2366
3071
|
|
|
2367
|
-
// src/
|
|
2368
|
-
function
|
|
3072
|
+
// src/Mask/mergeMasks.ts
|
|
3073
|
+
function mergeMasks(dst, dstWidth, src, opts) {
|
|
2369
3074
|
const {
|
|
2370
|
-
x: targetX = 0,
|
|
2371
|
-
y: targetY = 0,
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
w: width = src.width,
|
|
2375
|
-
h: height = src.height,
|
|
3075
|
+
x: targetX = 0,
|
|
3076
|
+
y: targetY = 0,
|
|
3077
|
+
w: width = 0,
|
|
3078
|
+
h: height = 0,
|
|
2376
3079
|
alpha: globalAlpha = 255,
|
|
2377
|
-
blendFn = sourceOverFast,
|
|
2378
|
-
mask,
|
|
2379
3080
|
maskType = 0 /* ALPHA */,
|
|
2380
3081
|
mw,
|
|
2381
3082
|
mx = 0,
|
|
2382
3083
|
my = 0,
|
|
2383
3084
|
invertMask = false
|
|
2384
3085
|
} = opts;
|
|
2385
|
-
if (globalAlpha === 0)
|
|
2386
|
-
|
|
2387
|
-
let y = targetY;
|
|
2388
|
-
let sx = sourceX;
|
|
2389
|
-
let sy = sourceY;
|
|
2390
|
-
let w = width;
|
|
2391
|
-
let h = height;
|
|
2392
|
-
if (sx < 0) {
|
|
2393
|
-
x -= sx;
|
|
2394
|
-
w += sx;
|
|
2395
|
-
sx = 0;
|
|
2396
|
-
}
|
|
2397
|
-
if (sy < 0) {
|
|
2398
|
-
y -= sy;
|
|
2399
|
-
h += sy;
|
|
2400
|
-
sy = 0;
|
|
2401
|
-
}
|
|
2402
|
-
w = Math.min(w, src.width - sx);
|
|
2403
|
-
h = Math.min(h, src.height - sy);
|
|
2404
|
-
if (x < 0) {
|
|
2405
|
-
sx -= x;
|
|
2406
|
-
w += x;
|
|
2407
|
-
x = 0;
|
|
2408
|
-
}
|
|
2409
|
-
if (y < 0) {
|
|
2410
|
-
sy -= y;
|
|
2411
|
-
h += y;
|
|
2412
|
-
y = 0;
|
|
3086
|
+
if (width <= 0 || height <= 0 || globalAlpha === 0) {
|
|
3087
|
+
return;
|
|
2413
3088
|
}
|
|
2414
|
-
const
|
|
2415
|
-
const
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
let sIdx = sy * sw + sx;
|
|
2427
|
-
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2428
|
-
const dStride = dw - actualW;
|
|
2429
|
-
const sStride = sw - actualW;
|
|
2430
|
-
const mStride = mPitch - actualW;
|
|
2431
|
-
const isOverwrite = blendFn.isOverwrite;
|
|
2432
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
2433
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
2434
|
-
const baseSrcColor = src32[sIdx];
|
|
2435
|
-
const baseSrcAlpha = baseSrcColor >>> 24;
|
|
2436
|
-
if (baseSrcAlpha === 0 && !isOverwrite) {
|
|
2437
|
-
dIdx++;
|
|
2438
|
-
sIdx++;
|
|
2439
|
-
mIdx++;
|
|
3089
|
+
const sPitch = mw ?? width;
|
|
3090
|
+
const isAlpha = maskType === 0 /* ALPHA */;
|
|
3091
|
+
for (let iy = 0; iy < height; iy++) {
|
|
3092
|
+
const dy = targetY + iy;
|
|
3093
|
+
const sy = my + iy;
|
|
3094
|
+
if (dy < 0 || sy < 0) {
|
|
3095
|
+
continue;
|
|
3096
|
+
}
|
|
3097
|
+
for (let ix = 0; ix < width; ix++) {
|
|
3098
|
+
const dx = targetX + ix;
|
|
3099
|
+
const sx = mx + ix;
|
|
3100
|
+
if (dx < 0 || dx >= dstWidth || sx < 0 || sx >= sPitch) {
|
|
2440
3101
|
continue;
|
|
2441
3102
|
}
|
|
3103
|
+
const dIdx = dy * dstWidth + dx;
|
|
3104
|
+
const sIdx = sy * sPitch + sx;
|
|
3105
|
+
const mVal = src[sIdx];
|
|
2442
3106
|
let weight = globalAlpha;
|
|
2443
|
-
if (
|
|
2444
|
-
const
|
|
2445
|
-
if (
|
|
2446
|
-
|
|
2447
|
-
if (effectiveM === 0) {
|
|
2448
|
-
dIdx++;
|
|
2449
|
-
sIdx++;
|
|
2450
|
-
mIdx++;
|
|
2451
|
-
continue;
|
|
2452
|
-
}
|
|
2453
|
-
if (globalAlpha === 255) {
|
|
2454
|
-
weight = effectiveM;
|
|
2455
|
-
} else if (effectiveM === 255) {
|
|
2456
|
-
weight = globalAlpha;
|
|
2457
|
-
} else {
|
|
2458
|
-
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2459
|
-
}
|
|
2460
|
-
} else {
|
|
2461
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2462
|
-
if (!isHit) {
|
|
2463
|
-
dIdx++;
|
|
2464
|
-
sIdx++;
|
|
2465
|
-
mIdx++;
|
|
2466
|
-
continue;
|
|
2467
|
-
}
|
|
2468
|
-
weight = globalAlpha;
|
|
2469
|
-
}
|
|
2470
|
-
if (weight === 0) {
|
|
2471
|
-
dIdx++;
|
|
2472
|
-
sIdx++;
|
|
2473
|
-
mIdx++;
|
|
3107
|
+
if (isAlpha) {
|
|
3108
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
3109
|
+
if (effectiveM === 0) {
|
|
3110
|
+
dst[dIdx] = 0;
|
|
2474
3111
|
continue;
|
|
2475
3112
|
}
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
currentSrcAlpha = weight;
|
|
2482
|
-
} else {
|
|
2483
|
-
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2484
|
-
}
|
|
2485
|
-
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
2486
|
-
dIdx++;
|
|
2487
|
-
sIdx++;
|
|
2488
|
-
mIdx++;
|
|
3113
|
+
weight = globalAlpha === 255 ? effectiveM : effectiveM * globalAlpha + 128 >> 8;
|
|
3114
|
+
} else {
|
|
3115
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
3116
|
+
if (!isHit) {
|
|
3117
|
+
dst[dIdx] = 0;
|
|
2489
3118
|
continue;
|
|
2490
3119
|
}
|
|
2491
|
-
|
|
3120
|
+
weight = globalAlpha;
|
|
3121
|
+
}
|
|
3122
|
+
if (weight === 0) {
|
|
3123
|
+
dst[dIdx] = 0;
|
|
3124
|
+
continue;
|
|
3125
|
+
}
|
|
3126
|
+
const da = dst[dIdx];
|
|
3127
|
+
if (da === 0) {
|
|
3128
|
+
} else if (weight === 255) {
|
|
3129
|
+
} else if (da === 255) {
|
|
3130
|
+
dst[dIdx] = weight;
|
|
3131
|
+
} else {
|
|
3132
|
+
dst[dIdx] = da * weight + 128 >> 8;
|
|
2492
3133
|
}
|
|
2493
|
-
dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
|
|
2494
|
-
dIdx++;
|
|
2495
|
-
sIdx++;
|
|
2496
|
-
mIdx++;
|
|
2497
3134
|
}
|
|
2498
|
-
dIdx += dStride;
|
|
2499
|
-
sIdx += sStride;
|
|
2500
|
-
mIdx += mStride;
|
|
2501
3135
|
}
|
|
2502
3136
|
}
|
|
2503
3137
|
|
|
2504
|
-
// src/PixelData/
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
if (typeof _x === "object") {
|
|
2511
|
-
x = _x.x ?? 0;
|
|
2512
|
-
y = _x.y ?? 0;
|
|
2513
|
-
w = _x.w ?? dst.width;
|
|
2514
|
-
h = _x.h ?? dst.height;
|
|
2515
|
-
} else if (typeof _x === "number") {
|
|
2516
|
-
x = _x;
|
|
2517
|
-
y = _y;
|
|
2518
|
-
w = _w;
|
|
2519
|
-
h = _h;
|
|
2520
|
-
} else {
|
|
2521
|
-
x = 0;
|
|
2522
|
-
y = 0;
|
|
2523
|
-
w = dst.width;
|
|
2524
|
-
h = dst.height;
|
|
3138
|
+
// src/PixelData/PixelData.ts
|
|
3139
|
+
var PixelData = class _PixelData {
|
|
3140
|
+
data32;
|
|
3141
|
+
imageData;
|
|
3142
|
+
get width() {
|
|
3143
|
+
return this.imageData.width;
|
|
2525
3144
|
}
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
x = 0;
|
|
3145
|
+
get height() {
|
|
3146
|
+
return this.imageData.height;
|
|
2529
3147
|
}
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
3148
|
+
constructor(imageData) {
|
|
3149
|
+
this.data32 = imageDataToUInt32Array(imageData);
|
|
3150
|
+
this.imageData = imageData;
|
|
2533
3151
|
}
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
return;
|
|
3152
|
+
set(imageData) {
|
|
3153
|
+
this.imageData = imageData;
|
|
3154
|
+
this.data32 = imageDataToUInt32Array(imageData);
|
|
2538
3155
|
}
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
3156
|
+
/**
|
|
3157
|
+
* Creates a deep copy of the PixelData using the environment's ImageData constructor.
|
|
3158
|
+
*/
|
|
3159
|
+
copy() {
|
|
3160
|
+
const buffer = new Uint8ClampedArray(this.imageData.data);
|
|
3161
|
+
const ImageConstructor = typeof ImageData !== "undefined" ? ImageData : this.imageData.constructor;
|
|
3162
|
+
const newImageData = new ImageConstructor(
|
|
3163
|
+
buffer,
|
|
3164
|
+
this.width,
|
|
3165
|
+
this.height
|
|
3166
|
+
);
|
|
3167
|
+
return new _PixelData(newImageData);
|
|
2544
3168
|
}
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
3169
|
+
};
|
|
3170
|
+
|
|
3171
|
+
// src/PixelData/applyCircleBrushToPixelData.ts
|
|
3172
|
+
function applyCircleBrushToPixelData(target, color, centerX, centerY, brushSize, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
|
|
3173
|
+
const r = brushSize / 2;
|
|
3174
|
+
const rSqr = r * r;
|
|
3175
|
+
const centerOffset = brushSize % 2 === 0 ? 0.5 : 0;
|
|
3176
|
+
const xStart = Math.max(0, Math.ceil(centerX - r));
|
|
3177
|
+
const xEnd = Math.min(target.width - 1, Math.floor(centerX + r));
|
|
3178
|
+
const yStart = Math.max(0, Math.ceil(centerY - r));
|
|
3179
|
+
const yEnd = Math.min(target.height - 1, Math.floor(centerY + r));
|
|
3180
|
+
const data32 = target.data32;
|
|
3181
|
+
const targetWidth = target.width;
|
|
3182
|
+
const baseColor = color & 16777215;
|
|
3183
|
+
const invR = 1 / r;
|
|
3184
|
+
const constantSrc = (alpha << 24 | baseColor) >>> 0;
|
|
3185
|
+
for (let cy = yStart; cy <= yEnd; cy++) {
|
|
3186
|
+
const dy = cy - centerY + centerOffset;
|
|
3187
|
+
const dySqr = dy * dy;
|
|
3188
|
+
const rowOffset = cy * targetWidth;
|
|
3189
|
+
for (let cx = xStart; cx <= xEnd; cx++) {
|
|
3190
|
+
const dx = cx - centerX + centerOffset;
|
|
3191
|
+
const dSqr = dx * dx + dySqr;
|
|
3192
|
+
if (dSqr <= rSqr) {
|
|
3193
|
+
const idx = rowOffset + cx;
|
|
3194
|
+
if (fallOff) {
|
|
3195
|
+
const strength = fallOff(Math.sqrt(dSqr) * invR);
|
|
3196
|
+
const fAlpha = alpha * strength & 255;
|
|
3197
|
+
const src = (fAlpha << 24 | baseColor) >>> 0;
|
|
3198
|
+
data32[idx] = blendFn(src, data32[idx]);
|
|
3199
|
+
} else {
|
|
3200
|
+
data32[idx] = blendFn(constantSrc, data32[idx]);
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
|
|
3207
|
+
// src/PixelData/applyRectBrushToPixelData.ts
|
|
3208
|
+
function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth, brushHeight, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
|
|
3209
|
+
const targetWidth = target.width;
|
|
3210
|
+
const targetHeight = target.height;
|
|
3211
|
+
const data32 = target.data32;
|
|
3212
|
+
const rawStartX = Math.floor(centerX - brushWidth / 2);
|
|
3213
|
+
const rawStartY = Math.floor(centerY - brushHeight / 2);
|
|
3214
|
+
const endX = Math.min(targetWidth, rawStartX + brushWidth);
|
|
3215
|
+
const endY = Math.min(targetHeight, rawStartY + brushHeight);
|
|
3216
|
+
const startX = Math.max(0, rawStartX);
|
|
3217
|
+
const startY = Math.max(0, rawStartY);
|
|
3218
|
+
const baseColor = color & 16777215;
|
|
3219
|
+
const constantSrc = (alpha << 24 | baseColor) >>> 0;
|
|
3220
|
+
const invHalfW = 1 / (brushWidth / 2);
|
|
3221
|
+
const invHalfH = 1 / (brushHeight / 2);
|
|
3222
|
+
for (let py = startY; py < endY; py++) {
|
|
3223
|
+
const rowOffset = py * targetWidth;
|
|
3224
|
+
const dy = Math.abs(py + 0.5 - centerY) * invHalfH;
|
|
3225
|
+
for (let px = startX; px < endX; px++) {
|
|
3226
|
+
if (fallOff) {
|
|
3227
|
+
const dx = Math.abs(px + 0.5 - centerX) * invHalfW;
|
|
3228
|
+
const dist = dx > dy ? dx : dy;
|
|
3229
|
+
const fAlpha = alpha * fallOff(dist) | 0;
|
|
3230
|
+
const src = (fAlpha << 24 | baseColor) >>> 0;
|
|
3231
|
+
data32[rowOffset + px] = blendFn(src, data32[rowOffset + px]);
|
|
3232
|
+
} else {
|
|
3233
|
+
data32[rowOffset + px] = blendFn(constantSrc, data32[rowOffset + px]);
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
2549
3236
|
}
|
|
2550
3237
|
}
|
|
3238
|
+
function getRectBrushBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight) {
|
|
3239
|
+
const rawStartX = Math.floor(centerX - brushWidth / 2);
|
|
3240
|
+
const rawStartY = Math.floor(centerY - brushHeight / 2);
|
|
3241
|
+
const rawEndX = rawStartX + brushWidth;
|
|
3242
|
+
const rawEndY = rawStartY + brushHeight;
|
|
3243
|
+
const startX = targetWidth !== void 0 ? Math.max(0, rawStartX) : rawStartX;
|
|
3244
|
+
const startY = targetHeight !== void 0 ? Math.max(0, rawStartY) : rawStartY;
|
|
3245
|
+
const endX = targetWidth !== void 0 ? Math.min(targetWidth, rawEndX) : rawEndX;
|
|
3246
|
+
const endY = targetHeight !== void 0 ? Math.min(targetHeight, rawEndY) : rawEndY;
|
|
3247
|
+
return {
|
|
3248
|
+
x: startX,
|
|
3249
|
+
y: startY,
|
|
3250
|
+
w: endX - startX,
|
|
3251
|
+
h: endY - startY
|
|
3252
|
+
};
|
|
3253
|
+
}
|
|
2551
3254
|
|
|
2552
3255
|
// src/PixelData/clearPixelData.ts
|
|
2553
3256
|
function clearPixelData(dst, rect) {
|
|
@@ -2595,16 +3298,6 @@ function extractPixelData(source, _x, _y, _w, _h) {
|
|
|
2595
3298
|
return result;
|
|
2596
3299
|
}
|
|
2597
3300
|
|
|
2598
|
-
// src/PixelData/invertPixelData.ts
|
|
2599
|
-
function invertPixelData(pixelData) {
|
|
2600
|
-
const data32 = pixelData.data32;
|
|
2601
|
-
const len = data32.length;
|
|
2602
|
-
for (let i = 0; i < len; i++) {
|
|
2603
|
-
data32[i] = data32[i] ^ 16777215;
|
|
2604
|
-
}
|
|
2605
|
-
return pixelData;
|
|
2606
|
-
}
|
|
2607
|
-
|
|
2608
3301
|
// src/PixelData/reflectPixelData.ts
|
|
2609
3302
|
function reflectPixelDataHorizontal(pixelData) {
|
|
2610
3303
|
const width = pixelData.width;
|
|
@@ -2695,16 +3388,54 @@ function rotateSquareInPlace(pixelData) {
|
|
|
2695
3388
|
}
|
|
2696
3389
|
}
|
|
2697
3390
|
}
|
|
3391
|
+
|
|
3392
|
+
// src/PixelData/writePixelDataBuffer.ts
|
|
3393
|
+
function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
3394
|
+
const { x, y, w, h } = typeof _x === "object" ? _x : {
|
|
3395
|
+
x: _x,
|
|
3396
|
+
y: _y,
|
|
3397
|
+
w: _w,
|
|
3398
|
+
h: _h
|
|
3399
|
+
};
|
|
3400
|
+
const dstW = target.width;
|
|
3401
|
+
const dstH = target.height;
|
|
3402
|
+
const dstData = target.data32;
|
|
3403
|
+
const x0 = Math.max(0, x);
|
|
3404
|
+
const y0 = Math.max(0, y);
|
|
3405
|
+
const x1 = Math.min(dstW, x + w);
|
|
3406
|
+
const y1 = Math.min(dstH, y + h);
|
|
3407
|
+
if (x1 <= x0 || y1 <= y0) {
|
|
3408
|
+
return;
|
|
3409
|
+
}
|
|
3410
|
+
const rowLen = x1 - x0;
|
|
3411
|
+
const srcCol = x0 - x;
|
|
3412
|
+
const srcYOffset = y0 - y;
|
|
3413
|
+
const actualH = y1 - y0;
|
|
3414
|
+
for (let row = 0; row < actualH; row++) {
|
|
3415
|
+
const dstStart = (y0 + row) * dstW + x0;
|
|
3416
|
+
const srcRow = srcYOffset + row;
|
|
3417
|
+
const srcStart = srcRow * w + srcCol;
|
|
3418
|
+
dstData.set(data.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
3419
|
+
}
|
|
3420
|
+
}
|
|
2698
3421
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2699
3422
|
0 && (module.exports = {
|
|
2700
3423
|
BASE_FAST_BLEND_MODE_FUNCTIONS,
|
|
2701
3424
|
BASE_PERFECT_BLEND_MODE_FUNCTIONS,
|
|
2702
3425
|
BaseBlendMode,
|
|
3426
|
+
HistoryManager,
|
|
2703
3427
|
IndexedImage,
|
|
2704
3428
|
MaskType,
|
|
3429
|
+
PixelAccumulator,
|
|
2705
3430
|
PixelData,
|
|
3431
|
+
PixelEngineConfig,
|
|
3432
|
+
PixelTile,
|
|
3433
|
+
PixelWriter,
|
|
2706
3434
|
UnsupportedFormatError,
|
|
3435
|
+
applyCircleBrushToPixelData,
|
|
2707
3436
|
applyMaskToPixelData,
|
|
3437
|
+
applyPatchTiles,
|
|
3438
|
+
applyRectBrushToPixelData,
|
|
2708
3439
|
base64DecodeArrayBuffer,
|
|
2709
3440
|
base64EncodeArrayBuffer,
|
|
2710
3441
|
blendColorPixelData,
|
|
@@ -2743,6 +3474,7 @@ function rotateSquareInPlace(pixelData) {
|
|
|
2743
3474
|
floodFillSelection,
|
|
2744
3475
|
getImageDataFromClipboard,
|
|
2745
3476
|
getIndexedImageColorCounts,
|
|
3477
|
+
getRectBrushBounds,
|
|
2746
3478
|
getSupportedPixelFormats,
|
|
2747
3479
|
hardLightFast,
|
|
2748
3480
|
hardLightPerfect,
|
|
@@ -2773,6 +3505,7 @@ function rotateSquareInPlace(pixelData) {
|
|
|
2773
3505
|
linearLightPerfect,
|
|
2774
3506
|
makeBlendModeRegistry,
|
|
2775
3507
|
makeFastBlendModeRegistry,
|
|
3508
|
+
makeFullPixelMutator,
|
|
2776
3509
|
makePerfectBlendModeRegistry,
|
|
2777
3510
|
makePixelCanvas,
|
|
2778
3511
|
makeReusableCanvas,
|
|
@@ -2780,6 +3513,12 @@ function rotateSquareInPlace(pixelData) {
|
|
|
2780
3513
|
mergeMasks,
|
|
2781
3514
|
multiplyFast,
|
|
2782
3515
|
multiplyPerfect,
|
|
3516
|
+
mutatorApplyMask,
|
|
3517
|
+
mutatorBlendColor,
|
|
3518
|
+
mutatorBlendPixel,
|
|
3519
|
+
mutatorBlendPixelData,
|
|
3520
|
+
mutatorFill,
|
|
3521
|
+
mutatorInvert,
|
|
2783
3522
|
overlayFast,
|
|
2784
3523
|
overlayPerfect,
|
|
2785
3524
|
overwriteBase,
|
|
@@ -2817,8 +3556,9 @@ function rotateSquareInPlace(pixelData) {
|
|
|
2817
3556
|
vividLightFast,
|
|
2818
3557
|
vividLightPerfect,
|
|
2819
3558
|
writeImageData,
|
|
2820
|
-
|
|
3559
|
+
writeImageDataBuffer,
|
|
2821
3560
|
writeImageDataToClipboard,
|
|
2822
|
-
writeImgBlobToClipboard
|
|
3561
|
+
writeImgBlobToClipboard,
|
|
3562
|
+
writePixelDataBuffer
|
|
2823
3563
|
});
|
|
2824
3564
|
//# sourceMappingURL=index.dev.cjs.map
|