@d5techs/3dgs-lib 1.4.22 → 1.4.23

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/3dgs-lib.js CHANGED
@@ -6301,91 +6301,231 @@ function findNearest(sortedCB, value) {
6301
6301
  }
6302
6302
  return lo;
6303
6303
  }
6304
- function kmeansVectors(vectors, dim, k, iterations) {
6305
- const n = vectors.length;
6306
- const labels = new Uint16Array(n);
6307
- if (n <= k) {
6308
- const centroids2 = [];
6309
- for (let i = 0; i < n; i++) {
6310
- centroids2.push(new Float32Array(vectors[i]));
6311
- labels[i] = i;
6304
+ function getGpuClusterShader(dim) {
6305
+ return (
6306
+ /* wgsl */
6307
+ `
6308
+ struct Uniforms {
6309
+ numPoints: u32,
6310
+ numCentroids: u32
6311
+ };
6312
+
6313
+ @group(0) @binding(0) var<uniform> uniforms: Uniforms;
6314
+ @group(0) @binding(1) var<storage, read> points: array<f32>;
6315
+ @group(0) @binding(2) var<storage, read> centroids: array<f32>;
6316
+ @group(0) @binding(3) var<storage, read_write> results: array<u32>;
6317
+
6318
+ const DIM = ${dim}u;
6319
+ const CHUNK_SIZE = 128u;
6320
+ var<workgroup> sharedChunk: array<f32, ${dim * 128}>;
6321
+
6322
+ fn calcDistSqr(point: array<f32, ${dim}>, cIdx: u32) -> f32 {
6323
+ var result = 0.0;
6324
+ var ci = cIdx * DIM;
6325
+ for (var i = 0u; i < DIM; i++) {
6326
+ let v = point[i] - sharedChunk[ci + i];
6327
+ result += v * v;
6328
+ }
6329
+ return result;
6330
+ }
6331
+
6332
+ @compute @workgroup_size(64)
6333
+ fn main(
6334
+ @builtin(local_invocation_index) localId: u32,
6335
+ @builtin(global_invocation_id) globalId: vec3u,
6336
+ @builtin(num_workgroups) numWgs: vec3u
6337
+ ) {
6338
+ let pointIdx = globalId.x + globalId.y * numWgs.x * 64u;
6339
+
6340
+ var point: array<f32, ${dim}>;
6341
+ if (pointIdx < uniforms.numPoints) {
6342
+ for (var i = 0u; i < DIM; i++) {
6343
+ point[i] = points[pointIdx * DIM + i];
6312
6344
  }
6313
- while (centroids2.length < k) centroids2.push(new Float32Array(dim));
6314
- return { centroids: centroids2, labels };
6315
6345
  }
6316
- const centroids = [];
6317
- centroids.push(new Float32Array(vectors[Math.floor(Math.random() * n)]));
6318
- const dist = new Float64Array(n);
6319
- dist.fill(Infinity);
6320
- for (let c = 1; c < k; c++) {
6321
- const last = centroids[c - 1];
6322
- let totalDist = 0;
6323
- for (let i = 0; i < n; i++) {
6324
- let d2 = 0;
6325
- for (let d = 0; d < dim; d++) {
6326
- const diff = vectors[i][d] - last[d];
6327
- d2 += diff * diff;
6328
- }
6329
- if (d2 < dist[i]) dist[i] = d2;
6330
- totalDist += dist[i];
6346
+
6347
+ var mind = 1e20;
6348
+ var mini = 0u;
6349
+
6350
+ let numChunks = (uniforms.numCentroids + CHUNK_SIZE - 1u) / CHUNK_SIZE;
6351
+ for (var chunk = 0u; chunk < numChunks; chunk++) {
6352
+
6353
+ let rowsPerThread = CHUNK_SIZE / 64u;
6354
+ let dstRow = localId * rowsPerThread;
6355
+ let srcRow = min(uniforms.numCentroids, chunk * CHUNK_SIZE + dstRow);
6356
+ let numRows = min(uniforms.numCentroids, srcRow + rowsPerThread) - srcRow;
6357
+
6358
+ var dst = dstRow * DIM;
6359
+ var src = srcRow * DIM;
6360
+ for (var c = 0u; c < numRows * DIM; c++) {
6361
+ sharedChunk[dst + c] = centroids[src + c];
6331
6362
  }
6332
- let target = Math.random() * totalDist;
6333
- let chosen = 0;
6334
- for (let i = 0; i < n; i++) {
6335
- target -= dist[i];
6336
- if (target <= 0) {
6337
- chosen = i;
6338
- break;
6363
+
6364
+ workgroupBarrier();
6365
+
6366
+ if (pointIdx < uniforms.numPoints) {
6367
+ let thisChunkSize = min(CHUNK_SIZE, uniforms.numCentroids - chunk * CHUNK_SIZE);
6368
+ for (var c = 0u; c < thisChunkSize; c++) {
6369
+ let d = calcDistSqr(point, c);
6370
+ if (d < mind) {
6371
+ mind = d;
6372
+ mini = chunk * CHUNK_SIZE + c;
6373
+ }
6339
6374
  }
6340
6375
  }
6341
- centroids.push(new Float32Array(vectors[chosen]));
6376
+
6377
+ workgroupBarrier();
6342
6378
  }
6343
- for (let iter = 0; iter < iterations; iter++) {
6344
- for (let i = 0; i < n; i++) {
6345
- let bestK = 0;
6346
- let bestD = Infinity;
6347
- for (let c = 0; c < k; c++) {
6348
- let d2 = 0;
6349
- for (let d = 0; d < dim; d++) {
6350
- const diff = vectors[i][d] - centroids[c][d];
6351
- d2 += diff * diff;
6352
- }
6353
- if (d2 < bestD) {
6354
- bestD = d2;
6355
- bestK = c;
6356
- }
6357
- }
6358
- labels[i] = bestK;
6379
+
6380
+ if (pointIdx < uniforms.numPoints) {
6381
+ results[pointIdx] = mini;
6382
+ }
6383
+ }`
6384
+ );
6385
+ }
6386
+ let _cachedDevice = null;
6387
+ let _deviceFailed = false;
6388
+ async function getGpuDevice() {
6389
+ if (_cachedDevice) return _cachedDevice;
6390
+ if (_deviceFailed) return null;
6391
+ try {
6392
+ if (typeof navigator === "undefined" || !navigator.gpu) {
6393
+ _deviceFailed = true;
6394
+ return null;
6359
6395
  }
6360
- const sums = [];
6361
- for (let c = 0; c < k; c++) sums.push(new Float64Array(dim));
6362
- const counts = new Uint32Array(k);
6363
- for (let i = 0; i < n; i++) {
6364
- const l = labels[i];
6365
- counts[l]++;
6366
- for (let d = 0; d < dim; d++) sums[l][d] += vectors[i][d];
6396
+ const adapter = await navigator.gpu.requestAdapter();
6397
+ if (!adapter) {
6398
+ _deviceFailed = true;
6399
+ return null;
6367
6400
  }
6368
- let changed = false;
6369
- for (let c = 0; c < k; c++) {
6370
- if (counts[c] > 0) {
6371
- for (let d = 0; d < dim; d++) {
6372
- const v = sums[c][d] / counts[c];
6373
- if (v !== centroids[c][d]) {
6374
- centroids[c][d] = v;
6375
- changed = true;
6376
- }
6377
- }
6401
+ _cachedDevice = await adapter.requestDevice({
6402
+ requiredLimits: {
6403
+ maxStorageBufferBindingSize: adapter.limits.maxStorageBufferBindingSize,
6404
+ maxBufferSize: adapter.limits.maxBufferSize
6378
6405
  }
6406
+ });
6407
+ _cachedDevice.lost.then(() => {
6408
+ _cachedDevice = null;
6409
+ });
6410
+ return _cachedDevice;
6411
+ } catch {
6412
+ _deviceFailed = true;
6413
+ return null;
6414
+ }
6415
+ }
6416
+ async function gpuAssignLabels(device, pointsFlat, centroidsFlat, numPoints, numCentroids, dim) {
6417
+ const WORKGROUP_SIZE2 = 64;
6418
+ const BATCH_SIZE = 1024 * WORKGROUP_SIZE2;
6419
+ const numBatches = Math.ceil(numPoints / BATCH_SIZE);
6420
+ const shaderModule = device.createShaderModule({ code: getGpuClusterShader(dim) });
6421
+ const bindGroupLayout = device.createBindGroupLayout({
6422
+ entries: [
6423
+ { binding: 0, visibility: GPUShaderStage.COMPUTE, buffer: { type: "uniform" } },
6424
+ { binding: 1, visibility: GPUShaderStage.COMPUTE, buffer: { type: "read-only-storage" } },
6425
+ { binding: 2, visibility: GPUShaderStage.COMPUTE, buffer: { type: "read-only-storage" } },
6426
+ { binding: 3, visibility: GPUShaderStage.COMPUTE, buffer: { type: "storage" } }
6427
+ ]
6428
+ });
6429
+ const pipeline = device.createComputePipeline({
6430
+ layout: device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] }),
6431
+ compute: { module: shaderModule, entryPoint: "main" }
6432
+ });
6433
+ const uniformBuf = device.createBuffer({ size: 8, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });
6434
+ const centroidsBuf = device.createBuffer({ size: centroidsFlat.byteLength, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST });
6435
+ device.queue.writeBuffer(centroidsBuf, 0, centroidsFlat.buffer);
6436
+ const pointsBufSize = BATCH_SIZE * dim * 4;
6437
+ const pointsBuf = device.createBuffer({ size: pointsBufSize, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST });
6438
+ const resultsBufSize = BATCH_SIZE * 4;
6439
+ const resultsBuf = device.createBuffer({ size: resultsBufSize, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC });
6440
+ const readbackBuf = device.createBuffer({ size: resultsBufSize, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST });
6441
+ const labels = new Uint32Array(numPoints);
6442
+ const bindGroup = device.createBindGroup({
6443
+ layout: bindGroupLayout,
6444
+ entries: [
6445
+ { binding: 0, resource: { buffer: uniformBuf } },
6446
+ { binding: 1, resource: { buffer: pointsBuf } },
6447
+ { binding: 2, resource: { buffer: centroidsBuf } },
6448
+ { binding: 3, resource: { buffer: resultsBuf } }
6449
+ ]
6450
+ });
6451
+ for (let batch = 0; batch < numBatches; batch++) {
6452
+ const offset = batch * BATCH_SIZE;
6453
+ const currentBatchSize = Math.min(numPoints - offset, BATCH_SIZE);
6454
+ const groups = Math.ceil(currentBatchSize / WORKGROUP_SIZE2);
6455
+ device.queue.writeBuffer(uniformBuf, 0, new Uint32Array([currentBatchSize, numCentroids]));
6456
+ device.queue.writeBuffer(pointsBuf, 0, pointsFlat.buffer, offset * dim * 4, currentBatchSize * dim * 4);
6457
+ const encoder = device.createCommandEncoder();
6458
+ const pass = encoder.beginComputePass();
6459
+ pass.setPipeline(pipeline);
6460
+ pass.setBindGroup(0, bindGroup);
6461
+ pass.dispatchWorkgroups(groups);
6462
+ pass.end();
6463
+ encoder.copyBufferToBuffer(resultsBuf, 0, readbackBuf, 0, currentBatchSize * 4);
6464
+ device.queue.submit([encoder.finish()]);
6465
+ await readbackBuf.mapAsync(GPUMapMode.READ);
6466
+ const mapped = new Uint32Array(readbackBuf.getMappedRange(0, currentBatchSize * 4));
6467
+ labels.set(mapped, offset);
6468
+ readbackBuf.unmap();
6469
+ }
6470
+ uniformBuf.destroy();
6471
+ centroidsBuf.destroy();
6472
+ pointsBuf.destroy();
6473
+ resultsBuf.destroy();
6474
+ readbackBuf.destroy();
6475
+ return labels;
6476
+ }
6477
+ async function kmeansGpu(pointsFlat, n, dim, k, iterations, onProgress) {
6478
+ const labels = new Uint32Array(n);
6479
+ if (n <= k) {
6480
+ const centroids2 = new Float32Array(k * dim);
6481
+ for (let i = 0; i < n; i++) {
6482
+ centroids2.set(pointsFlat.subarray(i * dim, i * dim + dim), i * dim);
6483
+ labels[i] = i;
6379
6484
  }
6380
- if (!changed) break;
6485
+ return { centroids: centroids2, labels };
6381
6486
  }
6487
+ const centroids = new Float32Array(k * dim);
6488
+ const indices = pickRandomIndices(n, k);
6489
+ for (let i = 0; i < k; i++) {
6490
+ centroids.set(pointsFlat.subarray(indices[i] * dim, indices[i] * dim + dim), i * dim);
6491
+ }
6492
+ const device = await getGpuDevice();
6493
+ for (let iter = 0; iter < iterations; iter++) {
6494
+ onProgress == null ? void 0 : onProgress(iter, iterations);
6495
+ if (device) {
6496
+ const newLabels = await gpuAssignLabels(device, pointsFlat, centroids, n, k, dim);
6497
+ labels.set(newLabels);
6498
+ } else {
6499
+ assignLabelsCpu(pointsFlat, centroids, labels, n, k, dim);
6500
+ }
6501
+ updateCentroids(pointsFlat, centroids, labels, n, k, dim);
6502
+ }
6503
+ onProgress == null ? void 0 : onProgress(iterations, iterations);
6504
+ if (device) {
6505
+ const finalLabels = await gpuAssignLabels(device, pointsFlat, centroids, n, k, dim);
6506
+ labels.set(finalLabels);
6507
+ } else {
6508
+ assignLabelsCpu(pointsFlat, centroids, labels, n, k, dim);
6509
+ }
6510
+ return { centroids, labels };
6511
+ }
6512
+ function pickRandomIndices(n, m) {
6513
+ const chosen = /* @__PURE__ */ new Set();
6514
+ for (let j = n - m; j < n; j++) {
6515
+ const t = Math.floor(Math.random() * (j + 1));
6516
+ chosen.add(chosen.has(t) ? j : t);
6517
+ }
6518
+ return [...chosen];
6519
+ }
6520
+ function assignLabelsCpu(points, centroids, labels, n, k, dim) {
6382
6521
  for (let i = 0; i < n; i++) {
6383
- let bestK = 0;
6384
- let bestD = Infinity;
6522
+ const pOff = i * dim;
6523
+ let bestK = 0, bestD = Infinity;
6385
6524
  for (let c = 0; c < k; c++) {
6525
+ const cOff = c * dim;
6386
6526
  let d2 = 0;
6387
6527
  for (let d = 0; d < dim; d++) {
6388
- const diff = vectors[i][d] - centroids[c][d];
6528
+ const diff = points[pOff + d] - centroids[cOff + d];
6389
6529
  d2 += diff * diff;
6390
6530
  }
6391
6531
  if (d2 < bestD) {
@@ -6395,7 +6535,25 @@ function kmeansVectors(vectors, dim, k, iterations) {
6395
6535
  }
6396
6536
  labels[i] = bestK;
6397
6537
  }
6398
- return { centroids: centroids.map((c) => new Float32Array(c)), labels };
6538
+ }
6539
+ function updateCentroids(points, centroids, labels, n, k, dim) {
6540
+ const sums = new Float64Array(k * dim);
6541
+ const counts = new Uint32Array(k);
6542
+ for (let i = 0; i < n; i++) {
6543
+ const l = labels[i];
6544
+ counts[l]++;
6545
+ const pOff = i * dim, sOff = l * dim;
6546
+ for (let d = 0; d < dim; d++) sums[sOff + d] += points[pOff + d];
6547
+ }
6548
+ for (let c = 0; c < k; c++) {
6549
+ if (counts[c] > 0) {
6550
+ const off = c * dim;
6551
+ for (let d = 0; d < dim; d++) centroids[off + d] = sums[off + d] / counts[c];
6552
+ } else {
6553
+ const idx = Math.floor(Math.random() * n);
6554
+ centroids.set(points.subarray(idx * dim, idx * dim + dim), c * dim);
6555
+ }
6556
+ }
6399
6557
  }
6400
6558
  function mortonSort(positions, count) {
6401
6559
  let minx = Infinity, miny = Infinity, minz = Infinity;
@@ -6466,11 +6624,12 @@ async function encodeWebP(width, height, pixelData) {
6466
6624
  }
6467
6625
  return new Uint8Array(await blob.arrayBuffer());
6468
6626
  }
6469
- async function serializeSOG(data, coordinateSystem = "blender", options = {}) {
6627
+ async function serializeSOG(data, coordinateSystem = "blender", options = {}, onProgress) {
6470
6628
  const { maxSHBands = 3, iterations = 10, paletteSize = 1024 } = options;
6471
6629
  const { count, colors, opacities } = data;
6472
6630
  let { positions, scales, rotations } = data;
6473
6631
  let shCoeffs = data.shCoeffs ? new Float32Array(data.shCoeffs) : void 0;
6632
+ onProgress == null ? void 0 : onProgress("坐标系变换", 0);
6474
6633
  if (coordinateSystem === "blender") {
6475
6634
  positions = new Float32Array(positions);
6476
6635
  scales = new Float32Array(scales);
@@ -6493,6 +6652,7 @@ async function serializeSOG(data, coordinateSystem = "blender", options = {}) {
6493
6652
  }
6494
6653
  }
6495
6654
  }
6655
+ onProgress == null ? void 0 : onProgress("Morton 排序", 0.05);
6496
6656
  const sortOrder = mortonSort(positions, count);
6497
6657
  const sPos = new Float32Array(count * 3);
6498
6658
  const sSca = new Float32Array(count * 3);
@@ -6525,6 +6685,7 @@ async function serializeSOG(data, coordinateSystem = "blender", options = {}) {
6525
6685
  }
6526
6686
  const { width, height } = calcImageDimensions(count);
6527
6687
  const totalPixels = width * height;
6688
+ onProgress == null ? void 0 : onProgress("编码位置", 0.1);
6528
6689
  const logPos = new Float32Array(count * 3);
6529
6690
  for (let i = 0; i < count * 3; i++) logPos[i] = symLog(sPos[i]);
6530
6691
  const mins = [Infinity, Infinity, Infinity];
@@ -6552,6 +6713,7 @@ async function serializeSOG(data, coordinateSystem = "blender", options = {}) {
6552
6713
  meansLData[off + 3] = 255;
6553
6714
  meansUData[off + 3] = 255;
6554
6715
  }
6716
+ onProgress == null ? void 0 : onProgress("编码缩放", 0.2);
6555
6717
  const logScales = new Float32Array(count * 3);
6556
6718
  for (let i = 0; i < count * 3; i++) logScales[i] = Math.log(Math.max(1e-8, sSca[i]));
6557
6719
  const scaleCodebook = buildCodebook(logScales, 256);
@@ -6564,6 +6726,7 @@ async function serializeSOG(data, coordinateSystem = "blender", options = {}) {
6564
6726
  scalesData[off + 2] = findNearest(scaleCodebook, logScales[i * 3 + 2]);
6565
6727
  scalesData[off + 3] = 255;
6566
6728
  }
6729
+ onProgress == null ? void 0 : onProgress("编码四元数", 0.3);
6567
6730
  const quatsData = new Uint8ClampedArray(totalPixels * 4);
6568
6731
  quatsData.fill(255);
6569
6732
  const SQRT2 = Math.SQRT2;
@@ -6616,6 +6779,7 @@ async function serializeSOG(data, coordinateSystem = "blender", options = {}) {
6616
6779
  quatsData[off + 2] = Math.round(Math.max(0, Math.min(255, (r2 / SQRT2 + 0.5) * 255)));
6617
6780
  quatsData[off + 3] = largest + 252;
6618
6781
  }
6782
+ onProgress == null ? void 0 : onProgress("编码颜色", 0.4);
6619
6783
  const dcValues = new Float32Array(count * 3);
6620
6784
  for (let i = 0; i < count; i++) {
6621
6785
  dcValues[i * 3] = (sCol[i * 3] - 0.5) / SH_C0;
@@ -6644,18 +6808,28 @@ async function serializeSOG(data, coordinateSystem = "blender", options = {}) {
6644
6808
  encodeWebP(width, height, sh0Data)
6645
6809
  ];
6646
6810
  if (actualBands > 0 && sSH) {
6647
- const vectors = new Array(count);
6811
+ onProgress == null ? void 0 : onProgress("压缩球谐系数 (GPU)", 0.5);
6812
+ const pointsFlat = new Float32Array(count * shDim);
6648
6813
  for (let i = 0; i < count; i++) {
6649
- const v = new Float32Array(shDim);
6650
6814
  const b = i * 45;
6651
- for (let j = 0; j < shDim; j++) v[j] = sSH[b + j];
6652
- vectors[i] = v;
6815
+ for (let j = 0; j < shDim; j++) pointsFlat[i * shDim + j] = sSH[b + j];
6653
6816
  }
6654
6817
  const effectivePaletteSize = Math.min(paletteSize, count);
6655
- const { centroids, labels } = kmeansVectors(vectors, shDim, effectivePaletteSize, iterations);
6656
- const allCoeffValues = new Float32Array(centroids.length * shDim);
6657
- for (let c = 0; c < centroids.length; c++) {
6658
- for (let d = 0; d < shDim; d++) allCoeffValues[c * shDim + d] = centroids[c][d];
6818
+ const { centroids, labels } = await kmeansGpu(
6819
+ pointsFlat,
6820
+ count,
6821
+ shDim,
6822
+ effectivePaletteSize,
6823
+ iterations,
6824
+ (iter, total) => {
6825
+ const p = 0.5 + 0.35 * (iter / total);
6826
+ onProgress == null ? void 0 : onProgress(`球谐聚类 ${iter}/${total}`, p);
6827
+ }
6828
+ );
6829
+ onProgress == null ? void 0 : onProgress("量化球谐 codebook", 0.88);
6830
+ const allCoeffValues = new Float32Array(effectivePaletteSize * shDim);
6831
+ for (let c = 0; c < effectivePaletteSize; c++) {
6832
+ for (let d = 0; d < shDim; d++) allCoeffValues[c * shDim + d] = centroids[c * shDim + d];
6659
6833
  }
6660
6834
  const shCodebook = buildCodebook(allCoeffValues, 256);
6661
6835
  const centW = 64 * numCoeffs;
@@ -6663,14 +6837,14 @@ async function serializeSOG(data, coordinateSystem = "blender", options = {}) {
6663
6837
  const centData = new Uint8ClampedArray(centW * centH * 4);
6664
6838
  centData.fill(255);
6665
6839
  for (let n = 0; n < effectivePaletteSize; n++) {
6666
- const entry = centroids[n];
6667
6840
  for (let c = 0; c < numCoeffs; c++) {
6668
6841
  const u = n % 64 * numCoeffs + c;
6669
6842
  const v = Math.floor(n / 64);
6670
6843
  const off = (v * centW + u) * 4;
6671
- centData[off] = findNearest(shCodebook, entry[c * 3]);
6672
- centData[off + 1] = findNearest(shCodebook, entry[c * 3 + 1]);
6673
- centData[off + 2] = findNearest(shCodebook, entry[c * 3 + 2]);
6844
+ const cOff = n * shDim;
6845
+ centData[off] = findNearest(shCodebook, centroids[cOff + c * 3]);
6846
+ centData[off + 1] = findNearest(shCodebook, centroids[cOff + c * 3 + 1]);
6847
+ centData[off + 2] = findNearest(shCodebook, centroids[cOff + c * 3 + 2]);
6674
6848
  centData[off + 3] = 255;
6675
6849
  }
6676
6850
  }
@@ -6694,6 +6868,7 @@ async function serializeSOG(data, coordinateSystem = "blender", options = {}) {
6694
6868
  files: ["sh_centroids.webp", "sh_labels.webp"]
6695
6869
  };
6696
6870
  }
6871
+ onProgress == null ? void 0 : onProgress("编码 WebP 图像", 0.92);
6697
6872
  const webps = await Promise.all(webpPromises);
6698
6873
  const [meansLWebP, meansUWebP, scalesWebP, quatsWebP, sh0WebP] = webps;
6699
6874
  const meta = {
@@ -6719,7 +6894,9 @@ async function serializeSOG(data, coordinateSystem = "blender", options = {}) {
6719
6894
  zipEntries["sh_centroids.webp"] = webps[5];
6720
6895
  zipEntries["sh_labels.webp"] = webps[6];
6721
6896
  }
6897
+ onProgress == null ? void 0 : onProgress("打包 ZIP", 0.98);
6722
6898
  const zipData = zipSync(zipEntries, { level: 0 });
6899
+ onProgress == null ? void 0 : onProgress("完成", 1);
6723
6900
  return zipData.buffer;
6724
6901
  }
6725
6902
  const WORKGROUP_SIZE$1 = 256;