// src/workers/renderer.worker.js // Color gradients const viridis = [ [68, 1, 84], [68, 2, 86], [69, 4, 87], [69, 5, 89], [70, 7, 90], [70, 8, 92], [70, 10, 93], [70, 11, 94], // ... (rest unchanged) [72, 223, 255] ]; // Dark 'hot' colormap: black → red only const hot = Array.from({length:256}, (_,i)=>{ let t = i/255; return [ Math.round(255 * t), 0, 0 ]; }); const cool = Array.from({length:256}, (_,i)=>{ let t = i/255; return [Math.round(255*t), Math.round(255*(1-t)), 255]; }); const rainbow = Array.from({length:256}, (_,i)=>{ let t = i/255; let r = Math.round(255 * Math.max(0, Math.min(1, 1.5 - Math.abs(4*t-3)))); let g = Math.round(255 * Math.max(0, Math.min(1, 1.5 - Math.abs(4*t-2)))); let b = Math.round(255 * Math.max(0, Math.min(1, 1.5 - Math.abs(4*t-1)))); return [r,g,b]; }); self.onmessage = function(event) { const { canvas, data, options = {}, gradient = 'viridis' } = event.data; const width = canvas.width; const height = canvas.height; const ctx = canvas.getContext('2d'); const intensityGrid = new Float32Array(data); // Find max intensity for normalization, ignore top 0.1% outliers for better color contrast const sorted = Array.from(intensityGrid).sort((a, b) => a - b); const max = sorted[Math.floor(sorted.length * 0.999)] || 1; function getColor(i) { // Log normalization for high contrast const t = Math.min(1, Math.log1p(i) / Math.log1p(max)); let palette = viridis; if (gradient === 'hot') palette = hot; else if (gradient === 'cool') palette = cool; else if (gradient === 'rainbow') palette = rainbow; const idx = Math.floor(t * (palette.length - 1)); const [r, g, b] = palette[idx]; // Alpha: fade in with intensity, sharper const a = Math.round(255 * Math.pow(t, 1.2)); return [r, g, b, a]; } // Draw pixels const imageData = ctx.createImageData(width, height); for (let i = 0; i < intensityGrid.length; i++) { const [r, g, b, a] = getColor(intensityGrid[i]); const p = i * 4; imageData.data[p] = r; imageData.data[p+1] = g; imageData.data[p+2] = b; imageData.data[p+3] = a; } ctx.putImageData(imageData, 0, 0); // Transfer rendered bitmap for display canvas.convertToBlob().then(blob => createImageBitmap(blob).then(bitmap => { self.postMessage({ bitmap }); }) ); };