← 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 →