Akquise-Demo mit Startseite (Tor-Intro, 24-h-Renovierung mit Uhr, Über uns, Fachbetrieb statt Discount), Galerie mit Filter und Großansicht, Kontaktseite mit Anfrageformular sowie Impressum- und Datenschutz-Entwürfen. Statisches HTML/CSS/JS, Seiten und Bilder werden über tools/ erzeugt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
76 lines
3.1 KiB
Python
76 lines
3.1 KiB
Python
"""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()
|