// Worker for processing video frames off the main thread interface ProcessMessage { type: 'process'; bitmap: ImageBitmap; targetWidth: number; targetHeight: number; sourceRect: { x: number; y: number; width: number; height: number; }; mirror: boolean; } let offscreenCanvas: OffscreenCanvas | null = null; let ctx: OffscreenCanvasRenderingContext2D | null = null; self.onmessage = (e: MessageEvent) => { const { bitmap, targetWidth, targetHeight, sourceRect, mirror } = e.data; try { // Create or resize canvas if (!offscreenCanvas || offscreenCanvas.width !== targetWidth || offscreenCanvas.height !== targetHeight) { offscreenCanvas = new OffscreenCanvas(targetWidth, targetHeight); ctx = offscreenCanvas.getContext('2d', { alpha: false, desynchronized: true, willReadFrequently: true }); } if (!ctx) { throw new Error('Failed to get canvas context'); } // Enable high-quality smoothing ctx.imageSmoothingEnabled = true; ctx.imageSmoothingQuality = 'medium'; // Draw with optional mirroring ctx.resetTransform(); if (mirror) { ctx.translate(targetWidth, 0); ctx.scale(-1, 1); } ctx.drawImage(bitmap, sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height, 0, 0, targetWidth, targetHeight); // Extract pixel data const imageData = ctx.getImageData(0, 0, targetWidth, targetHeight); // Send back (transfer the buffer for zero-copy) const response = { type: 'result', data: imageData.data, width: targetWidth, height: targetHeight }; self.postMessage(response, [imageData.data.buffer]); } catch (error) { self.postMessage({ type: 'error', error: String(error) }); } finally { // Clean up bitmap bitmap.close(); } };