I thought I would give this months community challenge a try. This is my first time using Python. It does take quite a while to run and it's not very colourful but it works.
from PIL import Image, ImageDraw
img = Image.new("RGB", (2400, 2400), "white")
draw = ImageDraw.Draw(img)
max_count = 200
width = img.size[0]
height = img.size[1]
for row in range(height):
for col in range(width):
str_output = ""
c = complex(
(col - float(width)/2.0)*5.0/float(width),
(row - float(height)/2.0)*5.0/float(height)
)
iteration = 0
z = 0
while abs(z) < 2 and iteration < max_count:
z = z**2 + c
iteration += 1
if abs(z) < 2:
draw.point((col, row), fill="black")
else:
draw.point((col, row), fill=(255 - iteration,255 - iteration,255 - iteration))
img.save('mandelbrot.png')
-
\$\begingroup\$ What version of Python are you using? \$\endgroup\$SuperBiasedMan– SuperBiasedMan2015年10月13日 11:00:12 +00:00Commented Oct 13, 2015 at 11:00
-
\$\begingroup\$ @SuperBiasedMan 3.whatever_the_latest_release_is \$\endgroup\$James Fenwick– James Fenwick2015年10月13日 11:01:59 +00:00Commented Oct 13, 2015 at 11:01
-
\$\begingroup\$ @JamesFenwick That would be 3.5 \$\endgroup\$Justin– Justin2015年10月14日 18:19:35 +00:00Commented Oct 14, 2015 at 18:19
2 Answers 2
Your constants should be in UPPER_SNAKE_CASE
MAX_COUNT = 200
WIDTH = img.size[0]
HEIGHT = img.size[1]
Instead of nested for loops, you can use itertools.product
which basically will perform the nested iteration you need:
from itertools import product
for row, col in product(range(height), range(width))
You don't use str_output
, you should clean up unused values.
You should have whitespace either side of your mathematical operators and have a space after each comma in a comma separated list of values:
(col - float(width) / 2.0) * 5.0 / float(width),
draw.point((col, row), fill=(255 - iteration, 255 - iteration, 255 - iteration))
You should also keep lines below 79 characters as the Python style guide dictates. You can split lines quite easily when they're in paretheses:
draw.point((col, row), fill=(255 - iteration, 255 - iteration,
255 - iteration))
Also your mileage may vary on whether or not this is more readable but you could use a ternary for your final if
condition. Like this:
draw.point((col, row), fill=("black" if abs(z) < 2 else
(255 - iteration, 255 - iteration,
255 - iteration))
The formatting is definitely more awkward, but I personally like these structures because it makes it clear that the only difference in the two results is that one condition.
This feels a bit backwards to me
img = Image.new("RGB", (2400, 2400), "white") width = img.size[0] height = img.size[1]
compared to this
WIDTH = 2400 HEIGHT = 2400 img = Image.new("RGB", (WIDTH, HEIGHT), "white")
You can eliminate all the
float
calls because you are using Python 3 where true division is the default.for
loops are generally preferred overwhile
loops. A possible way to arrange the inner loop is this:z = 0 for iteration in range(MAX_COUNT): z = z**2 + c if abs(z) >= 2: fill = (255 - iteration, 255 - iteration, 255 - iteration) break else: fill="black" draw.point((col, row), fill=fill)
Explore related questions
See similar questions with these tags.