function t(a,p){return B[a][p]=="F"?255:0}function L(a,p){u=a-m(a);return t(m(a),p)*(1-u)+t(m(a)+1,p)*u}function C(){j=v-d*D;for(g=e;g--;){c=n=w+g*E;f=j;for(k=M;--k&&c*c+(F=f*f)<4;){f=2*c*f+j;c=c*c-F+n}if(!x[k]){q=B[r=k/16]?t:L;x[k]=[q(r,0),q(r,1),q(r,2),255]}for(h=4;h--;)y.data[(g+d*e)*4+h]=x[k][h]}if(d==i)l[G](y,0,0);else{++d;l.fillRect(9,9,d*5/4,9);setTimeout(C)}}function H(){l.fillStyle="red";w=z-o;I=z+o;J=A-s;v=A+s;E=(I-w)/399;D=(v-J)/299;d=0;C()}var e=400,i=300,b="tImageData",G="pu"+b,K="ge"+b;b=document;b.write("<p>dblclick = zoom");b=b.body.children[0];b.width=e;b.height=i;b.style.background="#"+i;var l=b.getContext("2d"),y=l[K](0,0,e,i),o=1.5,z=1-o,A=0,s=9/8,M=96,E,D,w,I,J,v,m=parseInt,r,q,u,k,B=",F,FF,0F,0FF,00F,".split(","),x={},g,d,h,j,n,f,c,F;H();b.ondblclick=function(a){j=a.clientX;n=a.clientY;z+=o*(j/e-.5)*2;A-=s*(n/i-.5)*2;o/=3;s/=3;a=l[K](0,0,e,i);for(g=e;g--;)for(d=i;d--;){f=m(g/3)+j-67;c=m(d/3)+n-50;for(h=4;h--;)a.data[(g+d*e)*4+h]=f>0&&f<e&&c>0&&c<i?y.data[(f+c*e)*4+h]:0}l[G](a,0,0);H()}
document.write('<div>Press double click to zoom!</div>');
var canvas = document.getElementById('c');
canvas.width = 400;
canvas.height = 300;
canvas.style.backgroundColor = 'black';
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'red';
var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var center_re = -0.5;
var center_im = 0;
var r_re = 1.5;
var r_im = r_re * canvas.height / canvas.width;
var max_iteration = 100;
var re_factor, im_factor, min_re, max_re, min_im, max_im;
var colors = ['000000', '0000FF', '00FFFF', '00FF00', 'FFFF00', 'FF0000', '000000'];
function calcColors (n) {
var colorIndex = n / max_iteration * (colors.length - 1);
if (typeof colors[colorIndex] === 'string') {
return [
parseInt(colors[colorIndex].substr(0, 2), 16),
parseInt(colors[colorIndex].substr(2, 2), 16),
parseInt(colors[colorIndex].substr(4, 2), 16)
];
} else {
var colorIndex1 = Math.floor(colorIndex);
var t = colorIndex - colorIndex1;
return [
parseInt(parseInt(colors[colorIndex1].substr(0, 2), 16) * (1-t) + parseInt(colors[colorIndex1 + 1].substr(0, 2), 16) * t, 10),
parseInt(parseInt(colors[colorIndex1].substr(2, 2), 16) * (1-t) + parseInt(colors[colorIndex1 + 1].substr(2, 2), 16) * t, 10),
parseInt(parseInt(colors[colorIndex1].substr(4, 2), 16) * (1-t) + parseInt(colors[colorIndex1 + 1].substr(4, 2), 16) * t, 10)
];
}
}
var colorCache = {};
function getColors (n) {
if (!colorCache[n]) {
colorCache[n] = calcColors(n).concat(255);
}
return colorCache[n];
}
var y, index;
function run () {
var c_im = max_im - y * im_factor;
for (var x = 0; x < canvas.width; ++x) {
var c_re = min_re + x * re_factor;
var z_re = c_re;
var z_im = c_im;
for (var n = 0; n < max_iteration; ++n) {
var z_re2 = z_re * z_re;
var z_im2 = z_im * z_im;
if (z_re2 + z_im2 > 4) {
break;
}
z_im = 2 * z_re * z_im + c_im;
z_re = z_re2 - z_im2 + c_re;
}
var colors = getColors(n);
for (var i = 0; i < 4; i++) {
canvasData.data[index++] = colors[i];
}
}
if (y === canvas.height) {
// finish:
ctx.putImageData(canvasData, 0, 0);
} else {
// progressbar:
ctx.fillRect(10, canvas.height-20, Math.round(y * (canvas.width - 20) / canvas.height), 10);
// next row: (simple worker:)
++y;
setTimeout(run);
}
}
function draw () {
min_re = center_re - r_re;
max_re = center_re + r_re;
min_im = center_im - r_im;
max_im = center_im + r_im;
re_factor = (max_re - min_re) / (canvas.width - 1);
im_factor = (max_im - min_im) / (canvas.height - 1);
y = 0;
index = 0;
run();
}
function zoom (left, top) {
var tmpCanvasData = ctx.getImageData(0, 0, canvas.width, canvas.height),
index = 0;
for (var y = 0; y < canvas.height; ++y) {
var ty = Math.round(y / 3) + top;
for (var x = 0; x < canvas.width; ++x) {
var tx = Math.round(x / 3) + left;
var tnum = (tx + ty * canvas.width) * 4;
for (var i = 0; i < 4; i++) {
var l = tx > 0 && tx < canvas.width && ty > 0 && ty < canvas.height;
tmpCanvasData.data[index++] = l ? canvasData.data[tnum + i] : 0;
}
}
}
ctx.putImageData(tmpCanvasData, 0, 0);
}
canvas.ondblclick = function (e) {
var x = e.clientX,
y = e.clientY;
center_re += r_re * (x / canvas.width - 0.5) * 2;
center_im -= r_im * (y / canvas.height - 0.5) * 2;
r_re /= 3;
r_im /= 3;
zoom(x - Math.round(canvas.width / 6), y - Math.round(canvas.height / 6));
draw();
};
draw();