Skip to content

Instantly share code, notes, and snippets.

@williammalo
Forked from 140bytes/LICENSE.txt
Last active October 2, 2015 22:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save williammalo/2339080 to your computer and use it in GitHub Desktop.
Save williammalo/2339080 to your computer and use it in GitHub Desktop.
Draw mandelbrot fractal on canvas

Draws a mandelbrot fractal on a canvas.

usage:

mandelbrot(imageData,width)

Thanks to @atk for doing most of the minification work!

//version 2.0 (using alpha instead of color!)
function(d,w,x,y,a,b,e,f,i,q,z){
for(b=w;b--;y=3*b/w-1.5)
for(a=w;a--;e=x=3*a/w-2,f=y)
{
for(i=256;i--&&e*e+f*f<4;)q=e*e-f*f+x,f=2*e*f+y,e=q;
this[d][(w*b+a<<2)+3]=255-(i%8*32);
}
}
//version 2.1
function(d,w,x,y,a,b,e,f,i,q){
for(b=w;b--;y=3*b/w-1.5)
for(a=w;a--;e=x=3*a/w-2,f=y)
{
for(i=256;i--&&e*e+f*f<4;e=q)q=e*e-f*f+x,f=2*e*f+y;
this[d][(w*b+a<<2)+3]=255-i%8*32;
}
}
//version 3.0 (Thanks @atk!)
function(d,w,x,y,a,b,e,f,i,q){
for(b=w;b--;y=3*b/w-1.5)
for(a=w;a--;d[(w*b+a<<2)+3]=255-i%8*32,e=x=3*a/w-2,f=y)
for(i=256;i--&&e*e+f*f<4;e=q)q=e*e-f*f+x,f=2*e*f+y
}
//version 4.0 (Thanks again @atk!)
function(d,w,x,y,a,b,e,f,i,q){
for(b=w;b--;y=4*b/w-2)
for(a=w;a--;d[(w*b+a)*4+3]=i%8*32,e=x=4*a/w-2,f=y)
for(i=256;q=f*f,i--&&e*e+q<4;e=e*e-q+x)f=2*e*f+y
}
//version 5.0 (137 bytes)(@atk is an absolute boss!)
function(d,w,x,y,a,e,f,i,q){for(a=w*w;a--;d[a*4+3]=i%8*32,e=x=4*(a%w)/w-2,f=y=4*a/w/w-2)for(i=256;q=f*f,i--&&e*e+q<4;e=e*e-q+x)f=2*e*f+y}
//version 6.0 (115 bytes =D )
function(d,w,a,e,f,i,q){for(a=w*w*4;a-=4;d[a+3]=i%8*32)for(e=f=0,i=256;--i/e;f=q)q=2*e*f+a/w/w-2,e=e*e-f*f+a/w%4-2}
//version 6.1 (137 bytes) simpler syntax: mandelbrot(imageData)
function(d,w,a,e,f,i,q){for(w=Math.sqrt((a=pix.length)/4);a-=4;d[a+3]=i%8*32)for(e=f=0,i=256;--i/e;f=q)q=2*e*f+a/w/w-2,e=e*e-f*f+a/w%4-2}
function(d,w,a,e,f,i,q){for(a=w*w*4;a-=4;d[a+3]=i%8*32)for(e=f=0,i=256;--i/e;f=q)q=2*e*f+a/w/w-2,e=e*e-f*f+a/w%4-2}
{
"name": "drawMandelbrot",
"description": "Draws a mandelbrot fractal on a canvas.",
"keywords": [
"Mandelbrot",
"fractal",
"canvas",
"math"
]
}
<style>body{background:#000}/*make background black(it's just for the looks)*/</style>
<canvas id=canvas width=512 height=512></canvas>
<script>
var mandelbrot = function(d,w,a,e,f,i,q){for(a=w*w*4;a-=4;d[a+3]=i%8*32)for(e=f=0,i=256;--i/e;f=q)q=2*e*f+a/w/w-2,e=e*e-f*f+a/w%4-2}
var ctx = document.getElementById('canvas').getContext('2d');
var imgd = ctx.createImageData(512,512);
var pix = imgd.data;
for(i=512*512*4;i--;)pix[i]=256 //make canvas white (it's just for the looks)
mandelbrot(pix,512);
ctx.putImageData(imgd,0,0);
</script>
@atk
Copy link

atk commented Apr 10, 2012

replace a<<2 with a*4, save one byte; instead of using this[d], give the imageData directly to the function, save 6 more bytes:

function(d,w,x,y,a,b,e,f,i,q){for(b=w;b--;y=3*b/w-1.5)for(a=w;a--;e=x=3*a/w-2,f=y){for(i=256;i--&&e*e+f*f<4;e=q)q=e*e-f*f+x,f=2*e*f+y;d[(w*b+a*4)+3]=255-i%8*32;}}

Update: save 2 more bytes by rewiring what comes after the last for loop into the second loop's after-statement:

function(d,w,x,y,a,b,e,f,i,q){for(b=w;b--;y=3*b/w-1.5)for(a=w;a--;d[(w*b+a*4)+3]=255-i%8*32,e=x=3*a/w-2,f=y)for(i=256;i--&&e*e+f*f<4;e=q)q=e*e-f*f+x,f=2*e*f+y}

Another update: due to operator precedence, (w*b+a*4)+3 can be shortened to w*b+a*4+3, saving another 2 bytes (17 to go):

function(d,w,x,y,a,b,e,f,i,q){for(b=w;b--;y=3*b/w-1.5)for(a=w;a--;d[w*b+a*4+3]=255-i%8*32,e=x=3*a/w-2,f=y)for(i=256;i--&&e*e+f*f<4;e=q)q=e*e-f*f+x,f=2*e*f+y}

By the way, would you mind filling out the package.json?

@williammalo
Copy link
Author

@atk quote:"replace a<<2 with a_4"
It doesn't work, because "_" and "<<" don't have the same operator precedence.
Thanks for the other tricks tho!

@atk
Copy link

atk commented Apr 10, 2012

The last loop could be reduced by 2 bytes if we use q to store f*f instead of what later becomes e:

before:
for(i=256;i--&&e*e+f*f<4;e=q)q=e*e-f*f+x,f=2*e*f+y

after:
for(i=256;q=f*f,i--&&e*e+q<4;e=e*e-q+x)f=2*e*f+y

@atk
Copy link

atk commented Apr 10, 2012

btw. you are aware that i%8_32 will be the same as i%256 (you probably intended (i%8)_32 or you need to expand one more byte to use i%8<<5 instead. Anyway, the 255-i%256 is obviously used to invert the fractal; as much as it is probably visually pleasing, maybe we can lose the inverting in order to get closer to 140bytes. And thank you for updating the package.json

Update: you forgot to remove one of the closing curly brackets in your version 3.0.

@williammalo
Copy link
Author

@atk
I%8*32 is not the same as i%256, again because of operator precedence.
Yeah, the inverting is indeed useless, I removed it!

@atk
Copy link

atk commented Apr 10, 2012

Oh, just found an error in the operator precedence chart from mozilla :-)

What do you think, would we save bytes if we joined the first two loops into one by counting from w*w to 0?
Update: Got it:

function(d,w,x,y,a,e,f,i,q){for(a=w*w;a--;d[a*4+3]=i%8*32,e=x=4*(a%w)/w-2,f=y=4*a/w/w-2)for(i=256;q=f*f,i--&&e*e+q<4;e=e*e-q+x)f=2*e*f+y}

137bytes! Glad to have been your caddy on this golf course!

@williammalo
Copy link
Author

@atk
Thats funny, I actually use the mozilla chart for operator precedence.
=D yay for <140 bytes! I actually had the same idea but the code failed every time I tried, so I figured it wouldn't work.
You are a boss!

@atk
Copy link

atk commented Apr 11, 2012

Just one minor update: // is not a valid comment in css. In addition, I would put the background to the canvas element - the page looks better this way.

@williammalo
Copy link
Author

@atk

oups...

@p01
Copy link

p01 commented Apr 11, 2012

https://gist.github.com/1261166 the classic Mandelbrot set, in 140 bytes
https://gist.github.com/1267983 with panning and zooming, in 133 bytes ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment