Dither badge photos before drawing them

This commit is contained in:
2026-09-07 05:34:41 +00:00
parent a9e07b324d
commit cdc1bc4264
+12
View File
@@ -6,6 +6,7 @@ import { execFile } from 'node:child_process';
import { createCanvas, loadImage, GlobalFonts } from '@napi-rs/canvas'; import { createCanvas, loadImage, GlobalFonts } from '@napi-rs/canvas';
import config from './config.js'; import config from './config.js';
import { photoAbsolutePath } from './photos.js'; import { photoAbsolutePath } from './photos.js';
import { ditherPhoto } from './printing/dither.js';
import { printPng, printerHealth } from './printing/ql-print.js'; import { printPng, printerHealth } from './printing/ql-print.js';
/** /**
@@ -114,6 +115,17 @@ async function drawBadge(ctx, widthDots, heightDots, visit, site, accent, startY
} }
const photoSize = photo ? Math.round(unit * (portrait ? 0.52 : 0.5)) : 0; const photoSize = photo ? Math.round(unit * (portrait ? 0.52 : 0.5)) : 0;
// Thermal heads print pure black or nothing, so a photo has to be reduced to
// 1-bit before it lands on the canvas — otherwise the plane conversion
// thresholds it into a solid blob. Done once here rather than at each draw
// site, and at exactly photoSize: rescaling a dithered image resamples the
// dot pattern back into greys and undoes the whole thing.
//
// Skipped on the measuring pass, which never paints.
if (photo && photoSize > 0 && startY !== null) {
photo = ditherPhoto(photo, photoSize);
}
let cursorY = startY === null ? pad : startY; let cursorY = startY === null ? pad : startY;
let textLeft = pad; let textLeft = pad;
let textWidth = widthDots - pad * 2; let textWidth = widthDots - pad * 2;