Create a single team image from a folder full of portraits. The script in src/team_grid.py crops each photo, applies a rounded border, and renders the person’s name underneath so you can drop the finished grid into presentations or documentation.
- Python 3.9+ (ships with macOS and most Linux distributions)
pipto install the one dependency (Pillow, for image processing)
python3 -m venv .venv
source .venv/bin/activate
pip install PillowThe virtual environment is optional, but it keeps the dependency isolated.
- Add portrait images (
.png,.jpg,.jpeg) to theimport/directory. The folder is in.gitignore, so none of the source photos are checked in. - Provide labels so the script knows which name goes with each file. By default it looks for
import/labels.json:
{
"portrait-ada.png": "Ada Lovelace",
"grace_hopper.jpg": "Grace Hopper"
}You can also supply labels as a CSV (filename,name) or a plain text file with filename=Name pairs, and point to it with --labels. Individual overrides are supported with --name image.png="Display Name" or with inline JSON via --labels-json '{"image.png": "Display Name"}'.
python3 src/team_grid.py \
--input-dir import \
--labels import/labels.json \
--output export/team-grid.png--input-dirdefaults toimport.--outputdefaults toexport/team-grid.png; the folder is created automatically.--sort labelsorts the grid by the rendered name instead of the filename.
When the command finishes, open the PNG in export/ to review the result.
--columns 5changes how many portraits fit per row, or omit it to let the script pick an even grid.--width/--heightcontrol the canvas size.--background "#f5f5f5"fills the canvas instead of staying transparent.--image-size,--border, and--border-radiustune the portrait frame.--font,--font-size,--min-font-size, and--text-coloradjust the label pill.--focus-x/--focus-ybias the crop for portraits that need extra headroom.
Run python3 src/team_grid.py --help for the full list of options.
- “No supported images found”: confirm the input directory contains
.png,.jpg, or.jpegfiles. - “Labels file not found”: either create
import/labels.jsonor point to a different file with--labels. - Missing font characters: supply a custom font file via
--font path/to/font.ttf.
Keep this README close, drop fresh portraits in import/, update labels.json, and rerun the command whenever you need an updated team grid.