pixel-data-js 0.3.0 → 0.5.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 +1405 -70
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +1355 -68
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +1405 -70
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +581 -64
- package/dist/index.prod.js +1355 -68
- package/dist/index.prod.js.map +1 -1
- package/package.json +14 -3
- package/src/Algorithm/floodFillSelection.ts +229 -0
- package/src/Canvas/PixelCanvas.ts +31 -0
- package/src/Canvas/ReusableCanvas.ts +44 -0
- package/src/Canvas/_constants.ts +2 -0
- package/src/Clipboard/getImageDataFromClipboard.ts +42 -0
- package/src/Clipboard/writeImageDataToClipboard.ts +25 -0
- package/src/Clipboard/writeImgBlobToClipboard.ts +13 -0
- package/src/ImageData/{extractImageData.ts → extractImageDataPixels.ts} +21 -3
- package/src/ImageData/imageDataToAlphaMask.ts +35 -0
- package/src/ImageData/imageDataToDataUrl.ts +27 -0
- package/src/ImageData/imageDataToImgBlob.ts +31 -0
- package/src/ImageData/imgBlobToImageData.ts +52 -0
- package/src/ImageData/invertImageData.ts +10 -0
- package/src/ImageData/resizeImageData.ts +75 -0
- package/src/ImageData/{writeImageData.ts → writeImageDataPixels.ts} +22 -3
- package/src/Input/fileInputChangeToImageData.ts +37 -0
- package/src/Input/fileToImageData.ts +75 -0
- package/src/Input/getSupportedRasterFormats.ts +74 -0
- package/src/Mask/extractMask.ts +86 -0
- package/src/Mask/mergeMasks.ts +1 -6
- package/src/PixelData/blendColorPixelData.ts +9 -9
- package/src/PixelData/fillPixelData.ts +51 -12
- package/src/PixelData/invertPixelData.ts +16 -0
- package/src/PixelData/pixelDataToAlphaMask.ts +28 -0
- package/src/Rect/trimRectBounds.ts +118 -0
- package/src/_types.ts +37 -20
- package/src/blend-modes.ts +506 -66
- package/src/color.ts +6 -6
- package/src/globals.d.ts +2 -0
- package/src/index.ts +37 -1
package/dist/index.dev.js
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
// src/_types.ts
|
|
2
|
-
var MaskType = /* @__PURE__ */ ((MaskType2) => {
|
|
3
|
-
MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
|
|
4
|
-
MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
|
|
5
|
-
return MaskType2;
|
|
6
|
-
})(MaskType || {});
|
|
7
|
-
|
|
8
1
|
// src/blend-modes.ts
|
|
2
|
+
var overwriteColor32 = (src, dst) => src;
|
|
9
3
|
var sourceOverColor32 = (src, dst) => {
|
|
10
4
|
const a = src >>> 24 & 255;
|
|
11
5
|
if (a === 255) return src;
|
|
@@ -22,6 +16,112 @@ var sourceOverColor32 = (src, dst) => {
|
|
|
22
16
|
const outA = a + ((dst >>> 24 & 255) * invA >> 8);
|
|
23
17
|
return (outA << 24 | outRB | outG) >>> 0;
|
|
24
18
|
};
|
|
19
|
+
var darkenColor32 = (src, dst) => {
|
|
20
|
+
const sa = src >>> 24 & 255;
|
|
21
|
+
if (sa === 0) return dst;
|
|
22
|
+
const br = Math.min(src & 255, dst & 255);
|
|
23
|
+
const bg = Math.min(src >> 8 & 255, dst >> 8 & 255);
|
|
24
|
+
const bb = Math.min(src >> 16 & 255, dst >> 16 & 255);
|
|
25
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
26
|
+
const dr = dst & 255;
|
|
27
|
+
const dg = dst >> 8 & 255;
|
|
28
|
+
const db = dst >> 16 & 255;
|
|
29
|
+
const invA = 255 - sa;
|
|
30
|
+
const r = br * sa + dr * invA >> 8;
|
|
31
|
+
const g = bg * sa + dg * invA >> 8;
|
|
32
|
+
const b = bb * sa + db * invA >> 8;
|
|
33
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
34
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
35
|
+
};
|
|
36
|
+
var multiplyColor32 = (src, dst) => {
|
|
37
|
+
const sa = src >>> 24 & 255;
|
|
38
|
+
if (sa === 0) return dst;
|
|
39
|
+
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
40
|
+
const br = (src & 255) * dr + 128 >> 8;
|
|
41
|
+
const bg = (src >> 8 & 255) * dg >> 8;
|
|
42
|
+
const bb = (src >> 16 & 255) * db >> 8;
|
|
43
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
44
|
+
const invA = 255 - sa;
|
|
45
|
+
const r = br * sa + dr * invA >> 8;
|
|
46
|
+
const g = bg * sa + dg * invA >> 8;
|
|
47
|
+
const b = bb * sa + db * invA >> 8;
|
|
48
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
49
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
50
|
+
};
|
|
51
|
+
var colorBurnColor32 = (src, dst) => {
|
|
52
|
+
const sa = src >>> 24 & 255;
|
|
53
|
+
if (sa === 0) return dst;
|
|
54
|
+
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
55
|
+
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
56
|
+
const br = dr === 255 ? 255 : Math.max(0, 255 - (255 - dr << 8) / (sr || 1));
|
|
57
|
+
const bg = dg === 255 ? 255 : Math.max(0, 255 - (255 - dg << 8) / (sg || 1));
|
|
58
|
+
const bb = db === 255 ? 255 : Math.max(0, 255 - (255 - db << 8) / (sb || 1));
|
|
59
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
60
|
+
const invA = 255 - sa;
|
|
61
|
+
const r = br * sa + dr * invA >> 8;
|
|
62
|
+
const g = bg * sa + dg * invA >> 8;
|
|
63
|
+
const b = bb * sa + db * invA >> 8;
|
|
64
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
65
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
66
|
+
};
|
|
67
|
+
var linearBurnColor32 = (src, dst) => {
|
|
68
|
+
const sa = src >>> 24 & 255;
|
|
69
|
+
if (sa === 0) return dst;
|
|
70
|
+
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
71
|
+
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
72
|
+
const br = Math.max(0, dr + sr - 255);
|
|
73
|
+
const bg = Math.max(0, dg + sg - 255);
|
|
74
|
+
const bb = Math.max(0, db + sb - 255);
|
|
75
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
76
|
+
const invA = 255 - sa;
|
|
77
|
+
const r = br * sa + dr * invA >> 8;
|
|
78
|
+
const g = bg * sa + dg * invA >> 8;
|
|
79
|
+
const b = bb * sa + db * invA >> 8;
|
|
80
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
81
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
82
|
+
};
|
|
83
|
+
var darkerColor32 = (src, dst) => {
|
|
84
|
+
const sa = src >>> 24 & 255;
|
|
85
|
+
if (sa === 0) return dst;
|
|
86
|
+
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
87
|
+
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
88
|
+
const lumSrc = sr * 77 + sg * 151 + sb * 28;
|
|
89
|
+
const lumDst = dr * 77 + dg * 151 + db * 28;
|
|
90
|
+
let br, bg, bb;
|
|
91
|
+
if (lumSrc < lumDst) {
|
|
92
|
+
br = sr;
|
|
93
|
+
bg = sg;
|
|
94
|
+
bb = sb;
|
|
95
|
+
} else {
|
|
96
|
+
br = dr;
|
|
97
|
+
bg = dg;
|
|
98
|
+
bb = db;
|
|
99
|
+
}
|
|
100
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
101
|
+
const invA = 255 - sa;
|
|
102
|
+
const r = br * sa + dr * invA >> 8;
|
|
103
|
+
const g = bg * sa + dg * invA >> 8;
|
|
104
|
+
const b = bb * sa + db * invA >> 8;
|
|
105
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
106
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
107
|
+
};
|
|
108
|
+
var lightenColor32 = (src, dst) => {
|
|
109
|
+
const sa = src >>> 24 & 255;
|
|
110
|
+
if (sa === 0) return dst;
|
|
111
|
+
const br = Math.max(src & 255, dst & 255);
|
|
112
|
+
const bg = Math.max(src >> 8 & 255, dst >> 8 & 255);
|
|
113
|
+
const bb = Math.max(src >> 16 & 255, dst >> 16 & 255);
|
|
114
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
115
|
+
const dr = dst & 255;
|
|
116
|
+
const dg = dst >> 8 & 255;
|
|
117
|
+
const db = dst >> 16 & 255;
|
|
118
|
+
const invA = 255 - sa;
|
|
119
|
+
const r = br * sa + dr * invA >> 8;
|
|
120
|
+
const g = bg * sa + dg * invA >> 8;
|
|
121
|
+
const b = bb * sa + db * invA >> 8;
|
|
122
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
123
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
124
|
+
};
|
|
25
125
|
var screenColor32 = (src, dst) => {
|
|
26
126
|
const sa = src >>> 24 & 255;
|
|
27
127
|
if (sa === 0) return dst;
|
|
@@ -37,6 +137,22 @@ var screenColor32 = (src, dst) => {
|
|
|
37
137
|
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
38
138
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
39
139
|
};
|
|
140
|
+
var colorDodgeColor32 = (src, dst) => {
|
|
141
|
+
const sa = src >>> 24 & 255;
|
|
142
|
+
if (sa === 0) return dst;
|
|
143
|
+
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
144
|
+
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
145
|
+
const br = sr === 255 ? 255 : Math.min(255, (dr << 8) / (255 - sr));
|
|
146
|
+
const bg = sg === 255 ? 255 : Math.min(255, (dg << 8) / (255 - sg));
|
|
147
|
+
const bb = sb === 255 ? 255 : Math.min(255, (db << 8) / (255 - sb));
|
|
148
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
149
|
+
const invA = 255 - sa;
|
|
150
|
+
const r = br * sa + dr * invA >> 8;
|
|
151
|
+
const g = bg * sa + dg * invA >> 8;
|
|
152
|
+
const b = bb * sa + db * invA >> 8;
|
|
153
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
154
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
155
|
+
};
|
|
40
156
|
var linearDodgeColor32 = (src, dst) => {
|
|
41
157
|
const sa = src >>> 24 & 255;
|
|
42
158
|
if (sa === 0) return dst;
|
|
@@ -52,13 +168,23 @@ var linearDodgeColor32 = (src, dst) => {
|
|
|
52
168
|
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
53
169
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
54
170
|
};
|
|
55
|
-
var
|
|
171
|
+
var lighterColor32 = (src, dst) => {
|
|
56
172
|
const sa = src >>> 24 & 255;
|
|
57
173
|
if (sa === 0) return dst;
|
|
58
174
|
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
const
|
|
175
|
+
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
176
|
+
const lumSrc = sr * 77 + sg * 151 + sb * 28;
|
|
177
|
+
const lumDst = dr * 77 + dg * 151 + db * 28;
|
|
178
|
+
let br, bg, bb;
|
|
179
|
+
if (lumSrc > lumDst) {
|
|
180
|
+
br = sr;
|
|
181
|
+
bg = sg;
|
|
182
|
+
bb = sb;
|
|
183
|
+
} else {
|
|
184
|
+
br = dr;
|
|
185
|
+
bg = dg;
|
|
186
|
+
bb = db;
|
|
187
|
+
}
|
|
62
188
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
63
189
|
const invA = 255 - sa;
|
|
64
190
|
const r = br * sa + dr * invA >> 8;
|
|
@@ -67,13 +193,14 @@ var multiplyColor32 = (src, dst) => {
|
|
|
67
193
|
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
68
194
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
69
195
|
};
|
|
70
|
-
var
|
|
196
|
+
var overlayColor32 = (src, dst) => {
|
|
71
197
|
const sa = src >>> 24 & 255;
|
|
72
198
|
if (sa === 0) return dst;
|
|
199
|
+
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
73
200
|
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
74
|
-
const br =
|
|
75
|
-
const bg =
|
|
76
|
-
const bb =
|
|
201
|
+
const br = dr < 128 ? 2 * sr * dr >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8);
|
|
202
|
+
const bg = dg < 128 ? 2 * sg * dg >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8);
|
|
203
|
+
const bb = db < 128 ? 2 * sb * db >> 8 : 255 - (2 * (255 - sb) * (255 - db) >> 8);
|
|
77
204
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
78
205
|
const invA = 255 - sa;
|
|
79
206
|
const r = br * sa + dr * invA >> 8;
|
|
@@ -82,11 +209,27 @@ var differenceColor32 = (src, dst) => {
|
|
|
82
209
|
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
83
210
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
84
211
|
};
|
|
85
|
-
var
|
|
212
|
+
var softLightColor32 = (src, dst) => {
|
|
86
213
|
const sa = src >>> 24 & 255;
|
|
87
214
|
if (sa === 0) return dst;
|
|
215
|
+
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
88
216
|
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
217
|
+
const br = (255 - dr) * (sr * dr >> 8) + dr * (255 - ((255 - sr) * (255 - dr) >> 8)) >> 8;
|
|
218
|
+
const bg = (255 - dg) * (sg * dg >> 8) + dg * (255 - ((255 - sg) * (255 - dg) >> 8)) >> 8;
|
|
219
|
+
const bb = (255 - db) * (sb * db >> 8) + db * (255 - ((255 - sb) * (255 - db) >> 8)) >> 8;
|
|
220
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
221
|
+
const invA = 255 - sa;
|
|
222
|
+
const r = br * sa + dr * invA >> 8;
|
|
223
|
+
const g = bg * sa + dg * invA >> 8;
|
|
224
|
+
const b = bb * sa + db * invA >> 8;
|
|
225
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
226
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
227
|
+
};
|
|
228
|
+
var hardLightColor32 = (src, dst) => {
|
|
229
|
+
const sa = src >>> 24 & 255;
|
|
230
|
+
if (sa === 0) return dst;
|
|
89
231
|
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
232
|
+
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
90
233
|
const br = sr < 128 ? 2 * sr * dr >> 8 : 255 - (2 * (255 - sr) * (255 - dr) >> 8);
|
|
91
234
|
const bg = sg < 128 ? 2 * sg * dg >> 8 : 255 - (2 * (255 - sg) * (255 - dg) >> 8);
|
|
92
235
|
const bb = sb < 128 ? 2 * sb * db >> 8 : 255 - (2 * (255 - sb) * (255 - db) >> 8);
|
|
@@ -98,14 +241,46 @@ var hardLightColor32 = (src, dst) => {
|
|
|
98
241
|
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
99
242
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
100
243
|
};
|
|
101
|
-
var
|
|
244
|
+
var vividLightColor32 = (src, dst) => {
|
|
245
|
+
const sa = src >>> 24 & 255;
|
|
246
|
+
if (sa === 0) return dst;
|
|
247
|
+
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
248
|
+
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
249
|
+
const br = sr < 128 ? sr === 0 ? 0 : Math.max(0, 255 - (255 - dr << 8) / (2 * sr)) : sr === 255 ? 255 : Math.min(255, (dr << 8) / (2 * (255 - sr)));
|
|
250
|
+
const bg = sg < 128 ? sg === 0 ? 0 : Math.max(0, 255 - (255 - dg << 8) / (2 * sg)) : sg === 255 ? 255 : Math.min(255, (dg << 8) / (2 * (255 - sg)));
|
|
251
|
+
const bb = sb < 128 ? sb === 0 ? 0 : Math.max(0, 255 - (255 - db << 8) / (2 * sb)) : sb === 255 ? 255 : Math.min(255, (db << 8) / (2 * (255 - sb)));
|
|
252
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
253
|
+
const invA = 255 - sa;
|
|
254
|
+
const r = br * sa + dr * invA >> 8;
|
|
255
|
+
const g = bg * sa + dg * invA >> 8;
|
|
256
|
+
const b = bb * sa + db * invA >> 8;
|
|
257
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
258
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
259
|
+
};
|
|
260
|
+
var linearLightColor32 = (src, dst) => {
|
|
102
261
|
const sa = src >>> 24 & 255;
|
|
103
262
|
if (sa === 0) return dst;
|
|
263
|
+
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
104
264
|
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
265
|
+
const br = Math.max(0, Math.min(255, dr + 2 * sr - 255));
|
|
266
|
+
const bg = Math.max(0, Math.min(255, dg + 2 * sg - 255));
|
|
267
|
+
const bb = Math.max(0, Math.min(255, db + 2 * sb - 255));
|
|
268
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
269
|
+
const invA = 255 - sa;
|
|
270
|
+
const r = br * sa + dr * invA >> 8;
|
|
271
|
+
const g = bg * sa + dg * invA >> 8;
|
|
272
|
+
const b = bb * sa + db * invA >> 8;
|
|
273
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
274
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
275
|
+
};
|
|
276
|
+
var pinLightColor32 = (src, dst) => {
|
|
277
|
+
const sa = src >>> 24 & 255;
|
|
278
|
+
if (sa === 0) return dst;
|
|
105
279
|
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
106
|
-
const
|
|
107
|
-
const
|
|
108
|
-
const
|
|
280
|
+
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
281
|
+
const br = sr < 128 ? Math.min(dr, 2 * sr) : Math.max(dr, 2 * (sr - 128));
|
|
282
|
+
const bg = sg < 128 ? Math.min(dg, 2 * sg) : Math.max(dg, 2 * (sg - 128));
|
|
283
|
+
const bb = sb < 128 ? Math.min(db, 2 * sb) : Math.max(db, 2 * (sb - 128));
|
|
109
284
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
110
285
|
const invA = 255 - sa;
|
|
111
286
|
const r = br * sa + dr * invA >> 8;
|
|
@@ -114,14 +289,61 @@ var colorBurnColor32 = (src, dst) => {
|
|
|
114
289
|
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
115
290
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
116
291
|
};
|
|
117
|
-
var
|
|
292
|
+
var hardMixColor32 = (src, dst) => {
|
|
293
|
+
const sa = src >>> 24 & 255;
|
|
294
|
+
if (sa === 0) return dst;
|
|
295
|
+
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
296
|
+
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
297
|
+
const br = (sr < 128 ? sr === 0 ? 0 : Math.max(0, 255 - (255 - dr << 8) / (2 * sr)) : sr === 255 ? 255 : Math.min(255, (dr << 8) / (2 * (255 - sr)))) < 128 ? 0 : 255;
|
|
298
|
+
const bg = (sg < 128 ? sg === 0 ? 0 : Math.max(0, 255 - (255 - dg << 8) / (2 * sg)) : sg === 255 ? 255 : Math.min(255, (dg << 8) / (2 * (255 - sg)))) < 128 ? 0 : 255;
|
|
299
|
+
const bb = (sb < 128 ? sb === 0 ? 0 : Math.max(0, 255 - (255 - db << 8) / (2 * sb)) : sb === 255 ? 255 : Math.min(255, (db << 8) / (2 * (255 - sb)))) < 128 ? 0 : 255;
|
|
300
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
301
|
+
const invA = 255 - sa;
|
|
302
|
+
const r = br * sa + dr * invA >> 8;
|
|
303
|
+
const g = bg * sa + dg * invA >> 8;
|
|
304
|
+
const b = bb * sa + db * invA >> 8;
|
|
305
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
306
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
307
|
+
};
|
|
308
|
+
var differenceColor32 = (src, dst) => {
|
|
309
|
+
const sa = src >>> 24 & 255;
|
|
310
|
+
if (sa === 0) return dst;
|
|
311
|
+
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
312
|
+
const br = Math.abs((src & 255) - dr);
|
|
313
|
+
const bg = Math.abs((src >> 8 & 255) - dg);
|
|
314
|
+
const bb = Math.abs((src >> 16 & 255) - db);
|
|
315
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
316
|
+
const invA = 255 - sa;
|
|
317
|
+
const r = br * sa + dr * invA >> 8;
|
|
318
|
+
const g = bg * sa + dg * invA >> 8;
|
|
319
|
+
const b = bb * sa + db * invA >> 8;
|
|
320
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
321
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
322
|
+
};
|
|
323
|
+
var exclusionColor32 = (src, dst) => {
|
|
118
324
|
const sa = src >>> 24 & 255;
|
|
119
325
|
if (sa === 0) return dst;
|
|
326
|
+
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
120
327
|
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
328
|
+
const br = dr + sr - (dr * sr >> 7);
|
|
329
|
+
const bg = dg + sg - (dg * sg >> 7);
|
|
330
|
+
const bb = db + sb - (db * sb >> 7);
|
|
331
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
332
|
+
const invA = 255 - sa;
|
|
333
|
+
const r = br * sa + dr * invA >> 8;
|
|
334
|
+
const g = bg * sa + dg * invA >> 8;
|
|
335
|
+
const b = bb * sa + db * invA >> 8;
|
|
336
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
337
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
338
|
+
};
|
|
339
|
+
var subtractColor32 = (src, dst) => {
|
|
340
|
+
const sa = src >>> 24 & 255;
|
|
341
|
+
if (sa === 0) return dst;
|
|
121
342
|
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
122
|
-
const
|
|
123
|
-
const
|
|
124
|
-
const
|
|
343
|
+
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
344
|
+
const br = Math.max(0, dr - sr);
|
|
345
|
+
const bg = Math.max(0, dg - sg);
|
|
346
|
+
const bb = Math.max(0, db - sb);
|
|
125
347
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
126
348
|
const invA = 255 - sa;
|
|
127
349
|
const r = br * sa + dr * invA >> 8;
|
|
@@ -130,16 +352,100 @@ var overlayColor32 = (src, dst) => {
|
|
|
130
352
|
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
131
353
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
132
354
|
};
|
|
133
|
-
var
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
355
|
+
var divideColor32 = (src, dst) => {
|
|
356
|
+
const sa = src >>> 24 & 255;
|
|
357
|
+
if (sa === 0) return dst;
|
|
358
|
+
const dr = dst & 255, dg = dst >> 8 & 255, db = dst >> 16 & 255;
|
|
359
|
+
const sr = src & 255, sg = src >> 8 & 255, sb = src >> 16 & 255;
|
|
360
|
+
const br = sr === 0 ? 255 : Math.min(255, (dr << 8) / sr);
|
|
361
|
+
const bg = sg === 0 ? 255 : Math.min(255, (dg << 8) / sg);
|
|
362
|
+
const bb = sb === 0 ? 255 : Math.min(255, (db << 8) / sb);
|
|
363
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
364
|
+
const invA = 255 - sa;
|
|
365
|
+
const r = br * sa + dr * invA >> 8;
|
|
366
|
+
const g = bg * sa + dg * invA >> 8;
|
|
367
|
+
const b = bb * sa + db * invA >> 8;
|
|
368
|
+
const a = 255 * sa + (dst >>> 24 & 255) * invA >> 8;
|
|
369
|
+
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
142
370
|
};
|
|
371
|
+
var BlendMode = /* @__PURE__ */ ((BlendMode2) => {
|
|
372
|
+
BlendMode2[BlendMode2["overwrite"] = 0] = "overwrite";
|
|
373
|
+
BlendMode2[BlendMode2["sourceOver"] = 1] = "sourceOver";
|
|
374
|
+
BlendMode2[BlendMode2["darken"] = 2] = "darken";
|
|
375
|
+
BlendMode2[BlendMode2["multiply"] = 3] = "multiply";
|
|
376
|
+
BlendMode2[BlendMode2["colorBurn"] = 4] = "colorBurn";
|
|
377
|
+
BlendMode2[BlendMode2["linearBurn"] = 5] = "linearBurn";
|
|
378
|
+
BlendMode2[BlendMode2["darkerColor"] = 6] = "darkerColor";
|
|
379
|
+
BlendMode2[BlendMode2["lighten"] = 7] = "lighten";
|
|
380
|
+
BlendMode2[BlendMode2["screen"] = 8] = "screen";
|
|
381
|
+
BlendMode2[BlendMode2["colorDodge"] = 9] = "colorDodge";
|
|
382
|
+
BlendMode2[BlendMode2["linearDodge"] = 10] = "linearDodge";
|
|
383
|
+
BlendMode2[BlendMode2["lighterColor"] = 11] = "lighterColor";
|
|
384
|
+
BlendMode2[BlendMode2["overlay"] = 12] = "overlay";
|
|
385
|
+
BlendMode2[BlendMode2["softLight"] = 13] = "softLight";
|
|
386
|
+
BlendMode2[BlendMode2["hardLight"] = 14] = "hardLight";
|
|
387
|
+
BlendMode2[BlendMode2["vividLight"] = 15] = "vividLight";
|
|
388
|
+
BlendMode2[BlendMode2["linearLight"] = 16] = "linearLight";
|
|
389
|
+
BlendMode2[BlendMode2["pinLight"] = 17] = "pinLight";
|
|
390
|
+
BlendMode2[BlendMode2["hardMix"] = 18] = "hardMix";
|
|
391
|
+
BlendMode2[BlendMode2["difference"] = 19] = "difference";
|
|
392
|
+
BlendMode2[BlendMode2["exclusion"] = 20] = "exclusion";
|
|
393
|
+
BlendMode2[BlendMode2["subtract"] = 21] = "subtract";
|
|
394
|
+
BlendMode2[BlendMode2["divide"] = 22] = "divide";
|
|
395
|
+
return BlendMode2;
|
|
396
|
+
})(BlendMode || {});
|
|
397
|
+
var BLENDER_REGISTRY = [
|
|
398
|
+
[0 /* overwrite */, overwriteColor32],
|
|
399
|
+
[1 /* sourceOver */, sourceOverColor32],
|
|
400
|
+
[2 /* darken */, darkenColor32],
|
|
401
|
+
[3 /* multiply */, multiplyColor32],
|
|
402
|
+
[4 /* colorBurn */, colorBurnColor32],
|
|
403
|
+
[5 /* linearBurn */, linearBurnColor32],
|
|
404
|
+
[6 /* darkerColor */, darkerColor32],
|
|
405
|
+
[7 /* lighten */, lightenColor32],
|
|
406
|
+
[8 /* screen */, screenColor32],
|
|
407
|
+
[9 /* colorDodge */, colorDodgeColor32],
|
|
408
|
+
[10 /* linearDodge */, linearDodgeColor32],
|
|
409
|
+
[11 /* lighterColor */, lighterColor32],
|
|
410
|
+
[12 /* overlay */, overlayColor32],
|
|
411
|
+
[13 /* softLight */, softLightColor32],
|
|
412
|
+
[14 /* hardLight */, hardLightColor32],
|
|
413
|
+
[15 /* vividLight */, vividLightColor32],
|
|
414
|
+
[16 /* linearLight */, linearLightColor32],
|
|
415
|
+
[17 /* pinLight */, pinLightColor32],
|
|
416
|
+
[18 /* hardMix */, hardMixColor32],
|
|
417
|
+
[19 /* difference */, differenceColor32],
|
|
418
|
+
[20 /* exclusion */, exclusionColor32],
|
|
419
|
+
[21 /* subtract */, subtractColor32],
|
|
420
|
+
[22 /* divide */, divideColor32]
|
|
421
|
+
];
|
|
422
|
+
var COLOR_32_BLEND_MODES = [];
|
|
423
|
+
for (const [index, blend] of BLENDER_REGISTRY) {
|
|
424
|
+
COLOR_32_BLEND_MODES[index] = blend;
|
|
425
|
+
}
|
|
426
|
+
var COLOR_32_BLEND_TO_INDEX = new Map(
|
|
427
|
+
BLENDER_REGISTRY.map((entry, index) => {
|
|
428
|
+
return [
|
|
429
|
+
entry[1],
|
|
430
|
+
index
|
|
431
|
+
];
|
|
432
|
+
})
|
|
433
|
+
);
|
|
434
|
+
var INDEX_TO_COLOR_32_BLEND = new Map(
|
|
435
|
+
BLENDER_REGISTRY.map((entry, index) => {
|
|
436
|
+
return [
|
|
437
|
+
index,
|
|
438
|
+
entry[1]
|
|
439
|
+
];
|
|
440
|
+
})
|
|
441
|
+
);
|
|
442
|
+
|
|
443
|
+
// src/_types.ts
|
|
444
|
+
var MaskType = /* @__PURE__ */ ((MaskType2) => {
|
|
445
|
+
MaskType2[MaskType2["ALPHA"] = 0] = "ALPHA";
|
|
446
|
+
MaskType2[MaskType2["BINARY"] = 1] = "BINARY";
|
|
447
|
+
return MaskType2;
|
|
448
|
+
})(MaskType || {});
|
|
143
449
|
|
|
144
450
|
// src/color.ts
|
|
145
451
|
function packColor(r, g, b, a) {
|
|
@@ -204,20 +510,8 @@ function color32ToCssRGBA(color) {
|
|
|
204
510
|
return `rgba(${r},${g},${b},${alpha})`;
|
|
205
511
|
}
|
|
206
512
|
|
|
207
|
-
// src/ImageData/
|
|
208
|
-
function
|
|
209
|
-
return new ImageData(data.slice(), width, height);
|
|
210
|
-
}
|
|
211
|
-
function copyImageDataLike({ data, width, height }) {
|
|
212
|
-
return {
|
|
213
|
-
data: data.slice(),
|
|
214
|
-
width,
|
|
215
|
-
height
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// src/ImageData/extractImageData.ts
|
|
220
|
-
function extractImageData(imageData, _x, _y, _w, _h) {
|
|
513
|
+
// src/ImageData/extractImageDataPixels.ts
|
|
514
|
+
function extractImageDataPixels(imageData, _x, _y, _w, _h) {
|
|
221
515
|
const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
|
|
222
516
|
const { width: srcW, height: srcH, data: src } = imageData;
|
|
223
517
|
if (w <= 0 || h <= 0) return new Uint8ClampedArray(0);
|
|
@@ -239,28 +533,509 @@ function extractImageData(imageData, _x, _y, _w, _h) {
|
|
|
239
533
|
return out;
|
|
240
534
|
}
|
|
241
535
|
|
|
242
|
-
// src/
|
|
243
|
-
function
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
536
|
+
// src/Mask/extractMask.ts
|
|
537
|
+
function extractMask(mask, maskWidth, xOrRect, y, w, h) {
|
|
538
|
+
let finalX;
|
|
539
|
+
let finalY;
|
|
540
|
+
let finalW;
|
|
541
|
+
let finalH;
|
|
542
|
+
if (typeof xOrRect === "object") {
|
|
543
|
+
finalX = xOrRect.x;
|
|
544
|
+
finalY = xOrRect.y;
|
|
545
|
+
finalW = xOrRect.w;
|
|
546
|
+
finalH = xOrRect.h;
|
|
547
|
+
} else {
|
|
548
|
+
finalX = xOrRect;
|
|
549
|
+
finalY = y;
|
|
550
|
+
finalW = w;
|
|
551
|
+
finalH = h;
|
|
252
552
|
}
|
|
253
|
-
|
|
553
|
+
const out = new Uint8Array(finalW * finalH);
|
|
554
|
+
const srcH = mask.length / maskWidth;
|
|
555
|
+
for (let row = 0; row < finalH; row++) {
|
|
556
|
+
const currentSrcY = finalY + row;
|
|
557
|
+
if (currentSrcY < 0 || currentSrcY >= srcH) {
|
|
558
|
+
continue;
|
|
559
|
+
}
|
|
560
|
+
const start = Math.max(0, finalX);
|
|
561
|
+
const end = Math.min(maskWidth, finalX + finalW);
|
|
562
|
+
if (start < end) {
|
|
563
|
+
const srcOffset = currentSrcY * maskWidth + start;
|
|
564
|
+
const dstOffset = row * finalW + (start - finalX);
|
|
565
|
+
const count = end - start;
|
|
566
|
+
out.set(
|
|
567
|
+
mask.subarray(srcOffset, srcOffset + count),
|
|
568
|
+
dstOffset
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return out;
|
|
254
573
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
574
|
+
|
|
575
|
+
// src/Rect/trimRectBounds.ts
|
|
576
|
+
function trimRectBounds(target, bounds) {
|
|
577
|
+
const originalX = target.x;
|
|
578
|
+
const originalY = target.y;
|
|
579
|
+
const originalW = target.w;
|
|
580
|
+
const intersectedX = Math.max(target.x, bounds.x);
|
|
581
|
+
const intersectedY = Math.max(target.y, bounds.y);
|
|
582
|
+
const intersectedMaxX = Math.min(
|
|
583
|
+
target.x + target.w,
|
|
584
|
+
bounds.x + bounds.w
|
|
585
|
+
);
|
|
586
|
+
const intersectedMaxY = Math.min(
|
|
587
|
+
target.y + target.h,
|
|
588
|
+
bounds.y + bounds.h
|
|
589
|
+
);
|
|
590
|
+
if (intersectedMaxX <= intersectedX || intersectedMaxY <= intersectedY) {
|
|
591
|
+
target.w = 0;
|
|
592
|
+
target.h = 0;
|
|
593
|
+
if ("mask" in target && target.mask) {
|
|
594
|
+
target.mask = new Uint8Array(0);
|
|
595
|
+
}
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
const intersectedW = intersectedMaxX - intersectedX;
|
|
599
|
+
const intersectedH = intersectedMaxY - intersectedY;
|
|
600
|
+
const offsetX = intersectedX - originalX;
|
|
601
|
+
const offsetY = intersectedY - originalY;
|
|
602
|
+
target.x = intersectedX;
|
|
603
|
+
target.y = intersectedY;
|
|
604
|
+
target.w = intersectedW;
|
|
605
|
+
target.h = intersectedH;
|
|
606
|
+
if ("mask" in target && target.mask) {
|
|
607
|
+
const currentMask = extractMask(
|
|
608
|
+
target.mask,
|
|
609
|
+
originalW,
|
|
610
|
+
offsetX,
|
|
611
|
+
offsetY,
|
|
612
|
+
intersectedW,
|
|
613
|
+
intersectedH
|
|
614
|
+
);
|
|
615
|
+
let minX = intersectedW;
|
|
616
|
+
let maxX = -1;
|
|
617
|
+
let minY = intersectedH;
|
|
618
|
+
let maxY = -1;
|
|
619
|
+
for (let y = 0; y < intersectedH; y++) {
|
|
620
|
+
for (let x = 0; x < intersectedW; x++) {
|
|
621
|
+
if (currentMask[y * intersectedW + x] !== 0) {
|
|
622
|
+
if (x < minX) minX = x;
|
|
623
|
+
if (x > maxX) maxX = x;
|
|
624
|
+
if (y < minY) minY = y;
|
|
625
|
+
if (y > maxY) maxY = y;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
if (maxX === -1) {
|
|
630
|
+
target.w = 0;
|
|
631
|
+
target.h = 0;
|
|
632
|
+
target.mask = new Uint8Array(0);
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
const finalW = maxX - minX + 1;
|
|
636
|
+
const finalH = maxY - minY + 1;
|
|
637
|
+
if (finalW !== intersectedW || finalH !== intersectedH) {
|
|
638
|
+
target.mask = extractMask(
|
|
639
|
+
currentMask,
|
|
640
|
+
intersectedW,
|
|
641
|
+
minX,
|
|
642
|
+
minY,
|
|
643
|
+
finalW,
|
|
644
|
+
finalH
|
|
645
|
+
);
|
|
646
|
+
target.x += minX;
|
|
647
|
+
target.y += minY;
|
|
648
|
+
target.w = finalW;
|
|
649
|
+
target.h = finalH;
|
|
650
|
+
} else {
|
|
651
|
+
target.mask = currentMask;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
261
654
|
}
|
|
262
|
-
|
|
263
|
-
|
|
655
|
+
|
|
656
|
+
// src/Algorithm/floodFillSelection.ts
|
|
657
|
+
function floodFillSelection(img, startX, startY, {
|
|
658
|
+
contiguous = true,
|
|
659
|
+
tolerance = 0,
|
|
660
|
+
bounds
|
|
661
|
+
} = {}) {
|
|
662
|
+
let imageData;
|
|
663
|
+
let data32;
|
|
664
|
+
if ("data32" in img) {
|
|
665
|
+
data32 = img.data32;
|
|
666
|
+
imageData = img.imageData;
|
|
667
|
+
} else {
|
|
668
|
+
data32 = new Uint32Array(
|
|
669
|
+
img.data.buffer,
|
|
670
|
+
img.data.byteOffset,
|
|
671
|
+
img.data.byteLength >> 2
|
|
672
|
+
);
|
|
673
|
+
imageData = img;
|
|
674
|
+
}
|
|
675
|
+
const {
|
|
676
|
+
width,
|
|
677
|
+
height
|
|
678
|
+
} = img;
|
|
679
|
+
const limit = bounds || {
|
|
680
|
+
x: 0,
|
|
681
|
+
y: 0,
|
|
682
|
+
w: width,
|
|
683
|
+
h: height
|
|
684
|
+
};
|
|
685
|
+
const xMin = Math.max(0, limit.x);
|
|
686
|
+
const xMax = Math.min(width - 1, limit.x + limit.w - 1);
|
|
687
|
+
const yMin = Math.max(0, limit.y);
|
|
688
|
+
const yMax = Math.min(height - 1, limit.y + limit.h - 1);
|
|
689
|
+
if (startX < xMin || startX > xMax || startY < yMin || startY > yMax) {
|
|
690
|
+
return null;
|
|
691
|
+
}
|
|
692
|
+
const baseColor = data32[startY * width + startX];
|
|
693
|
+
let matchCount = 0;
|
|
694
|
+
const matchX = new Uint16Array(width * height);
|
|
695
|
+
const matchY = new Uint16Array(width * height);
|
|
696
|
+
let minX = startX;
|
|
697
|
+
let maxX = startX;
|
|
698
|
+
let minY = startY;
|
|
699
|
+
let maxY = startY;
|
|
700
|
+
if (contiguous) {
|
|
701
|
+
const visited = new Uint8Array(width * height);
|
|
702
|
+
const stack = new Uint32Array(width * height);
|
|
703
|
+
let stackPtr = 0;
|
|
704
|
+
stack[stackPtr++] = startY << 16 | startX;
|
|
705
|
+
visited[startY * width + startX] = 1;
|
|
706
|
+
while (stackPtr > 0) {
|
|
707
|
+
const val = stack[--stackPtr];
|
|
708
|
+
const x = val & 65535;
|
|
709
|
+
const y = val >>> 16;
|
|
710
|
+
matchX[matchCount] = x;
|
|
711
|
+
matchY[matchCount] = y;
|
|
712
|
+
matchCount++;
|
|
713
|
+
if (x < minX) minX = x;
|
|
714
|
+
if (x > maxX) maxX = x;
|
|
715
|
+
if (y < minY) minY = y;
|
|
716
|
+
if (y > maxY) maxY = y;
|
|
717
|
+
if (x + 1 <= xMax) {
|
|
718
|
+
const idx = y * width + (x + 1);
|
|
719
|
+
if (!visited[idx] && colorDistance(data32[idx], baseColor) <= tolerance) {
|
|
720
|
+
visited[idx] = 1;
|
|
721
|
+
stack[stackPtr++] = y << 16 | x + 1;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
if (x - 1 >= xMin) {
|
|
725
|
+
const idx = y * width + (x - 1);
|
|
726
|
+
if (!visited[idx] && colorDistance(data32[idx], baseColor) <= tolerance) {
|
|
727
|
+
visited[idx] = 1;
|
|
728
|
+
stack[stackPtr++] = y << 16 | x - 1;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
if (y + 1 <= yMax) {
|
|
732
|
+
const idx = (y + 1) * width + x;
|
|
733
|
+
if (!visited[idx] && colorDistance(data32[idx], baseColor) <= tolerance) {
|
|
734
|
+
visited[idx] = 1;
|
|
735
|
+
stack[stackPtr++] = y + 1 << 16 | x;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
if (y - 1 >= yMin) {
|
|
739
|
+
const idx = (y - 1) * width + x;
|
|
740
|
+
if (!visited[idx] && colorDistance(data32[idx], baseColor) <= tolerance) {
|
|
741
|
+
visited[idx] = 1;
|
|
742
|
+
stack[stackPtr++] = y - 1 << 16 | x;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
} else {
|
|
747
|
+
for (let y = yMin; y <= yMax; y++) {
|
|
748
|
+
for (let x = xMin; x <= xMax; x++) {
|
|
749
|
+
const color = data32[y * width + x];
|
|
750
|
+
if (colorDistance(color, baseColor) <= tolerance) {
|
|
751
|
+
matchX[matchCount] = x;
|
|
752
|
+
matchY[matchCount] = y;
|
|
753
|
+
matchCount++;
|
|
754
|
+
if (x < minX) minX = x;
|
|
755
|
+
if (x > maxX) maxX = x;
|
|
756
|
+
if (y < minY) minY = y;
|
|
757
|
+
if (y > maxY) maxY = y;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
if (matchCount === 0) {
|
|
763
|
+
return null;
|
|
764
|
+
}
|
|
765
|
+
const selectionRect = {
|
|
766
|
+
x: minX,
|
|
767
|
+
y: minY,
|
|
768
|
+
w: maxX - minX + 1,
|
|
769
|
+
h: maxY - minY + 1,
|
|
770
|
+
mask: new Uint8Array((maxX - minX + 1) * (maxY - minY + 1)),
|
|
771
|
+
maskType: 1 /* BINARY */
|
|
772
|
+
};
|
|
773
|
+
const sw = selectionRect.w;
|
|
774
|
+
const sh = selectionRect.h;
|
|
775
|
+
const finalMask = selectionRect.mask;
|
|
776
|
+
for (let i = 0; i < matchCount; i++) {
|
|
777
|
+
const mx = matchX[i] - selectionRect.x;
|
|
778
|
+
const my = matchY[i] - selectionRect.y;
|
|
779
|
+
if (mx >= 0 && mx < sw && my >= 0 && my < sh) {
|
|
780
|
+
finalMask[my * sw + mx] = 1;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
trimRectBounds(
|
|
784
|
+
selectionRect,
|
|
785
|
+
{ x: 0, y: 0, w: width, h: height }
|
|
786
|
+
);
|
|
787
|
+
const extracted = extractImageDataPixels(
|
|
788
|
+
imageData,
|
|
789
|
+
selectionRect.x,
|
|
790
|
+
selectionRect.y,
|
|
791
|
+
selectionRect.w,
|
|
792
|
+
selectionRect.h
|
|
793
|
+
);
|
|
794
|
+
return {
|
|
795
|
+
startX,
|
|
796
|
+
startY,
|
|
797
|
+
selectionRect,
|
|
798
|
+
pixels: extracted
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// src/Canvas/_constants.ts
|
|
803
|
+
var OFFSCREEN_CANVAS_CTX_FAILED = "Failed to create OffscreenCanvas context";
|
|
804
|
+
var CANVAS_CTX_FAILED = "Failed to create Canvas context";
|
|
805
|
+
|
|
806
|
+
// src/Canvas/PixelCanvas.ts
|
|
807
|
+
function makePixelCanvas(canvas) {
|
|
808
|
+
const ctx = canvas.getContext("2d");
|
|
809
|
+
if (!ctx) throw new Error(CANVAS_CTX_FAILED);
|
|
810
|
+
ctx.imageSmoothingEnabled = false;
|
|
811
|
+
return {
|
|
812
|
+
canvas,
|
|
813
|
+
ctx,
|
|
814
|
+
resize(w, h) {
|
|
815
|
+
canvas.width = w;
|
|
816
|
+
canvas.height = h;
|
|
817
|
+
ctx.imageSmoothingEnabled = false;
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// src/Canvas/ReusableCanvas.ts
|
|
823
|
+
function makeReusableCanvas() {
|
|
824
|
+
let canvas = null;
|
|
825
|
+
let ctx = null;
|
|
826
|
+
function get2(width, height) {
|
|
827
|
+
if (canvas === null) {
|
|
828
|
+
canvas = document.createElement("canvas");
|
|
829
|
+
ctx = canvas.getContext("2d");
|
|
830
|
+
if (!ctx) throw new Error(CANVAS_CTX_FAILED);
|
|
831
|
+
}
|
|
832
|
+
if (canvas.width !== width || canvas.height !== height) {
|
|
833
|
+
canvas.width = width;
|
|
834
|
+
canvas.height = height;
|
|
835
|
+
ctx.imageSmoothingEnabled = false;
|
|
836
|
+
} else {
|
|
837
|
+
ctx.clearRect(0, 0, width, height);
|
|
838
|
+
}
|
|
839
|
+
return { canvas, ctx };
|
|
840
|
+
}
|
|
841
|
+
get2.reset = () => {
|
|
842
|
+
canvas = null;
|
|
843
|
+
ctx = null;
|
|
844
|
+
};
|
|
845
|
+
return get2;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// src/ImageData/imgBlobToImageData.ts
|
|
849
|
+
async function imgBlobToImageData(blob) {
|
|
850
|
+
let bitmap = null;
|
|
851
|
+
try {
|
|
852
|
+
bitmap = await createImageBitmap(blob);
|
|
853
|
+
const canvas = new OffscreenCanvas(
|
|
854
|
+
bitmap.width,
|
|
855
|
+
bitmap.height
|
|
856
|
+
);
|
|
857
|
+
const ctx = canvas.getContext("2d");
|
|
858
|
+
if (!ctx) {
|
|
859
|
+
throw new Error("Failed to get 2D context");
|
|
860
|
+
}
|
|
861
|
+
ctx.drawImage(bitmap, 0, 0);
|
|
862
|
+
return ctx.getImageData(
|
|
863
|
+
0,
|
|
864
|
+
0,
|
|
865
|
+
bitmap.width,
|
|
866
|
+
bitmap.height
|
|
867
|
+
);
|
|
868
|
+
} finally {
|
|
869
|
+
bitmap?.close();
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// src/Clipboard/getImageDataFromClipboard.ts
|
|
874
|
+
async function getImageDataFromClipboard(clipboardEvent) {
|
|
875
|
+
const items = clipboardEvent?.clipboardData?.items;
|
|
876
|
+
if (!items?.length) return null;
|
|
877
|
+
for (let i = 0; i < items.length; i++) {
|
|
878
|
+
const item = items[i];
|
|
879
|
+
if (item.type.startsWith("image/")) {
|
|
880
|
+
const blob = item.getAsFile();
|
|
881
|
+
if (!blob) {
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
return imgBlobToImageData(blob);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// src/ImageData/imageDataToImgBlob.ts
|
|
891
|
+
async function imageDataToImgBlob(imageData) {
|
|
892
|
+
const canvas = new OffscreenCanvas(imageData.width, imageData.height);
|
|
893
|
+
const ctx = canvas.getContext("2d");
|
|
894
|
+
if (!ctx) throw new Error("could not create 2d context");
|
|
895
|
+
ctx.putImageData(imageData, 0, 0);
|
|
896
|
+
return canvas.convertToBlob({
|
|
897
|
+
type: "image/png"
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
// src/Clipboard/writeImgBlobToClipboard.ts
|
|
902
|
+
async function writeImgBlobToClipboard(blob) {
|
|
903
|
+
const item = new ClipboardItem({
|
|
904
|
+
"image/png": blob
|
|
905
|
+
});
|
|
906
|
+
await navigator.clipboard.write([item]);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// src/Clipboard/writeImageDataToClipboard.ts
|
|
910
|
+
async function writeImageDataToClipboard(imageData) {
|
|
911
|
+
const blob = await imageDataToImgBlob(imageData);
|
|
912
|
+
return writeImgBlobToClipboard(blob);
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// src/ImageData/copyImageData.ts
|
|
916
|
+
function copyImageData({ data, width, height }) {
|
|
917
|
+
return new ImageData(data.slice(), width, height);
|
|
918
|
+
}
|
|
919
|
+
function copyImageDataLike({ data, width, height }) {
|
|
920
|
+
return {
|
|
921
|
+
data: data.slice(),
|
|
922
|
+
width,
|
|
923
|
+
height
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
// src/PixelData/pixelDataToAlphaMask.ts
|
|
928
|
+
function pixelDataToAlphaMask(pixelData) {
|
|
929
|
+
const {
|
|
930
|
+
data32,
|
|
931
|
+
width,
|
|
932
|
+
height
|
|
933
|
+
} = pixelData;
|
|
934
|
+
const len = data32.length;
|
|
935
|
+
const mask = new Uint8Array(width * height);
|
|
936
|
+
for (let i = 0; i < len; i++) {
|
|
937
|
+
const val = data32[i];
|
|
938
|
+
mask[i] = val >>> 24 & 255;
|
|
939
|
+
}
|
|
940
|
+
return mask;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
// src/ImageData/imageDataToAlphaMask.ts
|
|
944
|
+
function imageDataToAlphaMask(imageData) {
|
|
945
|
+
const {
|
|
946
|
+
width,
|
|
947
|
+
height,
|
|
948
|
+
data
|
|
949
|
+
} = imageData;
|
|
950
|
+
const data32 = new Uint32Array(
|
|
951
|
+
data.buffer,
|
|
952
|
+
data.byteOffset,
|
|
953
|
+
data.byteLength >> 2
|
|
954
|
+
);
|
|
955
|
+
const len = data32.length;
|
|
956
|
+
const mask = new Uint8Array(width * height);
|
|
957
|
+
for (let i = 0; i < len; i++) {
|
|
958
|
+
const val = data32[i];
|
|
959
|
+
mask[i] = val >>> 24 & 255;
|
|
960
|
+
}
|
|
961
|
+
return mask;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
// src/ImageData/imageDataToDataUrl.ts
|
|
965
|
+
var get = makeReusableCanvas();
|
|
966
|
+
function imageDataToDataUrl(imageData) {
|
|
967
|
+
const { canvas, ctx } = get(imageData.width, imageData.height);
|
|
968
|
+
ctx.putImageData(imageData, 0, 0);
|
|
969
|
+
return canvas.toDataURL();
|
|
970
|
+
}
|
|
971
|
+
imageDataToDataUrl.reset = get.reset;
|
|
972
|
+
|
|
973
|
+
// src/ImageData/invertImageData.ts
|
|
974
|
+
function invertImageData(imageData) {
|
|
975
|
+
const data = imageData.data;
|
|
976
|
+
let length = data.length;
|
|
977
|
+
for (let i = 0; i < length; i += 4) {
|
|
978
|
+
data[i] = 255 - data[i];
|
|
979
|
+
data[i + 1] = 255 - data[i + 1];
|
|
980
|
+
data[i + 2] = 255 - data[i + 2];
|
|
981
|
+
}
|
|
982
|
+
return imageData;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
// src/ImageData/resizeImageData.ts
|
|
986
|
+
function resizeImageData(current, newWidth, newHeight, offsetX = 0, offsetY = 0) {
|
|
987
|
+
const result = new ImageData(newWidth, newHeight);
|
|
988
|
+
const {
|
|
989
|
+
width: oldW,
|
|
990
|
+
height: oldH,
|
|
991
|
+
data: oldData
|
|
992
|
+
} = current;
|
|
993
|
+
const newData = result.data;
|
|
994
|
+
const x0 = Math.max(0, offsetX);
|
|
995
|
+
const y0 = Math.max(0, offsetY);
|
|
996
|
+
const x1 = Math.min(newWidth, offsetX + oldW);
|
|
997
|
+
const y1 = Math.min(newHeight, offsetY + oldH);
|
|
998
|
+
if (x1 <= x0 || y1 <= y0) {
|
|
999
|
+
return result;
|
|
1000
|
+
}
|
|
1001
|
+
const rowCount = y1 - y0;
|
|
1002
|
+
const rowLen = (x1 - x0) * 4;
|
|
1003
|
+
for (let row = 0; row < rowCount; row++) {
|
|
1004
|
+
const dstY = y0 + row;
|
|
1005
|
+
const srcY = dstY - offsetY;
|
|
1006
|
+
const srcX = x0 - offsetX;
|
|
1007
|
+
const dstStart = (dstY * newWidth + x0) * 4;
|
|
1008
|
+
const srcStart = (srcY * oldW + srcX) * 4;
|
|
1009
|
+
newData.set(
|
|
1010
|
+
oldData.subarray(srcStart, srcStart + rowLen),
|
|
1011
|
+
dstStart
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
return result;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// src/ImageData/serialization.ts
|
|
1018
|
+
function base64EncodeArrayBuffer(buffer) {
|
|
1019
|
+
const binary = String.fromCharCode(...new Uint8Array(buffer));
|
|
1020
|
+
return btoa(binary);
|
|
1021
|
+
}
|
|
1022
|
+
function base64DecodeArrayBuffer(encoded) {
|
|
1023
|
+
const binary = atob(encoded);
|
|
1024
|
+
const bytes = new Uint8ClampedArray(binary.length);
|
|
1025
|
+
for (let i = 0; i < binary.length; i++) {
|
|
1026
|
+
bytes[i] = binary.charCodeAt(i);
|
|
1027
|
+
}
|
|
1028
|
+
return bytes;
|
|
1029
|
+
}
|
|
1030
|
+
function serializeImageData(imageData) {
|
|
1031
|
+
return {
|
|
1032
|
+
width: imageData.width,
|
|
1033
|
+
height: imageData.height,
|
|
1034
|
+
data: base64EncodeArrayBuffer(imageData.data.buffer)
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
function serializeNullableImageData(imageData) {
|
|
1038
|
+
if (!imageData) return null;
|
|
264
1039
|
return serializeImageData(imageData);
|
|
265
1040
|
}
|
|
266
1041
|
function deserializeRawImageData(serialized) {
|
|
@@ -279,6 +1054,407 @@ function deserializeNullableImageData(serialized) {
|
|
|
279
1054
|
return deserializeImageData(serialized);
|
|
280
1055
|
}
|
|
281
1056
|
|
|
1057
|
+
// src/ImageData/writeImageDataPixels.ts
|
|
1058
|
+
function writeImageDataPixels(imageData, data, _x, _y, _w, _h) {
|
|
1059
|
+
const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
|
|
1060
|
+
const { width: dstW, height: dstH, data: dst } = imageData;
|
|
1061
|
+
const x0 = Math.max(0, x);
|
|
1062
|
+
const y0 = Math.max(0, y);
|
|
1063
|
+
const x1 = Math.min(dstW, x + w);
|
|
1064
|
+
const y1 = Math.min(dstH, y + h);
|
|
1065
|
+
if (x1 <= x0 || y1 <= y0) return;
|
|
1066
|
+
const rowLen = (x1 - x0) * 4;
|
|
1067
|
+
const srcCol = x0 - x;
|
|
1068
|
+
const srcYOffset = y0 - y;
|
|
1069
|
+
const actualH = y1 - y0;
|
|
1070
|
+
for (let row = 0; row < actualH; row++) {
|
|
1071
|
+
const dstStart = ((y0 + row) * dstW + x0) * 4;
|
|
1072
|
+
const srcRow = srcYOffset + row;
|
|
1073
|
+
const o = (srcRow * w + srcCol) * 4;
|
|
1074
|
+
dst.set(data.subarray(o, o + rowLen), dstStart);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
// src/Input/fileInputChangeToImageData.ts
|
|
1079
|
+
async function fileInputChangeToImageData(event) {
|
|
1080
|
+
const target = event.target;
|
|
1081
|
+
const file = target.files?.[0];
|
|
1082
|
+
if (!file) return null;
|
|
1083
|
+
return await fileToImageData(file);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
// src/Input/fileToImageData.ts
|
|
1087
|
+
var UnsupportedFormatError = class extends Error {
|
|
1088
|
+
constructor(mimeType) {
|
|
1089
|
+
super(`File type ${mimeType} is not a supported image format.`);
|
|
1090
|
+
this.name = "UnsupportedFormatError";
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
async function fileToImageData(file) {
|
|
1094
|
+
if (!file) return null;
|
|
1095
|
+
if (!file.type.startsWith("image/")) {
|
|
1096
|
+
throw new UnsupportedFormatError(file.type);
|
|
1097
|
+
}
|
|
1098
|
+
let bitmap = null;
|
|
1099
|
+
try {
|
|
1100
|
+
bitmap = await createImageBitmap(file);
|
|
1101
|
+
const canvas = new OffscreenCanvas(
|
|
1102
|
+
bitmap.width,
|
|
1103
|
+
bitmap.height
|
|
1104
|
+
);
|
|
1105
|
+
const ctx = canvas.getContext("2d");
|
|
1106
|
+
if (!ctx) throw new Error(OFFSCREEN_CANVAS_CTX_FAILED);
|
|
1107
|
+
ctx.drawImage(
|
|
1108
|
+
bitmap,
|
|
1109
|
+
0,
|
|
1110
|
+
0
|
|
1111
|
+
);
|
|
1112
|
+
return ctx.getImageData(
|
|
1113
|
+
0,
|
|
1114
|
+
0,
|
|
1115
|
+
bitmap.width,
|
|
1116
|
+
bitmap.height
|
|
1117
|
+
);
|
|
1118
|
+
} finally {
|
|
1119
|
+
bitmap?.close();
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
// src/Input/getSupportedRasterFormats.ts
|
|
1124
|
+
var formatsPromise = null;
|
|
1125
|
+
var defaultRasterMimes = [
|
|
1126
|
+
"image/png",
|
|
1127
|
+
"image/jpeg",
|
|
1128
|
+
"image/webp",
|
|
1129
|
+
"image/avif",
|
|
1130
|
+
"image/gif",
|
|
1131
|
+
"image/bmp"
|
|
1132
|
+
];
|
|
1133
|
+
async function getSupportedPixelFormats(rasterMimes = defaultRasterMimes) {
|
|
1134
|
+
if (formatsPromise) {
|
|
1135
|
+
return formatsPromise;
|
|
1136
|
+
}
|
|
1137
|
+
const probeCanvas = async () => {
|
|
1138
|
+
const canvas = new OffscreenCanvas(1, 1);
|
|
1139
|
+
const results = await Promise.all(
|
|
1140
|
+
rasterMimes.map(async (mime) => {
|
|
1141
|
+
try {
|
|
1142
|
+
const blob = await canvas.convertToBlob({
|
|
1143
|
+
type: mime
|
|
1144
|
+
});
|
|
1145
|
+
return blob.type === mime ? mime : null;
|
|
1146
|
+
} catch {
|
|
1147
|
+
return null;
|
|
1148
|
+
}
|
|
1149
|
+
})
|
|
1150
|
+
);
|
|
1151
|
+
return results.filter((type) => {
|
|
1152
|
+
return type !== null;
|
|
1153
|
+
});
|
|
1154
|
+
};
|
|
1155
|
+
formatsPromise = probeCanvas().catch((error) => {
|
|
1156
|
+
formatsPromise = null;
|
|
1157
|
+
throw error;
|
|
1158
|
+
});
|
|
1159
|
+
return formatsPromise;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
// src/Mask/copyMask.ts
|
|
1163
|
+
function copyMask(src) {
|
|
1164
|
+
return src.slice();
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
// src/Mask/invertMask.ts
|
|
1168
|
+
function invertBinaryMask(dst) {
|
|
1169
|
+
const len = dst.length;
|
|
1170
|
+
for (let i = 0; i < len; i++) {
|
|
1171
|
+
dst[i] = dst[i] === 0 ? 1 : 0;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
function invertAlphaMask(dst) {
|
|
1175
|
+
const len = dst.length;
|
|
1176
|
+
for (let i = 0; i < len; i++) {
|
|
1177
|
+
dst[i] = 255 - dst[i];
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
// src/Mask/mergeMasks.ts
|
|
1182
|
+
function mergeMasks(dst, dstWidth, src, opts) {
|
|
1183
|
+
const {
|
|
1184
|
+
x: targetX = 0,
|
|
1185
|
+
y: targetY = 0,
|
|
1186
|
+
w: width = 0,
|
|
1187
|
+
h: height = 0,
|
|
1188
|
+
alpha: globalAlpha = 255,
|
|
1189
|
+
maskType = 0 /* ALPHA */,
|
|
1190
|
+
mw,
|
|
1191
|
+
mx = 0,
|
|
1192
|
+
my = 0,
|
|
1193
|
+
invertMask = false
|
|
1194
|
+
} = opts;
|
|
1195
|
+
if (width <= 0 || height <= 0 || globalAlpha === 0) {
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
const sPitch = mw ?? width;
|
|
1199
|
+
const isAlpha = maskType === 0 /* ALPHA */;
|
|
1200
|
+
for (let iy = 0; iy < height; iy++) {
|
|
1201
|
+
const dy = targetY + iy;
|
|
1202
|
+
const sy = my + iy;
|
|
1203
|
+
if (dy < 0 || sy < 0) {
|
|
1204
|
+
continue;
|
|
1205
|
+
}
|
|
1206
|
+
for (let ix = 0; ix < width; ix++) {
|
|
1207
|
+
const dx = targetX + ix;
|
|
1208
|
+
const sx = mx + ix;
|
|
1209
|
+
if (dx < 0 || dx >= dstWidth || sx < 0 || sx >= sPitch) {
|
|
1210
|
+
continue;
|
|
1211
|
+
}
|
|
1212
|
+
const dIdx = dy * dstWidth + dx;
|
|
1213
|
+
const sIdx = sy * sPitch + sx;
|
|
1214
|
+
const mVal = src[sIdx];
|
|
1215
|
+
let weight = globalAlpha;
|
|
1216
|
+
if (isAlpha) {
|
|
1217
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
1218
|
+
if (effectiveM === 0) {
|
|
1219
|
+
dst[dIdx] = 0;
|
|
1220
|
+
continue;
|
|
1221
|
+
}
|
|
1222
|
+
weight = globalAlpha === 255 ? effectiveM : effectiveM * globalAlpha + 128 >> 8;
|
|
1223
|
+
} else {
|
|
1224
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
1225
|
+
if (!isHit) {
|
|
1226
|
+
dst[dIdx] = 0;
|
|
1227
|
+
continue;
|
|
1228
|
+
}
|
|
1229
|
+
weight = globalAlpha;
|
|
1230
|
+
}
|
|
1231
|
+
if (weight === 0) {
|
|
1232
|
+
dst[dIdx] = 0;
|
|
1233
|
+
continue;
|
|
1234
|
+
}
|
|
1235
|
+
const da = dst[dIdx];
|
|
1236
|
+
if (da === 0) {
|
|
1237
|
+
} else if (weight === 255) {
|
|
1238
|
+
} else if (da === 255) {
|
|
1239
|
+
dst[dIdx] = weight;
|
|
1240
|
+
} else {
|
|
1241
|
+
dst[dIdx] = da * weight + 128 >> 8;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
// src/PixelData.ts
|
|
1248
|
+
var PixelData = class {
|
|
1249
|
+
constructor(imageData) {
|
|
1250
|
+
this.imageData = imageData;
|
|
1251
|
+
this.width = imageData.width;
|
|
1252
|
+
this.height = imageData.height;
|
|
1253
|
+
this.data32 = new Uint32Array(
|
|
1254
|
+
imageData.data.buffer,
|
|
1255
|
+
imageData.data.byteOffset,
|
|
1256
|
+
imageData.data.byteLength >> 2
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
data32;
|
|
1260
|
+
width;
|
|
1261
|
+
height;
|
|
1262
|
+
};
|
|
1263
|
+
|
|
1264
|
+
// src/PixelData/applyMaskToPixelData.ts
|
|
1265
|
+
function applyMaskToPixelData(dst, mask, opts) {
|
|
1266
|
+
const {
|
|
1267
|
+
x: targetX = 0,
|
|
1268
|
+
y: targetY = 0,
|
|
1269
|
+
w: width = dst.width,
|
|
1270
|
+
h: height = dst.height,
|
|
1271
|
+
alpha: globalAlpha = 255,
|
|
1272
|
+
maskType = 0 /* ALPHA */,
|
|
1273
|
+
mw,
|
|
1274
|
+
mx = 0,
|
|
1275
|
+
my = 0,
|
|
1276
|
+
invertMask = false
|
|
1277
|
+
} = opts;
|
|
1278
|
+
let x = targetX;
|
|
1279
|
+
let y = targetY;
|
|
1280
|
+
let w = width;
|
|
1281
|
+
let h = height;
|
|
1282
|
+
if (x < 0) {
|
|
1283
|
+
w += x;
|
|
1284
|
+
x = 0;
|
|
1285
|
+
}
|
|
1286
|
+
if (y < 0) {
|
|
1287
|
+
h += y;
|
|
1288
|
+
y = 0;
|
|
1289
|
+
}
|
|
1290
|
+
const actualW = Math.min(w, dst.width - x);
|
|
1291
|
+
const actualH = Math.min(h, dst.height - y);
|
|
1292
|
+
if (actualW <= 0 || actualH <= 0 || globalAlpha === 0) {
|
|
1293
|
+
return;
|
|
1294
|
+
}
|
|
1295
|
+
const dst32 = dst.data32;
|
|
1296
|
+
const dw = dst.width;
|
|
1297
|
+
const mPitch = mw ?? width;
|
|
1298
|
+
const isAlpha = maskType === 0 /* ALPHA */;
|
|
1299
|
+
const dx = x - targetX;
|
|
1300
|
+
const dy = y - targetY;
|
|
1301
|
+
let dIdx = y * dw + x;
|
|
1302
|
+
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
1303
|
+
const dStride = dw - actualW;
|
|
1304
|
+
const mStride = mPitch - actualW;
|
|
1305
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
1306
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
1307
|
+
const mVal = mask[mIdx];
|
|
1308
|
+
let weight = globalAlpha;
|
|
1309
|
+
if (isAlpha) {
|
|
1310
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
1311
|
+
if (effectiveM === 0) {
|
|
1312
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
1313
|
+
dIdx++;
|
|
1314
|
+
mIdx++;
|
|
1315
|
+
continue;
|
|
1316
|
+
}
|
|
1317
|
+
weight = globalAlpha === 255 ? effectiveM : effectiveM * globalAlpha + 128 >> 8;
|
|
1318
|
+
} else {
|
|
1319
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
1320
|
+
if (!isHit) {
|
|
1321
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
1322
|
+
dIdx++;
|
|
1323
|
+
mIdx++;
|
|
1324
|
+
continue;
|
|
1325
|
+
}
|
|
1326
|
+
weight = globalAlpha;
|
|
1327
|
+
}
|
|
1328
|
+
if (weight === 0) {
|
|
1329
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
1330
|
+
} else {
|
|
1331
|
+
const d = dst32[dIdx];
|
|
1332
|
+
const da = d >>> 24;
|
|
1333
|
+
let finalAlpha = da;
|
|
1334
|
+
if (da === 0) {
|
|
1335
|
+
} else if (weight === 255) {
|
|
1336
|
+
} else if (da === 255) {
|
|
1337
|
+
finalAlpha = weight;
|
|
1338
|
+
} else {
|
|
1339
|
+
finalAlpha = da * weight + 128 >> 8;
|
|
1340
|
+
}
|
|
1341
|
+
dst32[dIdx] = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
1342
|
+
}
|
|
1343
|
+
dIdx++;
|
|
1344
|
+
mIdx++;
|
|
1345
|
+
}
|
|
1346
|
+
dIdx += dStride;
|
|
1347
|
+
mIdx += mStride;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
// src/PixelData/blendColorPixelData.ts
|
|
1352
|
+
function blendColorPixelData(dst, color, opts) {
|
|
1353
|
+
const {
|
|
1354
|
+
x: targetX = 0,
|
|
1355
|
+
y: targetY = 0,
|
|
1356
|
+
w: width = dst.width,
|
|
1357
|
+
h: height = dst.height,
|
|
1358
|
+
alpha: globalAlpha = 255,
|
|
1359
|
+
blendFn = sourceOverColor32,
|
|
1360
|
+
mask,
|
|
1361
|
+
maskType = 0 /* ALPHA */,
|
|
1362
|
+
mw,
|
|
1363
|
+
mx = 0,
|
|
1364
|
+
my = 0,
|
|
1365
|
+
invertMask = false
|
|
1366
|
+
} = opts;
|
|
1367
|
+
if (globalAlpha === 0) return;
|
|
1368
|
+
let x = targetX;
|
|
1369
|
+
let y = targetY;
|
|
1370
|
+
let w = width;
|
|
1371
|
+
let h = height;
|
|
1372
|
+
if (x < 0) {
|
|
1373
|
+
w += x;
|
|
1374
|
+
x = 0;
|
|
1375
|
+
}
|
|
1376
|
+
if (y < 0) {
|
|
1377
|
+
h += y;
|
|
1378
|
+
y = 0;
|
|
1379
|
+
}
|
|
1380
|
+
const actualW = Math.min(w, dst.width - x);
|
|
1381
|
+
const actualH = Math.min(h, dst.height - y);
|
|
1382
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
1383
|
+
const dst32 = dst.data32;
|
|
1384
|
+
const dw = dst.width;
|
|
1385
|
+
const mPitch = mw ?? width;
|
|
1386
|
+
const isAlphaMask = maskType === 0 /* ALPHA */;
|
|
1387
|
+
const dx = x - targetX;
|
|
1388
|
+
const dy = y - targetY;
|
|
1389
|
+
let dIdx = y * dw + x;
|
|
1390
|
+
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
1391
|
+
const dStride = dw - actualW;
|
|
1392
|
+
const mStride = mPitch - actualW;
|
|
1393
|
+
const baseSrcColor = color;
|
|
1394
|
+
const baseSrcAlpha = baseSrcColor >>> 24;
|
|
1395
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
1396
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
1397
|
+
if (baseSrcAlpha === 0) {
|
|
1398
|
+
dIdx++;
|
|
1399
|
+
mIdx++;
|
|
1400
|
+
continue;
|
|
1401
|
+
}
|
|
1402
|
+
let weight = globalAlpha;
|
|
1403
|
+
if (mask) {
|
|
1404
|
+
const mVal = mask[mIdx];
|
|
1405
|
+
if (isAlphaMask) {
|
|
1406
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
1407
|
+
if (effectiveM === 0) {
|
|
1408
|
+
dIdx++;
|
|
1409
|
+
mIdx++;
|
|
1410
|
+
continue;
|
|
1411
|
+
}
|
|
1412
|
+
if (globalAlpha === 255) {
|
|
1413
|
+
weight = effectiveM;
|
|
1414
|
+
} else if (effectiveM === 255) {
|
|
1415
|
+
weight = globalAlpha;
|
|
1416
|
+
} else {
|
|
1417
|
+
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
1418
|
+
}
|
|
1419
|
+
} else {
|
|
1420
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
1421
|
+
if (!isHit) {
|
|
1422
|
+
dIdx++;
|
|
1423
|
+
mIdx++;
|
|
1424
|
+
continue;
|
|
1425
|
+
}
|
|
1426
|
+
weight = globalAlpha;
|
|
1427
|
+
}
|
|
1428
|
+
if (weight === 0) {
|
|
1429
|
+
dIdx++;
|
|
1430
|
+
mIdx++;
|
|
1431
|
+
continue;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
let currentSrcAlpha = baseSrcAlpha;
|
|
1435
|
+
let currentSrcColor = baseSrcColor;
|
|
1436
|
+
if (weight < 255) {
|
|
1437
|
+
if (baseSrcAlpha === 255) {
|
|
1438
|
+
currentSrcAlpha = weight;
|
|
1439
|
+
} else {
|
|
1440
|
+
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
1441
|
+
}
|
|
1442
|
+
if (currentSrcAlpha === 0) {
|
|
1443
|
+
dIdx++;
|
|
1444
|
+
mIdx++;
|
|
1445
|
+
continue;
|
|
1446
|
+
}
|
|
1447
|
+
currentSrcColor = (baseSrcColor & 16777215 | currentSrcAlpha << 24) >>> 0;
|
|
1448
|
+
}
|
|
1449
|
+
dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
|
|
1450
|
+
dIdx++;
|
|
1451
|
+
mIdx++;
|
|
1452
|
+
}
|
|
1453
|
+
dIdx += dStride;
|
|
1454
|
+
mIdx += mStride;
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
|
|
282
1458
|
// src/PixelData/blendPixelData.ts
|
|
283
1459
|
function blendPixelData(dst, src, opts) {
|
|
284
1460
|
const {
|
|
@@ -414,40 +1590,151 @@ function blendPixelData(dst, src, opts) {
|
|
|
414
1590
|
mIdx += mStride;
|
|
415
1591
|
}
|
|
416
1592
|
}
|
|
1593
|
+
|
|
1594
|
+
// src/PixelData/fillPixelData.ts
|
|
1595
|
+
function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
1596
|
+
let x;
|
|
1597
|
+
let y;
|
|
1598
|
+
let w;
|
|
1599
|
+
let h;
|
|
1600
|
+
if (typeof _x === "object") {
|
|
1601
|
+
x = _x.x ?? 0;
|
|
1602
|
+
y = _x.y ?? 0;
|
|
1603
|
+
w = _x.w ?? dst.width;
|
|
1604
|
+
h = _x.h ?? dst.height;
|
|
1605
|
+
} else if (typeof _x === "number") {
|
|
1606
|
+
x = _x;
|
|
1607
|
+
y = _y;
|
|
1608
|
+
w = _w;
|
|
1609
|
+
h = _h;
|
|
1610
|
+
} else {
|
|
1611
|
+
x = 0;
|
|
1612
|
+
y = 0;
|
|
1613
|
+
w = dst.width;
|
|
1614
|
+
h = dst.height;
|
|
1615
|
+
}
|
|
1616
|
+
if (x < 0) {
|
|
1617
|
+
w += x;
|
|
1618
|
+
x = 0;
|
|
1619
|
+
}
|
|
1620
|
+
if (y < 0) {
|
|
1621
|
+
h += y;
|
|
1622
|
+
y = 0;
|
|
1623
|
+
}
|
|
1624
|
+
const actualW = Math.min(w, dst.width - x);
|
|
1625
|
+
const actualH = Math.min(h, dst.height - y);
|
|
1626
|
+
if (actualW <= 0 || actualH <= 0) {
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1629
|
+
const dst32 = dst.data32;
|
|
1630
|
+
const dw = dst.width;
|
|
1631
|
+
if (actualW === dw && actualH === dst.height && x === 0 && y === 0) {
|
|
1632
|
+
dst32.fill(color);
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
1636
|
+
const start = (y + iy) * dw + x;
|
|
1637
|
+
const end = start + actualW;
|
|
1638
|
+
dst32.fill(color, start, end);
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
// src/PixelData/clearPixelData.ts
|
|
1643
|
+
function clearPixelData(dst, rect) {
|
|
1644
|
+
fillPixelData(dst, 0, rect);
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
// src/PixelData/invertPixelData.ts
|
|
1648
|
+
function invertPixelData(pixelData) {
|
|
1649
|
+
const data32 = pixelData.data32;
|
|
1650
|
+
const len = data32.length;
|
|
1651
|
+
for (let i = 0; i < len; i++) {
|
|
1652
|
+
data32[i] = data32[i] ^ 16777215;
|
|
1653
|
+
}
|
|
1654
|
+
return pixelData;
|
|
1655
|
+
}
|
|
417
1656
|
export {
|
|
1657
|
+
BlendMode,
|
|
418
1658
|
COLOR_32_BLEND_MODES,
|
|
1659
|
+
COLOR_32_BLEND_TO_INDEX,
|
|
1660
|
+
INDEX_TO_COLOR_32_BLEND,
|
|
419
1661
|
MaskType,
|
|
1662
|
+
PixelData,
|
|
1663
|
+
UnsupportedFormatError,
|
|
1664
|
+
applyMaskToPixelData,
|
|
420
1665
|
base64DecodeArrayBuffer,
|
|
421
1666
|
base64EncodeArrayBuffer,
|
|
1667
|
+
blendColorPixelData,
|
|
422
1668
|
blendPixelData,
|
|
1669
|
+
clearPixelData,
|
|
423
1670
|
color32ToCssRGBA,
|
|
424
1671
|
color32ToHex,
|
|
425
1672
|
colorBurnColor32,
|
|
426
1673
|
colorDistance,
|
|
1674
|
+
colorDodgeColor32,
|
|
427
1675
|
copyImageData,
|
|
428
1676
|
copyImageDataLike,
|
|
1677
|
+
copyMask,
|
|
1678
|
+
darkenColor32,
|
|
1679
|
+
darkerColor32,
|
|
429
1680
|
deserializeImageData,
|
|
430
1681
|
deserializeNullableImageData,
|
|
431
1682
|
deserializeRawImageData,
|
|
432
1683
|
differenceColor32,
|
|
433
|
-
|
|
1684
|
+
divideColor32,
|
|
1685
|
+
exclusionColor32,
|
|
1686
|
+
extractImageDataPixels,
|
|
1687
|
+
extractMask,
|
|
1688
|
+
fileInputChangeToImageData,
|
|
1689
|
+
fileToImageData,
|
|
1690
|
+
fillPixelData,
|
|
1691
|
+
floodFillSelection,
|
|
1692
|
+
getImageDataFromClipboard,
|
|
1693
|
+
getSupportedPixelFormats,
|
|
434
1694
|
hardLightColor32,
|
|
1695
|
+
hardMixColor32,
|
|
1696
|
+
imageDataToAlphaMask,
|
|
1697
|
+
imageDataToDataUrl,
|
|
1698
|
+
imageDataToImgBlob,
|
|
1699
|
+
imgBlobToImageData,
|
|
1700
|
+
invertAlphaMask,
|
|
1701
|
+
invertBinaryMask,
|
|
1702
|
+
invertImageData,
|
|
1703
|
+
invertPixelData,
|
|
435
1704
|
lerpColor32,
|
|
436
1705
|
lerpColor32Fast,
|
|
1706
|
+
lightenColor32,
|
|
1707
|
+
lighterColor32,
|
|
1708
|
+
linearBurnColor32,
|
|
437
1709
|
linearDodgeColor32,
|
|
1710
|
+
linearLightColor32,
|
|
1711
|
+
makePixelCanvas,
|
|
1712
|
+
makeReusableCanvas,
|
|
1713
|
+
mergeMasks,
|
|
438
1714
|
multiplyColor32,
|
|
439
1715
|
overlayColor32,
|
|
1716
|
+
overwriteColor32,
|
|
440
1717
|
packColor,
|
|
441
1718
|
packRGBA,
|
|
1719
|
+
pinLightColor32,
|
|
1720
|
+
pixelDataToAlphaMask,
|
|
1721
|
+
resizeImageData,
|
|
442
1722
|
screenColor32,
|
|
443
1723
|
serializeImageData,
|
|
444
1724
|
serializeNullableImageData,
|
|
1725
|
+
softLightColor32,
|
|
445
1726
|
sourceOverColor32,
|
|
1727
|
+
subtractColor32,
|
|
1728
|
+
trimRectBounds,
|
|
446
1729
|
unpackAlpha,
|
|
447
1730
|
unpackBlue,
|
|
448
1731
|
unpackColor,
|
|
449
1732
|
unpackColorTo,
|
|
450
1733
|
unpackGreen,
|
|
451
|
-
unpackRed
|
|
1734
|
+
unpackRed,
|
|
1735
|
+
vividLightColor32,
|
|
1736
|
+
writeImageDataPixels,
|
|
1737
|
+
writeImageDataToClipboard,
|
|
1738
|
+
writeImgBlobToClipboard
|
|
452
1739
|
};
|
|
453
1740
|
//# sourceMappingURL=index.dev.js.map
|