You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
3.0 KiB

#!/usr/bin/env python3
# Copyright (C) 2021 harrysentonbury
# GNU General Public License v3.0
import numpy as np
from PIL import Image
from numba import jit
import argparse
parser = argparse.ArgumentParser(prog="FRACTAL")
parser.add_argument("-m", "--magnification", nargs="?", metavar='MAGNIFICATION',
help="required magnification", type=float, default=1.0)
parser.add_argument("-n", "--nodisplay", action="store_false",
help="do not display output")
parser.add_argument("-o", "--outfile", nargs="?", metavar="SAVE_AS",
help="save as <path to filename.whateva>", type=str)
parser.add_argument("-s", "--size", nargs="?", metavar="SIZE",
help="Size by y pixels default=700", type=int, default=700)
parser.add_argument("-x", "--xyoffset", action='store', nargs=2, metavar="OFFSET",
help="row and column offset", type=float, default=[0.0, 0.0])
args = parser.parse_args()
if args.magnification < 1.0:
parser.error("magnification must have a minimum value of 1")
if abs(args.xyoffset[1]) > 1 or args.xyoffset[0] < -2 or args.xyoffset[0] > 1:
parser.error("xyoffset must range between -2 to 1 and -1 to 1 respectively")
@jit
def mandelbrot(re, im, iter_limit):
c = complex(re, im)
z = complex(0.0, 0.0)
for i in range(iter_limit):
z = z**2 + c
if (z.real**2) + (z.imag**2) >= 4:
return i
return iter_limit
try:
iteration_limit = 85
columns = args.size
rows = int(columns * 1.5)
magnification = args.magnification
row_offset = args.xyoffset[0]
col_offset = args.xyoffset[1]
row_extent = (np.array([-2, 1.0]) + (row_offset * magnification)) * 1 / magnification
column_extent = (np.array([1.0, -1.0]) + (col_offset * magnification)) * 1 / magnification
result = np.zeros([rows, columns])
for row_index, re in enumerate(np.linspace(row_extent[0], row_extent[1], rows)):
for column_index, im in enumerate(np.linspace(column_extent[0], column_extent[1], columns)):
result[row_index, column_index] = mandelbrot(re, im, iteration_limit)
result = result.T
print(f"image size: {result.shape[1]}, {result.shape[0]}")
image_array = np.zeros((columns, rows, 3), dtype=np.uint8)
for real in range(rows):
for imaginary in range(columns):
indexed = result[imaginary, real]
image_array[imaginary, real] = (np.uint8(170 - (indexed * 2)), # RED
np.uint8((np.sin((indexed) * np.pi / 85) * 255)), # GREEN
np.uint8(80 + (indexed * 2)) # BLUE
)
new_image = Image.fromarray(image_array, "RGB")
if args.outfile:
new_image.save(args.outfile)
print("image saved")
if args.nodisplay:
new_image.show()
except KeyboardInterrupt:
parser.exit("\n Interupt by user")
except Exception as e:
parser.exit(f"{type(e).__name__}: {str(e)}")