64 lines
1.8 KiB
JavaScript
64 lines
1.8 KiB
JavaScript
/**
|
||
* Minimaler PNG-Encoder – nur für den Platzhalter-Anbieter des Job-Dispatchers.
|
||
*
|
||
* Bewusst ohne Fremdbibliothek: das Repo soll für einen Testbildgenerator keine
|
||
* Abhängigkeit mitschleppen. `zlib` bringt Node mit, mehr braucht ein PNG nicht.
|
||
*/
|
||
import { deflateSync } from 'node:zlib';
|
||
|
||
const CRC = (() => {
|
||
const t = new Int32Array(256);
|
||
for (let n = 0; n < 256; n++) {
|
||
let c = n;
|
||
for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
||
t[n] = c;
|
||
}
|
||
return t;
|
||
})();
|
||
|
||
function crc32(buf) {
|
||
let c = -1;
|
||
for (let i = 0; i < buf.length; i++) c = CRC[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
|
||
return (c ^ -1) >>> 0;
|
||
}
|
||
|
||
function chunk(typ, daten) {
|
||
const len = Buffer.alloc(4);
|
||
len.writeUInt32BE(daten.length);
|
||
const körper = Buffer.concat([Buffer.from(typ, 'ascii'), daten]);
|
||
const crc = Buffer.alloc(4);
|
||
crc.writeUInt32BE(crc32(körper));
|
||
return Buffer.concat([len, körper, crc]);
|
||
}
|
||
|
||
/**
|
||
* @param {number} breite
|
||
* @param {number} hoehe
|
||
* @param {(x:number,y:number)=>[number,number,number]} farbe RGB je Pixel
|
||
*/
|
||
export function pngErzeugen(breite, hoehe, farbe) {
|
||
const roh = Buffer.alloc(hoehe * (breite * 3 + 1));
|
||
let p = 0;
|
||
for (let y = 0; y < hoehe; y++) {
|
||
roh[p++] = 0; // Filter: none
|
||
for (let x = 0; x < breite; x++) {
|
||
const [r, g, b] = farbe(x, y);
|
||
roh[p++] = r; roh[p++] = g; roh[p++] = b;
|
||
}
|
||
}
|
||
|
||
const ihdr = Buffer.alloc(13);
|
||
ihdr.writeUInt32BE(breite, 0);
|
||
ihdr.writeUInt32BE(hoehe, 4);
|
||
ihdr[8] = 8; // bit depth
|
||
ihdr[9] = 2; // colour type: truecolour
|
||
ihdr[10] = 0; ihdr[11] = 0; ihdr[12] = 0;
|
||
|
||
return Buffer.concat([
|
||
Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
|
||
chunk('IHDR', ihdr),
|
||
chunk('IDAT', deflateSync(roh, { level: 9 })),
|
||
chunk('IEND', Buffer.alloc(0)),
|
||
]);
|
||
}
|