Search code examples
pythontkintermandelbrot

How to render Mandelbrot Set faster?


I'm currently drawing the Mandelbrot set pixel by pixel with PhotoImage and tkinter. I'm using basically the algorithm directly with no modifications. Are there methods to make the calculation faster? Maybe filling in large areas of color quickly, or precalcuating constants?

Part of the code:

ITERATIONS = 50
WIDTH, HEIGHT = 600, 600
CENTER = (-.5, 0)
DIAMETER = 2.5

def mandel(c):
    z = 0
    for i in range(ITERATIONS):
        z = z**2 + c
        if abs(z) > 2:
            return i     
    return ITERATIONS

root = Tk()
canvas = Canvas(root, width=WIDTH,height=HEIGHT)
canvas.pack()
img = PhotoImage(width=WIDTH, height=HEIGHT)
canvas.create_image((WIDTH/2, HEIGHT/2), image=img, state="normal")


real = CENTER[0] - 0.5 * DIAMETER
imag = CENTER[1] - 0.5 * DIAMETER

def color(i):
    colors = ("#0000AA", "#88DDFF", "#FF8800", "#000000")
    if i == ITERATIONS:
        return colors[-1]
    else:
        choice = (i//2) % len(colors)
    return colors[choice]

for x in range(WIDTH):
    for y in range(HEIGHT):
        i = mandel(complex(real, imag))

        img.put(color(i), (x, HEIGHT-y))

        imag += DIAMETER / HEIGHT
    imag = CENTER[1] - 0.5 * DIAMETER
    real += DIAMETER / WIDTH

mainloop()

Solution

  • Setting one pixel at a time is likely the main source of the slowdown. Instead of calling put for each pixel, computer a whole row of pixels, or an entire matrix of pixels, and then call put one time at the end of the loop.

    You can find an example here, among other places: https://web.archive.org/web/20170512214049/http://tkinter.unpythonic.net:80/wiki/PhotoImage#Fill_Many_Pixels_at_Once