Skip to content

Instantly share code, notes, and snippets.

@dgant
Created August 11, 2023 22:02
Show Gist options
  • Save dgant/89304e9f539a3ac9e13128631aeffe78 to your computer and use it in GitHub Desktop.
Save dgant/89304e9f539a3ac9e13128631aeffe78 to your computer and use it in GitHub Desktop.
import math
import random
import numpy as np
import sounddevice as sd
from PIL import Image, ImageDraw
def distance(x, y):
return (x**2 + y**2) ** 0.5
def generate_image(id):
width = 512
height = width
diagonal = distance(width, height)
center_x = width // 2
center_y = height // 2
image = Image.new('L', (width, height), 255)
draw = ImageDraw.Draw(image)
levels = 11
cracks = 3
def crack(x, y, scale, axis, ttk):
angle = random.gauss(axis, math.pi / 6)
length = scale * (2 + 0.5 * ttk) * random.uniform(1, 3)
end_x = x + length * math.cos(angle)
end_y = y + length * math.sin(angle)
dist = distance(x - center_x, y - center_y)
value = min(192, int(1024 * dist / diagonal / scale))
draw.line([(x, y), (end_x, end_y)], fill=(value), width = 1)
if ttk > 0:
crack(end_x, end_y, scale, axis, ttk - 1)
if random.randint(1, 4) > 1:
crack(end_x, end_y, scale, angle, ttk - 1)
if random.randint(1, 4) > 2:
crack(end_x, end_y, scale, angle, ttk - 2)
if random.randint(1, 4) > 2:
crack(end_x, end_y, scale, angle, ttk - 3)
cycle = 0
for scale in [2, 2, 3, 4, 5]:
print(f'Cracking @{scale}', flush=True)
cycle += 1
for i in range(cracks):
crack(center_x, center_y, scale, (2 * i / cracks + cycle) * math.pi, levels)
copy = image.copy()
steps = [[int(max(1, min(8, 4 * diagonal / max(1, distance(x - center_x, y - center_y))))) for y in range(height)] for x in range(width)]
changed = True
for i in range(0, 32):
if changed:
print(f'Convolution #{i}', flush=True)
changed = False
swap = copy
copy = image
image = swap
for ox in range(width):
for oy in range(height):
ov = copy.getpixel((ox, oy))
step = steps[ox][oy]
for delta in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
x = ox + delta[0]
if 0 <= x < width:
y = oy + delta[1]
if 0 <= y < height:
v = image.getpixel((x, y))
nv = min(v, ov + step)
if nv != v:
changed = True
image.putpixel((x, y), nv)
#print(f'v: {v}, ox: {ox}, oy: {oy}, delta: {delta}, x: {x}, y: {y}, ov: {ov}, nv: {nv}')
image.save(f'cracks{id}.png', 'PNG')
def generate_bell_sound(duration, frequency):
t = np.linspace(0, duration, int(44100 * duration), False)
waveform = 0.1 * np.sin(2 * np.pi * frequency * t)
waveform += 0.05 * np.sin(4 * np.pi * frequency * t)
waveform += 0.025 * np.sin(8 * np.pi * frequency * t)
return waveform
if __name__ == "__main__":
bell_waveform = generate_bell_sound(0.25, 220)
for i in range(20):
generate_image(i)
sd.play(bell_waveform)
print('Generated image #' + str(i), flush=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment