Eerste commit voor Helvoirt Gevelreiniging
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
"""Genereer de social-share-afbeelding (OG-image) 1200x630 voor Helvoirt Gevelreiniging.
|
||||
|
||||
Neemt een echte werkfoto (schone gevel), crop-cover naar 1200x630, legt er een
|
||||
petrol-gradient over (links/onder donker voor leesbaarheid) en zet de wordmark +
|
||||
tagline + 4,9-Google-regel eroverheen. Output: public/images/og-default.webp.
|
||||
|
||||
Draaien (Windows):
|
||||
$py = "C:\\Users\\info\\AppData\\Local\\Programs\\Python\\Python312\\python.exe"
|
||||
& $py scripts/make-og.py
|
||||
"""
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import os
|
||||
|
||||
W, H = 1200, 630
|
||||
SRC = os.path.join("public", "images", "hero-after.webp")
|
||||
OUT = os.path.join("public", "images", "og-default.webp")
|
||||
|
||||
# Merkkleuren (uit tokens.css)
|
||||
PETROL_DEEP = (21, 54, 61) # #15363d
|
||||
CYAAN = (78, 191, 217) # #4ebfd9
|
||||
STAR = (255, 196, 0)
|
||||
WHITE = (255, 255, 255)
|
||||
SOFT = (199, 218, 224) # #c7dae0 (on-dark-soft)
|
||||
|
||||
FONTS = "C:/Windows/Fonts"
|
||||
|
||||
|
||||
def load(name, size):
|
||||
return ImageFont.truetype(os.path.join(FONTS, name), size)
|
||||
|
||||
|
||||
def cover(im, w, h):
|
||||
"""Schaal + crop zodat de foto het hele vlak vult (object-fit: cover)."""
|
||||
src_ratio = im.width / im.height
|
||||
dst_ratio = w / h
|
||||
if src_ratio > dst_ratio:
|
||||
new_h = h
|
||||
new_w = round(h * src_ratio)
|
||||
else:
|
||||
new_w = w
|
||||
new_h = round(w / src_ratio)
|
||||
im = im.resize((new_w, new_h), Image.LANCZOS)
|
||||
left = (new_w - w) // 2
|
||||
top = (new_h - h) // 2
|
||||
return im.crop((left, top, left + w, top + h))
|
||||
|
||||
|
||||
def main():
|
||||
base = cover(Image.open(SRC).convert("RGB"), W, H)
|
||||
|
||||
# Petrol-gradient: links sterk donker -> rechts transparant (tekst leesbaar links).
|
||||
overlay = Image.new("RGBA", (W, H), (0, 0, 0, 0))
|
||||
od = overlay.load()
|
||||
for x in range(W):
|
||||
# alpha van ~0.92 links naar ~0.05 rechts
|
||||
t = x / W
|
||||
a = int(235 * (1 - t) ** 1.5 + 12)
|
||||
for y in range(H):
|
||||
od[x, y] = (*PETROL_DEEP, a)
|
||||
# extra donkere voet onderaan voor de tagline
|
||||
foot = Image.new("RGBA", (W, H), (0, 0, 0, 0))
|
||||
fd = foot.load()
|
||||
for y in range(H):
|
||||
t = max(0, (y - H * 0.55) / (H * 0.45))
|
||||
a = int(160 * t)
|
||||
for x in range(W):
|
||||
fd[x, y] = (*PETROL_DEEP, a)
|
||||
|
||||
img = Image.alpha_composite(base.convert("RGBA"), overlay)
|
||||
img = Image.alpha_composite(img, foot)
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# Cyaan accent-balk links
|
||||
draw.rectangle([0, 0, 12, H], fill=CYAAN)
|
||||
|
||||
pad = 70
|
||||
# Wordmark (twee regels, zwaar)
|
||||
f_brand = load("ariblk.ttf", 86)
|
||||
f_sub = load("ariblk.ttf", 86)
|
||||
draw.text((pad, 150), "Helvoirt", font=f_brand, fill=WHITE)
|
||||
draw.text((pad, 248), "Gevelreiniging", font=f_sub, fill=CYAAN)
|
||||
|
||||
# Tagline
|
||||
f_tag = load("segoeui.ttf", 34)
|
||||
draw.text((pad, 372), "Gevelreiniging · voegwerk · dakreiniging + coating", font=f_tag, fill=SOFT)
|
||||
|
||||
# 4,9 op Google (sterren + tekst). Sterren via Segoe UI Symbol (heeft U+2605).
|
||||
f_score = load("arialbd.ttf", 40)
|
||||
f_stars = load("seguisym.ttf", 34)
|
||||
y_score = 452
|
||||
draw.text((pad, y_score), "★★★★★", font=f_stars, fill=STAR)
|
||||
stars_w = draw.textlength("★★★★★", font=f_stars)
|
||||
draw.text((pad + stars_w + 20, y_score - 3), "4,9 op Google", font=f_score, fill=WHITE)
|
||||
|
||||
# Werkgebied-regel
|
||||
f_region = load("segoeui.ttf", 28)
|
||||
draw.text((pad, 520), "Helvoirt en omgeving", font=f_region, fill=SOFT)
|
||||
|
||||
img.convert("RGB").save(OUT, "WEBP", quality=88, method=6)
|
||||
print("OG-image geschreven:", OUT, Image.open(OUT).size)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user