FireGarden - 6 months ago 24

Python Question

First, here's the code I have:

`from PIL import Image as im`

import numpy as np

def mandelbrot_iteration(c):

iters = 0

while abs(c)<2 and iters<200:

c=c**2+c

iters+=1

return iters

HEIGHT = 400

WIDTH = 500

diag = im.new('L',(WIDTH, HEIGHT))

pix = diag.load()

x_pts = np.arange(-2,2,4/WIDTH)

y_pts = np.arange(-2,2,4/HEIGHT)

for x in x_pts:

for y in y_pts:

pix[x+2,y+2]=mandelbrot_iteration(complex(x,y))

diag.save("Fractal.png")

I thought this was quite straight forward. I see how many interations each point on a grid of complex numbers takes to grow past an abs. value of 2 and plot these values as a colour at each point (with 200 being the cutoff, assuming the sequence doesn't diverge). In the range specified, there should definitely be some non-trivial things going on, but no matter what I try, the image made is plain black.

Also this method of generating images has almost zero documentation. I've searched a lot, and this:

im.load()

Allocates storage for the image and loads it from the file (or from

the source, for lazy operations). In normal cases, you don’t need to

call this method, since the Image class automatically loads an opened

image when it is accessed for the first time.

(New in 1.1.6) In 1.1.6 and later, load returns a pixel access object

that can be used to read and modify pixels. The access object behaves

like a 2-dimensional array, so you can do:

pix = im.load() print pix[x, y] pix[x, y] = value

Access via this object is a lot faster than getpixel and putpixel

Is

Answer

The immediate problem is your *scale* is off.

In this line `pix[x+2,y+2]=...`

, with your ranges for `x`

and `y`

, the only pixels that are being drawn are `0..4`

. Since the last few pixels drawn are black, the entire top left 4x4 square is black (and the rest is 0 – also black – by default, for a new image).

That can be fixed like this:

```
from PIL import Image as im
import numpy as np
def mandelbrot_iteration(c):
iters = 0
while abs(c)<2 and iters<200:
c=c**2+c
iters+=1
return iters
HEIGHT = 400
WIDTH = 500
diag = im.new('L',(WIDTH, HEIGHT))
pix = diag.load()
x_pts = np.arange(-2,2,4.0/WIDTH)
y_pts = np.arange(-2,2,4.0/HEIGHT)
for x in x_pts:
for y in y_pts:
pix[WIDTH*(x+2)/4.0,HEIGHT*(y+2)/4.0]=mandelbrot_iteration(complex(x,y))
diag.show()
```

although the result is not yet a good Mandelbrot...

With hcs' comment "mandelbrot iteration should be z=0, while abs(z)<2, z=z**2+c" applied, you'd use this code

```
from PIL import Image as im
import numpy as np
def mandelbrot_iteration(c):
iters = 0
z = 0
while abs(z)<2 and iters<200:
z=z**2+c
iters+=1
return iters
HEIGHT = 400
WIDTH = 500
diag = im.new('L',(WIDTH, HEIGHT))
pix = diag.load()
x_pts = np.arange(-2,2,4.0/WIDTH)
y_pts = np.arange(-2,2,4.0/HEIGHT)
for x in x_pts:
for y in y_pts:
pix[WIDTH*(x+2)/4.0,HEIGHT*(y+2)/4.0]=mandelbrot_iteration(complex(x,y))
# diag.show()
diag.save("Fractal.png")
```

and lo and behold, a true Mandelbrot pops up: