The demonstration should load (above), on most browsers. You may need to whitelist Javascript for crawlingrobotfortress.blogspot.com to view it. I must admit I'm not 100% certain how to embedd javascript on Blogger posts reliably. Let's see if it works. Mouse over the canvass to adjust the feedback controls.
<center> <canvas height="1" id="feedbackcanvas" width="1"> Sorry, your browser does not support canvas and/or Javascript. </canvas> <script type="application/javascript"> function feedback(){ var N = 512; var N2 = N/2; // Initialize canvas data structures var feedbackcanvas = document.getElementById('feedbackcanvas'); feedbackcanvas.width = N; feedbackcanvas.height = N; var ctx = feedbackcanvas.getContext('2d'); var imageData = ctx.getImageData(0, 0, N, N); // Initialize color map var colormap = new Uint32Array( 256 ); for (var i=0; i<256; i++) { var hue = 6.0*i/256; var r=0; var g=0; var b=0; var C=250; if (hue<1) { r+=C; g+=C*hue; } else if (hue<2) { r+=C*(2-hue); g+=C; } else if (hue<3) { g+=C; b+=C*(hue-2); } else if (hue<4) { g+=C*(4-hue); b+=C; } else if (hue<5) { r+=C*(hue-4); b+=C; } else { r+=C; b+=C*(6-hue); } r = Math.round(r); g = Math.round(g); b = Math.round(b); color = 0xff000000 | (r<<16)|(g<<8)|b; colormap[i] = color; } // Compute lookup table map var map = new Uint32Array( N*N*2 ); for (var y = 0; y < N; ++y) { for (var x = 0; x < N; ++x) { var real = (x-N2)*4.0/N; var imag = (y-N2)*4.0/N; var real2 = real; var imag2 = imag; var x2 = Math.round((real2*N/4+N2)*256); var y2 = Math.round((imag2*N/4+N2)*256); var index = y*N + x; map[index*2 ] = x2; map[index*2+1] = y2; } } var recurrentBuffer1 = new Uint8Array( N*N + 1); var recurrentBuffer2 = new Uint8Array( N*N + 1); recurrentBuffer1[N*N] = 255; recurrentBuffer2[N*N] = 255; for (var y = 0; y < N; ++y) for (var x = 0; x < N; ++x) recurrentBuffer1[y*N + x] = x & 0xff; offsetx = 64*256; offsety = 32*256; costheta = 0; sintheta = 0; function iterate() { for (var y = 0; y < N2; ++y) for (var x = 0; x < N2; ++x) { var index = y*N + x; var x2 = map[index*2 ] - N2*256; var y2 = map[index*2+1] - N2*256; var x3 = (costheta * x2 + sintheta * y2 >> 8) + N2*256 + offsetx; var y3 = (costheta * y2 - sintheta * x2 >> 8) + N2*256 + offsety; var xi = x3 >> 8; var yi = y3 >> 8; var xf = x3 & 0xff; var yf = y3 & 0xff; var index = xi+yi*N; var colorA = recurrentBuffer1[index & 262143]; var colorB = recurrentBuffer1[index+1 & 262143]; var colorC = recurrentBuffer1[index+N & 262143]; var colorD = recurrentBuffer1[index+N+1 & 262143]; var colorE = colorA*(256-xf)+colorB*xf >> 8; var colorF = colorC*(256-xf)+colorD*xf >> 8; var color = colorE*(256-yf)+colorF*yf >> 8; if (xi>=0 && yi>=0 && xi<n && yi<N) {color += 10;} else {color = ~color;} recurrentBuffer2[y*N + x] = color; recurrentBuffer2[(N-1-y)*N + x] = color; recurrentBuffer2[(N-1-y)*N + (N-1-x)] = color; recurrentBuffer2[y*N + (N-1-x)] = color; } var temp = recurrentBuffer2; recurrentBuffer2 = recurrentBuffer1; recurrentBuffer1 = temp; } var buf = new ArrayBuffer(imageData.data.length); var buf8 = new Uint8ClampedArray(buf); var data = new Uint32Array(buf); // Mouse listener callback feedbackcanvas.onmousemove = function(e) { var mouseX, mouseY; if(e.offsetX) { mouseX = e.offsetX; mouseY = e.offsetY; } else if(e.layerX) { mouseX = e.layerX; mouseY = e.layerY; } mouseX -= N2; mouseY -= N2; offsetx = mouseX*256; offsety = mouseY*256; mouseTheta = Math.atan2(mouseX,mouseY); mouseRadius = 300; costheta = Math.cos(mouseTheta)*mouseRadius; sintheta = Math.sin(mouseTheta)*mouseRadius; }; function render() { iterate(); for (var y = 0;y < N;++y) { for (var x = 0;x < N;++x) { var value = recurrentBuffer2[y*N+x]; data[y*N + x] = colormap[value]; } } imageData.data.set(buf8); ctx.putImageData(imageData, 0, 0); setTimeout(render, 10); } setTimeout(render, 66); } </script> <body onload="feedback()"></body> </center>