This commit is contained in:
Tour
2025-12-08 22:30:37 +01:00
parent 7f2c46773e
commit 613b6345f2
9 changed files with 1605 additions and 1393 deletions

BIN
public/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

File diff suppressed because it is too large Load Diff

BIN
public/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

BIN
public/favicon-256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
public/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

20
public/favicon.svg Normal file
View File

@@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64" role="img" aria-label="App.model">
<defs>
<linearGradient id="g" x1="0" x2="1" y1="0" y2="1">
<stop offset="0" stop-color="#60a5fa"/>
<stop offset="1" stop-color="#818cf8"/>
</linearGradient>
<filter id="s" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="0" dy="2" stdDeviation="4" flood-color="#0f172a" flood-opacity="0.6"/>
</filter>
</defs>
<rect x="2" y="2" width="60" height="60" rx="12" ry="12" fill="url(#g)" filter="url(#s)"/>
<g transform="translate(32,34) scale(0.9)">
<path d="M-12,-8 L0,-22 L12,-8 Z" fill="#0f172a" opacity="0.95"/>
<rect x="-10" y="-8" width="20" height="16" rx="3" ry="3" fill="#0f172a" opacity="0.95"/>
<rect x="-3" y="0" width="6" height="8" rx="1" ry="1" fill="#60a5fa"/>
<circle cx="10" cy="-4" r="3" fill="#fbbf24" stroke="#fff5" stroke-width="0.6"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 960 B

View File

@@ -1,14 +1,65 @@
from PIL import Image
# python
from pathlib import Path
import cairosvg
from PIL import Image
# Convert SVG to PNG first
png_path = "./public/img/favicon.png"
ico_path = "./public/img/favicon.ico"
PUBLIC = Path("./public")
PUBLIC.mkdir(parents=True, exist_ok=True)
cairosvg.svg2png(url="./public/img/favicon.svg", write_to=png_path)
# SVG content for `public/favicon.svg`
SVG = """<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64" role="img" aria-label="App.model">
<defs>
<linearGradient id="g" x1="0" x2="1" y1="0" y2="1">
<stop offset="0" stop-color="#60a5fa"/>
<stop offset="1" stop-color="#818cf8"/>
</linearGradient>
<filter id="s" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="0" dy="2" stdDeviation="4" flood-color="#0f172a" flood-opacity="0.6"/>
</filter>
</defs>
# Convert PNG → ICO
img = Image.open(png_path)
img.save(ico_path, format='ICO', sizes=[(32,32),(16,16), (48,48), (64,64)])
<rect x="2" y="2" width="60" height="60" rx="12" ry="12" fill="url(#g)" filter="url(#s)"/>
ico_path
<g transform="translate(32,34) scale(0.9)">
<path d="M-12,-8 L0,-22 L12,-8 Z" fill="#0f172a" opacity="0.95"/>
<rect x="-10" y="-8" width="20" height="16" rx="3" ry="3" fill="#0f172a" opacity="0.95"/>
<rect x="-3" y="0" width="6" height="8" rx="1" ry="1" fill="#60a5fa"/>
<circle cx="10" cy="-4" r="3" fill="#fbbf24" stroke="#fff5" stroke-width="0.6"/>
</g>
</svg>
"""
svg_path = PUBLIC / "favicon.svg"
svg_path.write_text(SVG, encoding="utf-8")
# Render a high-resolution source PNG (256x256) from the SVG
base_png = PUBLIC / "favicon-256.png"
cairosvg.svg2png(url=str(svg_path), write_to=str(base_png), output_width=256, output_height=256)
# Produce PNG icons at required sizes
sizes_and_names = [
(32, PUBLIC / "favicon-32x32.png"),
(16, PUBLIC / "favicon-16x16.png"),
(180, PUBLIC / "apple-touch-icon.png"),
]
with Image.open(base_png) as im:
im = im.convert("RGBA")
for size, out_path in sizes_and_names:
icon = im.resize((size, size), resample=Image.LANCZOS)
icon.save(out_path, format="PNG")
# Save multi-size ICO (source should be sufficiently large for quality)
ico_path = PUBLIC / "favicon.ico"
im.save(ico_path, format="ICO", sizes=[(16,16), (32,32), (48,48), (64,64)])
# Optionally remove the intermediate 256 PNG
# base_png.unlink()
print("Created:", *[str(p) for p in [
svg_path,
PUBLIC / "favicon-32x32.png",
PUBLIC / "favicon-16x16.png",
PUBLIC / "apple-touch-icon.png",
PUBLIC / "favicon.ico"
]])