/** * Web Worker for computing GCD table bitmap * Computes n x n 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 }; } // Compute GCD using Euclidean algorithm function gcd(a: number, b: number): number { while (b !== 0) { const temp = b; b = a % b; a = temp; } return a; } self.onmessage = (e: MessageEvent<{ n: number }>) => { const { n } = e.data; // Create ImageData for n x n grid const imageData = new ImageData(n, n); const data = imageData.data; // Compute GCD table and fill ImageData // First pass: compute log(gcd) values and find max const logValues: number[] = new Array(n * n); let maxLogValue = 0; for (let i = 1; i <= n; i++) { for (let j = 1; j <= n; j++) { const gcdValue = gcd(i, j); const logValue = Math.log(gcdValue); const index = (i - 1) * n + (j - 1); logValues[index] = logValue; maxLogValue = Math.max(maxLogValue, logValue); } } // Second pass: map log values to colors for (let i = 1; i <= n; i++) { for (let j = 1; j <= n; j++) { const index = (i - 1) * n + (j - 1); const logValue = logValues[index]; const color = valueToColor(logValue, maxLogValue); // Calculate pixel index (RGBA format) const pixelIndex = index * 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] ); };