@thi.ng/pixel-io-pfm
Version:
Portable FloatMap image format support for @thi.ng/pixel
35 lines (34 loc) • 1.47 kB
JavaScript
import { defError } from "@thi.ng/errors/deferror";
import { floatBuffer } from "@thi.ng/pixel/float";
import { FLOAT_RGB } from "@thi.ng/pixel/format/float-rgb";
const PFMError = defError(() => `illegal PFM file`);
const __error = (msg) => {
throw new PFMError(msg);
};
const readPFM = (buf, linearRGB = true) => {
const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
if (view.getUint16(0, false) !== 20550) __error();
if (view.getUint8(2) !== 10) __error();
const idx = buf.indexOf(10, 3);
if (idx < 0) __error("missing dimensions");
const [width, height] = new TextDecoder().decode(buf.subarray(3, idx)).split(" ").map((x) => parseInt(x));
if (isNaN(width) || isNaN(height) || width < 1 || height < 1)
__error("invalid dimensions");
const idx2 = buf.indexOf(10, idx + 1);
if (idx2 < 0) __error("missing byte order");
const littleEndian = parseFloat(new TextDecoder().decode(buf.subarray(idx, idx2))) < 0;
const process = linearRGB ? __linearSrgb : (x) => x;
const img = floatBuffer(width, height, FLOAT_RGB);
const strideY = img.stride[1];
for (let src = idx2 + 1, dest = (height - 1) * strideY, data = img.data; dest >= 0; dest -= strideY) {
for (let x = 0; x < strideY; x++, src += 4) {
data[dest + x] = process(view.getFloat32(src, littleEndian));
}
}
return img;
};
const __linearSrgb = (x) => x <= 3130805e-9 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055;
export {
PFMError,
readPFM
};