37 lines
1.9 KiB
Python
37 lines
1.9 KiB
Python
"""Work-Death Balance icon: the existing nerd-zombie face in an amber badge.
|
|
|
|
Called by make_boot_splash.py with the already keyed full-resolution mascot, so
|
|
there is no second keying pass or new AI artwork. Reference coordinates are for
|
|
our original 1024x1024 mascot (not a generic automatic face detector).
|
|
"""
|
|
import hashlib
|
|
from pathlib import Path
|
|
from PIL import Image, ImageChops, ImageDraw
|
|
|
|
|
|
def build_favicon(mascot: Image.Image, root: Path) -> dict:
|
|
assert mascot.size == (1024, 1024), 'Update the head mask for a different source'
|
|
face = mascot.convert('RGBA').copy()
|
|
mask = Image.new('L', face.size)
|
|
ImageDraw.Draw(mask).polygon([
|
|
(235, 240), (280, 195), (320, 110), (512, 80), (700, 140),
|
|
(780, 245), (770, 385), (748, 460), (694, 610), (640, 710),
|
|
(530, 755), (420, 735), (328, 650), (277, 520), (228, 395),
|
|
], fill=255)
|
|
face.putalpha(ImageChops.multiply(face.getchannel('A'), mask))
|
|
face = face.crop((220, 80, 790, 755))
|
|
face.thumbnail((440, 460), Image.Resampling.LANCZOS)
|
|
icon = Image.new('RGBA', (512, 512))
|
|
ImageDraw.Draw(icon).rounded_rectangle((7, 7, 504, 504), radius=96,
|
|
fill=(13, 16, 15, 255),
|
|
outline=(255, 186, 48, 255), width=14)
|
|
icon.alpha_composite(face, ((512 - face.width) // 2, (512 - face.height) // 2))
|
|
output = root / 'assets/branding/work_death_icon.png'
|
|
icon.save(output, optimize=True)
|
|
preview = root / 'tools/branding/favicon_preview_32.png'
|
|
icon.resize((32, 32), Image.Resampling.LANCZOS).save(preview, optimize=True)
|
|
return {'file': str(output.relative_to(root)), 'size': [512, 512],
|
|
'sha256': hashlib.sha256(output.read_bytes()).hexdigest(),
|
|
'method': 'existing chroma-keyed mascot head, dark rounded badge, amber outline; Pillow',
|
|
'preview': str(preview.relative_to(root))}
|