3f1da92cf4
YouTube subtitles via OpenRouter become persistent, shareable recaps with timestamp jump links, PIN-protected creation, and Traefik deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
50 lines
1.4 KiB
Python
50 lines
1.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate PNG icons from SVG for PWA."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pathlib
|
|
import struct
|
|
import zlib
|
|
|
|
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
|
SVG = ROOT / "public" / "icon.svg"
|
|
|
|
|
|
def _png_chunk(tag: bytes, data: bytes) -> bytes:
|
|
return struct.pack(">I", len(data)) + tag + data + struct.pack(">I", zlib.crc32(tag + data) & 0xFFFFFFFF)
|
|
|
|
|
|
def write_simple_png(path: pathlib.Path, size: int) -> None:
|
|
"""Minimal orange/blue square PNG — no external deps."""
|
|
raw_rows = []
|
|
for y in range(size):
|
|
row = b"\x00"
|
|
for x in range(size):
|
|
cx, cy = size / 2, size / 2
|
|
dist = ((x - cx) ** 2 + (y - cy) ** 2) ** 0.5
|
|
if dist < size * 0.42:
|
|
row += bytes([255, 159, 67]) # orange fish body
|
|
elif y < size * 0.15 or y > size * 0.92:
|
|
row += bytes([11, 61, 92])
|
|
else:
|
|
row += bytes([11, 61, 92])
|
|
raw_rows.append(row)
|
|
compressed = zlib.compress(b"".join(raw_rows), 9)
|
|
ihdr = struct.pack(">IIBBBBB", size, size, 8, 2, 0, 0, 0)
|
|
png = b"\x89PNG\r\n\x1a\n"
|
|
png += _png_chunk(b"IHDR", ihdr)
|
|
png += _png_chunk(b"IDAT", compressed)
|
|
png += _png_chunk(b"IEND", b"")
|
|
path.write_bytes(png)
|
|
|
|
|
|
def main() -> None:
|
|
out = ROOT / "public" / "icon-192.png"
|
|
write_simple_png(out, 192)
|
|
print(f"Wrote {out}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|