"""Wandelt die Originalfotos aus tools/orig in AVIF und WebP (800 px und volle Breite) für assets/img um. Die Originale stammen von der alten Seite normtor.de. Neue Fotos in tools/orig ablegen, unten in IMAGES eintragen und neu erzeugen: python3 tools/build_images.py (braucht Pillow mit AVIF: pip install pillow) """ from pathlib import Path from PIL import Image, ImageOps ROOT = Path(__file__).resolve().parent.parent SRC = ROOT / "tools/orig" OUT = ROOT / "assets/img" # Ziel-Name: (Quelldatei, Zuschnitt als (links, oben, rechts, unten) in Pixeln oder None) IMAGES = { "hero": ("dst_superior_style_graualu.jpg", None), "haas": ("haas.jpg", (80, 0, 880, 960)), "flair-1": ("flair_db_703_1.jpg", None), "flair-2": ("flair_db_703_2.jpg", None), "garagenhof": ("web1.jpg", None), "doppelgarage-beige": ("web2.jpg", None), "anthrazit-solo": ("web3.jpg", None), "doppelgarage-hell": ("web4.jpg", None), "anthrazit-iso": ("web5.jpg", None), "condor-granit": ("condoor_granit.jpg", None), "condor-schraegschnitt": ("condoor_schraegschnitt1.jpg", None), "condor-ligna": ("condoor_wood_ligna_light2.jpg", None), "condor-schlupftuer": ("condor-mit-schlupftuerer.jpg", None), "smart-style": ("dst_smart_style_anth_glatt.jpg", None), "smart-trend": ("dst_smart_trend_eiche_dunkel_woodgrain.jpg", None), "superior-eiche": ("dst_superior_eiche_hell_style_glatt_01.jpg", None), "superior-linea": ("dst_superior_linea_verkehrsweiss_glatt.jpg", None), "superior-graualu": ("dst_superior_style_graualu.jpg", None), "sst-style": ("sst_style_anthrazitgrau_01.jpg", None), "sst-trend": ("sst_trend_anthrazitgrau_01.jpg", None), "sst-design": ("sst.gif", None), "mueller-muenster": ("mueller_muenster.jpg", None), "essenbach-ohu": ("essenbach-ohu1.jpg", None), "elegant": ("elegant-taubenblau.gif", None), "variant": ("modell-variant.jpg", None), "rustiko": ("eder2.jpg", None), "prominent-rottenburg": ("jahnstr-rottenburg.jpg", None), "eurostyle-iso": ("muech3.jpg", None), "topline-iso": ("rott2.jpg", None), } def save(im, name, w): if im.width > w: im = im.resize((w, round(im.height * w / im.width)), Image.LANCZOS) im.save(OUT / f"{name}-{w}.webp", quality=80, method=6) im.save(OUT / f"{name}-{w}.avif", quality=58, speed=4) def main(): OUT.mkdir(parents=True, exist_ok=True) for old in OUT.glob("*"): old.unlink() for name, (src, crop) in IMAGES.items(): im = ImageOps.exif_transpose(Image.open(SRC / src)).convert("RGB") if crop: im = im.crop(crop) # Kleine Altbilder (350 px) gibt es nur als -800 (in Originalgröße), große zusätzlich als -1200 save(im, name, 800) if im.width > 800: save(im, name, 1200) # Vorschaubild für Messenger und soziale Netzwerke hero = Image.open(SRC / IMAGES["hero"][0]).convert("RGB") ImageOps.fit(hero, (1200, 630), centering=(0.5, 0.6)).save(OUT / "og.jpg", quality=82) print(f"{len(IMAGES)} Bilder nach {OUT.relative_to(ROOT)} geschrieben") if __name__ == "__main__": main()