165 lines
5.2 KiB
Python
165 lines
5.2 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
Icon-Generator für DocuMentor
|
||
|
|
|
||
|
|
Erstellt ein Icon aus einem PNG oder generiert ein Standard-Icon.
|
||
|
|
Unterstützt Windows (.ico) und verschiedene Größen.
|
||
|
|
|
||
|
|
Verwendung:
|
||
|
|
python create_icon.py # Generiert Standard-Icon
|
||
|
|
python create_icon.py source.png # Konvertiert PNG zu ICO
|
||
|
|
"""
|
||
|
|
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
try:
|
||
|
|
from PIL import Image, ImageDraw, ImageFont
|
||
|
|
except ImportError:
|
||
|
|
print("Fehler: Pillow ist nicht installiert.")
|
||
|
|
print("Installation: uv pip install pillow")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
|
||
|
|
def create_default_icon(output_path: Path):
|
||
|
|
"""Erstellt ein Standard-Icon mit DocuMentor-Branding."""
|
||
|
|
sizes = [256, 128, 64, 48, 32, 16]
|
||
|
|
images = []
|
||
|
|
|
||
|
|
for size in sizes:
|
||
|
|
# Neues Bild erstellen mit Farbverlauf
|
||
|
|
img = Image.new('RGB', (size, size), color='white')
|
||
|
|
draw = ImageDraw.Draw(img)
|
||
|
|
|
||
|
|
# Hintergrund: Blau-Verlauf (vereinfacht als solides Blau)
|
||
|
|
bg_color = (41, 128, 185) # Professionelles Blau
|
||
|
|
draw.rectangle([0, 0, size, size], fill=bg_color)
|
||
|
|
|
||
|
|
# Dokument-Symbol (vereinfachte Darstellung)
|
||
|
|
margin = size // 8
|
||
|
|
doc_left = margin
|
||
|
|
doc_top = margin
|
||
|
|
doc_right = size - margin
|
||
|
|
doc_bottom = size - margin
|
||
|
|
|
||
|
|
# Weißes Dokument
|
||
|
|
draw.rectangle(
|
||
|
|
[doc_left, doc_top, doc_right, doc_bottom],
|
||
|
|
fill='white',
|
||
|
|
outline=(52, 73, 94),
|
||
|
|
width=max(1, size // 64)
|
||
|
|
)
|
||
|
|
|
||
|
|
# Ecke umgeknickt (rechts oben)
|
||
|
|
fold_size = size // 6
|
||
|
|
points = [
|
||
|
|
(doc_right - fold_size, doc_top),
|
||
|
|
(doc_right, doc_top + fold_size),
|
||
|
|
(doc_right - fold_size, doc_top + fold_size),
|
||
|
|
]
|
||
|
|
draw.polygon(points, fill=(220, 220, 220), outline=(52, 73, 94))
|
||
|
|
|
||
|
|
# Text-Linien im Dokument (nur bei größeren Icons)
|
||
|
|
if size >= 32:
|
||
|
|
line_margin = doc_left + size // 12
|
||
|
|
line_width = doc_right - doc_left - size // 6
|
||
|
|
line_count = min(3, size // 32)
|
||
|
|
line_spacing = (doc_bottom - doc_top - fold_size) // (line_count + 2)
|
||
|
|
|
||
|
|
for i in range(line_count):
|
||
|
|
y = doc_top + fold_size + line_spacing * (i + 1)
|
||
|
|
draw.rectangle(
|
||
|
|
[line_margin, y, line_margin + line_width, y + max(1, size // 128)],
|
||
|
|
fill=(52, 73, 94)
|
||
|
|
)
|
||
|
|
|
||
|
|
# "M" für Mentor (nur bei großen Icons)
|
||
|
|
if size >= 64:
|
||
|
|
try:
|
||
|
|
# Versuche System-Font zu verwenden
|
||
|
|
font_size = size // 4
|
||
|
|
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", font_size)
|
||
|
|
except:
|
||
|
|
# Fallback auf Default-Font
|
||
|
|
font = ImageFont.load_default()
|
||
|
|
|
||
|
|
text = "M"
|
||
|
|
# Zentrieren (grobe Schätzung)
|
||
|
|
bbox = draw.textbbox((0, 0), text, font=font)
|
||
|
|
text_width = bbox[2] - bbox[0]
|
||
|
|
text_height = bbox[3] - bbox[1]
|
||
|
|
text_x = (size - text_width) // 2
|
||
|
|
text_y = doc_bottom - text_height - margin // 2
|
||
|
|
|
||
|
|
draw.text((text_x, text_y), text, fill=bg_color, font=font)
|
||
|
|
|
||
|
|
images.append(img)
|
||
|
|
|
||
|
|
# Als ICO speichern
|
||
|
|
images[0].save(
|
||
|
|
output_path,
|
||
|
|
format='ICO',
|
||
|
|
sizes=[(img.width, img.height) for img in images],
|
||
|
|
append_images=images[1:]
|
||
|
|
)
|
||
|
|
print(f"✓ Standard-Icon erstellt: {output_path}")
|
||
|
|
|
||
|
|
|
||
|
|
def convert_png_to_ico(source_path: Path, output_path: Path):
|
||
|
|
"""Konvertiert ein PNG-Bild zu einem Multi-Size ICO."""
|
||
|
|
try:
|
||
|
|
img = Image.open(source_path)
|
||
|
|
|
||
|
|
# Zu RGBA konvertieren falls nötig
|
||
|
|
if img.mode != 'RGBA':
|
||
|
|
img = img.convert('RGBA')
|
||
|
|
|
||
|
|
# Verschiedene Größen erstellen
|
||
|
|
sizes = [256, 128, 64, 48, 32, 16]
|
||
|
|
images = []
|
||
|
|
|
||
|
|
for size in sizes:
|
||
|
|
resized = img.resize((size, size), Image.Resampling.LANCZOS)
|
||
|
|
images.append(resized)
|
||
|
|
|
||
|
|
# Als ICO speichern
|
||
|
|
images[0].save(
|
||
|
|
output_path,
|
||
|
|
format='ICO',
|
||
|
|
sizes=[(img.width, img.height) for img in images],
|
||
|
|
append_images=images[1:]
|
||
|
|
)
|
||
|
|
print(f"✓ Icon erstellt aus {source_path.name}: {output_path}")
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
print(f"✗ Fehler beim Konvertieren: {e}")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
project_root = Path(__file__).parent
|
||
|
|
resources_dir = project_root / "resources"
|
||
|
|
resources_dir.mkdir(exist_ok=True)
|
||
|
|
|
||
|
|
output_ico = resources_dir / "icon.ico"
|
||
|
|
|
||
|
|
if len(sys.argv) > 1:
|
||
|
|
# PNG zu ICO konvertieren
|
||
|
|
source_path = Path(sys.argv[1])
|
||
|
|
if not source_path.exists():
|
||
|
|
print(f"Fehler: Datei nicht gefunden: {source_path}")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
convert_png_to_ico(source_path, output_ico)
|
||
|
|
else:
|
||
|
|
# Standard-Icon generieren
|
||
|
|
print("Erstelle Standard-Icon...")
|
||
|
|
create_default_icon(output_ico)
|
||
|
|
|
||
|
|
print(f"\nIcon gespeichert: {output_ico}")
|
||
|
|
print("Das Icon wird automatisch von PyInstaller und Inno Setup verwendet.")
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|