2016-11-28 27 views
1

我在Python中使用PIL模塊製作了Mandelbrot分形。 現在,我想要製作一個放大到一個點的GIF。我在線觀看了其他代碼,但不用說,我不明白,因爲我使用的模式有點不同(我使用的是類)。如何製作mandelbrot分形縮放(Python)的gif?

我知道,要放大我需要改變規模......但我顯然不知道如何實現它。

from PIL import Image 
import random 


class Fractal: 
    """Fractal class.""" 

    def __init__(self, size, scale, computation): 
     """Constructor. 

     Arguments: 
     size -- the size of the image as a tuple (x, y) 
     scale -- the scale of x and y as a list of 2-tuple 
       [(minimum_x, minimum_y), (maximum_x, maximum_y)] 
     computation -- the function used for computing pixel values as a function 
     """ 
     self.size = size 
     self.scale = scale 
     self.computation = computation 
     self.img = Image.new("RGB", (size[0], size[1])) 

    def compute(self): 
     """ 
     Create the fractal by computing every pixel value. 
     """ 
     for y in range(self.size[1]): 
      for x in range(self.size[0]): 
       i = self.pixel_value((x, y)) 
       r = i % 8 * 32 
       g = i % 16 * 16 
       b = i % 32 * 8 
       self.img.putpixel((x, y), (r, g, b)) 

    def pixel_value(self, pixel): 
     """ 
     Return the number of iterations it took for the pixel to go out of bounds. 

     Arguments: 
     pixel -- the pixel coordinate (x, y) 

     Returns: 
     the number of iterations of computation it took to go out of bounds as integer. 
     """ 
     # x = pixel[0] * (self.scale[1][0] - self.scale[0][0])/self.size[0] + self.scale[0][0] 
     # y = pixel[1] * (self.scale[1][1] - self.scale[0][1])/self.size[1] + self.scale[0][1] 
     x = (pixel[0]/self.size[0]) * (self.scale[1][0] - self.scale[0][0]) + self.scale[0][0] 
     y = (pixel[1]/self.size[1]) * (self.scale[1][1] - self.scale[0][1]) + self.scale[0][1] 

     return self.computation((x, y)) 

    def save_image(self, filename): 
     """ 
     Save the image to hard drive. 

     Arguments: 
     filename -- the file name to save the file to as a string. 
     """ 
     self.img.save(filename, "PNG") 

if __name__ == "__main__": 
    def mandelbrot_computation(pixel): 
     """Return integer -> how many iterations it takes for the pixel to escape the mandelbrot set.""" 
     c = complex(pixel[0], pixel[1]) # Complex number: A + Bi (A is real number, B is imaginary number). 
     z = 0 # We are assuming the starting z value for each square is 0. 
     iterations = 0 # Will count how many iterations it takes for a pixel to escape the mandelbrot set. 

     for i in range(255): # The more iterations, the more detailed the mandelbrot set will be. 
      if abs(z) >= 2.0: # Checks, if pixel escapes the mandelbrot set. Same as square root of pix[0] and pix[1]. 
       break 
      z = z**2 + c 
      iterations += 1 

     return iterations 

    mandelbrot = Fractal((1000, 1000), [(-2, -2), (2, 2)], mandelbrot_computation()) 
    mandelbrot.compute() 
    mandelbrot.save_image("mandelbrot.png") 
+0

歡迎StackOverflow上。請閱讀並遵守幫助文檔中的發佈準則。 [如何問](http://stackoverflow.com/help/how-to-ask)和[最小,完整,可驗證的示例](http://stackoverflow.com/help/mcve)在這裏適用。 – Prune

+0

你好,謝謝。對不起,我衝過這個問題,因爲它一直困擾我很久。感謝您的詳細解答! –

+0

我們在這裏提供幫助。如果您堅持發佈指南,您會得到更好的答案,使速度讀者更容易解決問題。 – Prune

回答

1

這是一個「簡單的」線性變換,包括scale(縮放)和translate(移位),就像您在線性代數中學到的一樣。你記得一個像

s(y-k) = r(x-h) + c 

翻譯是(h,k);每個方向的尺度是(r,s)。

要實現這個,你需要改變你的循環增量。要在每個方向上放大因子k,您需要減小座標的範圍,同樣減少像素位置之間的增量。

這裏最重要的是部分解耦你的顯示座標和你的數學值:你不再顯示標記爲(0.2,-0.5)的位置的0.2 - 0.5i的值。新的職位將從您的新框架邊界計算。

您的舊代碼是不是這個完全正確:

for y in range(self.size[1]): 
     for x in range(self.size[0]): 
      i = self.pixel_value((x, y)) 
      ... 
      self.img.putpixel((x, y), (r, g, b)) 

相反,你需要的是這樣的:

# Assume that the limits x_min, x_max, y_min, y_max 
    # are assigned by the zoom operation. 
    x_inc = (x_max - x_min)/self.size[0] 
    y_inc = (y_max - y_min)/self.size[1] 
    for y in range(self.size[1]): 
     for x in range(self.size[0]): 
      a = x*x_inc + x_min 
      b = y*y_inc + y_min 
      i = self.pixel_value((a, b)) 
      ... 
      self.img.putpixel((x, y), (r, g, b))