gallery.py

At d794128

d794128History

Preview

Code · 2.7 KiB
#!/usr/bin/env python3
"""Render a labeled silhouette library and four curated glass compositions."""
from pathlib import Path
import argparse
from PIL import Image, ImageDraw, ImageFont
from shapes import SHAPES
from renderer import render

ROOT=Path(__file__).parent

def glass(role='middle',warmth=0.,hue=0.,opacity=.93):
    return dict(role=role,warmth=warmth,hue=hue,opacity=opacity)

def piece(name,center,radius,rotation,role):
    return dict(shape=name,center=center,radius=radius,rotation=rotation,material=glass(role))

STUDIES={
    'soft-forms':[
        piece('cloud',(300,350),240,-.3,'outer'),
        piece('bubbles',(588,580),305,.24,'middle'),
        piece('pebble',(365,864),240,-.45,'front')],
    'cutouts':[
        piece('seaweed',(305,365),252,-.3,'outer'),
        piece('coral',(604,554),325,.3,'middle'),
        piece('bean',(350,835),294,-.7,'front')],
    'celestial':[
        piece('crescent',(322,350),260,-.22,'outer'),
        piece('star',(594,559),326,.21,'middle'),
        piece('sparkle',(377,845),282,-.19,'front')],
    'orchard':[
        piece('apple',(337,395),223,-.18,'outer'),
        piece('pear',(614,563),316,.20,'middle'),
        piece('lemon',(355,826),277,-.48,'front')]
}

def font(size):
    # Pillow's bundled font keeps the sheet portable across operating systems.
    return ImageFont.load_default(size=size)

def sampler():
    cellw,cellh=360,420
    sheet=Image.new('RGB',(1440,1860),(241,235,232));draw=ImageDraw.Draw(sheet)
    draw.text((48,36),'GLASS / SHAPE LIBRARY',font=font(30),fill=(46,42,55))
    draw.text((48,83),'16 silhouettes · one iridescent material · generated from curves',font=font(17),fill=(104,97,110))
    for i,(name,label) in enumerate(SHAPES.items()):
        tile=render(scale=.34,specs=[piece(name,(486,565),370,0,'middle')])
        tile=tile.crop((0,10,tile.width,355))
        x=(i%4)*cellw; y=142+(i//4)*cellh
        sheet.paste(tile,(x+(cellw-tile.width)//2,y))
        draw.text((x+28,y+357),label,font=font(20),fill=(46,42,55))
        draw.text((x+28,y+385),name,font=font(14),fill=(112,103,117))
    return sheet

def main():
    ap=argparse.ArgumentParser(description=__doc__)
    ap.add_argument('--output-dir',type=Path,default=ROOT/'renders')
    ap.add_argument('--only',choices=['sampler',*STUDIES],help='Render only one asset')
    args=ap.parse_args();args.output_dir.mkdir(parents=True,exist_ok=True)
    if args.only in (None,'sampler'):
        path=args.output_dir/'shape-library.png';sampler().save(path);print(path)
    for name,specs in STUDIES.items():
        if args.only in (None,name):
            path=args.output_dir/f'shape-study-{name}.png'
            render(specs=specs).save(path);print(path)
if __name__=='__main__':main()

Files