/** * Web Worker for computing multiplication table bitmap * Computes (prime-1) x (prime-1) ImageData and transfers it back to main thread */ // Inline color computation function (copied from colorUtils.ts) function valueToColor(value: number, max: number): { r: number; g: number; b: number } { const t = value / max; // Smooth gradient from dark purple-blue to bright yellow-orange let r: number, g: number, b: number; // Red channel: smooth increase r = Math.floor(13 + 242 * Math.pow(t, 0.5)); // Green channel: gentle S-curve for smoothness g = Math.floor(8 + 247 * Math.pow(t, 1.5)); // Blue channel: decrease from purple to yellow b = Math.floor(135 * Math.pow(1 - t, 2)); // Clamp values to valid range r = Math.min(255, Math.max(0, r)); g = Math.min(255, Math.max(0, g)); b = Math.min(255, Math.max(0, b)); return { r, g, b }; } self.onmessage = (e: MessageEvent<{ prime: number }>) => { const { prime } = e.data; // Create ImageData for (prime-1) x (prime-1) grid const size = prime - 1; const imageData = new ImageData(size, size); const data = imageData.data; // Compute multiplication table and fill ImageData for (let i = 1; i < prime; i++) { for (let j = 1; j < prime; j++) { const value = (i * j) % prime; const color = valueToColor(value, prime - 1); // Calculate pixel index (RGBA format) const pixelIndex = ((i - 1) * size + (j - 1)) * 4; data[pixelIndex] = color.r; // Red data[pixelIndex + 1] = color.g; // Green data[pixelIndex + 2] = color.b; // Blue data[pixelIndex + 3] = 255; // Alpha (fully opaque) } } // Transfer ImageData back to main thread using transferable objects self.postMessage( { type: 'complete', imageData }, // @ts-expect-error - TypeScript doesn't recognize this overload but it's valid [imageData.data.buffer] ); };