vue3-image-compressor 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -2
- package/dist/assets/imageWorker-B_HCdCy9.js +24 -0
- package/dist/vue-image-compressor.js +98 -100
- package/dist/vue-image-compressor.umd.cjs +1 -1
- package/package.json +1 -1
- package/src/composables/useWorker.ts +1 -2
- package/src/utils/compressFile.ts +1 -2
- package/src/workers/imageWorker.ts +1 -1
- package/dist/assets/imageWorker-Qv3pCULy.js +0 -1042
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ref as y, onUnmounted as Y, computed as
|
|
2
|
-
const
|
|
1
|
+
import { ref as y, onUnmounted as Y, computed as G, defineComponent as Z, openBlock as z, createElementBlock as k, createElementVNode as E, withModifiers as J, renderSlot as S, toDisplayString as D, unref as v, createCommentVNode as C, withDirectives as ee, isRef as te, Fragment as oe, renderList as re, vModelSelect as ne, createTextVNode as se } from "vue";
|
|
2
|
+
const j = {
|
|
3
3
|
mozJPEG: {
|
|
4
4
|
label: "MozJPEG",
|
|
5
5
|
mimeType: "image/jpeg",
|
|
@@ -124,14 +124,14 @@ const G = {
|
|
|
124
124
|
wp2: {
|
|
125
125
|
quality: 75
|
|
126
126
|
}
|
|
127
|
-
}, ae = Object.keys(
|
|
128
|
-
async function
|
|
127
|
+
}, ae = Object.keys(j);
|
|
128
|
+
async function H(r) {
|
|
129
129
|
const o = await createImageBitmap(r), n = document.createElement("canvas");
|
|
130
130
|
n.width = o.width, n.height = o.height;
|
|
131
131
|
const t = n.getContext("2d");
|
|
132
132
|
return t.drawImage(o, 0, 0), t.getImageData(0, 0, n.width, n.height);
|
|
133
133
|
}
|
|
134
|
-
async function
|
|
134
|
+
async function A(r, o, n) {
|
|
135
135
|
const t = document.createElement("canvas");
|
|
136
136
|
return t.width = r.width, t.height = r.height, t.getContext("2d").putImageData(r, 0, 0), new Promise((s) => {
|
|
137
137
|
t.toBlob(
|
|
@@ -159,7 +159,7 @@ function le(r) {
|
|
|
159
159
|
n.onload = () => o(!0), n.onerror = () => o(!1), n.src = `data:${r};base64,`;
|
|
160
160
|
});
|
|
161
161
|
}
|
|
162
|
-
function
|
|
162
|
+
function Q(r, o, n) {
|
|
163
163
|
return new File([r], o, { type: n });
|
|
164
164
|
}
|
|
165
165
|
function $(r, o = 2) {
|
|
@@ -230,10 +230,9 @@ function pe() {
|
|
|
230
230
|
o.value = !0, t = new Worker(
|
|
231
231
|
new URL(
|
|
232
232
|
/* @vite-ignore */
|
|
233
|
-
"
|
|
233
|
+
"" + new URL("assets/imageWorker-B_HCdCy9.js", import.meta.url).href,
|
|
234
234
|
import.meta.url
|
|
235
|
-
)
|
|
236
|
-
{ type: "module" }
|
|
235
|
+
)
|
|
237
236
|
), r.value = !0, n.value = null;
|
|
238
237
|
} catch (b) {
|
|
239
238
|
n.value = b instanceof Error ? b : new Error("Failed to start worker"), console.error("Worker start failed:", b);
|
|
@@ -257,11 +256,11 @@ function pe() {
|
|
|
257
256
|
async function h(b, O) {
|
|
258
257
|
if (b.aborted)
|
|
259
258
|
throw new DOMException("AbortError", "AbortError");
|
|
260
|
-
return clearTimeout(e), new Promise((
|
|
259
|
+
return clearTimeout(e), new Promise((I, P) => {
|
|
261
260
|
const T = () => {
|
|
262
261
|
a(), P(new DOMException("AbortError", "AbortError"));
|
|
263
262
|
};
|
|
264
|
-
b.addEventListener("abort", T), O().then(
|
|
263
|
+
b.addEventListener("abort", T), O().then(I).catch(P).finally(() => {
|
|
265
264
|
b.removeEventListener("abort", T), p();
|
|
266
265
|
});
|
|
267
266
|
});
|
|
@@ -279,7 +278,7 @@ function pe() {
|
|
|
279
278
|
};
|
|
280
279
|
}
|
|
281
280
|
function me() {
|
|
282
|
-
const r = y(!1), o = y(0), n = y(null), t = y(null), e = y(null), { getWorkerApi: s, executeTask: a } = pe(), p =
|
|
281
|
+
const r = y(!1), o = y(0), n = y(null), t = y(null), e = y(null), { getWorkerApi: s, executeTask: a } = pe(), p = G(() => r.value && !!e.value);
|
|
283
282
|
async function u(f, i) {
|
|
284
283
|
const l = await ie(i), d = await le(l), w = await s();
|
|
285
284
|
if (!d) {
|
|
@@ -294,7 +293,7 @@ function me() {
|
|
|
294
293
|
if (l === "image/qoi")
|
|
295
294
|
return a(f, () => w.qoiDecode(i));
|
|
296
295
|
}
|
|
297
|
-
return
|
|
296
|
+
return H(i);
|
|
298
297
|
}
|
|
299
298
|
async function h(f, i, l) {
|
|
300
299
|
if (l === 0) return i;
|
|
@@ -305,7 +304,7 @@ function me() {
|
|
|
305
304
|
);
|
|
306
305
|
}
|
|
307
306
|
async function b(f, i, l) {
|
|
308
|
-
var g,
|
|
307
|
+
var g, _;
|
|
309
308
|
let d = i;
|
|
310
309
|
const w = await s();
|
|
311
310
|
return (g = l.resize) != null && g.enabled && (d = await a(
|
|
@@ -318,7 +317,7 @@ function me() {
|
|
|
318
317
|
premultiply: !0,
|
|
319
318
|
linearRGB: !0
|
|
320
319
|
})
|
|
321
|
-
)), (
|
|
320
|
+
)), (_ = l.quantize) != null && _.enabled && (d = await a(
|
|
322
321
|
f,
|
|
323
322
|
() => w.quantize(d, {
|
|
324
323
|
numColors: l.quantize.numColors || 256,
|
|
@@ -329,16 +328,16 @@ function me() {
|
|
|
329
328
|
async function O(f, i, l) {
|
|
330
329
|
const d = await s(), w = l.encoder;
|
|
331
330
|
if (w === "browserJPEG")
|
|
332
|
-
return (await
|
|
331
|
+
return (await A(
|
|
333
332
|
i,
|
|
334
333
|
"image/jpeg",
|
|
335
334
|
l.encoderOptions.quality
|
|
336
335
|
)).arrayBuffer();
|
|
337
336
|
if (w === "browserPNG")
|
|
338
|
-
return (await
|
|
337
|
+
return (await A(i, "image/png")).arrayBuffer();
|
|
339
338
|
if (w === "browserGIF")
|
|
340
339
|
throw new Error("Browser GIF encoding not supported directly");
|
|
341
|
-
const
|
|
340
|
+
const _ = {
|
|
342
341
|
mozJPEG: d.mozjpegEncode,
|
|
343
342
|
webP: d.webpEncode,
|
|
344
343
|
avif: d.avifEncode,
|
|
@@ -347,14 +346,14 @@ function me() {
|
|
|
347
346
|
qoi: d.qoiEncode,
|
|
348
347
|
wp2: d.wp2Encode
|
|
349
348
|
}[w];
|
|
350
|
-
if (!
|
|
349
|
+
if (!_)
|
|
351
350
|
throw new Error(`Unknown encoder: ${w}`);
|
|
352
351
|
return (await a(
|
|
353
352
|
f,
|
|
354
|
-
() =>
|
|
353
|
+
() => _.call(d, i, l.encoderOptions)
|
|
355
354
|
)).buffer;
|
|
356
355
|
}
|
|
357
|
-
async function
|
|
356
|
+
async function I(f, i) {
|
|
358
357
|
var w;
|
|
359
358
|
e.value = new AbortController();
|
|
360
359
|
const l = e.value.signal;
|
|
@@ -369,30 +368,30 @@ function me() {
|
|
|
369
368
|
width: 0,
|
|
370
369
|
height: 0,
|
|
371
370
|
blobUrl: V(f)
|
|
372
|
-
},
|
|
373
|
-
g.width =
|
|
371
|
+
}, _ = await u(l, f);
|
|
372
|
+
g.width = _.width, g.height = _.height, o.value = 25;
|
|
374
373
|
const U = await h(
|
|
375
374
|
l,
|
|
376
|
-
|
|
375
|
+
_,
|
|
377
376
|
i.rotate || 0
|
|
378
377
|
);
|
|
379
378
|
o.value = 35;
|
|
380
|
-
const
|
|
379
|
+
const R = await b(l, U, i);
|
|
381
380
|
o.value = 50;
|
|
382
|
-
const F = await O(l,
|
|
381
|
+
const F = await O(l, R, i);
|
|
383
382
|
o.value = 80;
|
|
384
|
-
const
|
|
383
|
+
const q = j[i.encoder], B = X(
|
|
385
384
|
f.name,
|
|
386
|
-
(
|
|
387
|
-
), L =
|
|
385
|
+
(q == null ? void 0 : q.extension) || "bin"
|
|
386
|
+
), L = Q(
|
|
388
387
|
F,
|
|
389
|
-
|
|
390
|
-
(
|
|
388
|
+
B,
|
|
389
|
+
(q == null ? void 0 : q.mimeType) || "application/octet-stream"
|
|
391
390
|
), M = {
|
|
392
391
|
file: L,
|
|
393
392
|
size: L.size,
|
|
394
|
-
width:
|
|
395
|
-
height:
|
|
393
|
+
width: R.width,
|
|
394
|
+
height: R.height,
|
|
396
395
|
blobUrl: V(L)
|
|
397
396
|
}, m = {
|
|
398
397
|
original: g,
|
|
@@ -406,8 +405,8 @@ function me() {
|
|
|
406
405
|
} catch (g) {
|
|
407
406
|
if (g instanceof DOMException && g.name === "AbortError")
|
|
408
407
|
throw n.value = "已取消", g;
|
|
409
|
-
const
|
|
410
|
-
throw n.value =
|
|
408
|
+
const _ = g instanceof Error ? g.message : "压缩失败";
|
|
409
|
+
throw n.value = _, console.error("Compression error:", g), g;
|
|
411
410
|
} finally {
|
|
412
411
|
r.value = !1, e.value = null;
|
|
413
412
|
}
|
|
@@ -421,7 +420,7 @@ function me() {
|
|
|
421
420
|
i.href = f.blobUrl, i.download = f.file.name, document.body.appendChild(i), i.click(), document.body.removeChild(i);
|
|
422
421
|
}
|
|
423
422
|
return {
|
|
424
|
-
compress:
|
|
423
|
+
compress: I,
|
|
425
424
|
cancel: P,
|
|
426
425
|
downloadResult: T,
|
|
427
426
|
isCompressing: r,
|
|
@@ -432,14 +431,14 @@ function me() {
|
|
|
432
431
|
};
|
|
433
432
|
}
|
|
434
433
|
function fe() {
|
|
435
|
-
const r = y("mozJPEG"), o = y({}), n =
|
|
434
|
+
const r = y("mozJPEG"), o = y({}), n = G(() => j[r.value]), t = G(
|
|
436
435
|
() => N[r.value]
|
|
437
|
-
), e =
|
|
436
|
+
), e = G(
|
|
438
437
|
() => ae.map((u) => ({
|
|
439
438
|
type: u,
|
|
440
|
-
label:
|
|
441
|
-
mimeType:
|
|
442
|
-
extension:
|
|
439
|
+
label: j[u].label,
|
|
440
|
+
mimeType: j[u].mimeType,
|
|
441
|
+
extension: j[u].extension
|
|
443
442
|
}))
|
|
444
443
|
);
|
|
445
444
|
function s(u) {
|
|
@@ -471,7 +470,7 @@ const ve = { class: "image-compressor" }, we = {
|
|
|
471
470
|
}, ge = { class: "preview-item" }, be = ["src"], Ee = { class: "preview-item" }, he = ["src"], ye = {
|
|
472
471
|
key: 1,
|
|
473
472
|
class: "compressing"
|
|
474
|
-
},
|
|
473
|
+
}, _e = ["value"], xe = { key: 2 }, ze = {
|
|
475
474
|
key: 1,
|
|
476
475
|
class: "encoder-settings"
|
|
477
476
|
}, ke = ["value"], Oe = {
|
|
@@ -480,10 +479,10 @@ const ve = { class: "image-compressor" }, we = {
|
|
|
480
479
|
}, Pe = ["value"], Te = {
|
|
481
480
|
key: 2,
|
|
482
481
|
class: "actions"
|
|
483
|
-
}, De = ["disabled"],
|
|
482
|
+
}, De = ["disabled"], Ce = {
|
|
484
483
|
key: 3,
|
|
485
484
|
class: "error"
|
|
486
|
-
},
|
|
485
|
+
}, Ie = /* @__PURE__ */ Z({
|
|
487
486
|
__name: "ImageCompressor",
|
|
488
487
|
props: {
|
|
489
488
|
defaultEncoder: {},
|
|
@@ -496,7 +495,7 @@ const ve = { class: "image-compressor" }, we = {
|
|
|
496
495
|
cancel: h,
|
|
497
496
|
downloadResult: b,
|
|
498
497
|
isCompressing: O,
|
|
499
|
-
progress:
|
|
498
|
+
progress: I,
|
|
500
499
|
error: P,
|
|
501
500
|
result: T,
|
|
502
501
|
canCancel: f
|
|
@@ -508,22 +507,22 @@ const ve = { class: "image-compressor" }, we = {
|
|
|
508
507
|
updateOption: g
|
|
509
508
|
} = fe();
|
|
510
509
|
n.defaultEncoder && w(n.defaultEncoder), n.defaultOptions && Object.entries(n.defaultOptions).forEach(([m, c]) => g(m, c));
|
|
511
|
-
const
|
|
510
|
+
const _ = G(
|
|
512
511
|
() => s.value ? $(s.value.size) : ""
|
|
513
|
-
), U =
|
|
512
|
+
), U = G(
|
|
514
513
|
() => T.value ? $(T.value.compressed.size) : ""
|
|
515
|
-
),
|
|
514
|
+
), R = G(
|
|
516
515
|
() => ["mozJPEG", "webP", "jxl", "browserJPEG", "wp2"].includes(i.value)
|
|
517
516
|
);
|
|
518
517
|
function F(m) {
|
|
519
518
|
const c = m.target;
|
|
520
|
-
c.files && c.files[0] &&
|
|
519
|
+
c.files && c.files[0] && B(c.files[0]);
|
|
521
520
|
}
|
|
522
|
-
function
|
|
521
|
+
function q(m) {
|
|
523
522
|
var c;
|
|
524
|
-
(c = m.dataTransfer) != null && c.files[0] &&
|
|
523
|
+
(c = m.dataTransfer) != null && c.files[0] && B(m.dataTransfer.files[0]);
|
|
525
524
|
}
|
|
526
|
-
function
|
|
525
|
+
function B(m) {
|
|
527
526
|
m.type.startsWith("image/") && (a.value && URL.revokeObjectURL(a.value), p.value && (URL.revokeObjectURL(p.value), p.value = ""), s.value = m, a.value = URL.createObjectURL(m));
|
|
528
527
|
}
|
|
529
528
|
function L() {
|
|
@@ -548,7 +547,7 @@ const ve = { class: "image-compressor" }, we = {
|
|
|
548
547
|
return (m, c) => (z(), k("div", ve, [
|
|
549
548
|
E("div", {
|
|
550
549
|
class: "upload-zone",
|
|
551
|
-
onDrop: J(
|
|
550
|
+
onDrop: J(q, ["prevent"]),
|
|
552
551
|
onDragover: c[1] || (c[1] = J(() => {
|
|
553
552
|
}, ["prevent"]))
|
|
554
553
|
}, [
|
|
@@ -562,7 +561,7 @@ const ve = { class: "image-compressor" }, we = {
|
|
|
562
561
|
}, null, 544),
|
|
563
562
|
E("div", {
|
|
564
563
|
class: "upload-prompt",
|
|
565
|
-
onClick: c[0] || (c[0] = (
|
|
564
|
+
onClick: c[0] || (c[0] = (x) => {
|
|
566
565
|
var W;
|
|
567
566
|
return (W = e.value) == null ? void 0 : W.click();
|
|
568
567
|
})
|
|
@@ -579,7 +578,7 @@ const ve = { class: "image-compressor" }, we = {
|
|
|
579
578
|
src: a.value,
|
|
580
579
|
alt: "Original"
|
|
581
580
|
}, null, 8, be),
|
|
582
|
-
E("p", null, D(
|
|
581
|
+
E("p", null, D(_.value), 1)
|
|
583
582
|
]),
|
|
584
583
|
E("div", Ee, [
|
|
585
584
|
c[8] || (c[8] = E("h4", null, "压缩后", -1)),
|
|
@@ -589,28 +588,28 @@ const ve = { class: "image-compressor" }, we = {
|
|
|
589
588
|
alt: "Compressed"
|
|
590
589
|
}, null, 8, he)) : v(O) ? (z(), k("div", ye, [
|
|
591
590
|
E("progress", {
|
|
592
|
-
value: v(
|
|
591
|
+
value: v(I),
|
|
593
592
|
max: "100"
|
|
594
|
-
}, null, 8,
|
|
595
|
-
E("p", null, "压缩中... " + D(v(
|
|
596
|
-
])) :
|
|
597
|
-
U.value ? (z(), k("p",
|
|
593
|
+
}, null, 8, _e),
|
|
594
|
+
E("p", null, "压缩中... " + D(v(I)) + "%", 1)
|
|
595
|
+
])) : C("", !0),
|
|
596
|
+
U.value ? (z(), k("p", xe, D(U.value), 1)) : C("", !0)
|
|
598
597
|
])
|
|
599
|
-
])) :
|
|
598
|
+
])) : C("", !0),
|
|
600
599
|
a.value ? (z(), k("div", ze, [
|
|
601
600
|
c[9] || (c[9] = E("label", null, "编码器:", -1)),
|
|
602
601
|
ee(E("select", {
|
|
603
|
-
"onUpdate:modelValue": c[2] || (c[2] = (
|
|
602
|
+
"onUpdate:modelValue": c[2] || (c[2] = (x) => te(i) ? i.value = x : null),
|
|
604
603
|
onChange: L
|
|
605
604
|
}, [
|
|
606
|
-
(z(!0), k(oe, null, re(v(d), (
|
|
607
|
-
key:
|
|
608
|
-
value:
|
|
609
|
-
}, D(
|
|
605
|
+
(z(!0), k(oe, null, re(v(d), (x) => (z(), k("option", {
|
|
606
|
+
key: x.type,
|
|
607
|
+
value: x.type
|
|
608
|
+
}, D(x.label) + " (" + D(x.extension) + ") ", 9, ke))), 128))
|
|
610
609
|
], 544), [
|
|
611
610
|
[ne, v(i)]
|
|
612
611
|
]),
|
|
613
|
-
|
|
612
|
+
R.value ? (z(), k("div", Oe, [
|
|
614
613
|
E("label", null, [
|
|
615
614
|
se(" 质量: " + D(v(l).quality ?? 75) + " ", 1),
|
|
616
615
|
E("input", {
|
|
@@ -618,15 +617,15 @@ const ve = { class: "image-compressor" }, we = {
|
|
|
618
617
|
min: "0",
|
|
619
618
|
max: "100",
|
|
620
619
|
value: v(l).quality ?? 75,
|
|
621
|
-
onInput: c[3] || (c[3] = (
|
|
620
|
+
onInput: c[3] || (c[3] = (x) => v(g)("quality", Number(x.target.value)))
|
|
622
621
|
}, null, 40, Pe)
|
|
623
622
|
])
|
|
624
|
-
])) :
|
|
623
|
+
])) : C("", !0),
|
|
625
624
|
S(m.$slots, "encoder-settings", {
|
|
626
625
|
encoder: v(i),
|
|
627
626
|
options: v(l)
|
|
628
627
|
}, void 0, !0)
|
|
629
|
-
])) :
|
|
628
|
+
])) : C("", !0),
|
|
630
629
|
a.value ? (z(), k("div", Te, [
|
|
631
630
|
E("button", {
|
|
632
631
|
onClick: M,
|
|
@@ -636,31 +635,31 @@ const ve = { class: "image-compressor" }, we = {
|
|
|
636
635
|
v(f) ? (z(), k("button", {
|
|
637
636
|
key: 0,
|
|
638
637
|
onClick: c[4] || (c[4] = //@ts-ignore
|
|
639
|
-
(...
|
|
638
|
+
(...x) => v(h) && v(h)(...x)),
|
|
640
639
|
class: "btn-secondary"
|
|
641
|
-
}, " 取消 ")) :
|
|
640
|
+
}, " 取消 ")) : C("", !0),
|
|
642
641
|
v(T) ? (z(), k("button", {
|
|
643
642
|
key: 1,
|
|
644
643
|
onClick: c[5] || (c[5] = //@ts-ignore
|
|
645
|
-
(...
|
|
644
|
+
(...x) => v(b) && v(b)(...x)),
|
|
646
645
|
class: "btn-success"
|
|
647
|
-
}, " 下载 (节省 " + D(v(T).savingsPercent) + "%) ", 1)) :
|
|
648
|
-
])) :
|
|
649
|
-
v(P) ? (z(), k("div",
|
|
646
|
+
}, " 下载 (节省 " + D(v(T).savingsPercent) + "%) ", 1)) : C("", !0)
|
|
647
|
+
])) : C("", !0),
|
|
648
|
+
v(P) ? (z(), k("div", Ce, D(v(P)), 1)) : C("", !0)
|
|
650
649
|
]));
|
|
651
650
|
}
|
|
652
|
-
}),
|
|
651
|
+
}), qe = (r, o) => {
|
|
653
652
|
const n = r.__vccOpts || r;
|
|
654
653
|
for (const [t, e] of o)
|
|
655
654
|
n[t] = e;
|
|
656
655
|
return n;
|
|
657
|
-
}, Me = /* @__PURE__ */
|
|
656
|
+
}, Me = /* @__PURE__ */ qe(Ie, [["__scopeId", "data-v-d7e6eec9"]]), Be = [
|
|
658
657
|
{ value: "lanczos3", label: "Lanczos3" },
|
|
659
658
|
{ value: "catrom", label: "Catrom" },
|
|
660
659
|
{ value: "mitchell", label: "Mitchell" },
|
|
661
660
|
{ value: "triangle", label: "Triangle" },
|
|
662
661
|
{ value: "vector", label: "Vector" }
|
|
663
|
-
],
|
|
662
|
+
], Ae = [
|
|
664
663
|
{ value: "stretch", label: "拉伸" },
|
|
665
664
|
{ value: "contain", label: "适应" }
|
|
666
665
|
], Fe = [
|
|
@@ -668,7 +667,7 @@ const ve = { class: "image-compressor" }, we = {
|
|
|
668
667
|
{ value: 90, label: "顺时针 90°" },
|
|
669
668
|
{ value: 180, label: "旋转 180°" },
|
|
670
669
|
{ value: 270, label: "逆时针 90°" }
|
|
671
|
-
],
|
|
670
|
+
], Re = {
|
|
672
671
|
mozJPEG: "mozjpegEncode",
|
|
673
672
|
webP: "webpEncode",
|
|
674
673
|
avif: "avifEncode",
|
|
@@ -677,26 +676,25 @@ const ve = { class: "image-compressor" }, we = {
|
|
|
677
676
|
qoi: "qoiEncode",
|
|
678
677
|
wp2: "wp2Encode"
|
|
679
678
|
};
|
|
680
|
-
function
|
|
679
|
+
function je() {
|
|
681
680
|
return new Worker(
|
|
682
681
|
new URL(
|
|
683
682
|
/* @vite-ignore */
|
|
684
|
-
"
|
|
683
|
+
"" + new URL("assets/imageWorker-B_HCdCy9.js", import.meta.url).href,
|
|
685
684
|
import.meta.url
|
|
686
|
-
)
|
|
687
|
-
{ type: "module" }
|
|
685
|
+
)
|
|
688
686
|
);
|
|
689
687
|
}
|
|
690
|
-
function
|
|
688
|
+
function Ge(r, o, n, t) {
|
|
691
689
|
return new Promise((e, s) => {
|
|
692
|
-
const a =
|
|
690
|
+
const a = je();
|
|
693
691
|
let p = !1;
|
|
694
692
|
function u() {
|
|
695
693
|
p || (p = !0, a.terminate());
|
|
696
694
|
}
|
|
697
695
|
a.addEventListener("message", (O) => {
|
|
698
|
-
const { result:
|
|
699
|
-
u(), P ? s(new Error(P)) : e(
|
|
696
|
+
const { result: I, error: P } = O.data;
|
|
697
|
+
u(), P ? s(new Error(P)) : e(I.buffer);
|
|
700
698
|
}), a.addEventListener("error", (O) => {
|
|
701
699
|
u(), s(O.error || O);
|
|
702
700
|
});
|
|
@@ -704,7 +702,7 @@ function Re(r, o, n, t) {
|
|
|
704
702
|
u(), s(new DOMException("AbortError", "AbortError"));
|
|
705
703
|
};
|
|
706
704
|
t && t.addEventListener("abort", h, { once: !0 });
|
|
707
|
-
const b =
|
|
705
|
+
const b = Re[r];
|
|
708
706
|
if (!b) {
|
|
709
707
|
u(), s(new Error(`Unknown encoder: ${r}`));
|
|
710
708
|
return;
|
|
@@ -719,22 +717,22 @@ async function Ne(r, o = {}) {
|
|
|
719
717
|
const t = o.encoder || "mozJPEG", e = {
|
|
720
718
|
...N[t],
|
|
721
719
|
...o.encoderOptions
|
|
722
|
-
}, s =
|
|
720
|
+
}, s = j[t], a = await H(r);
|
|
723
721
|
if (n != null && n.aborted)
|
|
724
722
|
throw new DOMException("AbortError", "AbortError");
|
|
725
723
|
let p;
|
|
726
724
|
if (t === "browserJPEG")
|
|
727
|
-
p = await (await
|
|
725
|
+
p = await (await A(
|
|
728
726
|
a,
|
|
729
727
|
"image/jpeg",
|
|
730
728
|
e.quality
|
|
731
729
|
)).arrayBuffer();
|
|
732
730
|
else if (t === "browserPNG")
|
|
733
|
-
p = await (await
|
|
731
|
+
p = await (await A(a, "image/png")).arrayBuffer();
|
|
734
732
|
else {
|
|
735
733
|
if (t === "browserGIF")
|
|
736
734
|
throw new Error("Browser GIF encoding not supported directly");
|
|
737
|
-
p = await
|
|
735
|
+
p = await Ge(
|
|
738
736
|
t,
|
|
739
737
|
a,
|
|
740
738
|
e,
|
|
@@ -743,7 +741,7 @@ async function Ne(r, o = {}) {
|
|
|
743
741
|
}
|
|
744
742
|
if (n != null && n.aborted)
|
|
745
743
|
throw new DOMException("AbortError", "AbortError");
|
|
746
|
-
const u = X(r.name, s.extension), h =
|
|
744
|
+
const u = X(r.name, s.extension), h = Q(
|
|
747
745
|
p,
|
|
748
746
|
u,
|
|
749
747
|
s.mimeType
|
|
@@ -763,13 +761,13 @@ async function Ne(r, o = {}) {
|
|
|
763
761
|
export {
|
|
764
762
|
N as DEFAULT_ENCODER_OPTIONS,
|
|
765
763
|
ae as ENCODER_LIST,
|
|
766
|
-
|
|
767
|
-
|
|
764
|
+
j as ENCODER_REGISTRY,
|
|
765
|
+
Ae as FIT_METHODS,
|
|
768
766
|
Me as ImageCompressor,
|
|
769
|
-
|
|
767
|
+
Be as RESIZE_METHODS,
|
|
770
768
|
Fe as ROTATE_OPTIONS,
|
|
771
|
-
|
|
772
|
-
|
|
769
|
+
Q as arrayBufferToFile,
|
|
770
|
+
H as blobToImageData,
|
|
773
771
|
K as calculateSavings,
|
|
774
772
|
le as canDecodeImageType,
|
|
775
773
|
Ne as compressFile,
|
|
@@ -777,7 +775,7 @@ export {
|
|
|
777
775
|
$ as formatBytes,
|
|
778
776
|
X as generateCompressedFilename,
|
|
779
777
|
Le as getImageDimensions,
|
|
780
|
-
|
|
778
|
+
A as imageDataToBlob,
|
|
781
779
|
ce as revokeBlobUrl,
|
|
782
780
|
ie as sniffMimeType,
|
|
783
781
|
me as useCompression,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(u,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(u=typeof globalThis<"u"?globalThis:u||self,e(u.VueImageCompressor={},u.Vue))})(this,function(u,e){"use strict";var I=typeof document<"u"?document.currentScript:null;const B={mozJPEG:{label:"MozJPEG",mimeType:"image/jpeg",extension:"jpg"},webP:{label:"WebP",mimeType:"image/webp",extension:"webp"},avif:{label:"AVIF",mimeType:"image/avif",extension:"avif"},jxl:{label:"JPEG XL",mimeType:"image/jxl",extension:"jxl"},oxiPNG:{label:"OxiPNG",mimeType:"image/png",extension:"png"},browserJPEG:{label:"Browser JPEG",mimeType:"image/jpeg",extension:"jpg"},browserPNG:{label:"Browser PNG",mimeType:"image/png",extension:"png"},browserGIF:{label:"Browser GIF",mimeType:"image/gif",extension:"gif"},qoi:{label:"QOI",mimeType:"image/qoi",extension:"qoi"},wp2:{label:"WebP2",mimeType:"image/webp2",extension:"wp2"}},x={mozJPEG:{quality:75,baseline:!1,arithmetic:!1,progressive:!0,optimize_coding:!0,smoothing:0,color_space:3,quant_table:3,trellis_multipass:!1,trellis_opt_zero:!1,trellis_opt_table:!1,trellis_loops:1,auto_subsample:!0,chroma_subsample:2,separate_chroma_quality:!1,chroma_quality:75},webP:{quality:75,target_size:0,target_PSNR:0,method:4,sns_strength:50,filter_strength:60,filter_sharpness:0,filter_type:1,partitions:0,segments:4,pass:1,show_compressed:0,preprocessing:0,autofilter:0,partition_limit:0,alpha_compression:1,alpha_filtering:1,alpha_quality:100,lossless:0,exact:0,use_delta_palette:0,vlnr:0,near_lossless:60},avif:{cqLevel:33,denoiseLevel:0,cqAlphaLevel:-1,tileRows:0,tileCols:0,speed:6,subsample:1,chromaDeltaQ:!1,sharpness:0,tune:0},jxl:{effort:7,quality:75,progressive:!1,targetPsize:0},oxiPNG:{level:2},browserJPEG:{quality:.75},browserPNG:{},browserGIF:{},qoi:{},wp2:{quality:75}},A=Object.keys(B);async function q(r){const n=await createImageBitmap(r),a=document.createElement("canvas");a.width=n.width,a.height=n.height;const o=a.getContext("2d");return o.drawImage(n,0,0),o.getImageData(0,0,a.width,a.height)}async function N(r,n,a){const o=document.createElement("canvas");return o.width=r.width,o.height=r.height,o.getContext("2d").putImageData(r,0,0),new Promise(i=>{o.toBlob(s=>i(s),n,a)})}function Z(r){return new Promise((n,a)=>{const o=new Image;o.onload=()=>{n({width:o.width,height:o.height}),URL.revokeObjectURL(o.src)},o.onerror=a,o.src=URL.createObjectURL(r)})}async function W(r){const n=new Uint8Array(await r.slice(0,4).arrayBuffer());return n[0]===137&&n[1]===80?"image/png":n[0]===255&&n[1]===216?"image/jpeg":n[0]===71&&n[1]===73?"image/gif":n[0]===82&&n[1]===73?"image/webp":n[0]===0&&n[1]===0?"image/avif":r.type||"image/jpeg"}function J(r){return new Promise(n=>{const a=new Image;a.onload=()=>n(!0),a.onerror=()=>n(!1),a.src=`data:${r};base64,`})}function L(r,n,a){return new File([r],n,{type:a})}function M(r,n=2){if(r===0)return"0 Bytes";const a=1024,o=n<0?0:n,t=["Bytes","KB","MB","GB"],i=Math.floor(Math.log(r)/Math.log(a));return parseFloat((r/Math.pow(a,i)).toFixed(o))+" "+t[i]}function S(r,n){if(r===0)return 0;const a=Math.round((r-n)/r*100);return Math.max(0,a)}function G(r,n){return`${r.replace(/\.[^.]+$/,"")}_compressed.${n}`}function V(r){return URL.createObjectURL(r)}function $(r){URL.revokeObjectURL(r)}const X=1e4;function ee(r){let n=0;const a=new Map;r.addEventListener("message",t=>{const{id:i,result:s,error:p}=t.data,m=a.get(i);m&&(a.delete(i),p?m.reject(new Error(p)):m.resolve(s))}),r.addEventListener("error",t=>{console.error("Worker error:",{message:t.message,filename:t.filename,lineno:t.lineno,colno:t.colno,error:t.error}),a.forEach(i=>i.reject(t)),a.clear()});function o(t,...i){return new Promise((s,p)=>{const m=++n;a.set(m,{resolve:s,reject:p}),r.postMessage({id:m,method:t,args:i})})}return{avifDecode:t=>o("avifDecode",t),jxlDecode:t=>o("jxlDecode",t),qoiDecode:t=>o("qoiDecode",t),webpDecode:t=>o("webpDecode",t),wp2Decode:t=>o("wp2Decode",t),avifEncode:(t,i)=>o("avifEncode",t,i),jxlEncode:(t,i)=>o("jxlEncode",t,i),mozjpegEncode:(t,i)=>o("mozjpegEncode",t,i),oxipngEncode:(t,i)=>o("oxipngEncode",t,i),qoiEncode:(t,i)=>o("qoiEncode",t,i),webpEncode:(t,i)=>o("webpEncode",t,i),wp2Encode:(t,i)=>o("wp2Encode",t,i),rotate:(t,i)=>o("rotate",t,i),quantize:(t,i)=>o("quantize",t,i),resize:(t,i)=>o("resize",t,i)}}function H(){const r=e.ref(!1),n=e.ref(!1),a=e.ref(null);let o=null,t=null;function i(){if(!o)try{n.value=!0,o=new Worker(new URL("/assets/imageWorker-Qv3pCULy.js",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:I&&I.tagName.toUpperCase()==="SCRIPT"&&I.src||new URL("vue-image-compressor.umd.cjs",document.baseURI).href),{type:"module"}),r.value=!0,a.value=null}catch(h){a.value=h instanceof Error?h:new Error("Failed to start worker"),console.error("Worker start failed:",h)}finally{n.value=!1}}function s(){t&&(clearTimeout(t),t=null),o&&(o.terminate(),o=null,r.value=!1)}function p(){t&&clearTimeout(t),t=window.setTimeout(()=>{s()},X)}async function m(){if(o||i(),!o)throw new Error("Worker failed to initialize");return ee(o)}async function y(h,T){if(h.aborted)throw new DOMException("AbortError","AbortError");return clearTimeout(t),new Promise((C,O)=>{const D=()=>{s(),O(new DOMException("AbortError","AbortError"))};h.addEventListener("abort",D),T().then(C).catch(O).finally(()=>{h.removeEventListener("abort",D),p()})})}return e.onUnmounted(()=>{s()}),{isReady:r,isLoading:n,error:a,worker:o,getWorkerApi:m,executeTask:y,terminateWorker:s}}function Q(){const r=e.ref(!1),n=e.ref(0),a=e.ref(null),o=e.ref(null),t=e.ref(null),{getWorkerApi:i,executeTask:s}=H(),p=e.computed(()=>r.value&&!!t.value);async function m(E,l){const c=await W(l),f=await J(c),w=await i();if(!f){if(c==="image/avif")return s(E,()=>w.avifDecode(l));if(c==="image/webp")return s(E,()=>w.webpDecode(l));if(c==="image/jxl")return s(E,()=>w.jxlDecode(l));if(c==="image/webp2")return s(E,()=>w.wp2Decode(l));if(c==="image/qoi")return s(E,()=>w.qoiDecode(l))}return q(l)}async function y(E,l,c){if(c===0)return l;const f=await i();return s(E,()=>f.rotate(l,{rotate:c}))}async function h(E,l,c){var b,k;let f=l;const w=await i();return(b=c.resize)!=null&&b.enabled&&(f=await s(E,()=>w.resize(f,{width:c.resize.width||f.width,height:c.resize.height||f.height,method:c.resize.method||"lanczos3",fitMethod:c.resize.fitMethod||"stretch",premultiply:!0,linearRGB:!0}))),(k=c.quantize)!=null&&k.enabled&&(f=await s(E,()=>w.quantize(f,{numColors:c.quantize.numColors||256,dither:c.quantize.dither||1}))),f}async function T(E,l,c){const f=await i(),w=c.encoder;if(w==="browserJPEG")return(await N(l,"image/jpeg",c.encoderOptions.quality)).arrayBuffer();if(w==="browserPNG")return(await N(l,"image/png")).arrayBuffer();if(w==="browserGIF")throw new Error("Browser GIF encoding not supported directly");const k={mozJPEG:f.mozjpegEncode,webP:f.webpEncode,avif:f.avifEncode,jxl:f.jxlEncode,oxiPNG:f.oxipngEncode,qoi:f.qoiEncode,wp2:f.wp2Encode}[w];if(!k)throw new Error(`Unknown encoder: ${w}`);return(await s(E,()=>k.call(f,l,c.encoderOptions))).buffer}async function C(E,l){var w;t.value=new AbortController;const c=t.value.signal;r.value=!0,n.value=0,a.value=null;const f=o.value;o.value=null,(w=f==null?void 0:f.compressed)!=null&&w.blobUrl&&$(f.compressed.blobUrl);try{n.value=10;const b={file:E,size:E.size,width:0,height:0,blobUrl:V(E)},k=await m(c,E);b.width=k.width,b.height=k.height,n.value=25;const P=await y(c,k,l.rotate||0);n.value=35;const z=await h(c,P,l);n.value=50;const F=await T(c,z,l);n.value=80;const v=B[l.encoder],j=G(E.name,(v==null?void 0:v.extension)||"bin"),R=L(F,j,(v==null?void 0:v.mimeType)||"application/octet-stream"),U={file:R,size:R.size,width:z.width,height:z.height,blobUrl:V(R)},g={original:b,compressed:U,savingsBytes:b.size-U.size,savingsPercent:S(b.size,U.size),encoderType:l.encoder,encoderOptions:l.encoderOptions};return o.value=g,n.value=100,g}catch(b){if(b instanceof DOMException&&b.name==="AbortError")throw a.value="已取消",b;const k=b instanceof Error?b.message:"压缩失败";throw a.value=k,console.error("Compression error:",b),b}finally{r.value=!1,t.value=null}}function O(){t.value&&t.value.abort()}function D(){if(!o.value)return;const{compressed:E}=o.value,l=document.createElement("a");l.href=E.blobUrl,l.download=E.file.name,document.body.appendChild(l),l.click(),document.body.removeChild(l)}return{compress:C,cancel:O,downloadResult:D,isCompressing:r,progress:n,error:a,result:o,canCancel:p}}function K(){const r=e.ref("mozJPEG"),n=e.ref({}),a=e.computed(()=>B[r.value]),o=e.computed(()=>x[r.value]),t=e.computed(()=>A.map(m=>({type:m,label:B[m].label,mimeType:B[m].mimeType,extension:B[m].extension})));function i(m){r.value=m,n.value={...x[m]}}function s(m,y){n.value={...n.value,[m]:y}}function p(){n.value={...o.value}}return p(),{selectedEncoder:r,encoderOptions:n,currentMeta:a,currentDefaults:o,availableEncoders:t,selectEncoder:i,updateOption:s,resetOptions:p}}const te={class:"image-compressor"},oe={key:0,class:"preview-area"},ne={class:"preview-item"},re=["src"],ae={class:"preview-item"},ie=["src"],se={key:1,class:"compressing"},le=["value"],ce={key:2},de={key:1,class:"encoder-settings"},me=["value"],ue={key:0,class:"quality-control"},fe=["value"],pe={key:2,class:"actions"},ge=["disabled"],Ee={key:3,class:"error"},we=((r,n)=>{const a=r.__vccOpts||r;for(const[o,t]of n)a[o]=t;return a})(e.defineComponent({__name:"ImageCompressor",props:{defaultEncoder:{},defaultOptions:{}},emits:["success","error","cancel"],setup(r,{emit:n}){const a=r,o=n,t=e.ref(null),i=e.ref(null),s=e.ref(""),p=e.ref(""),{compress:m,cancel:y,downloadResult:h,isCompressing:T,progress:C,error:O,result:D,canCancel:E}=Q(),{selectedEncoder:l,encoderOptions:c,availableEncoders:f,selectEncoder:w,updateOption:b}=K();a.defaultEncoder&&w(a.defaultEncoder),a.defaultOptions&&Object.entries(a.defaultOptions).forEach(([g,d])=>b(g,d));const k=e.computed(()=>i.value?M(i.value.size):""),P=e.computed(()=>D.value?M(D.value.compressed.size):""),z=e.computed(()=>["mozJPEG","webP","jxl","browserJPEG","wp2"].includes(l.value));function F(g){const d=g.target;d.files&&d.files[0]&&j(d.files[0])}function v(g){var d;(d=g.dataTransfer)!=null&&d.files[0]&&j(g.dataTransfer.files[0])}function j(g){g.type.startsWith("image/")&&(s.value&&URL.revokeObjectURL(s.value),p.value&&(URL.revokeObjectURL(p.value),p.value=""),i.value=g,s.value=URL.createObjectURL(g))}function R(){w(l.value)}async function U(){if(i.value)try{const g={encoder:l.value,encoderOptions:{...c.value}},d=await m(i.value,g);p.value=d.compressed.blobUrl,o("success",d)}catch(g){if(g instanceof DOMException&&g.name==="AbortError"){o("cancel");return}o("error",g instanceof Error?g:new Error(String(g)))}}return(g,d)=>(e.openBlock(),e.createElementBlock("div",te,[e.createElementVNode("div",{class:"upload-zone",onDrop:e.withModifiers(v,["prevent"]),onDragover:d[1]||(d[1]=e.withModifiers(()=>{},["prevent"]))},[e.createElementVNode("input",{type:"file",accept:"image/*",onChange:F,ref_key:"fileInput",ref:t,class:"file-input"},null,544),e.createElementVNode("div",{class:"upload-prompt",onClick:d[0]||(d[0]=_=>{var Y;return(Y=t.value)==null?void 0:Y.click()})},[e.renderSlot(g.$slots,"upload-prompt",{},()=>[d[6]||(d[6]=e.createElementVNode("p",null,"拖拽图片到此处,或点击上传",-1))],!0)])],32),s.value?(e.openBlock(),e.createElementBlock("div",oe,[e.createElementVNode("div",ne,[d[7]||(d[7]=e.createElementVNode("h4",null,"原始图片",-1)),e.createElementVNode("img",{src:s.value,alt:"Original"},null,8,re),e.createElementVNode("p",null,e.toDisplayString(k.value),1)]),e.createElementVNode("div",ae,[d[8]||(d[8]=e.createElementVNode("h4",null,"压缩后",-1)),p.value?(e.openBlock(),e.createElementBlock("img",{key:0,src:p.value,alt:"Compressed"},null,8,ie)):e.unref(T)?(e.openBlock(),e.createElementBlock("div",se,[e.createElementVNode("progress",{value:e.unref(C),max:"100"},null,8,le),e.createElementVNode("p",null,"压缩中... "+e.toDisplayString(e.unref(C))+"%",1)])):e.createCommentVNode("",!0),P.value?(e.openBlock(),e.createElementBlock("p",ce,e.toDisplayString(P.value),1)):e.createCommentVNode("",!0)])])):e.createCommentVNode("",!0),s.value?(e.openBlock(),e.createElementBlock("div",de,[d[9]||(d[9]=e.createElementVNode("label",null,"编码器:",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":d[2]||(d[2]=_=>e.isRef(l)?l.value=_:null),onChange:R},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(f),_=>(e.openBlock(),e.createElementBlock("option",{key:_.type,value:_.type},e.toDisplayString(_.label)+" ("+e.toDisplayString(_.extension)+") ",9,me))),128))],544),[[e.vModelSelect,e.unref(l)]]),z.value?(e.openBlock(),e.createElementBlock("div",ue,[e.createElementVNode("label",null,[e.createTextVNode(" 质量: "+e.toDisplayString(e.unref(c).quality??75)+" ",1),e.createElementVNode("input",{type:"range",min:"0",max:"100",value:e.unref(c).quality??75,onInput:d[3]||(d[3]=_=>e.unref(b)("quality",Number(_.target.value)))},null,40,fe)])])):e.createCommentVNode("",!0),e.renderSlot(g.$slots,"encoder-settings",{encoder:e.unref(l),options:e.unref(c)},void 0,!0)])):e.createCommentVNode("",!0),s.value?(e.openBlock(),e.createElementBlock("div",pe,[e.createElementVNode("button",{onClick:U,disabled:e.unref(T),class:"btn-primary"},e.toDisplayString(e.unref(T)?"压缩中...":"开始压缩"),9,ge),e.unref(E)?(e.openBlock(),e.createElementBlock("button",{key:0,onClick:d[4]||(d[4]=(..._)=>e.unref(y)&&e.unref(y)(..._)),class:"btn-secondary"}," 取消 ")):e.createCommentVNode("",!0),e.unref(D)?(e.openBlock(),e.createElementBlock("button",{key:1,onClick:d[5]||(d[5]=(..._)=>e.unref(h)&&e.unref(h)(..._)),class:"btn-success"}," 下载 (节省 "+e.toDisplayString(e.unref(D).savingsPercent)+"%) ",1)):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0),e.unref(O)?(e.openBlock(),e.createElementBlock("div",Ee,e.toDisplayString(e.unref(O)),1)):e.createCommentVNode("",!0)]))}}),[["__scopeId","data-v-d7e6eec9"]]),be=[{value:"lanczos3",label:"Lanczos3"},{value:"catrom",label:"Catrom"},{value:"mitchell",label:"Mitchell"},{value:"triangle",label:"Triangle"},{value:"vector",label:"Vector"}],he=[{value:"stretch",label:"拉伸"},{value:"contain",label:"适应"}],ye=[{value:0,label:"不旋转"},{value:90,label:"顺时针 90°"},{value:180,label:"旋转 180°"},{value:270,label:"逆时针 90°"}],ke={mozJPEG:"mozjpegEncode",webP:"webpEncode",avif:"avifEncode",jxl:"jxlEncode",oxiPNG:"oxipngEncode",qoi:"qoiEncode",wp2:"wp2Encode"};function _e(){return new Worker(new URL("/assets/imageWorker-Qv3pCULy.js",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:I&&I.tagName.toUpperCase()==="SCRIPT"&&I.src||new URL("vue-image-compressor.umd.cjs",document.baseURI).href),{type:"module"})}function Te(r,n,a,o){return new Promise((t,i)=>{const s=_e();let p=!1;function m(){p||(p=!0,s.terminate())}s.addEventListener("message",T=>{const{result:C,error:O}=T.data;m(),O?i(new Error(O)):t(C.buffer)}),s.addEventListener("error",T=>{m(),i(T.error||T)});const y=()=>{m(),i(new DOMException("AbortError","AbortError"))};o&&o.addEventListener("abort",y,{once:!0});const h=ke[r];if(!h){m(),i(new Error(`Unknown encoder: ${r}`));return}s.postMessage({id:1,method:h,args:[n,a]})})}async function Oe(r,n={}){const{signal:a}=n;if(a!=null&&a.aborted)throw new DOMException("AbortError","AbortError");const o=n.encoder||"mozJPEG",t={...x[o],...n.encoderOptions},i=B[o],s=await q(r);if(a!=null&&a.aborted)throw new DOMException("AbortError","AbortError");let p;if(o==="browserJPEG")p=await(await N(s,"image/jpeg",t.quality)).arrayBuffer();else if(o==="browserPNG")p=await(await N(s,"image/png")).arrayBuffer();else{if(o==="browserGIF")throw new Error("Browser GIF encoding not supported directly");p=await Te(o,s,t,a)}if(a!=null&&a.aborted)throw new DOMException("AbortError","AbortError");const m=G(r.name,i.extension),y=L(p,m,i.mimeType);return{file:y,originalSize:r.size,compressedSize:y.size,savingsBytes:r.size-y.size,savingsPercent:S(r.size,y.size),width:s.width,height:s.height,encoderType:o,encoderOptions:t}}u.DEFAULT_ENCODER_OPTIONS=x,u.ENCODER_LIST=A,u.ENCODER_REGISTRY=B,u.FIT_METHODS=he,u.ImageCompressor=we,u.RESIZE_METHODS=be,u.ROTATE_OPTIONS=ye,u.arrayBufferToFile=L,u.blobToImageData=q,u.calculateSavings=S,u.canDecodeImageType=J,u.compressFile=Oe,u.createBlobUrl=V,u.formatBytes=M,u.generateCompressedFilename=G,u.getImageDimensions=Z,u.imageDataToBlob=N,u.revokeBlobUrl=$,u.sniffMimeType=W,u.useCompression=Q,u.useEncoderRegistry=K,u.useWorker=H,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(u,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(u=typeof globalThis<"u"?globalThis:u||self,e(u.VueImageCompressor={},u.Vue))})(this,function(u,e){"use strict";var N=typeof document<"u"?document.currentScript:null;const O={mozJPEG:{label:"MozJPEG",mimeType:"image/jpeg",extension:"jpg"},webP:{label:"WebP",mimeType:"image/webp",extension:"webp"},avif:{label:"AVIF",mimeType:"image/avif",extension:"avif"},jxl:{label:"JPEG XL",mimeType:"image/jxl",extension:"jxl"},oxiPNG:{label:"OxiPNG",mimeType:"image/png",extension:"png"},browserJPEG:{label:"Browser JPEG",mimeType:"image/jpeg",extension:"jpg"},browserPNG:{label:"Browser PNG",mimeType:"image/png",extension:"png"},browserGIF:{label:"Browser GIF",mimeType:"image/gif",extension:"gif"},qoi:{label:"QOI",mimeType:"image/qoi",extension:"qoi"},wp2:{label:"WebP2",mimeType:"image/webp2",extension:"wp2"}},S={mozJPEG:{quality:75,baseline:!1,arithmetic:!1,progressive:!0,optimize_coding:!0,smoothing:0,color_space:3,quant_table:3,trellis_multipass:!1,trellis_opt_zero:!1,trellis_opt_table:!1,trellis_loops:1,auto_subsample:!0,chroma_subsample:2,separate_chroma_quality:!1,chroma_quality:75},webP:{quality:75,target_size:0,target_PSNR:0,method:4,sns_strength:50,filter_strength:60,filter_sharpness:0,filter_type:1,partitions:0,segments:4,pass:1,show_compressed:0,preprocessing:0,autofilter:0,partition_limit:0,alpha_compression:1,alpha_filtering:1,alpha_quality:100,lossless:0,exact:0,use_delta_palette:0,vlnr:0,near_lossless:60},avif:{cqLevel:33,denoiseLevel:0,cqAlphaLevel:-1,tileRows:0,tileCols:0,speed:6,subsample:1,chromaDeltaQ:!1,sharpness:0,tune:0},jxl:{effort:7,quality:75,progressive:!1,targetPsize:0},oxiPNG:{level:2},browserJPEG:{quality:.75},browserPNG:{},browserGIF:{},qoi:{},wp2:{quality:75}},A=Object.keys(O);async function j(r){const n=await createImageBitmap(r),a=document.createElement("canvas");a.width=n.width,a.height=n.height;const o=a.getContext("2d");return o.drawImage(n,0,0),o.getImageData(0,0,a.width,a.height)}async function z(r,n,a){const o=document.createElement("canvas");return o.width=r.width,o.height=r.height,o.getContext("2d").putImageData(r,0,0),new Promise(i=>{o.toBlob(s=>i(s),n,a)})}function Z(r){return new Promise((n,a)=>{const o=new Image;o.onload=()=>{n({width:o.width,height:o.height}),URL.revokeObjectURL(o.src)},o.onerror=a,o.src=URL.createObjectURL(r)})}async function W(r){const n=new Uint8Array(await r.slice(0,4).arrayBuffer());return n[0]===137&&n[1]===80?"image/png":n[0]===255&&n[1]===216?"image/jpeg":n[0]===71&&n[1]===73?"image/gif":n[0]===82&&n[1]===73?"image/webp":n[0]===0&&n[1]===0?"image/avif":r.type||"image/jpeg"}function J(r){return new Promise(n=>{const a=new Image;a.onload=()=>n(!0),a.onerror=()=>n(!1),a.src=`data:${r};base64,`})}function q(r,n,a){return new File([r],n,{type:a})}function L(r,n=2){if(r===0)return"0 Bytes";const a=1024,o=n<0?0:n,t=["Bytes","KB","MB","GB"],i=Math.floor(Math.log(r)/Math.log(a));return parseFloat((r/Math.pow(a,i)).toFixed(o))+" "+t[i]}function M(r,n){if(r===0)return 0;const a=Math.round((r-n)/r*100);return Math.max(0,a)}function G(r,n){return`${r.replace(/\.[^.]+$/,"")}_compressed.${n}`}function F(r){return URL.createObjectURL(r)}function H(r){URL.revokeObjectURL(r)}const X=1e4;function ee(r){let n=0;const a=new Map;r.addEventListener("message",t=>{const{id:i,result:s,error:p}=t.data,m=a.get(i);m&&(a.delete(i),p?m.reject(new Error(p)):m.resolve(s))}),r.addEventListener("error",t=>{console.error("Worker error:",{message:t.message,filename:t.filename,lineno:t.lineno,colno:t.colno,error:t.error}),a.forEach(i=>i.reject(t)),a.clear()});function o(t,...i){return new Promise((s,p)=>{const m=++n;a.set(m,{resolve:s,reject:p}),r.postMessage({id:m,method:t,args:i})})}return{avifDecode:t=>o("avifDecode",t),jxlDecode:t=>o("jxlDecode",t),qoiDecode:t=>o("qoiDecode",t),webpDecode:t=>o("webpDecode",t),wp2Decode:t=>o("wp2Decode",t),avifEncode:(t,i)=>o("avifEncode",t,i),jxlEncode:(t,i)=>o("jxlEncode",t,i),mozjpegEncode:(t,i)=>o("mozjpegEncode",t,i),oxipngEncode:(t,i)=>o("oxipngEncode",t,i),qoiEncode:(t,i)=>o("qoiEncode",t,i),webpEncode:(t,i)=>o("webpEncode",t,i),wp2Encode:(t,i)=>o("wp2Encode",t,i),rotate:(t,i)=>o("rotate",t,i),quantize:(t,i)=>o("quantize",t,i),resize:(t,i)=>o("resize",t,i)}}function $(){const r=e.ref(!1),n=e.ref(!1),a=e.ref(null);let o=null,t=null;function i(){if(!o)try{n.value=!0,o=new Worker(new URL(""+(typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__dirname+"/assets/imageWorker-B_HCdCy9.js").href:new URL("assets/imageWorker-B_HCdCy9.js",typeof document>"u"?location.href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"&&document.currentScript.src||document.baseURI).href),typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:N&&N.tagName.toUpperCase()==="SCRIPT"&&N.src||new URL("vue-image-compressor.umd.cjs",document.baseURI).href)),r.value=!0,a.value=null}catch(h){a.value=h instanceof Error?h:new Error("Failed to start worker"),console.error("Worker start failed:",h)}finally{n.value=!1}}function s(){t&&(clearTimeout(t),t=null),o&&(o.terminate(),o=null,r.value=!1)}function p(){t&&clearTimeout(t),t=window.setTimeout(()=>{s()},X)}async function m(){if(o||i(),!o)throw new Error("Worker failed to initialize");return ee(o)}async function y(h,T){if(h.aborted)throw new DOMException("AbortError","AbortError");return clearTimeout(t),new Promise((D,C)=>{const B=()=>{s(),C(new DOMException("AbortError","AbortError"))};h.addEventListener("abort",B),T().then(D).catch(C).finally(()=>{h.removeEventListener("abort",B),p()})})}return e.onUnmounted(()=>{s()}),{isReady:r,isLoading:n,error:a,worker:o,getWorkerApi:m,executeTask:y,terminateWorker:s}}function Q(){const r=e.ref(!1),n=e.ref(0),a=e.ref(null),o=e.ref(null),t=e.ref(null),{getWorkerApi:i,executeTask:s}=$(),p=e.computed(()=>r.value&&!!t.value);async function m(E,l){const c=await W(l),f=await J(c),w=await i();if(!f){if(c==="image/avif")return s(E,()=>w.avifDecode(l));if(c==="image/webp")return s(E,()=>w.webpDecode(l));if(c==="image/jxl")return s(E,()=>w.jxlDecode(l));if(c==="image/webp2")return s(E,()=>w.wp2Decode(l));if(c==="image/qoi")return s(E,()=>w.qoiDecode(l))}return j(l)}async function y(E,l,c){if(c===0)return l;const f=await i();return s(E,()=>f.rotate(l,{rotate:c}))}async function h(E,l,c){var b,_;let f=l;const w=await i();return(b=c.resize)!=null&&b.enabled&&(f=await s(E,()=>w.resize(f,{width:c.resize.width||f.width,height:c.resize.height||f.height,method:c.resize.method||"lanczos3",fitMethod:c.resize.fitMethod||"stretch",premultiply:!0,linearRGB:!0}))),(_=c.quantize)!=null&&_.enabled&&(f=await s(E,()=>w.quantize(f,{numColors:c.quantize.numColors||256,dither:c.quantize.dither||1}))),f}async function T(E,l,c){const f=await i(),w=c.encoder;if(w==="browserJPEG")return(await z(l,"image/jpeg",c.encoderOptions.quality)).arrayBuffer();if(w==="browserPNG")return(await z(l,"image/png")).arrayBuffer();if(w==="browserGIF")throw new Error("Browser GIF encoding not supported directly");const _={mozJPEG:f.mozjpegEncode,webP:f.webpEncode,avif:f.avifEncode,jxl:f.jxlEncode,oxiPNG:f.oxipngEncode,qoi:f.qoiEncode,wp2:f.wp2Encode}[w];if(!_)throw new Error(`Unknown encoder: ${w}`);return(await s(E,()=>_.call(f,l,c.encoderOptions))).buffer}async function D(E,l){var w;t.value=new AbortController;const c=t.value.signal;r.value=!0,n.value=0,a.value=null;const f=o.value;o.value=null,(w=f==null?void 0:f.compressed)!=null&&w.blobUrl&&H(f.compressed.blobUrl);try{n.value=10;const b={file:E,size:E.size,width:0,height:0,blobUrl:F(E)},_=await m(c,E);b.width=_.width,b.height=_.height,n.value=25;const P=await y(c,_,l.rotate||0);n.value=35;const I=await h(c,P,l);n.value=50;const V=await T(c,I,l);n.value=80;const R=O[l.encoder],x=G(E.name,(R==null?void 0:R.extension)||"bin"),v=q(V,x,(R==null?void 0:R.mimeType)||"application/octet-stream"),U={file:v,size:v.size,width:I.width,height:I.height,blobUrl:F(v)},g={original:b,compressed:U,savingsBytes:b.size-U.size,savingsPercent:M(b.size,U.size),encoderType:l.encoder,encoderOptions:l.encoderOptions};return o.value=g,n.value=100,g}catch(b){if(b instanceof DOMException&&b.name==="AbortError")throw a.value="已取消",b;const _=b instanceof Error?b.message:"压缩失败";throw a.value=_,console.error("Compression error:",b),b}finally{r.value=!1,t.value=null}}function C(){t.value&&t.value.abort()}function B(){if(!o.value)return;const{compressed:E}=o.value,l=document.createElement("a");l.href=E.blobUrl,l.download=E.file.name,document.body.appendChild(l),l.click(),document.body.removeChild(l)}return{compress:D,cancel:C,downloadResult:B,isCompressing:r,progress:n,error:a,result:o,canCancel:p}}function K(){const r=e.ref("mozJPEG"),n=e.ref({}),a=e.computed(()=>O[r.value]),o=e.computed(()=>S[r.value]),t=e.computed(()=>A.map(m=>({type:m,label:O[m].label,mimeType:O[m].mimeType,extension:O[m].extension})));function i(m){r.value=m,n.value={...S[m]}}function s(m,y){n.value={...n.value,[m]:y}}function p(){n.value={...o.value}}return p(),{selectedEncoder:r,encoderOptions:n,currentMeta:a,currentDefaults:o,availableEncoders:t,selectEncoder:i,updateOption:s,resetOptions:p}}const te={class:"image-compressor"},oe={key:0,class:"preview-area"},ne={class:"preview-item"},re=["src"],ae={class:"preview-item"},ie=["src"],se={key:1,class:"compressing"},le=["value"],ce={key:2},de={key:1,class:"encoder-settings"},me=["value"],ue={key:0,class:"quality-control"},fe=["value"],pe={key:2,class:"actions"},ge=["disabled"],Ee={key:3,class:"error"},we=((r,n)=>{const a=r.__vccOpts||r;for(const[o,t]of n)a[o]=t;return a})(e.defineComponent({__name:"ImageCompressor",props:{defaultEncoder:{},defaultOptions:{}},emits:["success","error","cancel"],setup(r,{emit:n}){const a=r,o=n,t=e.ref(null),i=e.ref(null),s=e.ref(""),p=e.ref(""),{compress:m,cancel:y,downloadResult:h,isCompressing:T,progress:D,error:C,result:B,canCancel:E}=Q(),{selectedEncoder:l,encoderOptions:c,availableEncoders:f,selectEncoder:w,updateOption:b}=K();a.defaultEncoder&&w(a.defaultEncoder),a.defaultOptions&&Object.entries(a.defaultOptions).forEach(([g,d])=>b(g,d));const _=e.computed(()=>i.value?L(i.value.size):""),P=e.computed(()=>B.value?L(B.value.compressed.size):""),I=e.computed(()=>["mozJPEG","webP","jxl","browserJPEG","wp2"].includes(l.value));function V(g){const d=g.target;d.files&&d.files[0]&&x(d.files[0])}function R(g){var d;(d=g.dataTransfer)!=null&&d.files[0]&&x(g.dataTransfer.files[0])}function x(g){g.type.startsWith("image/")&&(s.value&&URL.revokeObjectURL(s.value),p.value&&(URL.revokeObjectURL(p.value),p.value=""),i.value=g,s.value=URL.createObjectURL(g))}function v(){w(l.value)}async function U(){if(i.value)try{const g={encoder:l.value,encoderOptions:{...c.value}},d=await m(i.value,g);p.value=d.compressed.blobUrl,o("success",d)}catch(g){if(g instanceof DOMException&&g.name==="AbortError"){o("cancel");return}o("error",g instanceof Error?g:new Error(String(g)))}}return(g,d)=>(e.openBlock(),e.createElementBlock("div",te,[e.createElementVNode("div",{class:"upload-zone",onDrop:e.withModifiers(R,["prevent"]),onDragover:d[1]||(d[1]=e.withModifiers(()=>{},["prevent"]))},[e.createElementVNode("input",{type:"file",accept:"image/*",onChange:V,ref_key:"fileInput",ref:t,class:"file-input"},null,544),e.createElementVNode("div",{class:"upload-prompt",onClick:d[0]||(d[0]=k=>{var Y;return(Y=t.value)==null?void 0:Y.click()})},[e.renderSlot(g.$slots,"upload-prompt",{},()=>[d[6]||(d[6]=e.createElementVNode("p",null,"拖拽图片到此处,或点击上传",-1))],!0)])],32),s.value?(e.openBlock(),e.createElementBlock("div",oe,[e.createElementVNode("div",ne,[d[7]||(d[7]=e.createElementVNode("h4",null,"原始图片",-1)),e.createElementVNode("img",{src:s.value,alt:"Original"},null,8,re),e.createElementVNode("p",null,e.toDisplayString(_.value),1)]),e.createElementVNode("div",ae,[d[8]||(d[8]=e.createElementVNode("h4",null,"压缩后",-1)),p.value?(e.openBlock(),e.createElementBlock("img",{key:0,src:p.value,alt:"Compressed"},null,8,ie)):e.unref(T)?(e.openBlock(),e.createElementBlock("div",se,[e.createElementVNode("progress",{value:e.unref(D),max:"100"},null,8,le),e.createElementVNode("p",null,"压缩中... "+e.toDisplayString(e.unref(D))+"%",1)])):e.createCommentVNode("",!0),P.value?(e.openBlock(),e.createElementBlock("p",ce,e.toDisplayString(P.value),1)):e.createCommentVNode("",!0)])])):e.createCommentVNode("",!0),s.value?(e.openBlock(),e.createElementBlock("div",de,[d[9]||(d[9]=e.createElementVNode("label",null,"编码器:",-1)),e.withDirectives(e.createElementVNode("select",{"onUpdate:modelValue":d[2]||(d[2]=k=>e.isRef(l)?l.value=k:null),onChange:v},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(f),k=>(e.openBlock(),e.createElementBlock("option",{key:k.type,value:k.type},e.toDisplayString(k.label)+" ("+e.toDisplayString(k.extension)+") ",9,me))),128))],544),[[e.vModelSelect,e.unref(l)]]),I.value?(e.openBlock(),e.createElementBlock("div",ue,[e.createElementVNode("label",null,[e.createTextVNode(" 质量: "+e.toDisplayString(e.unref(c).quality??75)+" ",1),e.createElementVNode("input",{type:"range",min:"0",max:"100",value:e.unref(c).quality??75,onInput:d[3]||(d[3]=k=>e.unref(b)("quality",Number(k.target.value)))},null,40,fe)])])):e.createCommentVNode("",!0),e.renderSlot(g.$slots,"encoder-settings",{encoder:e.unref(l),options:e.unref(c)},void 0,!0)])):e.createCommentVNode("",!0),s.value?(e.openBlock(),e.createElementBlock("div",pe,[e.createElementVNode("button",{onClick:U,disabled:e.unref(T),class:"btn-primary"},e.toDisplayString(e.unref(T)?"压缩中...":"开始压缩"),9,ge),e.unref(E)?(e.openBlock(),e.createElementBlock("button",{key:0,onClick:d[4]||(d[4]=(...k)=>e.unref(y)&&e.unref(y)(...k)),class:"btn-secondary"}," 取消 ")):e.createCommentVNode("",!0),e.unref(B)?(e.openBlock(),e.createElementBlock("button",{key:1,onClick:d[5]||(d[5]=(...k)=>e.unref(h)&&e.unref(h)(...k)),class:"btn-success"}," 下载 (节省 "+e.toDisplayString(e.unref(B).savingsPercent)+"%) ",1)):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0),e.unref(C)?(e.openBlock(),e.createElementBlock("div",Ee,e.toDisplayString(e.unref(C)),1)):e.createCommentVNode("",!0)]))}}),[["__scopeId","data-v-d7e6eec9"]]),be=[{value:"lanczos3",label:"Lanczos3"},{value:"catrom",label:"Catrom"},{value:"mitchell",label:"Mitchell"},{value:"triangle",label:"Triangle"},{value:"vector",label:"Vector"}],he=[{value:"stretch",label:"拉伸"},{value:"contain",label:"适应"}],ye=[{value:0,label:"不旋转"},{value:90,label:"顺时针 90°"},{value:180,label:"旋转 180°"},{value:270,label:"逆时针 90°"}],_e={mozJPEG:"mozjpegEncode",webP:"webpEncode",avif:"avifEncode",jxl:"jxlEncode",oxiPNG:"oxipngEncode",qoi:"qoiEncode",wp2:"wp2Encode"};function ke(){return new Worker(new URL(""+(typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__dirname+"/assets/imageWorker-B_HCdCy9.js").href:new URL("assets/imageWorker-B_HCdCy9.js",typeof document>"u"?location.href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"&&document.currentScript.src||document.baseURI).href),typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:N&&N.tagName.toUpperCase()==="SCRIPT"&&N.src||new URL("vue-image-compressor.umd.cjs",document.baseURI).href))}function Te(r,n,a,o){return new Promise((t,i)=>{const s=ke();let p=!1;function m(){p||(p=!0,s.terminate())}s.addEventListener("message",T=>{const{result:D,error:C}=T.data;m(),C?i(new Error(C)):t(D.buffer)}),s.addEventListener("error",T=>{m(),i(T.error||T)});const y=()=>{m(),i(new DOMException("AbortError","AbortError"))};o&&o.addEventListener("abort",y,{once:!0});const h=_e[r];if(!h){m(),i(new Error(`Unknown encoder: ${r}`));return}s.postMessage({id:1,method:h,args:[n,a]})})}async function Ce(r,n={}){const{signal:a}=n;if(a!=null&&a.aborted)throw new DOMException("AbortError","AbortError");const o=n.encoder||"mozJPEG",t={...S[o],...n.encoderOptions},i=O[o],s=await j(r);if(a!=null&&a.aborted)throw new DOMException("AbortError","AbortError");let p;if(o==="browserJPEG")p=await(await z(s,"image/jpeg",t.quality)).arrayBuffer();else if(o==="browserPNG")p=await(await z(s,"image/png")).arrayBuffer();else{if(o==="browserGIF")throw new Error("Browser GIF encoding not supported directly");p=await Te(o,s,t,a)}if(a!=null&&a.aborted)throw new DOMException("AbortError","AbortError");const m=G(r.name,i.extension),y=q(p,m,i.mimeType);return{file:y,originalSize:r.size,compressedSize:y.size,savingsBytes:r.size-y.size,savingsPercent:M(r.size,y.size),width:s.width,height:s.height,encoderType:o,encoderOptions:t}}u.DEFAULT_ENCODER_OPTIONS=S,u.ENCODER_LIST=A,u.ENCODER_REGISTRY=O,u.FIT_METHODS=he,u.ImageCompressor=we,u.RESIZE_METHODS=be,u.ROTATE_OPTIONS=ye,u.arrayBufferToFile=q,u.blobToImageData=j,u.calculateSavings=M,u.canDecodeImageType=J,u.compressFile=Ce,u.createBlobUrl=F,u.formatBytes=L,u.generateCompressedFilename=G,u.getImageDimensions=Z,u.imageDataToBlob=z,u.revokeBlobUrl=H,u.sniffMimeType=W,u.useCompression=Q,u.useEncoderRegistry=K,u.useWorker=$,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -87,8 +87,7 @@ export function useWorker() {
|
|
|
87
87
|
try {
|
|
88
88
|
isLoading.value = true;
|
|
89
89
|
worker = new Worker(
|
|
90
|
-
new URL('../workers/imageWorker.ts', import.meta.url)
|
|
91
|
-
{ type: 'module' }
|
|
90
|
+
new URL('../workers/imageWorker.ts', import.meta.url)
|
|
92
91
|
);
|
|
93
92
|
isReady.value = true;
|
|
94
93
|
error.value = null;
|
|
@@ -51,8 +51,7 @@ const ENCODER_METHOD_MAP: Record<string, string> = {
|
|
|
51
51
|
|
|
52
52
|
function createWorker(): Worker {
|
|
53
53
|
return new Worker(
|
|
54
|
-
new URL('../workers/imageWorker.ts', import.meta.url)
|
|
55
|
-
{ type: 'module' }
|
|
54
|
+
new URL('../workers/imageWorker.ts', import.meta.url)
|
|
56
55
|
);
|
|
57
56
|
}
|
|
58
57
|
|
|
@@ -82,7 +82,7 @@ const workerApi: WorkerApi = {
|
|
|
82
82
|
return initEmscriptenModule(mozjpeg_enc, {
|
|
83
83
|
locateFile: (path: string) => {
|
|
84
84
|
if (path === 'mozjpeg_enc.wasm') {
|
|
85
|
-
return '
|
|
85
|
+
return '../codecs/mozjpeg/enc/mozjpeg_enc.wasm';
|
|
86
86
|
}
|
|
87
87
|
return path;
|
|
88
88
|
},
|