@thi.ng/pixel-io-netpbm
Version:
Multi-format NetPBM reader & writer support for @thi.ng/pixel
93 lines (92 loc) • 2.41 kB
JavaScript
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
};