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.
121 lines
3.8 KiB
121 lines
3.8 KiB
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, "[email protected]"),
|
|
(32, "icon_32x32.png"),
|
|
(64, "[email protected]"),
|
|
(128, "icon_128x128.png"),
|
|
(256, "[email protected]"),
|
|
(256, "icon_256x256.png"),
|
|
(512, "[email protected]"),
|
|
(512, "icon_512x512.png"),
|
|
(1024, "[email protected]"),
|
|
]
|
|
|
|
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")
|