[object Object]

← back to CelebritySignatures

wear: on-shirt signature uses the signer's color on light cloth, white on dark

5acdc48e2acae84dd13293079e234bd41355404c · 2026-09-09 15:22:54 -0700 · Steve

Extend the distinct per-signer color to the garment mockup (2D canvas, AOP tile,
and 3D decal): recolor the ink to the signer's own color on light colorways
(composited via multiply so fabric shading still reads), and to pure white on
dark colorways (source-over) where a dark color would be invisible. Generalizes
recolorToLight(img) -> recolorInk(img,hex); a small module bridge exposes the
shared inkColorFor() to the classic canvas script so shirt and swatch match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 5acdc48e2acae84dd13293079e234bd41355404c
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Sep 9 15:22:54 2026 -0700

    wear: on-shirt signature uses the signer's color on light cloth, white on dark
    
    Extend the distinct per-signer color to the garment mockup (2D canvas, AOP tile,
    and 3D decal): recolor the ink to the signer's own color on light colorways
    (composited via multiply so fabric shading still reads), and to pure white on
    dark colorways (source-over) where a dark color would be invisible. Generalizes
    recolorToLight(img) -> recolorInk(img,hex); a small module bridge exposes the
    shared inkColorFor() to the classic canvas script so shirt and swatch match.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 public/wear.html | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/public/wear.html b/public/wear.html
index 717cfdc..5c75421 100644
--- a/public/wear.html
+++ b/public/wear.html
@@ -111,6 +111,12 @@
 </style>
 <link rel="stylesheet" href="/assets/signature-preview.css">
 <script type="module" src="/assets/signature-preview.js"></script>
+<script type="module">
+  // Bridge the shared per-signer ink color into the classic garment-canvas
+  // script, so the on-shirt signature matches its swatch color exactly.
+  import {inkColorFor} from '/assets/signature-ink.js';
+  window.__signerInk = key => { const [r,g,b]=inkColorFor(key); return '#'+[r,g,b].map(v=>v.toString(16).padStart(2,'0')).join(''); };
+</script>
 </head>
 <body>
 <header>
@@ -371,19 +377,28 @@ function luminance(hex){
   const n = parseInt(hex.slice(1),16), r=(n>>16)&255, g=(n>>8)&255, b=n&255;
   return (0.299*r + 0.587*g + 0.114*b) / 255;
 }
-// Most signature source art is a dark stroke on a transparent ground — great
-// for 'multiply' on light cloth, invisible via 'multiply' on dark cloth (multiply
-// can only ever darken). For a dark garment, recolor the signature's opaque
-// pixels to a light ink and composite normally instead.
-function recolorToLight(img){
+// Repaint the signature's opaque strokes a solid ink color, preserving the
+// stroke's own alpha (anti-aliasing) via 'source-in'. Used to put the signer's
+// distinct color on light cloth and pure white on dark cloth.
+function recolorInk(img, hex){
   const off = document.createElement('canvas'); off.width = img.width; off.height = img.height;
   const octx = off.getContext('2d');
   octx.drawImage(img, 0, 0);
   octx.globalCompositeOperation = 'source-in';
-  octx.fillStyle = '#f5f3ee';
+  octx.fillStyle = hex;
   octx.fillRect(0, 0, off.width, off.height);
   return off;
 }
+// The ink color for the CURRENT signature on garment color `col`: the signer's
+// own distinct color on light cloth (composited via 'multiply' so fabric shading
+// still reads), switching to pure WHITE on dark cloth where a dark color would
+// be invisible. `window.__signerInk` is provided by a module bridge (below);
+// fall back to a legible dark ink if it hasn't loaded yet.
+function inkHexFor(col){
+  if (luminance(col.hex) < 0.4) return '#ffffff';                 // dark cloth → white
+  const key = state.sig && (state.sig.qid || state.sig.full_name);
+  return (window.__signerInk && key) ? window.__signerInk(key) : '#1a1a1a';
+}
 
 // ---- 3D viewer (Three.js) — classic-tee only ----------------------------
 // Free MIT-licensed crew-neck tee model (Starklord17/threejs-t-shirt, itself
@@ -436,7 +451,7 @@ function update3DGarment(){
   const cnv = document.createElement('canvas'); cnv.width = 512; cnv.height = 512;
   const cctx = cnv.getContext('2d');
   const ar = sigImg.width/sigImg.height; let w = 420, h = w/ar; if (h > 200) { h = 200; w = h*ar; }
-  const drawSrc = luminance(state.color.hex) < 0.4 ? recolorToLight(sigImg) : sigImg;
+  const drawSrc = recolorInk(sigImg, inkHexFor(state.color));   // signer color on light, white on dark
   cctx.drawImage(drawSrc, (512-w)/2, (512-h)/2, w, h);
   const decalTexture = new THREE.CanvasTexture(cnv);
   const decalMaterial = new THREE.MeshStandardMaterial({
@@ -497,7 +512,8 @@ function paintSignatures(ctx, g, col, tx, ty, s){
     const x = ob.x + (ob.w-w)/2, y = ob.y + (ob.h-h)/2;
     const cx = ob.x + ob.w/2, cy = ob.y + ob.h/2;
     const dark = luminance(col.hex) < 0.4;
-    const src = dark ? recolorToLight(sigImg) : sigImg;
+    // Colored ink (signer's own color) on light cloth; white ink on dark cloth.
+    const src = recolorInk(sigImg, inkHexFor(col));
     ctx.save();
     ctx.translate(tx, ty); ctx.scale(s, s);
     if (ob.rotation) { ctx.translate(cx, cy); ctx.rotate(ob.rotation * Math.PI / 180); ctx.translate(-cx, -cy); }
@@ -560,7 +576,7 @@ function paintAllover(ctx, g, col, photoImg, tx, ty, s){
   if (!(sigImg && sigImg.width) || !photoImg) return;
   const W = ctx.canvas.width, H = ctx.canvas.height;
   const dark = luminance(col.hex) < 0.4;
-  const src = dark ? recolorToLight(sigImg) : sigImg;
+  const src = recolorInk(sigImg, inkHexFor(col));   // signer color on light cloth, white on dark
   const tileW = Math.round(W * (g.alloverScale || 0.20));
   const tileH = Math.round(tileW * (src.height / src.width));
   const stepX = tileW + tileW*0.35, stepY = tileH + tileH*1.6;   // brick spacing

← a272fad wear: Lincoln-in-exact-tee campaign hero (kontext-fit, real  ·  back to CelebritySignatures  ·  signature-size: make the mobile grid slider actually resize b5ebc16 →