[object Object]

← 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

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 →