UNPKG

@thi.ng/pixel-io-pfm

Version:

Portable FloatMap image format support for @thi.ng/pixel

35 lines (34 loc) 1.47 kB
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 };