UNPKG

@thi.ng/pixel-io-netpbm

Version:

Multi-format NetPBM reader & writer support for @thi.ng/pixel

93 lines (92 loc) 2.41 kB
import { GRAY16 } from "@thi.ng/pixel/format/gray16"; const __formatComments = (comments = ["generated by @thi.ng/pixel-io-netpbm"]) => comments.map((x) => `# ${x}`).join("\n"); const __luminance = (c) => ((c >>> 16 & 255) * 29 + (c >>> 8 & 255) * 150 + (c & 255) * 76) / 255; const __initHeader = (magic, limits, size, buf, comments) => { const { width, height } = buf; let header = magic + "\n"; const comm = __formatComments(comments); if (comm.length) header += comm + "\n"; header += `${width} ${height} `; if (limits > 0) header += limits + "\n"; const dest = new Uint8Array(size + header.length); dest.set([...header].map((x) => x.charCodeAt(0))); return { dest, start: header.length, abgr: buf.format.toABGR }; }; const asPBM = (buf, comments) => { const { data, width, height } = buf; const { dest, start, abgr } = __initHeader( "P4", 0, Math.ceil(width / 8) * height, buf, comments ); const w1 = width - 1; for (let y = 0, i = start, j = 0; y < height; y++) { for (let x = 0, b = 0; x <= w1; x++, j++) { const xx = ~x & 7; if (__luminance(abgr(data[j])) < 128) { b |= 1 << xx; } if (xx === 0 || x === w1) { dest[i++] = b; b = 0; } } } return dest; }; const asPGM = (buf, comments) => { const { data, width, height } = buf; const { dest, start, abgr } = __initHeader( "P5", 255, width * height, buf, comments ); for (let i = start, j = 0; j < data.length; i++, j++) { dest[i] = __luminance(abgr(data[j])); } return dest; }; const asPGM16 = (buf, comments) => { if (buf.format !== GRAY16) buf = buf.as(GRAY16); const { data, width, height } = buf; const { dest, start } = __initHeader( "P5", 65535, width * height * 2, buf, comments ); for (let i = start, j = 0; j < data.length; i += 2, j++) { dest[i] = data[j] >> 8; dest[i + 1] = data[j] & 255; } return dest; }; const asPPM = (buf, comments) => { const { data, width, height } = buf; const { dest, start, abgr } = __initHeader( "P6", 255, width * 3 * height, buf, comments ); for (let i = start, j = 0; j < data.length; i += 3, j++) { const col = abgr(data[j]); dest[i] = col & 255; dest[i + 1] = col >> 8 & 255; dest[i + 2] = col >> 16 & 255; } return dest; }; export { asPBM, asPGM, asPGM16, asPPM };