Chapter 22

Image Synthesis

The Mandelbrot set is an interesting mathematical object that owes much of its popularity to the computer programs that create images of it.

Listing 22.1: Mandelbrot Set

 1 # mandelbrot.py
 2 from image import ImagePPM
 3
 4 def lerp(frac, low, high):
 5 return low + frac * (high − low)
 6
 7 def testpoint(c, maxreps):
 8 z = 0
 9 reps = 0
10 while abs(z) < 2 and reps < maxreps:
11   z = z ** 2 + c
12   reps += 1
13 frac = reps / maxreps
14 return (0, 0, int(lerp(frac, 0, 255)))
15
16 def mandelbrot(xint, yint, size, maxreps):
17 width, height = size
18 img = ImagePPM.new(size)
19 for i in range(width):
20  for j in range(height):
21    a = lerp(i / width, xint[0], xint[1])
22    b = lerp(1 − j / height, yint[0], yint[1])
23    c = complex(a, b)
24    img.putpixel((i, j), testpoint(c, maxreps))
25 return img
26
27 def main():
28 img = mandelbrot((−2, 0.7), (−1.2, 1.2), (900, 800), 50)
29 img.save("mbrot.ppm")
30
31 main()

⇒ Caution: As you experiment with this program, some changes may cause it to take a long time to run.

Complex Numbers

The Mandelbrot set is defined using complex numbers, which have the form a + bi where i2 = −1. Complex numbers are visualized by plotting z = a + bi as the point (a, b) in the usual plane ℝ2.

Squaring a complex number z = a + bi works like this:

z2=(a+bi)(a+bi)=a2+2abi+b2i2=(a2b2)+(2ab)i

The size of a complex number is given by its absolute value, which is computed as

|z|=|a+bi|=a2+b2

The following process decides whether or not a complex number c is in the Mandelbrot set:

 Begin with z = 0.
 Repeat: replace z with z ** 2 + c.
 If abs(z) <= 2 forever, then c is in the Mandelbrot set.

Programs cannot wait forever, so some upper limit must be set on the number of repetitions.

Complex Numbers in Python

Python supports complex numbers and complex arithmetic. We create a complex number with the built-in complex() function:

complex(a, b)

Complex number a + bi.

Then the arithmetic operations of addition, subtraction, multiplication, and exponentiation work as briefly described above. (Division is somewhat different, but we will not need it here.) The built-in absolute value function abs() also handles complex numbers correctly.

Parameter Tuples

The mandelbrot() function in Listing 22.1 requires quite a few parameters to specify the region to draw, the size of the resulting image, and the maximum number of repetitions to use when deciding whether or not a point is in the Mandelbrot set. By grouping these together into natural tuples, we make the parameter list manageable.

Linear Interpolation

There are several places in Listing 22.1 where we need to convert a fractional value in the interval [0, 1] to some other range [a, b]. Linear interpolation is the name for performing this conversion in a linear way, so that, for example, if the fraction is 1/3, then the interpolated value will be 1/3 of the way from a to b. Lerp is an abbreviation of linear interpolation.

Exercises

  1. 22.1 Rewrite the body of main() in Listing 22.1 to use only one line of code.
  2. 22.2 Using the lerp() function from Listing 22.1, compute the following:
    1. (a) lerp(0, 1, 2)
    2. (b) lerp(0.5, 3, 4)
    3. (c) lerp(1, 2, 3)
  3. 22.3 Use Listing 22.1 to:
    1. (a) Explain the need for the int() conversion in line 14.
    2. (b) Explain the need for “1 −” in line 22 instead of just j / height.
  4. 22.4 Use Listing 22.1 to:
    1. (a) Give the region of the complex plane that is being drawn.
    2. (b) Give the RGB color of points in the Mandelbrot set. Describe the color.
    3. (c) Give the approximate RGB color of points that require very few repetitions to know that they are not in the set. Describe the color.
    4. (d) Give the approximate RGB color of points that require almost the maximum number of repetitions to know that they are not in the set. Describe the color.
  5. 22.5 Describe and explain the effect of changing the maxreps parameter in Listing 22.1. How large a value are you able to use? How small?
  6. 22.6 Modify Listing 22.1 to reverse the color scheme of the original, so that points in the set are black and points not in the set are shades of blue.
  7. 22.7 Modify Listing 22.1 to separate out the color choice from the rest of the testpoint() function. Introduce a new function color(reps, maxreps) that computes the color based on reps and maxreps, and call this function at the end of testpoint(), after the number of reps has been determined.
  8. 22.8 Using the previous exercise, modify the color() function to highlight points that take many repetitions to decide that they are not in the Mandelbrot set. Set up three cases:
     reps == maxreps:  black
     0 <= frac < 0.5:  interpolate (0, 0, 100) to (0, 255, 100)
     0.5 <= frac < 1.0: interpolate (0, 255, 100) to white
  9. 22.9 Modify Listing 22.1 to show these sections of the Mandelbrot set.
    1. (a) Using x interval [−1,−0.7] and y interval [0.03, 0.3]
    2. (b) Using x interval [−1,−0.7] and y interval [−0.5, 0.5]

    Do either of the images appear distorted? Describe any distortion you see.

  10. 22.10 The aspect ratio of an image is the ratio of its width to its height. Use the images from the previous exercise to answer these questions about aspect ratio:
    1. (a) Compute the aspect ratio of the region in the complex plane for part (a).
    2. (b) Compute the aspect ratio of the region in the complex plane for part (b).
    3. (c) Compute the aspect ratio of the images created, based on the number of pixels used.

    Explain the distortion you found in Exercise 22.9.

  11. 22.11 It would be nice to have a function that automatically creates images with the correct aspect ratio. Let w and h be the actual width and height of the region being drawn. Then for any value s, if we let the width of the image (in pixels) be s · w and its height be s · h, the aspect ratio of the image will be

    swsh=wh,

    which is the same as the region being drawn. Thus, s can be used to control the final size of the image.

    1. (a) Write a function imgsize(xint, yint, scale) that returns an image size (width and height tuple) with the same aspect ratio as the given intervals and scaled according to scale.
    2. (b) Use the imgsize() function to write a function
       mandelbrotauto(xint, yint, scale, maxreps)

      that draws the Mandelbrot set over the intervals xint and yint using the correct aspect ratio.

    3. (c) Use the mandelbrotauto() function to correct the distortion from Exercise 22.9.
  12. 22.12 Use the previous exercise to write a function
     mandelbrotcentered(center, size, maxreps)

    that draws the region of the Mandelbrot set centered at center with width and height specified by the tuple size. (These are not the image width and height, but the size of the region being drawn in the complex plane.) Use your function to draw the region centered at (−0.1, 1) with width and height 0.2.

  13. 22.13 Create your own interesting view of the Mandelbrot set.
  14. 22.14 Julia sets are defined similarly to the Mandelbrot set. The main difference is in how they treat z and c for the iteration of f(z) = z2 + c. The Mandelbrot algorithm can be described as:
     for every c in the region:
     test point c beginning with z = 0

    In contrast, every c produces a different Julia set Jc. Given c, the Julia set algorithm for Jc is:

     for every z in the region:
     test point z beginning the iteration with z itself

    Note that c is still used in the iteration that replaces z with z2 + c. Values of z that stay bounded in the iteration are in Jc.

    Write a program to draw Jc for c = −0.8 + 0.2i over the region with x-interval [−1.6, 1.6] and y-interval [−0.9, 0.9].

  15. 22.15 Draw Julia sets for values of c that are both in and not in the Mandelbrot set. Describe the differences that you see.
  16. 22.16 Create your own interesting image of a Julia set.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.136.97.64