import sys import os import math from PIL import Image, ImageDraw, ImageFilter def create_app_icon(output_dir): os.makedirs(output_dir, exist_ok=True) iconset_dir = os.path.join(output_dir, "AppIcon.iconset") os.makedirs(iconset_dir, exist_ok=True) size = 1024 img = Image.new("RGBA", (size, size), (0, 0, 0, 0)) draw = ImageDraw.Draw(img) # Background Squircle / Rounded rect with gradient margin = 80 rect = [margin, margin, size - margin, size - margin] radius = 200 # Create base squircle mask mask = Image.new("L", (size, size), 0) mask_draw = ImageDraw.Draw(mask) mask_draw.rounded_rectangle(rect, radius=radius, fill=255) # Render gradient grad = Image.new("RGBA", (size, size)) grad_draw = ImageDraw.Draw(grad) # Rich Purple / Blue / Cyber Teal gradient for y in range(size): ratio = y / size r = int(79 + (124 - 79) * ratio) g = int(70 + (58 - 70) * ratio) b = int(229 + (237 - 229) * ratio) grad_draw.line([(0, y), (size, y)], fill=(r, g, b, 255)) img.paste(grad, (0, 0), mask) # Draw Inner Glowing Waveform & Microphone draw = ImageDraw.Draw(img) # Mic Capsule center_x = size // 2 center_y = size // 2 - 40 mic_w = 120 mic_h = 240 # Glow behind mic glow = Image.new("RGBA", (size, size), (0, 0, 0, 0)) glow_draw = ImageDraw.Draw(glow) glow_draw.rounded_rectangle([center_x - mic_w//2 - 20, center_y - mic_h//2 - 20, center_x + mic_w//2 + 20, center_y + mic_h//2 + 20], radius=80, fill=(255, 255, 255, 60)) glow = glow.filter(ImageFilter.GaussianBlur(30)) img.alpha_composite(glow) draw = ImageDraw.Draw(img) # Mic Body (Capsule) draw.rounded_rectangle( [center_x - mic_w//2, center_y - mic_h//2, center_x + mic_w//2, center_y + mic_h//2], radius=60, fill=(255, 255, 255, 250) ) # Mic Arc / Cradle cradle_w = 220 cradle_h = 200 arc_top = center_y - 20 draw.arc( [center_x - cradle_w//2, arc_top, center_x + cradle_w//2, arc_top + cradle_h], start=0, end=180, fill=(255, 255, 255, 240), width=24 ) # Mic Stand / Stem stem_top = arc_top + cradle_h draw.line([(center_x, stem_top), (center_x, stem_top + 70)], fill=(255, 255, 255, 240), width=24) # Mic Base draw.line([(center_x - 80, stem_top + 70), (center_x + 80, stem_top + 70)], fill=(255, 255, 255, 240), width=24) # Sonic Sound Waves on sides for side in [-1, 1]: for i, r in enumerate([190, 260]): wave_cx = center_x + side * 40 wave_w = r * 2 wave_h = r * 2 start_ang = 300 if side == 1 else 120 end_ang = 60 if side == 1 else 240 draw.arc( [wave_cx - wave_w//2, center_y - wave_h//2, wave_cx + wave_w//2, center_y + wave_h//2], start=start_ang, end=end_ang, fill=(255, 255, 255, 180 - i * 60), width=18 ) # Save standard sizes sizes = [ (16, "icon_16x16.png"), (32, "icon_16x16@2x.png"), (32, "icon_32x32.png"), (64, "icon_32x32@2x.png"), (128, "icon_128x128.png"), (256, "icon_128x128@2x.png"), (256, "icon_256x256.png"), (512, "icon_256x256@2x.png"), (512, "icon_512x512.png"), (1024, "icon_512x512@2x.png"), ] for s, name in sizes: resized = img.resize((s, s), Image.Resampling.LANCZOS) resized.save(os.path.join(iconset_dir, name)) master_path = os.path.join(output_dir, "AppIcon.png") img.save(master_path) print("Iconset generated in", iconset_dir) if __name__ == "__main__": create_app_icon("/tmp/soniox_build/resources")