DesignGym / core /contact.py
AdithyaSK's picture
AdithyaSK HF Staff
Serve Crello corpus aafdb0e86816 from the mounted bucket
df84e45 verified
Raw History Blame Contribute Delete
2.26 kB
"""Contact sheet: every asset of a task in one labelled image.
A vision model on the tools surface cannot open files, so it needs to *see*
which asset is which before it can place `a3` on the canvas. One image with a
labelled tile per asset is far cheaper than one tool call per asset, and the
checkerboard shows which assets are cut-outs and which are opaque photos.
"""
from __future__ import annotations
import io
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
TILE = 180
LABEL = 26
PAD = 10
def _checker(size: tuple[int, int], cell: int = 10) -> Image.Image:
img = Image.new("RGB", size, (255, 255, 255))
draw = ImageDraw.Draw(img)
for y in range(0, size[1], cell):
for x in range(0, size[0], cell):
if (x // cell + y // cell) % 2:
draw.rectangle([x, y, x + cell - 1, y + cell - 1], fill=(228, 228, 228))
return img
def contact_sheet(assets: list[dict], paths: dict[str, Path], font_path: Path | None = None,
cols: int = 4) -> bytes:
n = len(assets)
cols = max(1, min(cols, n))
rows = (n + cols - 1) // cols
width = cols * (TILE + PAD) + PAD
height = rows * (TILE + LABEL + PAD) + PAD
sheet = Image.new("RGB", (width, max(height, TILE)), (246, 246, 248))
draw = ImageDraw.Draw(sheet)
try:
font = ImageFont.truetype(str(font_path), 16) if font_path else ImageFont.load_default(16)
except Exception:
font = ImageFont.load_default()
for i, asset in enumerate(assets):
r, c = divmod(i, cols)
x0 = PAD + c * (TILE + PAD)
y0 = PAD + r * (TILE + LABEL + PAD)
tile = _checker((TILE, TILE))
with Image.open(paths[asset["id"]]) as im:
im = im.convert("RGBA")
im.thumbnail((TILE - 8, TILE - 8))
tile.paste(im, ((TILE - im.width) // 2, (TILE - im.height) // 2), im)
sheet.paste(tile, (x0, y0))
draw.rectangle([x0, y0, x0 + TILE - 1, y0 + TILE - 1], outline=(200, 200, 205))
label = f"{asset['id']} {asset['kind']} {asset['aspect']:.2f}:1"
draw.text((x0 + 2, y0 + TILE + 4), label, fill=(30, 30, 35), font=font)
buf = io.BytesIO()
sheet.save(buf, "PNG", optimize=True)
return buf.getvalue()