Fractal Image 2

   1 import Tkinter as tk
   2 import threading, Queue
   3 
   4 #Globals
   5 WIDE = 200         # image dimensions
   6 HIGH = 200         #
   7 
   8 REAL_FROM = -2     # bounds of fractal in the complex plane
   9 REAL_TO   =  1     #
  10 IMAG_FROM = -1.5   # imaginary coords => y-direction
  11 IMAG_TO   =  1.5   #
  12 
  13 N = 64
  14 
  15                 
  16 class MandelbrotWorker(threading.Thread):
  17     def __init__(self, aQueue, imgWidth, imgHeight, bounds, **kwargs):
  18         threading.Thread.__init__(self)
  19         self.setDaemon(1)
  20         self.imgWidth = imgWidth 
  21         self.imgHeight = imgHeight
  22         self.fwidth = float(imgWidth)
  23         self.fheight = float(imgHeight)
  24         self.mapLeft = bounds[0]
  25         self.mapTop = bounds[3]
  26         self.mapWidth = bounds[1] - bounds[0]
  27         self.mapHeight = bounds[3] - bounds[2]
  28         self.resultQueue = aQueue
  29         self.n = N
  30         self.start()
  31         
  32     def run(self):
  33         for x in xrange(self.imgWidth):
  34             for y in xrange(self.imgHeight):
  35                 percx = x/self.fwidth
  36                 percy = y/self.fheight
  37                 xp = self.mapLeft + percx*self.mapWidth
  38                 yp = self.mapTop - percy*self.mapHeight
  39                 o = complex(0,0)
  40                 z = complex(xp,yp)
  41                 colorcode = 0
  42                 for trials in xrange(self.n):
  43                     if abs(o) <= 2.0:
  44                         o = o**2 + z
  45                     else:
  46                         colorcode = trials
  47                         break
  48                 self.resultQueue.put((x,y,colorcode))
  49 
  50 
  51 class ThreadedFractal(tk.Toplevel):
  52     def __init__(self, master):
  53         tk.Toplevel.__init__(self, master)
  54         self.protocol('WM_DELETE_WINDOW', self.on_close)        
  55         self.status = tk.Label(self)
  56         self.status.pack(fill='x')
  57         self.display = tk.Label(self)
  58         self.display.pack()
  59         self.img = tk.PhotoImage(width=WIDE, height=HIGH)
  60         self.display.config(image=self.img)
  61         self.count = 0
  62         self.totalPixels = WIDE*HIGH 
  63         self.queue = Queue.Queue()
  64         self.rgb = []
  65         self.make_colours()
  66         self.go()
  67         
  68     def make_colours(self):
  69         for i in xrange(N):
  70             r = i*7%200 + 55
  71             g = i*9%200 + 55
  72             b = i*11%200 + 55
  73             colour = '#%02x%02x%02x' %(r,g,b)
  74             self.rgb.append(colour)
  75 
  76     def scheduler(self):
  77         self.after(0, self.poll)
  78             
  79     def go(self):
  80         self.workerThread = MandelbrotWorker(self.queue, WIDE, HIGH,
  81                                     (REAL_FROM,REAL_TO,IMAG_FROM,IMAG_TO))
  82         self.after(500, self.poll)
  83                 
  84     def poll(self):
  85         if self.count < self.totalPixels:
  86             try:
  87                 x,y,code = self.queue.get_nowait()
  88             except Queue.Empty:
  89                 pass
  90             else:
  91                 colour = self.rgb[code]
  92                 self.img.put(colour, to=(x,y))
  93                 self.count += 1
  94                 self.status.config(text='%s of %s pixels' %(self.count,
  95                                                             self.totalPixels))
  96             self.after_idle(self.scheduler)
  97             
  98     def on_close(self):
  99         self.master.destroy()
 100 
 101 
 102 root = tk.Tk()
 103 root.withdraw()
 104 app = ThreadedFractal(root)
 105 app.mainloop()
 106 

tkinter: FractalImage2 (last edited 2011-06-08 01:08:30 by AnthonyMuss)