@pixerate/editor 0.214.0 → 0.215.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/{chunk-UOGKSVRQ.cjs → chunk-B46UQUDC.cjs} +770 -733
- package/dist/{chunk-W3TOZTL7.js → chunk-F7Z2MKY2.js} +115 -4
- package/dist/{chunk-YBJXCQTR.js → chunk-QXY4YTRI.js} +738 -701
- package/dist/{chunk-H65IBXFI.cjs → chunk-S55JFWDA.cjs} +350 -239
- package/dist/{chunk-QYLWG22N.cjs → chunk-SS53NNZO.cjs} +304 -1
- package/dist/{chunk-LQ5SALHK.js → chunk-U7C655AM.js} +5 -311
- package/dist/{chunk-L52VMQZS.cjs → chunk-UC3PWFM3.cjs} +68 -374
- package/dist/{chunk-L3G23N5Y.js → chunk-ZNA3IQZF.js} +304 -1
- package/dist/image-editor/controller.d.cts +29 -0
- package/dist/image-editor/controller.d.ts +29 -0
- package/dist/image-editor/index.cjs +1224 -1074
- package/dist/image-editor/index.d.cts +1 -0
- package/dist/image-editor/index.d.ts +1 -0
- package/dist/image-editor/index.js +166 -16
- package/dist/image-editor/layers/edge-color.d.cts +27 -0
- package/dist/image-editor/layers/edge-color.d.ts +27 -0
- package/dist/image-editor/layers/serialize.d.cts +13 -0
- package/dist/image-editor/layers/serialize.d.ts +13 -0
- package/dist/image-editor/selection-worker.cjs +4 -4
- package/dist/image-editor/selection-worker.js +2 -2
- package/dist/paint-editor/index.cjs +79 -79
- package/dist/paint-editor/index.js +3 -3
- package/dist/raster/compositor.d.cts +10 -1
- package/dist/raster/compositor.d.ts +10 -1
- package/dist/raster/deep-compositor.d.cts +1 -1
- package/dist/raster/deep-compositor.d.ts +1 -1
- package/dist/raster/index.cjs +4 -2
- package/dist/raster/index.js +3 -1
- package/dist/raster/layers.d.cts +16 -0
- package/dist/raster/layers.d.ts +16 -0
- package/package.json +1 -1
- package/skills/pixerate-image-editor/SKILL.md +8 -6
- package/skills/pixerate-image-editor/references/paths.md +12 -0
- package/skills/pixerate-image-selection-masking/SKILL.md +8 -8
|
@@ -7,306 +7,11 @@
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
var _chunkK6PXS6DOcjs = require('./chunk-K6PXS6DO.cjs');
|
|
10
|
+
var _chunkSS53NNZOcjs = require('./chunk-SS53NNZO.cjs');
|
|
14
11
|
|
|
15
12
|
|
|
16
13
|
var _chunkMQDIP4CFcjs = require('./chunk-MQDIP4CF.cjs');
|
|
17
14
|
|
|
18
|
-
// src/image-editor/selection/refine.ts
|
|
19
|
-
var DEFAULT_REFINE_EDGE_PARAMS = {
|
|
20
|
-
radius: 0,
|
|
21
|
-
smartRadius: false,
|
|
22
|
-
smooth: 0,
|
|
23
|
-
feather: 0,
|
|
24
|
-
contrast: 0,
|
|
25
|
-
shiftEdge: 0
|
|
26
|
-
};
|
|
27
|
-
var GUIDED_FILTER_EPS = 1e-4;
|
|
28
|
-
var fin = (v, d) => typeof v === "number" && Number.isFinite(v) ? v : d;
|
|
29
|
-
function normalizeRefineEdgeParams(p = {}) {
|
|
30
|
-
return {
|
|
31
|
-
radius: Math.min(250, Math.max(0, fin(p.radius, 0))),
|
|
32
|
-
smartRadius: p.smartRadius === true,
|
|
33
|
-
smooth: Math.min(100, Math.max(0, fin(p.smooth, 0))),
|
|
34
|
-
feather: Math.min(1e3, Math.max(0, fin(p.feather, 0))),
|
|
35
|
-
contrast: Math.min(100, Math.max(0, fin(p.contrast, 0))),
|
|
36
|
-
shiftEdge: Math.min(100, Math.max(-100, fin(p.shiftEdge, 0)))
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
var gfRadius = (p) => Math.min(64, Math.max(1, Math.ceil(p.radius)));
|
|
40
|
-
var smoothSigma = (p) => p.smooth / 100 * 4;
|
|
41
|
-
var featherSigma = (p) => p.feather / 2;
|
|
42
|
-
function shiftAmount(p) {
|
|
43
|
-
const px = p.shiftEdge / 100 * Math.max(p.radius, 4);
|
|
44
|
-
return Number.isFinite(px) ? Math.min(64, Math.max(-64, px)) : 0;
|
|
45
|
-
}
|
|
46
|
-
function refineEdgeHalo(params = {}) {
|
|
47
|
-
const p = normalizeRefineEdgeParams(params);
|
|
48
|
-
const g = gfRadius(p);
|
|
49
|
-
const edge = p.radius > 0 ? Math.max(Math.ceil(p.radius), 2 * g + (p.smartRadius ? g + 1 : 0)) : 0;
|
|
50
|
-
return edge + Math.ceil(3 * smoothSigma(p)) + Math.ceil(3 * featherSigma(p)) + Math.ceil(Math.abs(shiftAmount(p))) + 2;
|
|
51
|
-
}
|
|
52
|
-
function boxMean(src, w, h, r) {
|
|
53
|
-
const tmp = new Float32Array(w * h);
|
|
54
|
-
const pre = new Float64Array(Math.max(w, h) + 1);
|
|
55
|
-
for (let y = 0; y < h; y++) {
|
|
56
|
-
const row = y * w;
|
|
57
|
-
for (let x = 0; x < w; x++) pre[x + 1] = pre[x] + src[row + x];
|
|
58
|
-
for (let x = 0; x < w; x++) {
|
|
59
|
-
const lo = Math.max(0, x - r);
|
|
60
|
-
const hi = Math.min(w, x + r + 1);
|
|
61
|
-
tmp[row + x] = (pre[hi] - pre[lo]) / (hi - lo);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
const out = new Float32Array(w * h);
|
|
65
|
-
for (let x = 0; x < w; x++) {
|
|
66
|
-
for (let y = 0; y < h; y++) pre[y + 1] = pre[y] + tmp[y * w + x];
|
|
67
|
-
for (let y = 0; y < h; y++) {
|
|
68
|
-
const lo = Math.max(0, y - r);
|
|
69
|
-
const hi = Math.min(h, y + r + 1);
|
|
70
|
-
out[y * w + x] = (pre[hi] - pre[lo]) / (hi - lo);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return out;
|
|
74
|
-
}
|
|
75
|
-
function guidedFilterColor(guide, p, w, h, r, eps = GUIDED_FILTER_EPS) {
|
|
76
|
-
const n = w * h;
|
|
77
|
-
const [c0, c1, c2] = guide;
|
|
78
|
-
const prod = (a, b2) => {
|
|
79
|
-
const o = new Float32Array(n);
|
|
80
|
-
for (let i = 0; i < n; i++) o[i] = a[i] * b2[i];
|
|
81
|
-
return o;
|
|
82
|
-
};
|
|
83
|
-
const m0 = boxMean(c0, w, h, r);
|
|
84
|
-
const m1 = boxMean(c1, w, h, r);
|
|
85
|
-
const m2 = boxMean(c2, w, h, r);
|
|
86
|
-
const mp = boxMean(p, w, h, r);
|
|
87
|
-
const mip0 = boxMean(prod(c0, p), w, h, r);
|
|
88
|
-
const mip1 = boxMean(prod(c1, p), w, h, r);
|
|
89
|
-
const mip2 = boxMean(prod(c2, p), w, h, r);
|
|
90
|
-
const s00 = boxMean(prod(c0, c0), w, h, r);
|
|
91
|
-
const s01 = boxMean(prod(c0, c1), w, h, r);
|
|
92
|
-
const s02 = boxMean(prod(c0, c2), w, h, r);
|
|
93
|
-
const s11 = boxMean(prod(c1, c1), w, h, r);
|
|
94
|
-
const s12 = boxMean(prod(c1, c2), w, h, r);
|
|
95
|
-
const s22 = boxMean(prod(c2, c2), w, h, r);
|
|
96
|
-
const a0 = new Float32Array(n);
|
|
97
|
-
const a1 = new Float32Array(n);
|
|
98
|
-
const a2 = new Float32Array(n);
|
|
99
|
-
const b = new Float32Array(n);
|
|
100
|
-
for (let i = 0; i < n; i++) {
|
|
101
|
-
const u0 = m0[i], u1 = m1[i], u2 = m2[i], up = mp[i];
|
|
102
|
-
const rr = s00[i] - u0 * u0 + eps;
|
|
103
|
-
const rg = s01[i] - u0 * u1;
|
|
104
|
-
const rb = s02[i] - u0 * u2;
|
|
105
|
-
const gg = s11[i] - u1 * u1 + eps;
|
|
106
|
-
const gb = s12[i] - u1 * u2;
|
|
107
|
-
const bb = s22[i] - u2 * u2 + eps;
|
|
108
|
-
const v0 = mip0[i] - u0 * up;
|
|
109
|
-
const v1 = mip1[i] - u1 * up;
|
|
110
|
-
const v2 = mip2[i] - u2 * up;
|
|
111
|
-
const i00 = gg * bb - gb * gb;
|
|
112
|
-
const i01 = gb * rb - rg * bb;
|
|
113
|
-
const i02 = rg * gb - gg * rb;
|
|
114
|
-
const i11 = rr * bb - rb * rb;
|
|
115
|
-
const i12 = rb * rg - rr * gb;
|
|
116
|
-
const i22 = rr * gg - rg * rg;
|
|
117
|
-
const det = rr * i00 + rg * i01 + rb * i02;
|
|
118
|
-
let x0 = 0, x1 = 0, x2 = 0;
|
|
119
|
-
if (Math.abs(det) >= 1e-30) {
|
|
120
|
-
x0 = (i00 * v0 + i01 * v1 + i02 * v2) / det;
|
|
121
|
-
x1 = (i01 * v0 + i11 * v1 + i12 * v2) / det;
|
|
122
|
-
x2 = (i02 * v0 + i12 * v1 + i22 * v2) / det;
|
|
123
|
-
}
|
|
124
|
-
a0[i] = x0;
|
|
125
|
-
a1[i] = x1;
|
|
126
|
-
a2[i] = x2;
|
|
127
|
-
b[i] = up - x0 * u0 - x1 * u1 - x2 * u2;
|
|
128
|
-
}
|
|
129
|
-
const ma0 = boxMean(a0, w, h, r);
|
|
130
|
-
const ma1 = boxMean(a1, w, h, r);
|
|
131
|
-
const ma2 = boxMean(a2, w, h, r);
|
|
132
|
-
const mb = boxMean(b, w, h, r);
|
|
133
|
-
const out = new Float32Array(n);
|
|
134
|
-
for (let i = 0; i < n; i++) out[i] = ma0[i] * c0[i] + ma1[i] * c1[i] + ma2[i] * c2[i] + mb[i];
|
|
135
|
-
return out;
|
|
136
|
-
}
|
|
137
|
-
function edgeWidth(guide, w, h, r) {
|
|
138
|
-
const n = w * h;
|
|
139
|
-
const y = new Float32Array(n);
|
|
140
|
-
for (let i = 0; i < n; i++) y[i] = 0.299 * guide[0][i] + 0.587 * guide[1][i] + 0.114 * guide[2][i];
|
|
141
|
-
const g = new Float32Array(n);
|
|
142
|
-
for (let yy = 0; yy < h; yy++) {
|
|
143
|
-
for (let xx = 0; xx < w; xx++) {
|
|
144
|
-
const gx = (y[yy * w + Math.min(w - 1, xx + 1)] - y[yy * w + Math.max(0, xx - 1)]) / 2;
|
|
145
|
-
const gy = (y[Math.min(h - 1, yy + 1) * w + xx] - y[Math.max(0, yy - 1) * w + xx]) / 2;
|
|
146
|
-
g[yy * w + xx] = Math.sqrt(gx * gx + gy * gy);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const gm = _chunkQYLWG22Ncjs.greyMorphology.call(void 0, g, w, h, r, true);
|
|
150
|
-
const hi = _chunkQYLWG22Ncjs.greyMorphology.call(void 0, y, w, h, r, true);
|
|
151
|
-
const lo = _chunkQYLWG22Ncjs.greyMorphology.call(void 0, y, w, h, r, false);
|
|
152
|
-
const out = new Float32Array(n);
|
|
153
|
-
for (let i = 0; i < n; i++) out[i] = (hi[i] - lo[i]) / Math.max(gm[i], 1e-4);
|
|
154
|
-
return out;
|
|
155
|
-
}
|
|
156
|
-
function refineCoverage(guide, m, w, h, params = {}, band = null) {
|
|
157
|
-
const p = normalizeRefineEdgeParams(params);
|
|
158
|
-
let a = Float32Array.from(m);
|
|
159
|
-
if ((p.radius > 0 || band) && guide) {
|
|
160
|
-
const n = w * h;
|
|
161
|
-
const boundary = new Uint8Array(n);
|
|
162
|
-
let any = false;
|
|
163
|
-
for (let y = 0; y < h; y++) {
|
|
164
|
-
for (let x = 0; x < w; x++) {
|
|
165
|
-
const i = y * w + x;
|
|
166
|
-
const v = m[i] >= 0.5;
|
|
167
|
-
const diff = x > 0 && m[i - 1] >= 0.5 !== v || x + 1 < w && m[i + 1] >= 0.5 !== v || y > 0 && m[i - w] >= 0.5 !== v || y + 1 < h && m[i + w] >= 0.5 !== v;
|
|
168
|
-
if (diff) {
|
|
169
|
-
boundary[i] = 1;
|
|
170
|
-
any = true;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
if (any || band) {
|
|
175
|
-
const dist = _chunkQYLWG22Ncjs.distanceTransform.call(void 0, boundary, w, h);
|
|
176
|
-
const r = band ? Math.max(4, gfRadius(p)) : gfRadius(p);
|
|
177
|
-
const q = guidedFilterColor(guide, m, w, h, r);
|
|
178
|
-
const widths = p.smartRadius ? edgeWidth(guide, w, h, r) : null;
|
|
179
|
-
for (let i = 0; i < n; i++) {
|
|
180
|
-
const reff = widths ? Math.min(Math.max(p.radius, 1.5), Math.max(1.5, widths[i])) : p.radius;
|
|
181
|
-
const edge = p.radius > 0 ? Math.min(1, Math.max(0, reff + 1 - dist[i])) : 0;
|
|
182
|
-
const wgt = band ? Math.max(edge, Math.min(1, Math.max(0, band[i]))) : edge;
|
|
183
|
-
if (wgt > 0) {
|
|
184
|
-
const qi = Math.min(1, Math.max(0, q[i]));
|
|
185
|
-
a[i] = m[i] + (qi - m[i]) * wgt;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
const ss = smoothSigma(p);
|
|
191
|
-
if (ss >= 0.3) {
|
|
192
|
-
a = _chunkK6PXS6DOcjs.gaussianBlur.call(void 0, a, w, h, ss, "clamp");
|
|
193
|
-
const gain = 1 + ss;
|
|
194
|
-
for (let i = 0; i < a.length; i++) a[i] = Math.min(1, Math.max(0, (a[i] - 0.5) * gain + 0.5));
|
|
195
|
-
}
|
|
196
|
-
a = _chunkK6PXS6DOcjs.gaussianBlur.call(void 0, a, w, h, featherSigma(p), "clamp");
|
|
197
|
-
if (p.contrast > 0) {
|
|
198
|
-
const gain = 1 / (1 - 0.99 * p.contrast / 100);
|
|
199
|
-
for (let i = 0; i < a.length; i++) a[i] = Math.min(1, Math.max(0, (a[i] - 0.5) * gain + 0.5));
|
|
200
|
-
}
|
|
201
|
-
const amount = shiftAmount(p);
|
|
202
|
-
if (Math.abs(amount) >= 1e-4) a = _chunkQYLWG22Ncjs.shiftCoverage.call(void 0, a, w, h, amount);
|
|
203
|
-
return a;
|
|
204
|
-
}
|
|
205
|
-
function guidePlanes(pixels, win) {
|
|
206
|
-
const box = _nullishCoalesce(win, () => ( { x: 0, y: 0, width: pixels.width, height: pixels.height }));
|
|
207
|
-
const n = box.width * box.height;
|
|
208
|
-
const r = new Float32Array(n);
|
|
209
|
-
const g = new Float32Array(n);
|
|
210
|
-
const b = new Float32Array(n);
|
|
211
|
-
const d = pixels.data;
|
|
212
|
-
for (let y = 0; y < box.height; y++) {
|
|
213
|
-
for (let x = 0; x < box.width; x++) {
|
|
214
|
-
const i = y * box.width + x;
|
|
215
|
-
const p = ((box.y + y) * pixels.width + box.x + x) * 4;
|
|
216
|
-
r[i] = d[p] / 255;
|
|
217
|
-
g[i] = d[p + 1] / 255;
|
|
218
|
-
b[i] = d[p + 2] / 255;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return [r, g, b];
|
|
222
|
-
}
|
|
223
|
-
function refineSelection(pixels, mask, params = {}, refineBrush = null) {
|
|
224
|
-
const p = normalizeRefineEdgeParams(params);
|
|
225
|
-
if (pixels && (pixels.width !== mask.width || pixels.height !== mask.height)) {
|
|
226
|
-
throw new Error("Refine Edge needs pixels the size of the selection");
|
|
227
|
-
}
|
|
228
|
-
if (!mask.bounds) return mask;
|
|
229
|
-
const brush = _optionalChain([refineBrush, 'optionalAccess', _ => _.bounds]) ? refineBrush : null;
|
|
230
|
-
const halo = refineEdgeHalo(p) + (brush ? 2 * Math.max(4, gfRadius(p)) : 0);
|
|
231
|
-
const b = brush ? {
|
|
232
|
-
x: Math.min(mask.bounds.x, brush.bounds.x),
|
|
233
|
-
y: Math.min(mask.bounds.y, brush.bounds.y),
|
|
234
|
-
r: Math.max(mask.bounds.x + mask.bounds.width, brush.bounds.x + brush.bounds.width),
|
|
235
|
-
btm: Math.max(mask.bounds.y + mask.bounds.height, brush.bounds.y + brush.bounds.height)
|
|
236
|
-
} : { x: mask.bounds.x, y: mask.bounds.y, r: mask.bounds.x + mask.bounds.width, btm: mask.bounds.y + mask.bounds.height };
|
|
237
|
-
const x0 = Math.max(0, b.x - halo);
|
|
238
|
-
const y0 = Math.max(0, b.y - halo);
|
|
239
|
-
const x1 = Math.min(mask.width, b.r + halo);
|
|
240
|
-
const y1 = Math.min(mask.height, b.btm + halo);
|
|
241
|
-
const ww = x1 - x0;
|
|
242
|
-
const wh = y1 - y0;
|
|
243
|
-
const m = new Float32Array(ww * wh);
|
|
244
|
-
for (let y = 0; y < wh; y++) {
|
|
245
|
-
const src = (y0 + y) * mask.width + x0;
|
|
246
|
-
for (let x = 0; x < ww; x++) m[y * ww + x] = mask.data[src + x] / 255;
|
|
247
|
-
}
|
|
248
|
-
const guide = pixels && (p.radius > 0 || brush) ? guidePlanes(pixels, { x: x0, y: y0, width: ww, height: wh }) : null;
|
|
249
|
-
let band = null;
|
|
250
|
-
if (brush) {
|
|
251
|
-
band = new Float32Array(ww * wh);
|
|
252
|
-
const bd = brush.data;
|
|
253
|
-
for (let y = 0; y < wh; y++) {
|
|
254
|
-
const src = (y0 + y) * mask.width + x0;
|
|
255
|
-
for (let x = 0; x < ww; x++) band[y * ww + x] = bd[src + x] / 255;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
const refined = refineCoverage(guide, m, ww, wh, p, band);
|
|
259
|
-
const out = new Uint8Array(mask.width * mask.height);
|
|
260
|
-
for (let y = 0; y < wh; y++) {
|
|
261
|
-
const dst = (y0 + y) * mask.width + x0;
|
|
262
|
-
for (let x = 0; x < ww; x++) out[dst + x] = _chunkQYLWG22Ncjs.coverageToByte.call(void 0, refined[y * ww + x]);
|
|
263
|
-
}
|
|
264
|
-
return _chunkQYLWG22Ncjs.createSelectionMask.call(void 0, mask.width, mask.height, out);
|
|
265
|
-
}
|
|
266
|
-
function decontaminateColors(rgba, coverage, w, h, amount, radius = 8) {
|
|
267
|
-
const out = Uint8ClampedArray.from(rgba);
|
|
268
|
-
const n = w * h;
|
|
269
|
-
const k = Math.min(1, Math.max(0, amount));
|
|
270
|
-
if (k === 0) return out;
|
|
271
|
-
const r = Math.max(2, Math.round(radius));
|
|
272
|
-
const fgW = new Float32Array(n);
|
|
273
|
-
const bgW = new Float32Array(n);
|
|
274
|
-
for (let i = 0; i < n; i++) {
|
|
275
|
-
fgW[i] = coverage[i] >= 250 ? 1 : 0;
|
|
276
|
-
bgW[i] = coverage[i] <= 5 ? 1 : 0;
|
|
277
|
-
}
|
|
278
|
-
const meanOf = (weights, radiusPx) => {
|
|
279
|
-
const wm = boxMean(weights, w, h, radiusPx);
|
|
280
|
-
const planes = [0, 1, 2].map((c) => {
|
|
281
|
-
const v = new Float32Array(n);
|
|
282
|
-
for (let i = 0; i < n; i++) v[i] = rgba[i * 4 + c] * weights[i];
|
|
283
|
-
const m = boxMean(v, w, h, radiusPx);
|
|
284
|
-
for (let i = 0; i < n; i++) m[i] = wm[i] > 1e-6 ? m[i] / wm[i] : NaN;
|
|
285
|
-
return m;
|
|
286
|
-
});
|
|
287
|
-
return { weight: wm, planes };
|
|
288
|
-
};
|
|
289
|
-
const fg = meanOf(fgW, r);
|
|
290
|
-
const fgWide = meanOf(fgW, r * 3);
|
|
291
|
-
const bg = meanOf(bgW, r);
|
|
292
|
-
for (let i = 0; i < n; i++) {
|
|
293
|
-
const c = coverage[i];
|
|
294
|
-
if (c <= 5 || c >= 250) continue;
|
|
295
|
-
const a = c / 255;
|
|
296
|
-
for (let ch = 0; ch < 3; ch++) {
|
|
297
|
-
const C = rgba[i * 4 + ch];
|
|
298
|
-
const B = bg.planes[ch][i];
|
|
299
|
-
const Fm = Number.isNaN(fg.planes[ch][i]) ? fgWide.planes[ch][i] : fg.planes[ch][i];
|
|
300
|
-
let F;
|
|
301
|
-
if (a >= 0.5 && !Number.isNaN(B)) F = (C - (1 - a) * B) / a;
|
|
302
|
-
else if (!Number.isNaN(Fm)) F = Fm;
|
|
303
|
-
else F = C;
|
|
304
|
-
out[i * 4 + ch] = Math.round(C + k * (Math.min(255, Math.max(0, F)) - C));
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
return out;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
15
|
// src/image-editor/selection/shapes.ts
|
|
311
16
|
function polygonCoverage(points, width, height, antiAlias = true) {
|
|
312
17
|
const { box, coverage } = polygonCoverageBox(points, width, height, antiAlias);
|
|
@@ -384,10 +89,10 @@ function polygonCoverageBox(points, width, height, antiAlias = true) {
|
|
|
384
89
|
}
|
|
385
90
|
function polygonSelection(width, height, points, options = {}) {
|
|
386
91
|
const { box, coverage } = polygonCoverageBox(points, width, height, _nullishCoalesce(options.antiAlias, () => ( true)));
|
|
387
|
-
if (!box) return
|
|
92
|
+
if (!box) return _chunkSS53NNZOcjs.createSelectionMask.call(void 0, width, height);
|
|
388
93
|
const out = new Uint8Array(coverage.length);
|
|
389
|
-
for (let i = 0; i < out.length; i++) out[i] =
|
|
390
|
-
return
|
|
94
|
+
for (let i = 0; i < out.length; i++) out[i] = _chunkSS53NNZOcjs.coverageToByte.call(void 0, coverage[i]);
|
|
95
|
+
return _chunkSS53NNZOcjs.selectionFromRegion.call(void 0, width, height, box, out);
|
|
391
96
|
}
|
|
392
97
|
function normalizeRect(rect) {
|
|
393
98
|
const x = rect.width < 0 ? rect.x + rect.width : rect.x;
|
|
@@ -671,7 +376,7 @@ var WORK_SIZE = 512;
|
|
|
671
376
|
var workCache = /* @__PURE__ */ new WeakMap();
|
|
672
377
|
function workImage(pixels, maxSide = WORK_SIZE) {
|
|
673
378
|
const sizes = workCache.get(pixels.data);
|
|
674
|
-
const cached = _optionalChain([sizes, 'optionalAccess',
|
|
379
|
+
const cached = _optionalChain([sizes, 'optionalAccess', _ => _.get, 'call', _2 => _2(maxSide)]);
|
|
675
380
|
if (cached && cached.sourceWidth === pixels.width && cached.sourceHeight === pixels.height) return cached;
|
|
676
381
|
const { width: W, height: H, data } = pixels;
|
|
677
382
|
const scale = Math.min(1, maxSide / Math.max(W, H));
|
|
@@ -850,7 +555,7 @@ function upscaleRegion(work, pixels, roi, label, enhance) {
|
|
|
850
555
|
out[Y * RW + X] = Math.round(alpha * 255);
|
|
851
556
|
}
|
|
852
557
|
}
|
|
853
|
-
return
|
|
558
|
+
return _chunkSS53NNZOcjs.selectionFromRegion.call(void 0, W, H, { x: X0, y: Y0, width: RW, height: RH }, out);
|
|
854
559
|
}
|
|
855
560
|
|
|
856
561
|
// src/image-editor/selection/segment/grabcut.ts
|
|
@@ -1012,7 +717,7 @@ function grabCutLabels(work, setup, iterations, onRound) {
|
|
|
1012
717
|
const graph = new GridGraph(rw, rh);
|
|
1013
718
|
for (let p = 0; p < n; p++) {
|
|
1014
719
|
if (hardBg[p]) graph.addTerminal(p, 0, HARD);
|
|
1015
|
-
else if (_optionalChain([hardFg, 'optionalAccess',
|
|
720
|
+
else if (_optionalChain([hardFg, 'optionalAccess', _3 => _3[p]])) graph.addTerminal(p, HARD, 0);
|
|
1016
721
|
else {
|
|
1017
722
|
const i = global[p] * 3;
|
|
1018
723
|
graph.addTerminal(p, Math.round(bg.cost(rgb[i], rgb[i + 1], rgb[i + 2]) * UNITS), Math.round(fg.cost(rgb[i], rgb[i + 1], rgb[i + 2]) * UNITS));
|
|
@@ -1027,7 +732,7 @@ function grabCutLabels(work, setup, iterations, onRound) {
|
|
|
1027
732
|
if (v !== label[p]) changed++;
|
|
1028
733
|
label[p] = v;
|
|
1029
734
|
}
|
|
1030
|
-
_optionalChain([onRound, 'optionalCall',
|
|
735
|
+
_optionalChain([onRound, 'optionalCall', _4 => _4((iter + 1) / iterations)]);
|
|
1031
736
|
if (changed <= n * 1e-3) break;
|
|
1032
737
|
}
|
|
1033
738
|
return label;
|
|
@@ -1063,10 +768,10 @@ function keepMainPieces(label, rw, rh, seed) {
|
|
|
1063
768
|
}
|
|
1064
769
|
function selectObjectIn(pixels, target, options = {}) {
|
|
1065
770
|
const report = options.onProgress;
|
|
1066
|
-
_optionalChain([report, 'optionalCall',
|
|
771
|
+
_optionalChain([report, 'optionalCall', _5 => _5(0, "Reducing the image")]);
|
|
1067
772
|
const work = workImage(pixels);
|
|
1068
|
-
_optionalChain([report, 'optionalCall',
|
|
1069
|
-
const round = (fraction) => _optionalChain([report, 'optionalCall',
|
|
773
|
+
_optionalChain([report, 'optionalCall', _6 => _6(0.1, "Finding the object")]);
|
|
774
|
+
const round = (fraction) => _optionalChain([report, 'optionalCall', _7 => _7(0.1 + 0.8 * fraction, "Finding the object")]);
|
|
1070
775
|
const { width: w, height: h, scale } = work;
|
|
1071
776
|
const iterations = Math.max(1, Math.round(_nullishCoalesce(options.iterations, () => ( 5))));
|
|
1072
777
|
const enhance = _nullishCoalesce(options.enhanceEdge, () => ( false));
|
|
@@ -1076,7 +781,7 @@ function selectObjectIn(pixels, target, options = {}) {
|
|
|
1076
781
|
const by0 = Math.max(0, Math.floor(r.y * scale));
|
|
1077
782
|
const bx1 = Math.min(w, Math.ceil((r.x + r.width) * scale));
|
|
1078
783
|
const by1 = Math.min(h, Math.ceil((r.y + r.height) * scale));
|
|
1079
|
-
if (bx1 - bx0 < 2 || by1 - by0 < 2) return
|
|
784
|
+
if (bx1 - bx0 < 2 || by1 - by0 < 2) return _chunkSS53NNZOcjs.createSelectionMask.call(void 0, pixels.width, pixels.height);
|
|
1080
785
|
const m = Math.max(8, Math.round(0.25 * Math.max(bx1 - bx0, by1 - by0)));
|
|
1081
786
|
const rx = Math.max(0, bx0 - m);
|
|
1082
787
|
const ry = Math.max(0, by0 - m);
|
|
@@ -1095,9 +800,9 @@ function selectObjectIn(pixels, target, options = {}) {
|
|
|
1095
800
|
}
|
|
1096
801
|
const label = grabCutLabels(work, { roi, initial, hardBg, hardFg: null }, iterations, round);
|
|
1097
802
|
keepMainPieces(label, roi.width, roi.height, null);
|
|
1098
|
-
_optionalChain([report, 'optionalCall',
|
|
803
|
+
_optionalChain([report, 'optionalCall', _8 => _8(0.9, "Scaling up")]);
|
|
1099
804
|
const out = upscaleRegion(work, pixels, roi, label, enhance);
|
|
1100
|
-
_optionalChain([report, 'optionalCall',
|
|
805
|
+
_optionalChain([report, 'optionalCall', _9 => _9(1, "Done")]);
|
|
1101
806
|
return out;
|
|
1102
807
|
}
|
|
1103
808
|
const px = Math.min(w - 1, Math.max(0, Math.floor(target.point.x * scale)));
|
|
@@ -1134,9 +839,9 @@ function selectObjectIn(pixels, target, options = {}) {
|
|
|
1134
839
|
}
|
|
1135
840
|
}
|
|
1136
841
|
if (!touches || whole) {
|
|
1137
|
-
_optionalChain([report, 'optionalCall',
|
|
842
|
+
_optionalChain([report, 'optionalCall', _10 => _10(0.9, "Scaling up")]);
|
|
1138
843
|
const out = upscaleRegion(work, pixels, roi, label, enhance);
|
|
1139
|
-
_optionalChain([report, 'optionalCall',
|
|
844
|
+
_optionalChain([report, 'optionalCall', _11 => _11(1, "Done")]);
|
|
1140
845
|
return out;
|
|
1141
846
|
}
|
|
1142
847
|
half = Math.round(half * 1.6);
|
|
@@ -1213,7 +918,7 @@ function segmentStroke(work, stroke, grown, start) {
|
|
|
1213
918
|
const bin = binOf(rgb, g);
|
|
1214
919
|
bgHist[bin]++;
|
|
1215
920
|
bgN++;
|
|
1216
|
-
if (stroke.mask[g] || _optionalChain([grown, 'optionalAccess',
|
|
921
|
+
if (stroke.mask[g] || _optionalChain([grown, 'optionalAccess', _12 => _12[g]])) {
|
|
1217
922
|
fgHist[bin]++;
|
|
1218
923
|
fgN++;
|
|
1219
924
|
}
|
|
@@ -1295,12 +1000,12 @@ function quickSelectStroke(pixels, stroke, options = {}) {
|
|
|
1295
1000
|
const roi = { x: rx, y: ry, width: Math.min(w, Math.ceil(x1 + margin)) - rx, height: Math.min(h, Math.ceil(y1 + margin)) - ry };
|
|
1296
1001
|
let grown = null;
|
|
1297
1002
|
const sel = options.grow ? options.selection : null;
|
|
1298
|
-
if (_optionalChain([sel, 'optionalAccess',
|
|
1003
|
+
if (_optionalChain([sel, 'optionalAccess', _13 => _13.bounds])) {
|
|
1299
1004
|
grown = new Uint8Array(w * h);
|
|
1300
1005
|
const b = sel.bounds;
|
|
1301
1006
|
for (let y = Math.max(0, Math.floor(b.y * scale)); y < Math.min(h, Math.ceil((b.y + b.height) * scale)); y++) {
|
|
1302
1007
|
for (let x = Math.max(0, Math.floor(b.x * scale)); x < Math.min(w, Math.ceil((b.x + b.width) * scale)); x++) {
|
|
1303
|
-
if (
|
|
1008
|
+
if (_chunkSS53NNZOcjs.selectionValueAt.call(void 0, sel, Math.min(sel.width - 1, Math.floor((x + 0.5) / scale)), Math.min(sel.height - 1, Math.floor((y + 0.5) / scale))) >= 0.5) grown[y * w + x] = 1;
|
|
1304
1009
|
}
|
|
1305
1010
|
}
|
|
1306
1011
|
}
|
|
@@ -1324,7 +1029,7 @@ function brushStrokeMask(width, height, points, size, hardness = 1) {
|
|
|
1324
1029
|
const by = Math.max(0, Math.floor(y0 - r - 1));
|
|
1325
1030
|
const bw = Math.min(width, Math.ceil(x1 + r + 1)) - bx;
|
|
1326
1031
|
const bh = Math.min(height, Math.ceil(y1 + r + 1)) - by;
|
|
1327
|
-
if (!(bw > 0 && bh > 0)) return
|
|
1032
|
+
if (!(bw > 0 && bh > 0)) return _chunkSS53NNZOcjs.createSelectionMask.call(void 0, width, height);
|
|
1328
1033
|
const out = new Uint8Array(bw * bh);
|
|
1329
1034
|
const segs = points.length === 1 ? [[points[0], points[0]]] : points.slice(1).map((p, i) => [points[i], p]);
|
|
1330
1035
|
for (let y = 0; y < bh; y++) {
|
|
@@ -1344,27 +1049,27 @@ function brushStrokeMask(width, height, points, size, hardness = 1) {
|
|
|
1344
1049
|
out[y * bw + x] = Math.round(Math.max(0, v) * 255);
|
|
1345
1050
|
}
|
|
1346
1051
|
}
|
|
1347
|
-
return
|
|
1052
|
+
return _chunkSS53NNZOcjs.selectionFromRegion.call(void 0, width, height, { x: bx, y: by, width: bw, height: bh }, out);
|
|
1348
1053
|
}
|
|
1349
1054
|
function applyRefineEdits(pixels, selection, edits, width, height) {
|
|
1350
|
-
let sel = _optionalChain([selection, 'optionalAccess',
|
|
1055
|
+
let sel = _optionalChain([selection, 'optionalAccess', _14 => _14.bounds]) ? selection : null;
|
|
1351
1056
|
let band = null;
|
|
1352
1057
|
for (const e of edits) {
|
|
1353
1058
|
if (e.kind === "object") {
|
|
1354
1059
|
if (!pixels) throw new Error("Object Selection needs the image pixels.");
|
|
1355
1060
|
if (!e.rect === !e.point) throw new Error("An object edit takes rect (a box around the object) or point (on it), not both.");
|
|
1356
1061
|
const region2 = selectObjectIn(pixels, e.rect ? { rect: e.rect } : { point: e.point });
|
|
1357
|
-
sel =
|
|
1062
|
+
sel = _chunkSS53NNZOcjs.combineSelections.call(void 0, sel, region2, _nullishCoalesce(e.mode, () => ( "add")));
|
|
1358
1063
|
continue;
|
|
1359
1064
|
}
|
|
1360
1065
|
if (!e.points.length) throw new Error(`A ${e.kind} stroke needs at least one point.`);
|
|
1361
1066
|
if (e.kind === "lasso") {
|
|
1362
1067
|
if (e.points.length < 3) throw new Error("A lasso edit needs at least 3 points.");
|
|
1363
|
-
sel =
|
|
1068
|
+
sel = _chunkSS53NNZOcjs.combineSelections.call(void 0, sel, polygonSelection(width, height, e.points, {}), _nullishCoalesce(e.mode, () => ( "add")));
|
|
1364
1069
|
continue;
|
|
1365
1070
|
}
|
|
1366
1071
|
if (e.kind === "refine-brush") {
|
|
1367
|
-
band =
|
|
1072
|
+
band = _chunkSS53NNZOcjs.combineSelections.call(void 0, band, brushStrokeMask(width, height, e.points, _nullishCoalesce(e.size, () => ( 40))), "add");
|
|
1368
1073
|
continue;
|
|
1369
1074
|
}
|
|
1370
1075
|
const mode = _nullishCoalesce(e.mode, () => ( "add"));
|
|
@@ -1375,7 +1080,7 @@ function applyRefineEdits(pixels, selection, edits, width, height) {
|
|
|
1375
1080
|
} else {
|
|
1376
1081
|
region = brushStrokeMask(width, height, e.points, _nullishCoalesce(e.size, () => ( 20)), _nullishCoalesce(e.hardness, () => ( 1)));
|
|
1377
1082
|
}
|
|
1378
|
-
sel =
|
|
1083
|
+
sel = _chunkSS53NNZOcjs.combineSelections.call(void 0, sel, region, mode);
|
|
1379
1084
|
}
|
|
1380
1085
|
return { selection: sel, refineBrush: band };
|
|
1381
1086
|
}
|
|
@@ -1422,7 +1127,7 @@ function softMaskToSelection(work, mask) {
|
|
|
1422
1127
|
out[Y * W + X] = Math.round(Math.min(1, Math.max(0, m)) * 255);
|
|
1423
1128
|
}
|
|
1424
1129
|
}
|
|
1425
|
-
return
|
|
1130
|
+
return _chunkSS53NNZOcjs.selectionFromRegion.call(void 0, W, H, { x: 0, y: 0, width: W, height: H }, out);
|
|
1426
1131
|
}
|
|
1427
1132
|
|
|
1428
1133
|
// src/image-editor/selection/segment/subject.ts
|
|
@@ -1594,14 +1299,14 @@ function otsuThreshold(values, weights) {
|
|
|
1594
1299
|
}
|
|
1595
1300
|
function findSubject(pixels, options = {}) {
|
|
1596
1301
|
const report = options.onProgress;
|
|
1597
|
-
_optionalChain([report, 'optionalCall',
|
|
1302
|
+
_optionalChain([report, 'optionalCall', _15 => _15(0, "Reducing the image")]);
|
|
1598
1303
|
const work = workImage(pixels);
|
|
1599
1304
|
const { width: w, height: h } = work;
|
|
1600
|
-
_optionalChain([report, 'optionalCall',
|
|
1305
|
+
_optionalChain([report, 'optionalCall', _16 => _16(0.1, "Grouping into superpixels")]);
|
|
1601
1306
|
const sp = slicSuperpixels(work);
|
|
1602
|
-
_optionalChain([report, 'optionalCall',
|
|
1307
|
+
_optionalChain([report, 'optionalCall', _17 => _17(0.3, "Measuring what stands out")]);
|
|
1603
1308
|
const sal = superpixelSaliency(sp, w, h);
|
|
1604
|
-
_optionalChain([report, 'optionalCall',
|
|
1309
|
+
_optionalChain([report, 'optionalCall', _18 => _18(0.4, "Finding the subject")]);
|
|
1605
1310
|
const t = otsuThreshold(sal, sp.size);
|
|
1606
1311
|
const n = w * h;
|
|
1607
1312
|
const initial = new Uint8Array(n);
|
|
@@ -1619,20 +1324,20 @@ function findSubject(pixels, options = {}) {
|
|
|
1619
1324
|
for (let y = 0; y < h; y++) {
|
|
1620
1325
|
for (const x of [0, w - 1]) if (sal[sp.label[y * w + x]] < t * 0.5) hardBg[y * w + x] = 1;
|
|
1621
1326
|
}
|
|
1622
|
-
const empty = (reason) => ({ selection:
|
|
1327
|
+
const empty = (reason) => ({ selection: _chunkSS53NNZOcjs.createSelectionMask.call(void 0, pixels.width, pixels.height), reason });
|
|
1623
1328
|
let guessed = 0;
|
|
1624
1329
|
for (let i = 0; i < n; i++) guessed += initial[i];
|
|
1625
1330
|
if (!guessed || guessed > n * 0.95) return empty("Nothing stands out from the background.");
|
|
1626
1331
|
const roi = { x: 0, y: 0, width: w, height: h };
|
|
1627
|
-
const label = grabCutLabels(work, { roi, initial, hardBg, hardFg }, 5, (f) => _optionalChain([report, 'optionalCall',
|
|
1332
|
+
const label = grabCutLabels(work, { roi, initial, hardBg, hardFg }, 5, (f) => _optionalChain([report, 'optionalCall', _19 => _19(0.4 + 0.5 * f, "Finding the subject")]));
|
|
1628
1333
|
keepMainPieces(label, w, h, null);
|
|
1629
1334
|
let kept = 0;
|
|
1630
1335
|
for (let i = 0; i < n; i++) kept += label[i];
|
|
1631
1336
|
if (kept < n * 2e-3) return empty("Nothing stands out from the background.");
|
|
1632
1337
|
if (kept > n * 0.97) return empty("The whole image looks like one subject; select it with select_all instead.");
|
|
1633
|
-
_optionalChain([report, 'optionalCall',
|
|
1338
|
+
_optionalChain([report, 'optionalCall', _20 => _20(0.9, "Scaling up")]);
|
|
1634
1339
|
const selection = upscaleRegion(work, pixels, roi, label, _nullishCoalesce(options.enhanceEdge, () => ( false)));
|
|
1635
|
-
_optionalChain([report, 'optionalCall',
|
|
1340
|
+
_optionalChain([report, 'optionalCall', _21 => _21(1, "Done")]);
|
|
1636
1341
|
return { selection };
|
|
1637
1342
|
}
|
|
1638
1343
|
|
|
@@ -1652,9 +1357,9 @@ function estimateNoise(luma, w, h) {
|
|
|
1652
1357
|
}
|
|
1653
1358
|
function focusArea(pixels, options = {}) {
|
|
1654
1359
|
const report = options.onProgress;
|
|
1655
|
-
_optionalChain([report, 'optionalCall',
|
|
1360
|
+
_optionalChain([report, 'optionalCall', _22 => _22(0, "Reducing the image")]);
|
|
1656
1361
|
const work = workImage(pixels, FOCUS_SIZE);
|
|
1657
|
-
_optionalChain([report, 'optionalCall',
|
|
1362
|
+
_optionalChain([report, 'optionalCall', _23 => _23(0.2, "Measuring sharpness")]);
|
|
1658
1363
|
const { width: w, height: h, scale } = work;
|
|
1659
1364
|
const n = w * h;
|
|
1660
1365
|
const luma = workLuma(work);
|
|
@@ -1671,10 +1376,10 @@ function focusArea(pixels, options = {}) {
|
|
|
1671
1376
|
}
|
|
1672
1377
|
}
|
|
1673
1378
|
const r = Math.max(2, Math.round(0.012 * Math.max(w, h)));
|
|
1674
|
-
const energy = boxMean(detail, w, h, r);
|
|
1379
|
+
const energy = _chunkSS53NNZOcjs.boxMean.call(void 0, detail, w, h, r);
|
|
1675
1380
|
const sharp = new Float32Array(n);
|
|
1676
1381
|
for (let i = 0; i < n; i++) sharp[i] = Math.log1p(Math.sqrt(energy[i]) * 400);
|
|
1677
|
-
_optionalChain([report, 'optionalCall',
|
|
1382
|
+
_optionalChain([report, 'optionalCall', _24 => _24(0.5, "Separating what is in focus")]);
|
|
1678
1383
|
const sorted = Float32Array.from(sharp).sort();
|
|
1679
1384
|
const top = sorted[Math.floor(n * 0.995)] || 1;
|
|
1680
1385
|
for (let i = 0; i < n; i++) sharp[i] = Math.min(1, sharp[i] / top);
|
|
@@ -1685,20 +1390,20 @@ function focusArea(pixels, options = {}) {
|
|
|
1685
1390
|
let mask = new Float32Array(n);
|
|
1686
1391
|
for (let i = 0; i < n; i++) mask[i] = sharp[i] >= t ? 1 : 0;
|
|
1687
1392
|
const c = 2 * r;
|
|
1688
|
-
const grown = boxMean(mask, w, h, c);
|
|
1393
|
+
const grown = _chunkSS53NNZOcjs.boxMean.call(void 0, mask, w, h, c);
|
|
1689
1394
|
for (let i = 0; i < n; i++) grown[i] = grown[i] > 1e-3 ? 1 : 0;
|
|
1690
|
-
const shrunk = boxMean(grown, w, h, c);
|
|
1395
|
+
const shrunk = _chunkSS53NNZOcjs.boxMean.call(void 0, grown, w, h, c);
|
|
1691
1396
|
for (let i = 0; i < n; i++) mask[i] = shrunk[i] >= 0.999 ? 1 : 0;
|
|
1692
|
-
const pulled = boxMean(mask, w, h, Math.max(1, Math.round(r / 2)));
|
|
1397
|
+
const pulled = _chunkSS53NNZOcjs.boxMean.call(void 0, mask, w, h, Math.max(1, Math.round(r / 2)));
|
|
1693
1398
|
for (let i = 0; i < n; i++) mask[i] = pulled[i] >= 0.999 ? 1 : 0;
|
|
1694
|
-
_optionalChain([report, 'optionalCall',
|
|
1399
|
+
_optionalChain([report, 'optionalCall', _25 => _25(0.7, "Fitting the edge")]);
|
|
1695
1400
|
const softness = Math.max(0, _nullishCoalesce(options.softness, () => ( 4))) * scale;
|
|
1696
1401
|
if (softness > 0) {
|
|
1697
|
-
const fitted = guidedFilterColor(workPlanes(work), mask, w, h, Math.max(1, Math.round(softness * 2)), 1e-3);
|
|
1402
|
+
const fitted = _chunkSS53NNZOcjs.guidedFilterColor.call(void 0, workPlanes(work), mask, w, h, Math.max(1, Math.round(softness * 2)), 1e-3);
|
|
1698
1403
|
for (let i = 0; i < n; i++) mask[i] = Math.min(1, Math.max(0, fitted[i]));
|
|
1699
1404
|
}
|
|
1700
1405
|
const selection = softMaskToSelection(work, mask);
|
|
1701
|
-
_optionalChain([report, 'optionalCall',
|
|
1406
|
+
_optionalChain([report, 'optionalCall', _26 => _26(1, "Done")]);
|
|
1702
1407
|
return { selection, noiseLevel: Math.round(sigma * 255 * 10) / 10 };
|
|
1703
1408
|
}
|
|
1704
1409
|
|
|
@@ -1721,9 +1426,9 @@ function lab(r, g, b) {
|
|
|
1721
1426
|
var sigmoid = (v) => 1 / (1 + Math.exp(-v));
|
|
1722
1427
|
function findSky(pixels, options = {}) {
|
|
1723
1428
|
const report = options.onProgress;
|
|
1724
|
-
_optionalChain([report, 'optionalCall',
|
|
1429
|
+
_optionalChain([report, 'optionalCall', _27 => _27(0, "Reducing the image")]);
|
|
1725
1430
|
const work = workImage(pixels, SKY_SIZE);
|
|
1726
|
-
_optionalChain([report, 'optionalCall',
|
|
1431
|
+
_optionalChain([report, 'optionalCall', _28 => _28(0.2, "Scoring the sky")]);
|
|
1727
1432
|
const { width: w, height: h, rgb, scale } = work;
|
|
1728
1433
|
const n = w * h;
|
|
1729
1434
|
const L = new Float32Array(n);
|
|
@@ -1735,7 +1440,7 @@ function findSky(pixels, options = {}) {
|
|
|
1735
1440
|
A[i] = a;
|
|
1736
1441
|
B[i] = b;
|
|
1737
1442
|
}
|
|
1738
|
-
const luma = boxMean(workLuma(work), w, h, 1);
|
|
1443
|
+
const luma = _chunkSS53NNZOcjs.boxMean.call(void 0, workLuma(work), w, h, 1);
|
|
1739
1444
|
const grad = new Float32Array(n);
|
|
1740
1445
|
for (let y = 0; y < h; y++) {
|
|
1741
1446
|
for (let x = 0; x < w; x++) {
|
|
@@ -1746,7 +1451,7 @@ function findSky(pixels, options = {}) {
|
|
|
1746
1451
|
}
|
|
1747
1452
|
}
|
|
1748
1453
|
const roughR = Math.max(1, Math.round(6e-3 * Math.max(w, h)));
|
|
1749
|
-
const rough = boxMean(grad, w, h, roughR);
|
|
1454
|
+
const rough = _chunkSS53NNZOcjs.boxMean.call(void 0, grad, w, h, roughR);
|
|
1750
1455
|
const score = new Float32Array(n);
|
|
1751
1456
|
for (let i = 0; i < n; i++) {
|
|
1752
1457
|
const chroma = Math.hypot(A[i], B[i]);
|
|
@@ -1759,7 +1464,7 @@ function findSky(pixels, options = {}) {
|
|
|
1759
1464
|
}
|
|
1760
1465
|
const threshold = Math.min(100, Math.max(0, _nullishCoalesce(options.threshold, () => ( 50))));
|
|
1761
1466
|
const t = 0.55 - (threshold - 50) * 6e-3;
|
|
1762
|
-
_optionalChain([report, 'optionalCall',
|
|
1467
|
+
_optionalChain([report, 'optionalCall', _29 => _29(0.5, "Growing the sky")]);
|
|
1763
1468
|
const sky = new Uint8Array(n);
|
|
1764
1469
|
const stack = [];
|
|
1765
1470
|
const seedRows = Math.max(1, Math.round(h * 0.04));
|
|
@@ -1772,7 +1477,7 @@ function findSky(pixels, options = {}) {
|
|
|
1772
1477
|
}
|
|
1773
1478
|
}
|
|
1774
1479
|
}
|
|
1775
|
-
if (!stack.length) return { selection:
|
|
1480
|
+
if (!stack.length) return { selection: _chunkSS53NNZOcjs.createSelectionMask.call(void 0, pixels.width, pixels.height), reason: "No sky was found along the top of the image." };
|
|
1776
1481
|
const low = t * 0.7;
|
|
1777
1482
|
while (stack.length) {
|
|
1778
1483
|
const p = stack.pop();
|
|
@@ -1816,17 +1521,17 @@ function findSky(pixels, options = {}) {
|
|
|
1816
1521
|
}
|
|
1817
1522
|
front = next;
|
|
1818
1523
|
}
|
|
1819
|
-
if (count < n * 5e-3) return { selection:
|
|
1820
|
-
_optionalChain([report, 'optionalCall',
|
|
1524
|
+
if (count < n * 5e-3) return { selection: _chunkSS53NNZOcjs.createSelectionMask.call(void 0, pixels.width, pixels.height), reason: "No sky was found along the top of the image." };
|
|
1525
|
+
_optionalChain([report, 'optionalCall', _30 => _30(0.7, "Fitting the edge")]);
|
|
1821
1526
|
let mask = Float32Array.from(sky);
|
|
1822
1527
|
const softness = Math.max(0, _nullishCoalesce(options.softness, () => ( 4))) * scale;
|
|
1823
1528
|
if (softness > 0) {
|
|
1824
|
-
const fitted = guidedFilterColor(workPlanes(work), mask, w, h, Math.max(1, Math.round(softness * 2)), 1e-3);
|
|
1529
|
+
const fitted = _chunkSS53NNZOcjs.guidedFilterColor.call(void 0, workPlanes(work), mask, w, h, Math.max(1, Math.round(softness * 2)), 1e-3);
|
|
1825
1530
|
mask = new Float32Array(n);
|
|
1826
1531
|
for (let i = 0; i < n; i++) mask[i] = Math.min(1, Math.max(0, fitted[i]));
|
|
1827
1532
|
}
|
|
1828
1533
|
const selection = softMaskToSelection(work, mask);
|
|
1829
|
-
_optionalChain([report, 'optionalCall',
|
|
1534
|
+
_optionalChain([report, 'optionalCall', _31 => _31(1, "Done")]);
|
|
1830
1535
|
return { selection };
|
|
1831
1536
|
}
|
|
1832
1537
|
|
|
@@ -1840,7 +1545,7 @@ function serializeMask(mask) {
|
|
|
1840
1545
|
return { width: mask.width, height: mask.height, bounds: { ...b }, bytes };
|
|
1841
1546
|
}
|
|
1842
1547
|
function deserializeMask(s) {
|
|
1843
|
-
return s.bounds ?
|
|
1548
|
+
return s.bounds ? _chunkSS53NNZOcjs.selectionFromRegion.call(void 0, s.width, s.height, s.bounds, s.bytes) : _chunkSS53NNZOcjs.createSelectionMask.call(void 0, s.width, s.height);
|
|
1844
1549
|
}
|
|
1845
1550
|
function runSelectionJob(job, pixels, onProgress) {
|
|
1846
1551
|
switch (job.op) {
|
|
@@ -1868,17 +1573,17 @@ function runSelectionJob(job, pixels, onProgress) {
|
|
|
1868
1573
|
})
|
|
1869
1574
|
};
|
|
1870
1575
|
case "fill": {
|
|
1871
|
-
_optionalChain([onProgress, 'optionalCall',
|
|
1576
|
+
_optionalChain([onProgress, 'optionalCall', _32 => _32(0, "Filling")]);
|
|
1872
1577
|
const filled = _chunkMQDIP4CFcjs.contentAwareFill.call(void 0, pixels.width, pixels.height, 4, pixels.data, job.hole, { seed: job.seed, exclude: job.exclude });
|
|
1873
|
-
_optionalChain([onProgress, 'optionalCall',
|
|
1874
|
-
return { mask:
|
|
1578
|
+
_optionalChain([onProgress, 'optionalCall', _33 => _33(1, "Done")]);
|
|
1579
|
+
return { mask: _chunkSS53NNZOcjs.createSelectionMask.call(void 0, 1, 1), pixels: Uint8ClampedArray.from(filled) };
|
|
1875
1580
|
}
|
|
1876
1581
|
case "refine-preview": {
|
|
1877
|
-
_optionalChain([onProgress, 'optionalCall',
|
|
1582
|
+
_optionalChain([onProgress, 'optionalCall', _34 => _34(0, "Refining")]);
|
|
1878
1583
|
const base = job.base ? deserializeMask(job.base) : null;
|
|
1879
1584
|
const { selection, refineBrush } = applyRefineEdits(pixels, base, job.edits, pixels.width, pixels.height);
|
|
1880
|
-
const mask = _optionalChain([selection, 'optionalAccess',
|
|
1881
|
-
_optionalChain([onProgress, 'optionalCall',
|
|
1585
|
+
const mask = _optionalChain([selection, 'optionalAccess', _35 => _35.bounds]) ? _chunkSS53NNZOcjs.refineSelection.call(void 0, pixels, selection, job.params, refineBrush) : _chunkSS53NNZOcjs.createSelectionMask.call(void 0, pixels.width, pixels.height);
|
|
1586
|
+
_optionalChain([onProgress, 'optionalCall', _36 => _36(1, "Done")]);
|
|
1882
1587
|
return { mask };
|
|
1883
1588
|
}
|
|
1884
1589
|
}
|
|
@@ -1919,7 +1624,7 @@ var SelectionWorkerClient = (_class2 = class {
|
|
|
1919
1624
|
__init9() {this.pending = /* @__PURE__ */ new Map()}
|
|
1920
1625
|
/** Runs `job` on `pixels` in the worker. Aborting `signal` terminates the worker and rejects with an `AbortError`. */
|
|
1921
1626
|
run(job, pixels, options = {}) {
|
|
1922
|
-
if (_optionalChain([options, 'access',
|
|
1627
|
+
if (_optionalChain([options, 'access', _37 => _37.signal, 'optionalAccess', _38 => _38.aborted])) return Promise.reject(abortError());
|
|
1923
1628
|
const worker = this.ensure();
|
|
1924
1629
|
let key = this.sent.get(pixels.data);
|
|
1925
1630
|
if (key === void 0) {
|
|
@@ -1930,7 +1635,7 @@ var SelectionWorkerClient = (_class2 = class {
|
|
|
1930
1635
|
const id = this.nextId++;
|
|
1931
1636
|
return new Promise((resolve, reject) => {
|
|
1932
1637
|
this.pending.set(id, { resolve, reject, onProgress: options.onProgress });
|
|
1933
|
-
_optionalChain([options, 'access',
|
|
1638
|
+
_optionalChain([options, 'access', _39 => _39.signal, 'optionalAccess', _40 => _40.addEventListener, 'call', _41 => _41(
|
|
1934
1639
|
"abort",
|
|
1935
1640
|
() => {
|
|
1936
1641
|
if (this.pending.has(id)) this.terminate(abortError());
|
|
@@ -1942,7 +1647,7 @@ var SelectionWorkerClient = (_class2 = class {
|
|
|
1942
1647
|
}
|
|
1943
1648
|
/** Stops the worker; jobs still running reject with `reason` (default an `AbortError`). */
|
|
1944
1649
|
terminate(reason = abortError()) {
|
|
1945
|
-
_optionalChain([this, 'access',
|
|
1650
|
+
_optionalChain([this, 'access', _42 => _42.worker, 'optionalAccess', _43 => _43.terminate, 'optionalCall', _44 => _44()]);
|
|
1946
1651
|
this.worker = null;
|
|
1947
1652
|
this.sent = /* @__PURE__ */ new WeakMap();
|
|
1948
1653
|
const pending = [...this.pending.values()];
|
|
@@ -1956,14 +1661,14 @@ var SelectionWorkerClient = (_class2 = class {
|
|
|
1956
1661
|
const msg = event.data;
|
|
1957
1662
|
const p = this.pending.get(msg.id);
|
|
1958
1663
|
if (!p) return;
|
|
1959
|
-
if (msg.type === "progress") _optionalChain([p, 'access',
|
|
1664
|
+
if (msg.type === "progress") _optionalChain([p, 'access', _45 => _45.onProgress, 'optionalCall', _46 => _46(msg.fraction, msg.stage)]);
|
|
1960
1665
|
else {
|
|
1961
1666
|
this.pending.delete(msg.id);
|
|
1962
1667
|
if (msg.type === "error") p.reject(new Error(msg.message));
|
|
1963
1668
|
else p.resolve({ mask: deserializeMask(msg.mask), reason: msg.reason, noiseLevel: msg.noiseLevel, pixels: msg.pixels });
|
|
1964
1669
|
}
|
|
1965
1670
|
};
|
|
1966
|
-
worker.onerror = (event) => this.terminate(new Error(_optionalChain([event, 'optionalAccess',
|
|
1671
|
+
worker.onerror = (event) => this.terminate(new Error(_optionalChain([event, 'optionalAccess', _47 => _47.message]) || "The selection worker failed."));
|
|
1967
1672
|
this.worker = worker;
|
|
1968
1673
|
return worker;
|
|
1969
1674
|
}
|
|
@@ -2007,15 +1712,4 @@ var SelectionWorkerClient = (_class2 = class {
|
|
|
2007
1712
|
|
|
2008
1713
|
|
|
2009
1714
|
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
exports.DEFAULT_REFINE_EDGE_PARAMS = DEFAULT_REFINE_EDGE_PARAMS; exports.GUIDED_FILTER_EPS = GUIDED_FILTER_EPS; exports.normalizeRefineEdgeParams = normalizeRefineEdgeParams; exports.refineEdgeHalo = refineEdgeHalo; exports.boxMean = boxMean; exports.guidedFilterColor = guidedFilterColor; exports.edgeWidth = edgeWidth; exports.refineCoverage = refineCoverage; exports.guidePlanes = guidePlanes; exports.refineSelection = refineSelection; exports.decontaminateColors = decontaminateColors; exports.polygonCoverage = polygonCoverage; exports.polygonCoverageBox = polygonCoverageBox; exports.polygonSelection = polygonSelection; exports.normalizeRect = normalizeRect; exports.rectSelection = rectSelection; exports.ellipsePoints = ellipsePoints; exports.ellipseSelection = ellipseSelection; exports.GridGraph = GridGraph; exports.WORK_SIZE = WORK_SIZE; exports.workImage = workImage; exports.GAMMA = GAMMA; exports.UNITS = UNITS; exports.smoothnessWeights = smoothnessWeights; exports.boxBlur = boxBlur; exports.upscaleRegion = upscaleRegion; exports.ColorGmm = ColorGmm; exports.grabCutLabels = grabCutLabels; exports.keepMainPieces = keepMainPieces; exports.selectObjectIn = selectObjectIn; exports.quickSelectStroke = quickSelectStroke; exports.REFINE_EDIT_KINDS = REFINE_EDIT_KINDS; exports.brushStrokeMask = brushStrokeMask; exports.applyRefineEdits = applyRefineEdits; exports.workPlanes = workPlanes; exports.workLuma = workLuma; exports.softMaskToSelection = softMaskToSelection; exports.slicSuperpixels = slicSuperpixels; exports.superpixelSaliency = superpixelSaliency; exports.otsuThreshold = otsuThreshold; exports.findSubject = findSubject; exports.focusArea = focusArea; exports.findSky = findSky; exports.serializeMask = serializeMask; exports.deserializeMask = deserializeMask; exports.runSelectionJob = runSelectionJob; exports.startSelectionWorker = startSelectionWorker; exports.SelectionWorkerClient = SelectionWorkerClient;
|
|
1715
|
+
exports.polygonCoverage = polygonCoverage; exports.polygonCoverageBox = polygonCoverageBox; exports.polygonSelection = polygonSelection; exports.normalizeRect = normalizeRect; exports.rectSelection = rectSelection; exports.ellipsePoints = ellipsePoints; exports.ellipseSelection = ellipseSelection; exports.GridGraph = GridGraph; exports.WORK_SIZE = WORK_SIZE; exports.workImage = workImage; exports.GAMMA = GAMMA; exports.UNITS = UNITS; exports.smoothnessWeights = smoothnessWeights; exports.boxBlur = boxBlur; exports.upscaleRegion = upscaleRegion; exports.ColorGmm = ColorGmm; exports.grabCutLabels = grabCutLabels; exports.keepMainPieces = keepMainPieces; exports.selectObjectIn = selectObjectIn; exports.quickSelectStroke = quickSelectStroke; exports.REFINE_EDIT_KINDS = REFINE_EDIT_KINDS; exports.brushStrokeMask = brushStrokeMask; exports.applyRefineEdits = applyRefineEdits; exports.workPlanes = workPlanes; exports.workLuma = workLuma; exports.softMaskToSelection = softMaskToSelection; exports.slicSuperpixels = slicSuperpixels; exports.superpixelSaliency = superpixelSaliency; exports.otsuThreshold = otsuThreshold; exports.findSubject = findSubject; exports.focusArea = focusArea; exports.findSky = findSky; exports.serializeMask = serializeMask; exports.deserializeMask = deserializeMask; exports.runSelectionJob = runSelectionJob; exports.startSelectionWorker = startSelectionWorker; exports.SelectionWorkerClient = SelectionWorkerClient;
|