This commit is contained in:
seb
2026-09-29 13:45:13 +02:00
parent 4cb050c285
commit 43e1ab98b7
7 changed files with 193 additions and 91 deletions

View File

@@ -0,0 +1,57 @@
self.onmessage = async (e) => {
const { id, file, maxDim = 1000, quality = 0.85 } = e.data;
try {
// Step 1: Get original dimensions without full pixel context decoding
const tempBitmap = await createImageBitmap(file);
const { width, height } = tempBitmap;
tempBitmap.close(); // Immediately release memory
// Step 2: Calculate target dimensions preserving aspect ratio
let targetWidth = width;
let targetHeight = height;
if (width > maxDim || height > maxDim) {
if (width > height) {
targetWidth = maxDim;
targetHeight = Math.round((height * maxDim) / width);
} else {
targetHeight = maxDim;
targetWidth = Math.round((width * maxDim) / height);
}
}
// Step 3: Decode and scale natively via createImageBitmap on GPU
const resizedBitmap = await createImageBitmap(file, {
resizeWidth: targetWidth,
resizeHeight: targetHeight,
resizeQuality: 'high',
});
// Step 4: Draw to OffscreenCanvas
const canvas = new OffscreenCanvas(targetWidth, targetHeight);
const ctx = canvas.getContext('2d', {
alpha: true,
desynchronized: true,
});
ctx.drawImage(resizedBitmap, 0, 0);
resizedBitmap.close(); // Clean up GPU memory
// Step 5: Native C++ WebP encoding directly to Blob
const webpBlob = await canvas.convertToBlob({
type: 'image/webp',
quality,
});
self.postMessage({
id,
success: true,
blob: webpBlob,
width: targetWidth,
height: targetHeight,
});
} catch (error) {
self.postMessage({ id, success: false, error: error?.message || String(error) });
}
};