/** * Minimal PNG encoder for generating simple RGBA images without native dependencies. * Used for QR codes, live probes, and other programmatic image generation. */ import { deflateSync } from "node:zlib"; const CRC_TABLE = (() => { const table = new Uint32Array(256); for (let i = 0; i < 256; i += 1) { let c = i; for (let k = 0; k < 8; k += 1) { c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; } table[i] = c >>> 0; } return table; })(); /** Compute CRC32 checksum for a buffer (used in PNG chunk encoding). */ export function crc32(buf: Buffer): number { let crc = 0xffffffff; for (let i = 0; i < buf.length; i += 1) { crc = CRC_TABLE[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8); } return (crc ^ 0xffffffff) >>> 0; } /** Create a PNG chunk with type, data, and CRC. */ export function pngChunk(type: string, data: Buffer): Buffer { const typeBuf = Buffer.from(type, "ascii"); const len = Buffer.alloc(4); len.writeUInt32BE(data.length, 0); const crc = crc32(Buffer.concat([typeBuf, data])); const crcBuf = Buffer.alloc(4); crcBuf.writeUInt32BE(crc, 0); return Buffer.concat([len, typeBuf, data, crcBuf]); } /** Write a pixel to an RGBA buffer. Ignores out-of-bounds writes. */ export function fillPixel( buf: Buffer, x: number, y: number, width: number, r: number, g: number, b: number, a = 255, ): void { if (x < 0 || y < 0 || x >= width) { return; } const idx = (y * width + x) * 4; if (idx < 0 || idx + 3 >= buf.length) { return; } buf[idx] = r; buf[idx + 1] = g; buf[idx + 2] = b; buf[idx + 3] = a; } /** Encode an RGBA buffer as a PNG image. */ export function encodePngRgba(buffer: Buffer, width: number, height: number): Buffer { const stride = width * 4; const raw = Buffer.alloc((stride + 1) * height); for (let row = 0; row < height; row += 1) { const rawOffset = row * (stride + 1); raw[rawOffset] = 0; // filter: none buffer.copy(raw, rawOffset + 1, row * stride, row * stride + stride); } const compressed = deflateSync(raw); const signature = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]); const ihdr = Buffer.alloc(13); ihdr.writeUInt32BE(width, 0); ihdr.writeUInt32BE(height, 4); ihdr[8] = 8; // bit depth ihdr[9] = 6; // color type RGBA ihdr[10] = 0; // compression ihdr[11] = 0; // filter ihdr[12] = 0; // interlace return Buffer.concat([ signature, pngChunk("IHDR", ihdr), pngChunk("IDAT", compressed), pngChunk("IEND", Buffer.alloc(0)), ]); }