← back to Beverlyhillsvideos
filmgen/brand_assets.py
51 lines
#!/usr/bin/env python3
"""Beverly Hills Videos brand assets: avatar, YouTube banner, Story-highlight covers."""
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import os
OUT = "public/social"; os.makedirs(OUT, exist_ok=True)
CREAM=(246,243,236); INK=(21,19,16); GREEN=(31,61,48); GOLD=(184,147,90); MUTED=(150,143,130)
SERIF="/System/Library/Fonts/Supplemental/Didot.ttc"
SANS="filmgen/fonts/Jost.ttf"
def sf(sz,i=0): return ImageFont.truetype(SERIF,sz,index=i)
def jf(sz): return ImageFont.truetype(SANS,sz)
def center(d,cx,y,txt,fnt,fill):
w=d.textlength(txt,font=fnt); d.text((cx-w/2,y),txt,font=fnt,fill=fill); return w
def tracked(d,cx,y,txt,fnt,fill,tr):
ws=[d.textlength(c,font=fnt) for c in txt]; tot=sum(ws)+tr*(len(txt)-1); x=cx-tot/2
for c,w in zip(txt,ws): d.text((x,y),c,font=fnt,fill=fill); x+=w+tr
def avatar():
S=1080; img=Image.new("RGB",(S,S),GREEN); d=ImageDraw.Draw(img)
# gold hairline ring
m=int(S*0.055); d.ellipse([m,m,S-m,S-m],outline=GOLD,width=3)
# BHV monogram
f=sf(430); center(d,S/2,S*0.20,"BHV",f,GOLD)
# micro wordmark
tracked(d,S/2,S*0.70,"BEVERLY HILLS VIDEOS",jf(34),CREAM,10)
img.save(f"{OUT}/avatar.png"); print("avatar.png 1080x1080")
def banner():
W,H=2560,1440; img=Image.new("RGB",(W,H),CREAM); d=ImageDraw.Draw(img)
cx=W/2
# subtle top/bottom green hairlines outside safe zone for depth
d.rectangle([0,0,W,10],fill=GREEN); d.rectangle([0,H-10,W,H],fill=GREEN)
# safe zone reference: central 1546x423 (y 508..931)
y0=508
tracked(d,cx,y0+30,"THE INSIDER FILM GUIDE",jf(30),GOLD,14)
center(d,cx,y0+95,"BEVERLY HILLS VIDEOS",sf(150),INK)
# gold hairline rule under wordmark
d.line([(cx-90,y0+300),(cx+90,y0+300)],fill=GOLD,width=2)
center(d,cx,y0+320,"Restaurant Films · Rodeo Drive · Five-Star Living",sf(46,1),MUTED)
img.save(f"{OUT}/banner.png"); print("banner.png 2560x1440 (text within 1546x423 safe zone)")
def highlight(label):
S=1080; img=Image.new("RGB",(S,S),CREAM); d=ImageDraw.Draw(img)
m=int(S*0.14); d.ellipse([m,m,S-m,S-m],outline=GREEN,width=6)
d.ellipse([m+18,m+18,S-m-18,S-m-18],outline=GOLD,width=2)
tracked(d,S/2,S*0.44,label.upper(),jf(88),GREEN,10)
img.save(f"{OUT}/highlight-{label.lower()}.png")
avatar(); banner()
for lb in ["Dining","Shopping","Hotels","Map","Guides"]: highlight(lb)
print("highlight covers:", "Dining Shopping Hotels Map Guides")