Windows-Support, Build-Skripte und Installer fuer PulseGate Desktop
Build Windows / build (push) Has been cancelled
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
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
#!/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())
|
||||
Reference in New Issue
Block a user