This commit is contained in:
seb
2026-09-27 22:01:47 +02:00
parent 68b793c9ba
commit d2aa9ff8b1
11 changed files with 1553 additions and 1 deletions

View File

@@ -0,0 +1,44 @@
import sharp from 'sharp';
import { renderLabel } from 'react-canvas-label-editor';
const THUMB_SIZE = 50;
/**
* Renders a 50×50 1-bit indexed PNG thumbnail for a label template.
*
* Workflow:
* 1. Render the label at its native pixel resolution via renderLabel().
* 2. Resize to 50×50 using Lanczos3 (covers).
* 3. Convert to 1-bit PNG:
* - Greyscale → threshold at 128 → 1-bit PNG.
* - Pixels outside the label area (transparent in the RGBA source) are
* rendered WHITE (255) so they read as 0 in the final 1-bit output,
* keeping the file as small as possible.
*
* @param {object} opts
* @param {number} opts.width - Label width in pixels.
* @param {number} opts.height - Label height in pixels.
* @param {Array} opts.objects - Label editor objects array.
* @returns {Promise<Buffer>} PNG buffer.
*/
export async function renderThumb({ width, height, objects }) {
// 1. Render at native resolution → RGBA PNG buffer
const nativePng = await renderLabel({ width, height, objects });
// 2. Resize to 50×50, convert to greyscale, flatten transparency to white,
// then threshold to 1-bit and output as PNG.
const thumb = await sharp(nativePng)
.resize(THUMB_SIZE, THUMB_SIZE, {
fit: 'contain',
background: { r: 255, g: 255, b: 255, alpha: 1 },
kernel: sharp.kernel.lanczos3,
})
.greyscale()
// Threshold: pixels ≥ 128 → white (0 in 1-bit), < 128 → black (1 in 1-bit)
.threshold(128)
// PNG with 1-bit colour depth; compression level 9 for smallest file
.png({ colours: 2, compressionLevel: 9, adaptiveFiltering: false })
.toBuffer();
return thumb;
}