Files
999/scripts/render_astral_supernova.py
T

163 lines
7.6 KiB
Python

import math
import numpy as np
from PIL import Image, ImageDraw, ImageFilter
SIZE = 1024
CENTER = SIZE / 2.0
# 1. Base interstellar background
bg = Image.open('/home/alexives/.gemini/antigravity-ide/brain/4ff924d9-3d7f-4202-9066-3ac5c3088b8e/chrome_sacred_triskelion_void_1791132439786.jpg').convert('RGBA')
bg = bg.resize((SIZE, SIZE), Image.Resampling.LANCZOS)
# Deep cosmic gas and photon disc
gas = Image.new('RGBA', (SIZE, SIZE), (0, 0, 0, 0))
gdraw = ImageDraw.Draw(gas)
gdraw.ellipse([100, 80, 924, 944], fill=(70, 20, 110, 120)) # Violet nebula
gdraw.ellipse([180, 160, 844, 864], fill=(0, 110, 180, 140)) # Cyan electric dust
gdraw.ellipse([250, 250, 774, 774], fill=(220, 130, 20, 110)) # Golden photon ring
gas = gas.filter(ImageFilter.GaussianBlur(55))
bg = Image.alpha_composite(bg, gas)
N_POINTS = 13
R_TIP = SIZE * 0.47
R_INNER = SIZE * 0.28
R_MEDALLION = SIZE * 0.255
R_CORE = SIZE * 0.092
start_angle = -math.pi / 2.0
tips = [(CENTER + R_TIP * math.cos(start_angle + i * 2 * math.pi / N_POINTS),
CENTER + R_TIP * math.sin(start_angle + i * 2 * math.pi / N_POINTS)) for i in range(N_POINTS)]
valleys = [(CENTER + R_INNER * math.cos(start_angle + (i + 0.5) * 2 * math.pi / N_POINTS),
CENTER + R_INNER * math.sin(start_angle + (i + 0.5) * 2 * math.pi / N_POINTS)) for i in range(N_POINTS)]
# Flaming rays
star_glow = Image.new('RGBA', (SIZE, SIZE), (0, 0, 0, 0))
sgdraw = ImageDraw.Draw(star_glow)
star_art = Image.new('RGBA', (SIZE, SIZE), (0, 0, 0, 0))
sadraw = ImageDraw.Draw(star_art)
for i in range(N_POINTS):
p_tip = tips[i]
p_vl = valleys[(i - 1) % N_POINTS]
p_vr = valleys[i]
ang_tip = start_angle + i * 2 * math.pi / N_POINTS
ang_vl = ang_tip - math.pi / N_POINTS
ang_vr = ang_tip + math.pi / N_POINTS
ctrl_r = (R_TIP + R_INNER) * 0.49
p_cl = (CENTER + ctrl_r * math.cos((ang_tip + ang_vl)*0.5 + 0.03), CENTER + ctrl_r * math.sin((ang_tip + ang_vl)*0.5 + 0.03))
p_cr = (CENTER + ctrl_r * math.cos((ang_tip + ang_vr)*0.5 - 0.03), CENTER + ctrl_r * math.sin((ang_tip + ang_vr)*0.5 - 0.03))
pts_l = [((1-t)**2 * p_vl[0] + 2*(1-t)*t * p_cl[0] + t**2 * p_tip[0],
(1-t)**2 * p_vl[1] + 2*(1-t)*t * p_cl[1] + t**2 * p_tip[1]) for t in np.linspace(0, 1, 30)]
pts_r = [((1-t)**2 * p_tip[0] + 2*(1-t)*t * p_cr[0] + t**2 * p_vr[0],
(1-t)**2 * p_tip[1] + 2*(1-t)*t * p_cr[1] + t**2 * p_vr[1]) for t in np.linspace(0, 1, 30)]
poly = [(CENTER, CENTER)] + pts_l + pts_r
sgdraw.polygon(poly, fill=(255, 120, 20, 90))
# Outer light strokes
for edge in [pts_l, pts_r]:
for p in range(len(edge) - 1):
sgdraw.line([edge[p], edge[p+1]], fill=(255, 170, 40, 220), width=8)
sadraw.line([edge[p], edge[p+1]], fill=(255, 235, 160, 255), width=3)
sadraw.line([edge[p], edge[p+1]], fill=(255, 255, 255, 255), width=1)
sadraw.line([CENTER, CENTER, p_tip[0], p_tip[1]], fill=(255, 255, 255, 255), width=2)
# Brilliant diffraction spike on tip
for l_s, w_s in [(20, 2), (10, 1)]:
sadraw.line([p_tip[0] - l_s, p_tip[1], p_tip[0] + l_s, p_tip[1]], fill=(255, 255, 255, 255), width=w_s)
sadraw.line([p_tip[0], p_tip[1] - l_s, p_tip[0], p_tip[1] + l_s], fill=(255, 255, 255, 255), width=w_s)
# Medallion
med = Image.new('RGBA', (SIZE, SIZE), (0, 0, 0, 0))
mdraw = ImageDraw.Draw(med)
mdraw.ellipse([CENTER - R_MEDALLION, CENTER - R_MEDALLION, CENTER + R_MEDALLION, CENTER + R_MEDALLION], fill=(2, 3, 10, 240), outline=(255, 215, 60, 255), width=4)
mdraw.ellipse([CENTER - R_MEDALLION - 4, CENTER - R_MEDALLION - 4, CENTER + R_MEDALLION + 4, CENTER + R_MEDALLION + 4], outline=(80, 220, 255, 210), width=2)
# Central loop
mdraw.ellipse([CENTER - R_CORE, CENTER - R_CORE, CENTER + R_CORE, CENTER + R_CORE], fill=(0, 2, 8, 255), outline=(255, 225, 90, 255), width=5)
mdraw.ellipse([CENTER - R_CORE + 4, CENTER - R_CORE + 4, CENTER + R_CORE - 4, CENTER + R_CORE - 4], outline=(100, 235, 255, 220), width=2)
# 3 Chrome fluid ribbons with spiral curls (завитушки девяток)
for k in range(3):
rot = start_angle + k * (2.0 * math.pi / 3.0)
outer = []
inner = []
steps = 70
for s in range(steps + 1):
t = s / float(steps)
t_curv = 0.5 * (1.0 - math.cos(t * math.pi))
cr = R_CORE + t_curv * (R_MEDALLION - R_CORE - 10)
ca = rot + t * 1.54
bx = CENTER + cr * math.cos(ca)
by = CENTER + cr * math.sin(ca)
outer.append((bx, by))
thick = math.sin(t * math.pi) * 17.0
ir = max(R_CORE, cr - thick)
inner.append((CENTER + ir * math.cos(ca + 0.08), CENTER + ir * math.sin(ca + 0.08)))
ribbon = outer + inner[::-1]
mdraw.polygon(ribbon, fill=(255, 175, 45, 160))
for p in range(len(outer) - 1):
sgdraw.line([outer[p], outer[p+1]], fill=(255, 190, 40, 220), width=8)
mdraw.line([outer[p], outer[p+1]], fill=(255, 255, 240, 255), width=3)
mdraw.line([outer[p], outer[p+1]], fill=(255, 255, 255, 255), width=1)
for p in range(len(inner) - 1):
mdraw.line([inner[p], inner[p+1]], fill=(70, 220, 255, 220), width=2)
# Elegant curly spiral flourish at the tip of the nine (завитушка)
tip_pt = outer[-1]
tip_ang = rot + 1.54
flourish_pts = []
for f in range(25):
ft = f / 24.0
f_r = 20 * (1.0 - ft * 0.7)
f_a = tip_ang + ft * math.pi * 1.65
fx = tip_pt[0] + f_r * math.cos(f_a) - 20 * math.cos(tip_ang)
fy = tip_pt[1] + f_r * math.sin(f_a) - 20 * math.sin(tip_ang)
flourish_pts.append((fx, fy))
for p in range(len(flourish_pts) - 1):
sgdraw.line([flourish_pts[p], flourish_pts[p+1]], fill=(255, 190, 50, 180), width=6)
mdraw.line([flourish_pts[p], flourish_pts[p+1]], fill=(255, 255, 255, 255), width=2)
# Abundant magical sparkles / stardust across the image
glitter = Image.new('RGBA', (SIZE, SIZE), (0, 0, 0, 0))
gldraw = ImageDraw.Draw(glitter)
np.random.seed(999)
tints = [(255, 255, 255), (255, 225, 120), (130, 235, 255), (255, 190, 240)]
for _ in range(160):
rad = np.random.uniform(R_CORE * 0.7, R_TIP * 0.98)
ang = np.random.uniform(0, 2 * math.pi)
gx = CENTER + rad * math.cos(ang)
gy = CENTER + rad * math.sin(ang)
sz = int(np.random.choice([2, 3, 4, 6], p=[0.5, 0.3, 0.15, 0.05]))
t = tints[np.random.randint(0, len(tints))]
gldraw.line([gx - sz*1.6, gy, gx + sz*1.6, gy], fill=t + (240,), width=1)
gldraw.line([gx, gy - sz*1.6, gx, gy + sz*1.6], fill=t + (240,), width=1)
gldraw.ellipse([gx - 1, gy - 1, gx + 1, gy + 1], fill=(255, 255, 255, 255))
# Giant interstellar center starburst
for l_c, w_c in [(42, 4), (24, 2), (10, 1)]:
mdraw.line([CENTER - l_c, CENTER, CENTER + l_c, CENTER], fill=(255, 255, 255, 255), width=w_c)
mdraw.line([CENTER, CENTER - l_c, CENTER, CENTER + l_c], fill=(255, 255, 255, 255), width=w_c)
mdraw.line([CENTER - 20, CENTER - 20, CENTER + 20, CENTER + 20], fill=(100, 230, 255, 220), width=2)
mdraw.line([CENTER - 20, CENTER + 20, CENTER + 20, CENTER - 20], fill=(100, 230, 255, 220), width=2)
comp = Image.alpha_composite(bg, star_glow.filter(ImageFilter.GaussianBlur(14)))
comp = Image.alpha_composite(comp, star_art)
comp = Image.alpha_composite(comp, med)
comp = Image.alpha_composite(comp, glitter)
# Rich cinematic bloom
bloom = comp.filter(ImageFilter.GaussianBlur(10))
final_img = Image.blend(comp, bloom, 0.26)
out_file = '/home/alexives/.gemini/antigravity-ide/brain/4ff924d9-3d7f-4202-9066-3ac5c3088b8e/star_13_astral_supernova_cinematic.png'
final_img.save(out_file, 'PNG')
print("Rendered ASTRAL SUPERNOVA CINEMATIC to", out_file)