Build Windows / build (push) Has been cancelled
- Python-App cross-platform: %APPDATA%-Konfiguration, Terminal-Erkennung (wt/cmd/powershell), Windows-kompatibler SSH-Start, Segoe-UI-Fonts - App-Icon (ICO/PNG) mit Skript ohne externe Abhaengigkeiten - PyInstaller-Build (build_windows.bat) und Inno-Setup-Installer - Gitea-Actions-Workflow fuer automatischen Windows-Build - requirements.txt, .gitignore, README aktualisiert; __pycache__ entfernt
94 lines
2.6 KiB
Python
94 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Generiert das PulseGate-Icon als .ico (und .png) ohne externe Abhängigkeiten."""
|
|
from __future__ import annotations
|
|
|
|
import struct
|
|
import sys
|
|
import zlib
|
|
from pathlib import Path
|
|
|
|
ACCENT = (0x00, 0xFF, 0x99)
|
|
SURFACE = (0x0D, 0x1B, 0x15)
|
|
BG = (0x07, 0x11, 0x0D)
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
OUT_DIR = ROOT / "assets"
|
|
SIZES = [16, 32, 48, 64, 128, 256]
|
|
|
|
|
|
def pixel(size: int, x: int, y: int) -> tuple[int, int, int, int]:
|
|
nx = (x + 0.5) / size
|
|
ny = (y + 0.5) / size
|
|
|
|
if nx < 0.08 or nx > 0.92 or ny < 0.08 or ny > 0.92:
|
|
return (*ACCENT, 255)
|
|
|
|
if 0.34 < nx < 0.66 and 0.34 < ny < 0.66:
|
|
return (*ACCENT, 255)
|
|
|
|
if 0.24 < nx < 0.76 and 0.24 < ny < 0.76:
|
|
return (*SURFACE, 255)
|
|
|
|
return (*BG, 255)
|
|
|
|
|
|
def bmp_data(size: int) -> bytes:
|
|
header = struct.pack("<IiiHHIIiiII", 40, size, size * 2, 1, 32, 0, size * size * 4, 0, 0, 0, 0)
|
|
xor = bytearray()
|
|
for y in range(size - 1, -1, -1):
|
|
for x in range(size):
|
|
r, g, b, a = pixel(size, x, y)
|
|
xor += bytes((b, g, r, a))
|
|
return header + bytes(xor)
|
|
|
|
|
|
def write_ico(path: Path) -> None:
|
|
blocks = [bmp_data(size) for size in SIZES]
|
|
count = len(SIZES)
|
|
total_size = 6 + 16 * count + sum(len(b) for b in blocks)
|
|
|
|
out = bytearray(struct.pack("<HHH", 0, 1, count))
|
|
offset = 6 + 16 * count
|
|
for size, block in zip(SIZES, blocks):
|
|
entry = struct.pack(
|
|
"<BBBBHHII",
|
|
size % 256,
|
|
size % 256,
|
|
0,
|
|
0,
|
|
1,
|
|
32,
|
|
len(block),
|
|
offset,
|
|
)
|
|
out += entry
|
|
offset += len(block)
|
|
for block in blocks:
|
|
out += block
|
|
path.write_bytes(bytes(out))
|
|
|
|
|
|
def write_png(path: Path, size: int) -> None:
|
|
raw = bytearray()
|
|
for y in range(size):
|
|
raw += b"\x00"
|
|
for x in range(size):
|
|
raw += bytes(pixel(size, x, y))
|
|
ihdr = struct.pack(">IIBBBBB", size, size, 8, 6, 0, 0, 0)
|
|
chunks = []
|
|
for chunk_type, data in ((b"IHDR", ihdr), (b"IDAT", zlib.compress(bytes(raw), 9)), (b"IEND", b"")):
|
|
crc = zlib.crc32(chunk_type + data) & 0xFFFFFFFF
|
|
chunks.append(struct.pack(">I", len(data)) + chunk_type + data + struct.pack(">I", crc))
|
|
path.write_bytes(b"\x89PNG\r\n\x1a\n" + b"".join(chunks))
|
|
|
|
|
|
def main() -> int:
|
|
OUT_DIR.mkdir(parents=True, exist_ok=True)
|
|
write_ico(OUT_DIR / "pulsegate.ico")
|
|
write_png(OUT_DIR / "pulsegate.png", 256)
|
|
print(f"Assets erzeugt in {OUT_DIR}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |