← All projects · Project 01
Programmatic Creative Pipeline
A Python and Node tool that takes one campaign brief and renders sixteen finished ad images, four products across four placement ratios, then exports them as a file a designer can keep editing.
The problem
The job was resizing. Four products at 1:1, 4:5, 9:16 and 1.91:1 is sixteen versions of the same layout done by hand, and the headline ends up a different size on every one. So I stopped fixing outputs and wrote the thing that makes them.
How it works
The drawing was not the hard part. The layout solver was. Text scales itself down until it fits inside each placement's safe area, and the payment marks are generated at render time rather than pasted in, so they are always the right size for the frame they land in.

The bit that does the work
1def autofit(t, fn, start, mw, tr=0): 2 """shrink until the string fits the safe width""" 3 z = start 4 while z > 10: 5 f = F(fn, z) 6 if tw(t, f, tr) <= mw: return f 7 z -= 2 8 return F(fn, 10) 9 10def text(cx, y, t, f, fill, tr=0, box=None): 11 x = cx - tw(t, f, tr) / 2 # centre on the axis 12 if tr == 0: d.text((x, y), t, font=f, fill=fill) 13 else: # manual letter-spacing 14 xx = x 15 for c in t: 16 b = d.textbbox((0, 0), c, font=f) 17 d.text((xx, y), c, font=f, fill=fill) 18 xx += b[2] - b[0] + tr 19 20 # every drawn element is also written to a spec, 21 # which is what makes the .pptx export possible 22 SPEC.append(dict( 23 kind='text', text=t, cx=cx, size=f.size, 24 color=HEX(fill), tracking=tr, weight=weight))
The layout solver: start big, measure, step down until the text fits the frame's safe width. Every element it draws also gets appended to a spec list, which is what lets the Node script rebuild the whole thing as an editable file.
What I learned. The interesting problem usually sits one level below the one you were handed. I was asked for ad variations and what I actually needed was a constraint solver. A tool nobody else can open is a dead end too, so exporting to an editable file mattered as much as the rendering did.