← back to CelebritySignatures
Murals: QR is now a signature-sized centre cell (drop panel/caption/shadow)
a8e8de11568025369ca567f36128587ebfa87afe · 2026-06-18 16:28:51 -0700 · Steve
Files touched
M output/collage-declaration-of-independence.pngM output/collage-hollywood.pngM output/collage-movies-classic.pngM output/collage-politics.pngM output/collage-sports.pngM output/collage-tv.pngM scripts/build-collages.py
Diff
commit a8e8de11568025369ca567f36128587ebfa87afe
Author: Steve <steve@designerwallcoverings.com>
Date: Thu Jun 18 16:28:51 2026 -0700
Murals: QR is now a signature-sized centre cell (drop panel/caption/shadow)
---
output/collage-declaration-of-independence.png | Bin 605845 -> 648537 bytes
output/collage-hollywood.png | Bin 762984 -> 799147 bytes
output/collage-movies-classic.png | Bin 788039 -> 834681 bytes
output/collage-politics.png | Bin 567976 -> 588745 bytes
output/collage-sports.png | Bin 330588 -> 355414 bytes
output/collage-tv.png | Bin 145377 -> 169782 bytes
scripts/build-collages.py | 55 ++++++++++---------------
7 files changed, 21 insertions(+), 34 deletions(-)
diff --git a/output/collage-declaration-of-independence.png b/output/collage-declaration-of-independence.png
index 1e2b48c..e03c263 100644
Binary files a/output/collage-declaration-of-independence.png and b/output/collage-declaration-of-independence.png differ
diff --git a/output/collage-hollywood.png b/output/collage-hollywood.png
index ef77859..77c8cce 100644
Binary files a/output/collage-hollywood.png and b/output/collage-hollywood.png differ
diff --git a/output/collage-movies-classic.png b/output/collage-movies-classic.png
index 5025d6c..1be8e4f 100644
Binary files a/output/collage-movies-classic.png and b/output/collage-movies-classic.png differ
diff --git a/output/collage-politics.png b/output/collage-politics.png
index 14a04f1..aeefd2a 100644
Binary files a/output/collage-politics.png and b/output/collage-politics.png differ
diff --git a/output/collage-sports.png b/output/collage-sports.png
index 3c8b422..a844c9f 100644
Binary files a/output/collage-sports.png and b/output/collage-sports.png differ
diff --git a/output/collage-tv.png b/output/collage-tv.png
index e1398e3..69b34d2 100644
Binary files a/output/collage-tv.png and b/output/collage-tv.png differ
diff --git a/scripts/build-collages.py b/scripts/build-collages.py
index 7afedb0..26b0e27 100644
--- a/scripts/build-collages.py
+++ b/scripts/build-collages.py
@@ -137,19 +137,18 @@ def fit(im):
return im.resize((max(1, int(im.width * r)), max(1, int(im.height * r))), Image.LANCZOS)
-def make_qr(data, target_px):
- """Render a crisp QR for `data`, scaled to ~target_px (snapped to module grid)."""
+def make_qr_cell(data):
+ """Render the QR as a signature-sized square (BOX_H tall, uniform with the
+ signature cells) so it reads as 'just another signature' in the grid — no
+ bigger or more prominent than the rest."""
qr = qrcode.QRCode(
error_correction=qrcode.constants.ERROR_CORRECT_M, # ~15% damage tolerance
- box_size=10, border=2,
+ box_size=10, border=2, # built-in quiet zone
)
qr.add_data(data)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white").convert("RGB")
- modules = qr.modules_count + 2 * qr.border # total grid incl. quiet zone
- box = max(4, round(target_px / modules)) # integer px/module → no blur
- side = box * modules
- return img.resize((side, side), Image.NEAREST)
+ return img.resize((BOX_H, BOX_H), Image.LANCZOS) # square, signature-sized
def render(category, cells, dropped, named, safe):
@@ -191,31 +190,6 @@ def render(category, cells, dropped, named, safe):
tw = d.textlength(label, font=f)
d.text((cx + (CELL_W - tw) / 2, cy + PAD + BOX_H + 4), label, font=f, fill=MUTED)
- # centred QR (no-names version only)
- if not named:
- grid_h = rows_ct * cell_h
- target = int(min(W, grid_h) / 3.4)
- target = max(190, min(320, target))
- qr_url = f"{BASE_URL}/output/collage-{safe}-named.png"
- qr = make_qr(qr_url, target)
- cap = "SCAN TO REVEAL NAMES"
- cf = font(15, bold=True)
- cap_w = d.textlength(cap, font=cf)
- pad_in = 18
- cap_gap = 12
- cap_h = 20
- panel_w = max(qr.width, int(cap_w)) + pad_in * 2
- panel_h = qr.height + cap_gap + cap_h + pad_in * 2
- px = (W - panel_w) // 2
- py = HEADER_H + (grid_h - panel_h) // 2
- # soft drop shadow + white panel + hairline border
- d.rectangle([px + 5, py + 6, px + panel_w + 5, py + panel_h + 6], fill=(214, 210, 202))
- d.rectangle([px, py, px + panel_w, py + panel_h], fill=(255, 255, 255), outline=(150, 146, 138), width=2)
- qx = px + (panel_w - qr.width) // 2
- qy = py + pad_in
- canvas.paste(qr, (qx, qy))
- d.text((px + (panel_w - cap_w) / 2, qy + qr.height + cap_gap), cap, font=cf, fill=INK)
-
# footer
d.text((PAD + 8, H - FOOTER_H + 14),
"Uniform sizing — no signature emphasized. Deceased or public-domain only; living-celebrity rows excluded (right of publicity).",
@@ -248,9 +222,22 @@ def build(category, rows):
print(f"[{category}] no images resolved, skipping"); return []
safe = re.sub(r"[^a-z0-9]+", "-", category.lower()).strip("-")
+
+ # The mural gets the QR dropped in as just another (nameless) signature cell,
+ # centred in the grid — same size, same placement as every signature. It links
+ # to the named "key" version. render() uses the same cols formula, so inserting
+ # at this index lands the QR in the middle row/column of the laid-out grid.
+ qr_url = f"{BASE_URL}/output/collage-{safe}-named.png"
+ qr_cell = ("", make_qr_cell(qr_url))
+ total = len(cells) + 1
+ cols = min(10, max(1, round(total ** 0.5)))
+ rows_ct = (total + cols - 1) // cols
+ center = min((rows_ct // 2) * cols + cols // 2, total - 1)
+ mural_cells = cells[:center] + [qr_cell] + cells[center:]
+
made = [
- render(category, cells, dropped, named=True, safe=safe), # the key (QR target)
- render(category, cells, dropped, named=False, safe=safe), # the mural (no names + QR)
+ render(category, cells, dropped, named=True, safe=safe), # the key (QR target)
+ render(category, mural_cells, dropped, named=False, safe=safe), # the mural (QR = a cell)
]
return made
← b04a4a9 Murals: hide names + centre QR to the named key
·
back to CelebritySignatures
·
QR points at public Kamatera host via short /k/<cat> route; ac66a5d →