"""Generate MixBoard iOS app icon — a stylized mixing board fader knob with a music note, on a dark gradient background.""" from PIL import Image, ImageDraw, ImageFont import math SIZE = 1024 CENTER = SIZE // 2 img = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0)) draw = ImageDraw.Draw(img) # Background — dark gradient with subtle green tint (Winamp vibes) for y in range(SIZE): t = y / SIZE r = int(10 + 15 * t) g = int(15 + 25 * t) b = int(12 + 18 * t) draw.line([(0, y), (SIZE, y)], fill=(r, g, b, 255)) # Rounded corners mask mask = Image.new("L", (SIZE, SIZE), 0) mask_draw = ImageDraw.Draw(mask) radius = int(SIZE * 0.22) mask_draw.rounded_rectangle([(0, 0), (SIZE - 1, SIZE - 1)], radius=radius, fill=255) # Apply rounded corners img.putalpha(mask) # Outer glow ring ring_cx, ring_cy = CENTER, CENTER + 20 ring_r_outer = 380 ring_r_inner = 310 for angle_deg in range(360): angle = math.radians(angle_deg) # Green glow gradient around the ring intensity = 0.6 + 0.4 * math.sin(angle * 2 + 0.5) g_val = int(200 * intensity) for r_offset in range(ring_r_inner, ring_r_outer): alpha_factor = 1.0 - abs(r_offset - (ring_r_inner + ring_r_outer) / 2) / ((ring_r_outer - ring_r_inner) / 2) alpha_factor = max(0, alpha_factor) ** 1.5 x = int(ring_cx + r_offset * math.cos(angle)) y = int(ring_cy + r_offset * math.sin(angle)) if 0 <= x < SIZE and 0 <= y < SIZE: existing = img.getpixel((x, y)) new_g = min(255, existing[1] + int(g_val * alpha_factor * 0.5)) img.putpixel((x, y), (existing[0], new_g, existing[2], existing[3])) # Central knob (fader/mixing board aesthetic) knob_r = 260 # Dark circle for y_off in range(-knob_r, knob_r + 1): for x_off in range(-knob_r, knob_r + 1): dist = math.sqrt(x_off ** 2 + y_off ** 2) if dist <= knob_r: x = ring_cx + x_off y = ring_cy + y_off if 0 <= x < SIZE and 0 <= y < SIZE: # Metallic gradient t = (y_off + knob_r) / (2 * knob_r) base = int(30 + 35 * (1 - t)) # Edge highlight edge = max(0, 1 - (knob_r - dist) / 15) if dist > knob_r - 15 else 0 highlight = int(80 * edge) r_val = min(255, base + highlight) g_val = min(255, base + highlight + int(20 * edge)) b_val = min(255, base + highlight) img.putpixel((int(x), int(y)), (r_val, g_val, b_val, 255)) # Knob indicator line (green, pointing up — like a fader position) line_w = 8 for y_off in range(-knob_r + 30, -60): for x_off in range(-line_w, line_w + 1): x = ring_cx + x_off y = ring_cy + y_off if 0 <= x < SIZE and 0 <= y < SIZE: dist_from_center = abs(x_off) alpha = max(0, 1 - dist_from_center / line_w) g_val = int(255 * alpha) existing = img.getpixel((x, y)) img.putpixel((x, y), (0, g_val, 0, 255)) # Music note symbol in center # Draw a simple eighth note note_cx, note_cy = ring_cx + 10, ring_cy + 30 note_color = (0, 220, 0, 255) # Note head (filled ellipse) head_rx, head_ry = 45, 35 for y_off in range(-head_ry, head_ry + 1): for x_off in range(-head_rx, head_rx + 1): # Rotated ellipse angle = -0.4 rx = x_off * math.cos(angle) - y_off * math.sin(angle) ry = x_off * math.sin(angle) + y_off * math.cos(angle) if (rx / head_rx) ** 2 + (ry / head_ry) ** 2 <= 1: x = note_cx + x_off y = note_cy + y_off if 0 <= x < SIZE and 0 <= y < SIZE: img.putpixel((int(x), int(y)), note_color) # Note stem stem_x = note_cx + 40 for y_off in range(-160, 10): for x_off in range(-4, 5): x = stem_x + x_off y = note_cy + y_off if 0 <= x < SIZE and 0 <= y < SIZE: img.putpixel((int(x), int(y)), note_color) # Flag (curved) for i in range(60): t = i / 60 fx = stem_x + int(35 * math.sin(t * math.pi * 0.8)) fy = note_cy - 160 + int(60 * t) for dx in range(-3, 4): for dy in range(-2, 3): x, y = fx + dx, fy + dy if 0 <= x < SIZE and 0 <= y < SIZE: img.putpixel((x, y), note_color) # "MB" text at bottom # Use a simple approach — draw M and B with rectangles text_y = SIZE - 130 text_color = (0, 180, 0, 200) # Just add a subtle "MixBoard" text feel with dots for i, char_x in enumerate(range(CENTER - 100, CENTER + 120, 22)): dot_r = 4 for dy in range(-dot_r, dot_r + 1): for dx in range(-dot_r, dot_r + 1): if dx ** 2 + dy ** 2 <= dot_r ** 2: x, y = char_x + dx, text_y + dy if 0 <= x < SIZE and 0 <= y < SIZE: alpha = int(150 * (1 - (dx ** 2 + dy ** 2) / dot_r ** 2)) existing = img.getpixel((x, y)) img.putpixel((x, y), (0, min(255, existing[1] + alpha), 0, existing[3])) # Save output_path = "/Users/vdrobkov/Misc/Documents/Copilot/Mixboard iOS/Sources/Resources/Assets.xcassets/AppIcon.appiconset/icon_1024.png" img.save(output_path, "PNG") print(f"Icon saved to {output_path}") print(f"Size: {img.size}")