← 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")