three-stdlib
Version:
stand-alone library of threejs examples
1 lines • 95.1 kB
Source Map (JSON)
{"version":3,"file":"EXRLoader.cjs","sources":["../../src/loaders/EXRLoader.js"],"sourcesContent":["import {\n Texture,\n DataTextureLoader,\n DataUtils,\n FloatType,\n HalfFloatType,\n LinearFilter,\n RedFormat,\n RGBAFormat,\n} from 'three'\nimport { unzlibSync } from 'fflate'\nimport { version } from '../_polyfill/constants'\n\n/**\n * OpenEXR loader currently supports uncompressed, ZIP(S), RLE, PIZ and DWA/B compression.\n * Supports reading as UnsignedByte, HalfFloat and Float type data texture.\n *\n * Referred to the original Industrial Light & Magic OpenEXR implementation and the TinyEXR / Syoyo Fujita\n * implementation, so I have preserved their copyright notices.\n */\n\n// /*\n// Copyright (c) 2014 - 2017, Syoyo Fujita\n// All rights reserved.\n\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are met:\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above copyright\n// notice, this list of conditions and the following disclaimer in the\n// documentation and/or other materials provided with the distribution.\n// * Neither the name of the Syoyo Fujita nor the\n// names of its contributors may be used to endorse or promote products\n// derived from this software without specific prior written permission.\n\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\n// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n// */\n\n// // TinyEXR contains some OpenEXR code, which is licensed under ------------\n\n// ///////////////////////////////////////////////////////////////////////////\n// //\n// // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas\n// // Digital Ltd. LLC\n// //\n// // All rights reserved.\n// //\n// // Redistribution and use in source and binary forms, with or without\n// // modification, are permitted provided that the following conditions are\n// // met:\n// // * Redistributions of source code must retain the above copyright\n// // notice, this list of conditions and the following disclaimer.\n// // * Redistributions in binary form must reproduce the above\n// // copyright notice, this list of conditions and the following disclaimer\n// // in the documentation and/or other materials provided with the\n// // distribution.\n// // * Neither the name of Industrial Light & Magic nor the names of\n// // its contributors may be used to endorse or promote products derived\n// // from this software without specific prior written permission.\n// //\n// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// // \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n// //\n// ///////////////////////////////////////////////////////////////////////////\n\n// // End of OpenEXR license -------------------------------------------------\n\n// https://github.com/mrdoob/three.js/pull/25771\nconst hasColorSpace = version >= 152\n\nclass EXRLoader extends DataTextureLoader {\n constructor(manager) {\n super(manager)\n\n this.type = HalfFloatType\n }\n\n parse(buffer) {\n const USHORT_RANGE = 1 << 16\n const BITMAP_SIZE = USHORT_RANGE >> 3\n\n const HUF_ENCBITS = 16 // literal (value) bit length\n const HUF_DECBITS = 14 // decoding bit size (>= 8)\n\n const HUF_ENCSIZE = (1 << HUF_ENCBITS) + 1 // encoding table size\n const HUF_DECSIZE = 1 << HUF_DECBITS // decoding table size\n const HUF_DECMASK = HUF_DECSIZE - 1\n\n const NBITS = 16\n const A_OFFSET = 1 << (NBITS - 1)\n const MOD_MASK = (1 << NBITS) - 1\n\n const SHORT_ZEROCODE_RUN = 59\n const LONG_ZEROCODE_RUN = 63\n const SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN\n\n const ULONG_SIZE = 8\n const FLOAT32_SIZE = 4\n const INT32_SIZE = 4\n const INT16_SIZE = 2\n const INT8_SIZE = 1\n\n const STATIC_HUFFMAN = 0\n const DEFLATE = 1\n\n const UNKNOWN = 0\n const LOSSY_DCT = 1\n const RLE = 2\n\n const logBase = Math.pow(2.7182818, 2.2)\n\n function reverseLutFromBitmap(bitmap, lut) {\n var k = 0\n\n for (var i = 0; i < USHORT_RANGE; ++i) {\n if (i == 0 || bitmap[i >> 3] & (1 << (i & 7))) {\n lut[k++] = i\n }\n }\n\n var n = k - 1\n\n while (k < USHORT_RANGE) lut[k++] = 0\n\n return n\n }\n\n function hufClearDecTable(hdec) {\n for (var i = 0; i < HUF_DECSIZE; i++) {\n hdec[i] = {}\n hdec[i].len = 0\n hdec[i].lit = 0\n hdec[i].p = null\n }\n }\n\n const getBitsReturn = { l: 0, c: 0, lc: 0 }\n\n function getBits(nBits, c, lc, uInt8Array, inOffset) {\n while (lc < nBits) {\n c = (c << 8) | parseUint8Array(uInt8Array, inOffset)\n lc += 8\n }\n\n lc -= nBits\n\n getBitsReturn.l = (c >> lc) & ((1 << nBits) - 1)\n getBitsReturn.c = c\n getBitsReturn.lc = lc\n }\n\n const hufTableBuffer = new Array(59)\n\n function hufCanonicalCodeTable(hcode) {\n for (var i = 0; i <= 58; ++i) hufTableBuffer[i] = 0\n for (var i = 0; i < HUF_ENCSIZE; ++i) hufTableBuffer[hcode[i]] += 1\n\n var c = 0\n\n for (var i = 58; i > 0; --i) {\n var nc = (c + hufTableBuffer[i]) >> 1\n hufTableBuffer[i] = c\n c = nc\n }\n\n for (var i = 0; i < HUF_ENCSIZE; ++i) {\n var l = hcode[i]\n if (l > 0) hcode[i] = l | (hufTableBuffer[l]++ << 6)\n }\n }\n\n function hufUnpackEncTable(uInt8Array, inDataView, inOffset, ni, im, iM, hcode) {\n var p = inOffset\n var c = 0\n var lc = 0\n\n for (; im <= iM; im++) {\n if (p.value - inOffset.value > ni) return false\n\n getBits(6, c, lc, uInt8Array, p)\n\n var l = getBitsReturn.l\n c = getBitsReturn.c\n lc = getBitsReturn.lc\n\n hcode[im] = l\n\n if (l == LONG_ZEROCODE_RUN) {\n if (p.value - inOffset.value > ni) {\n throw 'Something wrong with hufUnpackEncTable'\n }\n\n getBits(8, c, lc, uInt8Array, p)\n\n var zerun = getBitsReturn.l + SHORTEST_LONG_RUN\n c = getBitsReturn.c\n lc = getBitsReturn.lc\n\n if (im + zerun > iM + 1) {\n throw 'Something wrong with hufUnpackEncTable'\n }\n\n while (zerun--) hcode[im++] = 0\n\n im--\n } else if (l >= SHORT_ZEROCODE_RUN) {\n var zerun = l - SHORT_ZEROCODE_RUN + 2\n\n if (im + zerun > iM + 1) {\n throw 'Something wrong with hufUnpackEncTable'\n }\n\n while (zerun--) hcode[im++] = 0\n\n im--\n }\n }\n\n hufCanonicalCodeTable(hcode)\n }\n\n function hufLength(code) {\n return code & 63\n }\n\n function hufCode(code) {\n return code >> 6\n }\n\n function hufBuildDecTable(hcode, im, iM, hdecod) {\n for (; im <= iM; im++) {\n var c = hufCode(hcode[im])\n var l = hufLength(hcode[im])\n\n if (c >> l) {\n throw 'Invalid table entry'\n }\n\n if (l > HUF_DECBITS) {\n var pl = hdecod[c >> (l - HUF_DECBITS)]\n\n if (pl.len) {\n throw 'Invalid table entry'\n }\n\n pl.lit++\n\n if (pl.p) {\n var p = pl.p\n pl.p = new Array(pl.lit)\n\n for (var i = 0; i < pl.lit - 1; ++i) {\n pl.p[i] = p[i]\n }\n } else {\n pl.p = new Array(1)\n }\n\n pl.p[pl.lit - 1] = im\n } else if (l) {\n var plOffset = 0\n\n for (var i = 1 << (HUF_DECBITS - l); i > 0; i--) {\n var pl = hdecod[(c << (HUF_DECBITS - l)) + plOffset]\n\n if (pl.len || pl.p) {\n throw 'Invalid table entry'\n }\n\n pl.len = l\n pl.lit = im\n\n plOffset++\n }\n }\n }\n\n return true\n }\n\n const getCharReturn = { c: 0, lc: 0 }\n\n function getChar(c, lc, uInt8Array, inOffset) {\n c = (c << 8) | parseUint8Array(uInt8Array, inOffset)\n lc += 8\n\n getCharReturn.c = c\n getCharReturn.lc = lc\n }\n\n const getCodeReturn = { c: 0, lc: 0 }\n\n function getCode(po, rlc, c, lc, uInt8Array, inDataView, inOffset, outBuffer, outBufferOffset, outBufferEndOffset) {\n if (po == rlc) {\n if (lc < 8) {\n getChar(c, lc, uInt8Array, inOffset)\n c = getCharReturn.c\n lc = getCharReturn.lc\n }\n\n lc -= 8\n\n var cs = c >> lc\n var cs = new Uint8Array([cs])[0]\n\n if (outBufferOffset.value + cs > outBufferEndOffset) {\n return false\n }\n\n var s = outBuffer[outBufferOffset.value - 1]\n\n while (cs-- > 0) {\n outBuffer[outBufferOffset.value++] = s\n }\n } else if (outBufferOffset.value < outBufferEndOffset) {\n outBuffer[outBufferOffset.value++] = po\n } else {\n return false\n }\n\n getCodeReturn.c = c\n getCodeReturn.lc = lc\n }\n\n function UInt16(value) {\n return value & 0xffff\n }\n\n function Int16(value) {\n var ref = UInt16(value)\n return ref > 0x7fff ? ref - 0x10000 : ref\n }\n\n const wdec14Return = { a: 0, b: 0 }\n\n function wdec14(l, h) {\n var ls = Int16(l)\n var hs = Int16(h)\n\n var hi = hs\n var ai = ls + (hi & 1) + (hi >> 1)\n\n var as = ai\n var bs = ai - hi\n\n wdec14Return.a = as\n wdec14Return.b = bs\n }\n\n function wdec16(l, h) {\n var m = UInt16(l)\n var d = UInt16(h)\n\n var bb = (m - (d >> 1)) & MOD_MASK\n var aa = (d + bb - A_OFFSET) & MOD_MASK\n\n wdec14Return.a = aa\n wdec14Return.b = bb\n }\n\n function wav2Decode(buffer, j, nx, ox, ny, oy, mx) {\n var w14 = mx < 1 << 14\n var n = nx > ny ? ny : nx\n var p = 1\n var p2\n\n while (p <= n) p <<= 1\n\n p >>= 1\n p2 = p\n p >>= 1\n\n while (p >= 1) {\n var py = 0\n var ey = py + oy * (ny - p2)\n var oy1 = oy * p\n var oy2 = oy * p2\n var ox1 = ox * p\n var ox2 = ox * p2\n var i00, i01, i10, i11\n\n for (; py <= ey; py += oy2) {\n var px = py\n var ex = py + ox * (nx - p2)\n\n for (; px <= ex; px += ox2) {\n var p01 = px + ox1\n var p10 = px + oy1\n var p11 = p10 + ox1\n\n if (w14) {\n wdec14(buffer[px + j], buffer[p10 + j])\n\n i00 = wdec14Return.a\n i10 = wdec14Return.b\n\n wdec14(buffer[p01 + j], buffer[p11 + j])\n\n i01 = wdec14Return.a\n i11 = wdec14Return.b\n\n wdec14(i00, i01)\n\n buffer[px + j] = wdec14Return.a\n buffer[p01 + j] = wdec14Return.b\n\n wdec14(i10, i11)\n\n buffer[p10 + j] = wdec14Return.a\n buffer[p11 + j] = wdec14Return.b\n } else {\n wdec16(buffer[px + j], buffer[p10 + j])\n\n i00 = wdec14Return.a\n i10 = wdec14Return.b\n\n wdec16(buffer[p01 + j], buffer[p11 + j])\n\n i01 = wdec14Return.a\n i11 = wdec14Return.b\n\n wdec16(i00, i01)\n\n buffer[px + j] = wdec14Return.a\n buffer[p01 + j] = wdec14Return.b\n\n wdec16(i10, i11)\n\n buffer[p10 + j] = wdec14Return.a\n buffer[p11 + j] = wdec14Return.b\n }\n }\n\n if (nx & p) {\n var p10 = px + oy1\n\n if (w14) wdec14(buffer[px + j], buffer[p10 + j])\n else wdec16(buffer[px + j], buffer[p10 + j])\n\n i00 = wdec14Return.a\n buffer[p10 + j] = wdec14Return.b\n\n buffer[px + j] = i00\n }\n }\n\n if (ny & p) {\n var px = py\n var ex = py + ox * (nx - p2)\n\n for (; px <= ex; px += ox2) {\n var p01 = px + ox1\n\n if (w14) wdec14(buffer[px + j], buffer[p01 + j])\n else wdec16(buffer[px + j], buffer[p01 + j])\n\n i00 = wdec14Return.a\n buffer[p01 + j] = wdec14Return.b\n\n buffer[px + j] = i00\n }\n }\n\n p2 = p\n p >>= 1\n }\n\n return py\n }\n\n function hufDecode(\n encodingTable,\n decodingTable,\n uInt8Array,\n inDataView,\n inOffset,\n ni,\n rlc,\n no,\n outBuffer,\n outOffset,\n ) {\n var c = 0\n var lc = 0\n var outBufferEndOffset = no\n var inOffsetEnd = Math.trunc(inOffset.value + (ni + 7) / 8)\n\n while (inOffset.value < inOffsetEnd) {\n getChar(c, lc, uInt8Array, inOffset)\n\n c = getCharReturn.c\n lc = getCharReturn.lc\n\n while (lc >= HUF_DECBITS) {\n var index = (c >> (lc - HUF_DECBITS)) & HUF_DECMASK\n var pl = decodingTable[index]\n\n if (pl.len) {\n lc -= pl.len\n\n getCode(pl.lit, rlc, c, lc, uInt8Array, inDataView, inOffset, outBuffer, outOffset, outBufferEndOffset)\n\n c = getCodeReturn.c\n lc = getCodeReturn.lc\n } else {\n if (!pl.p) {\n throw 'hufDecode issues'\n }\n\n var j\n\n for (j = 0; j < pl.lit; j++) {\n var l = hufLength(encodingTable[pl.p[j]])\n\n while (lc < l && inOffset.value < inOffsetEnd) {\n getChar(c, lc, uInt8Array, inOffset)\n\n c = getCharReturn.c\n lc = getCharReturn.lc\n }\n\n if (lc >= l) {\n if (hufCode(encodingTable[pl.p[j]]) == ((c >> (lc - l)) & ((1 << l) - 1))) {\n lc -= l\n\n getCode(\n pl.p[j],\n rlc,\n c,\n lc,\n uInt8Array,\n inDataView,\n inOffset,\n outBuffer,\n outOffset,\n outBufferEndOffset,\n )\n\n c = getCodeReturn.c\n lc = getCodeReturn.lc\n\n break\n }\n }\n }\n\n if (j == pl.lit) {\n throw 'hufDecode issues'\n }\n }\n }\n }\n\n var i = (8 - ni) & 7\n\n c >>= i\n lc -= i\n\n while (lc > 0) {\n var pl = decodingTable[(c << (HUF_DECBITS - lc)) & HUF_DECMASK]\n\n if (pl.len) {\n lc -= pl.len\n\n getCode(pl.lit, rlc, c, lc, uInt8Array, inDataView, inOffset, outBuffer, outOffset, outBufferEndOffset)\n\n c = getCodeReturn.c\n lc = getCodeReturn.lc\n } else {\n throw 'hufDecode issues'\n }\n }\n\n return true\n }\n\n function hufUncompress(uInt8Array, inDataView, inOffset, nCompressed, outBuffer, nRaw) {\n var outOffset = { value: 0 }\n var initialInOffset = inOffset.value\n\n var im = parseUint32(inDataView, inOffset)\n var iM = parseUint32(inDataView, inOffset)\n\n inOffset.value += 4\n\n var nBits = parseUint32(inDataView, inOffset)\n\n inOffset.value += 4\n\n if (im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE) {\n throw 'Something wrong with HUF_ENCSIZE'\n }\n\n var freq = new Array(HUF_ENCSIZE)\n var hdec = new Array(HUF_DECSIZE)\n\n hufClearDecTable(hdec)\n\n var ni = nCompressed - (inOffset.value - initialInOffset)\n\n hufUnpackEncTable(uInt8Array, inDataView, inOffset, ni, im, iM, freq)\n\n if (nBits > 8 * (nCompressed - (inOffset.value - initialInOffset))) {\n throw 'Something wrong with hufUncompress'\n }\n\n hufBuildDecTable(freq, im, iM, hdec)\n\n hufDecode(freq, hdec, uInt8Array, inDataView, inOffset, nBits, iM, nRaw, outBuffer, outOffset)\n }\n\n function applyLut(lut, data, nData) {\n for (var i = 0; i < nData; ++i) {\n data[i] = lut[data[i]]\n }\n }\n\n function predictor(source) {\n for (var t = 1; t < source.length; t++) {\n var d = source[t - 1] + source[t] - 128\n source[t] = d\n }\n }\n\n function interleaveScalar(source, out) {\n var t1 = 0\n var t2 = Math.floor((source.length + 1) / 2)\n var s = 0\n var stop = source.length - 1\n\n while (true) {\n if (s > stop) break\n out[s++] = source[t1++]\n\n if (s > stop) break\n out[s++] = source[t2++]\n }\n }\n\n function decodeRunLength(source) {\n var size = source.byteLength\n var out = new Array()\n var p = 0\n\n var reader = new DataView(source)\n\n while (size > 0) {\n var l = reader.getInt8(p++)\n\n if (l < 0) {\n var count = -l\n size -= count + 1\n\n for (var i = 0; i < count; i++) {\n out.push(reader.getUint8(p++))\n }\n } else {\n var count = l\n size -= 2\n\n var value = reader.getUint8(p++)\n\n for (var i = 0; i < count + 1; i++) {\n out.push(value)\n }\n }\n }\n\n return out\n }\n\n function lossyDctDecode(cscSet, rowPtrs, channelData, acBuffer, dcBuffer, outBuffer) {\n var dataView = new DataView(outBuffer.buffer)\n\n var width = channelData[cscSet.idx[0]].width\n var height = channelData[cscSet.idx[0]].height\n\n var numComp = 3\n\n var numFullBlocksX = Math.floor(width / 8.0)\n var numBlocksX = Math.ceil(width / 8.0)\n var numBlocksY = Math.ceil(height / 8.0)\n var leftoverX = width - (numBlocksX - 1) * 8\n var leftoverY = height - (numBlocksY - 1) * 8\n\n var currAcComp = { value: 0 }\n var currDcComp = new Array(numComp)\n var dctData = new Array(numComp)\n var halfZigBlock = new Array(numComp)\n var rowBlock = new Array(numComp)\n var rowOffsets = new Array(numComp)\n\n for (let comp = 0; comp < numComp; ++comp) {\n rowOffsets[comp] = rowPtrs[cscSet.idx[comp]]\n currDcComp[comp] = comp < 1 ? 0 : currDcComp[comp - 1] + numBlocksX * numBlocksY\n dctData[comp] = new Float32Array(64)\n halfZigBlock[comp] = new Uint16Array(64)\n rowBlock[comp] = new Uint16Array(numBlocksX * 64)\n }\n\n for (let blocky = 0; blocky < numBlocksY; ++blocky) {\n var maxY = 8\n\n if (blocky == numBlocksY - 1) maxY = leftoverY\n\n var maxX = 8\n\n for (let blockx = 0; blockx < numBlocksX; ++blockx) {\n if (blockx == numBlocksX - 1) maxX = leftoverX\n\n for (let comp = 0; comp < numComp; ++comp) {\n halfZigBlock[comp].fill(0)\n\n // set block DC component\n halfZigBlock[comp][0] = dcBuffer[currDcComp[comp]++]\n // set block AC components\n unRleAC(currAcComp, acBuffer, halfZigBlock[comp])\n\n // UnZigZag block to float\n unZigZag(halfZigBlock[comp], dctData[comp])\n // decode float dct\n dctInverse(dctData[comp])\n }\n\n if (numComp == 3) {\n csc709Inverse(dctData)\n }\n\n for (let comp = 0; comp < numComp; ++comp) {\n convertToHalf(dctData[comp], rowBlock[comp], blockx * 64)\n }\n } // blockx\n\n let offset = 0\n\n for (let comp = 0; comp < numComp; ++comp) {\n const type = channelData[cscSet.idx[comp]].type\n\n for (let y = 8 * blocky; y < 8 * blocky + maxY; ++y) {\n offset = rowOffsets[comp][y]\n\n for (let blockx = 0; blockx < numFullBlocksX; ++blockx) {\n const src = blockx * 64 + (y & 0x7) * 8\n\n dataView.setUint16(offset + 0 * INT16_SIZE * type, rowBlock[comp][src + 0], true)\n dataView.setUint16(offset + 1 * INT16_SIZE * type, rowBlock[comp][src + 1], true)\n dataView.setUint16(offset + 2 * INT16_SIZE * type, rowBlock[comp][src + 2], true)\n dataView.setUint16(offset + 3 * INT16_SIZE * type, rowBlock[comp][src + 3], true)\n\n dataView.setUint16(offset + 4 * INT16_SIZE * type, rowBlock[comp][src + 4], true)\n dataView.setUint16(offset + 5 * INT16_SIZE * type, rowBlock[comp][src + 5], true)\n dataView.setUint16(offset + 6 * INT16_SIZE * type, rowBlock[comp][src + 6], true)\n dataView.setUint16(offset + 7 * INT16_SIZE * type, rowBlock[comp][src + 7], true)\n\n offset += 8 * INT16_SIZE * type\n }\n }\n\n // handle partial X blocks\n if (numFullBlocksX != numBlocksX) {\n for (let y = 8 * blocky; y < 8 * blocky + maxY; ++y) {\n const offset = rowOffsets[comp][y] + 8 * numFullBlocksX * INT16_SIZE * type\n const src = numFullBlocksX * 64 + (y & 0x7) * 8\n\n for (let x = 0; x < maxX; ++x) {\n dataView.setUint16(offset + x * INT16_SIZE * type, rowBlock[comp][src + x], true)\n }\n }\n }\n } // comp\n } // blocky\n\n var halfRow = new Uint16Array(width)\n var dataView = new DataView(outBuffer.buffer)\n\n // convert channels back to float, if needed\n for (var comp = 0; comp < numComp; ++comp) {\n channelData[cscSet.idx[comp]].decoded = true\n var type = channelData[cscSet.idx[comp]].type\n\n if (channelData[comp].type != 2) continue\n\n for (var y = 0; y < height; ++y) {\n const offset = rowOffsets[comp][y]\n\n for (var x = 0; x < width; ++x) {\n halfRow[x] = dataView.getUint16(offset + x * INT16_SIZE * type, true)\n }\n\n for (var x = 0; x < width; ++x) {\n dataView.setFloat32(offset + x * INT16_SIZE * type, decodeFloat16(halfRow[x]), true)\n }\n }\n }\n }\n\n function unRleAC(currAcComp, acBuffer, halfZigBlock) {\n var acValue\n var dctComp = 1\n\n while (dctComp < 64) {\n acValue = acBuffer[currAcComp.value]\n\n if (acValue == 0xff00) {\n dctComp = 64\n } else if (acValue >> 8 == 0xff) {\n dctComp += acValue & 0xff\n } else {\n halfZigBlock[dctComp] = acValue\n dctComp++\n }\n\n currAcComp.value++\n }\n }\n\n function unZigZag(src, dst) {\n dst[0] = decodeFloat16(src[0])\n dst[1] = decodeFloat16(src[1])\n dst[2] = decodeFloat16(src[5])\n dst[3] = decodeFloat16(src[6])\n dst[4] = decodeFloat16(src[14])\n dst[5] = decodeFloat16(src[15])\n dst[6] = decodeFloat16(src[27])\n dst[7] = decodeFloat16(src[28])\n dst[8] = decodeFloat16(src[2])\n dst[9] = decodeFloat16(src[4])\n\n dst[10] = decodeFloat16(src[7])\n dst[11] = decodeFloat16(src[13])\n dst[12] = decodeFloat16(src[16])\n dst[13] = decodeFloat16(src[26])\n dst[14] = decodeFloat16(src[29])\n dst[15] = decodeFloat16(src[42])\n dst[16] = decodeFloat16(src[3])\n dst[17] = decodeFloat16(src[8])\n dst[18] = decodeFloat16(src[12])\n dst[19] = decodeFloat16(src[17])\n\n dst[20] = decodeFloat16(src[25])\n dst[21] = decodeFloat16(src[30])\n dst[22] = decodeFloat16(src[41])\n dst[23] = decodeFloat16(src[43])\n dst[24] = decodeFloat16(src[9])\n dst[25] = decodeFloat16(src[11])\n dst[26] = decodeFloat16(src[18])\n dst[27] = decodeFloat16(src[24])\n dst[28] = decodeFloat16(src[31])\n dst[29] = decodeFloat16(src[40])\n\n dst[30] = decodeFloat16(src[44])\n dst[31] = decodeFloat16(src[53])\n dst[32] = decodeFloat16(src[10])\n dst[33] = decodeFloat16(src[19])\n dst[34] = decodeFloat16(src[23])\n dst[35] = decodeFloat16(src[32])\n dst[36] = decodeFloat16(src[39])\n dst[37] = decodeFloat16(src[45])\n dst[38] = decodeFloat16(src[52])\n dst[39] = decodeFloat16(src[54])\n\n dst[40] = decodeFloat16(src[20])\n dst[41] = decodeFloat16(src[22])\n dst[42] = decodeFloat16(src[33])\n dst[43] = decodeFloat16(src[38])\n dst[44] = decodeFloat16(src[46])\n dst[45] = decodeFloat16(src[51])\n dst[46] = decodeFloat16(src[55])\n dst[47] = decodeFloat16(src[60])\n dst[48] = decodeFloat16(src[21])\n dst[49] = decodeFloat16(src[34])\n\n dst[50] = decodeFloat16(src[37])\n dst[51] = decodeFloat16(src[47])\n dst[52] = decodeFloat16(src[50])\n dst[53] = decodeFloat16(src[56])\n dst[54] = decodeFloat16(src[59])\n dst[55] = decodeFloat16(src[61])\n dst[56] = decodeFloat16(src[35])\n dst[57] = decodeFloat16(src[36])\n dst[58] = decodeFloat16(src[48])\n dst[59] = decodeFloat16(src[49])\n\n dst[60] = decodeFloat16(src[57])\n dst[61] = decodeFloat16(src[58])\n dst[62] = decodeFloat16(src[62])\n dst[63] = decodeFloat16(src[63])\n }\n\n function dctInverse(data) {\n const a = 0.5 * Math.cos(3.14159 / 4.0)\n const b = 0.5 * Math.cos(3.14159 / 16.0)\n const c = 0.5 * Math.cos(3.14159 / 8.0)\n const d = 0.5 * Math.cos((3.0 * 3.14159) / 16.0)\n const e = 0.5 * Math.cos((5.0 * 3.14159) / 16.0)\n const f = 0.5 * Math.cos((3.0 * 3.14159) / 8.0)\n const g = 0.5 * Math.cos((7.0 * 3.14159) / 16.0)\n\n var alpha = new Array(4)\n var beta = new Array(4)\n var theta = new Array(4)\n var gamma = new Array(4)\n\n for (var row = 0; row < 8; ++row) {\n var rowPtr = row * 8\n\n alpha[0] = c * data[rowPtr + 2]\n alpha[1] = f * data[rowPtr + 2]\n alpha[2] = c * data[rowPtr + 6]\n alpha[3] = f * data[rowPtr + 6]\n\n beta[0] = b * data[rowPtr + 1] + d * data[rowPtr + 3] + e * data[rowPtr + 5] + g * data[rowPtr + 7]\n beta[1] = d * data[rowPtr + 1] - g * data[rowPtr + 3] - b * data[rowPtr + 5] - e * data[rowPtr + 7]\n beta[2] = e * data[rowPtr + 1] - b * data[rowPtr + 3] + g * data[rowPtr + 5] + d * data[rowPtr + 7]\n beta[3] = g * data[rowPtr + 1] - e * data[rowPtr + 3] + d * data[rowPtr + 5] - b * data[rowPtr + 7]\n\n theta[0] = a * (data[rowPtr + 0] + data[rowPtr + 4])\n theta[3] = a * (data[rowPtr + 0] - data[rowPtr + 4])\n theta[1] = alpha[0] + alpha[3]\n theta[2] = alpha[1] - alpha[2]\n\n gamma[0] = theta[0] + theta[1]\n gamma[1] = theta[3] + theta[2]\n gamma[2] = theta[3] - theta[2]\n gamma[3] = theta[0] - theta[1]\n\n data[rowPtr + 0] = gamma[0] + beta[0]\n data[rowPtr + 1] = gamma[1] + beta[1]\n data[rowPtr + 2] = gamma[2] + beta[2]\n data[rowPtr + 3] = gamma[3] + beta[3]\n\n data[rowPtr + 4] = gamma[3] - beta[3]\n data[rowPtr + 5] = gamma[2] - beta[2]\n data[rowPtr + 6] = gamma[1] - beta[1]\n data[rowPtr + 7] = gamma[0] - beta[0]\n }\n\n for (var column = 0; column < 8; ++column) {\n alpha[0] = c * data[16 + column]\n alpha[1] = f * data[16 + column]\n alpha[2] = c * data[48 + column]\n alpha[3] = f * data[48 + column]\n\n beta[0] = b * data[8 + column] + d * data[24 + column] + e * data[40 + column] + g * data[56 + column]\n beta[1] = d * data[8 + column] - g * data[24 + column] - b * data[40 + column] - e * data[56 + column]\n beta[2] = e * data[8 + column] - b * data[24 + column] + g * data[40 + column] + d * data[56 + column]\n beta[3] = g * data[8 + column] - e * data[24 + column] + d * data[40 + column] - b * data[56 + column]\n\n theta[0] = a * (data[column] + data[32 + column])\n theta[3] = a * (data[column] - data[32 + column])\n\n theta[1] = alpha[0] + alpha[3]\n theta[2] = alpha[1] - alpha[2]\n\n gamma[0] = theta[0] + theta[1]\n gamma[1] = theta[3] + theta[2]\n gamma[2] = theta[3] - theta[2]\n gamma[3] = theta[0] - theta[1]\n\n data[0 + column] = gamma[0] + beta[0]\n data[8 + column] = gamma[1] + beta[1]\n data[16 + column] = gamma[2] + beta[2]\n data[24 + column] = gamma[3] + beta[3]\n\n data[32 + column] = gamma[3] - beta[3]\n data[40 + column] = gamma[2] - beta[2]\n data[48 + column] = gamma[1] - beta[1]\n data[56 + column] = gamma[0] - beta[0]\n }\n }\n\n function csc709Inverse(data) {\n for (var i = 0; i < 64; ++i) {\n var y = data[0][i]\n var cb = data[1][i]\n var cr = data[2][i]\n\n data[0][i] = y + 1.5747 * cr\n data[1][i] = y - 0.1873 * cb - 0.4682 * cr\n data[2][i] = y + 1.8556 * cb\n }\n }\n\n function convertToHalf(src, dst, idx) {\n for (var i = 0; i < 64; ++i) {\n dst[idx + i] = DataUtils.toHalfFloat(toLinear(src[i]))\n }\n }\n\n function toLinear(float) {\n if (float <= 1) {\n return Math.sign(float) * Math.pow(Math.abs(float), 2.2)\n } else {\n return Math.sign(float) * Math.pow(logBase, Math.abs(float) - 1.0)\n }\n }\n\n function uncompressRAW(info) {\n return new DataView(info.array.buffer, info.offset.value, info.size)\n }\n\n function uncompressRLE(info) {\n var compressed = info.viewer.buffer.slice(info.offset.value, info.offset.value + info.size)\n\n var rawBuffer = new Uint8Array(decodeRunLength(compressed))\n var tmpBuffer = new Uint8Array(rawBuffer.length)\n\n predictor(rawBuffer) // revert predictor\n\n interleaveScalar(rawBuffer, tmpBuffer) // interleave pixels\n\n return new DataView(tmpBuffer.buffer)\n }\n\n function uncompressZIP(info) {\n var compressed = info.array.slice(info.offset.value, info.offset.value + info.size)\n var rawBuffer = unzlibSync(compressed)\n var tmpBuffer = new Uint8Array(rawBuffer.length)\n\n predictor(rawBuffer) // revert predictor\n\n interleaveScalar(rawBuffer, tmpBuffer) // interleave pixels\n\n return new DataView(tmpBuffer.buffer)\n }\n\n function uncompressPIZ(info) {\n var inDataView = info.viewer\n var inOffset = { value: info.offset.value }\n\n var outBuffer = new Uint16Array(info.width * info.scanlineBlockSize * (info.channels * info.type))\n var bitmap = new Uint8Array(BITMAP_SIZE)\n\n // Setup channel info\n var outBufferEnd = 0\n var pizChannelData = new Array(info.channels)\n for (var i = 0; i < info.channels; i++) {\n pizChannelData[i] = {}\n pizChannelData[i]['start'] = outBufferEnd\n pizChannelData[i]['end'] = pizChannelData[i]['start']\n pizChannelData[i]['nx'] = info.width\n pizChannelData[i]['ny'] = info.lines\n pizChannelData[i]['size'] = info.type\n\n outBufferEnd += pizChannelData[i].nx * pizChannelData[i].ny * pizChannelData[i].size\n }\n\n // Read range compression data\n\n var minNonZero = parseUint16(inDataView, inOffset)\n var maxNonZero = parseUint16(inDataView, inOffset)\n\n if (maxNonZero >= BITMAP_SIZE) {\n throw 'Something is wrong with PIZ_COMPRESSION BITMAP_SIZE'\n }\n\n if (minNonZero <= maxNonZero) {\n for (var i = 0; i < maxNonZero - minNonZero + 1; i++) {\n bitmap[i + minNonZero] = parseUint8(inDataView, inOffset)\n }\n }\n\n // Reverse LUT\n var lut = new Uint16Array(USHORT_RANGE)\n var maxValue = reverseLutFromBitmap(bitmap, lut)\n\n var length = parseUint32(inDataView, inOffset)\n\n // Huffman decoding\n hufUncompress(info.array, inDataView, inOffset, length, outBuffer, outBufferEnd)\n\n // Wavelet decoding\n for (var i = 0; i < info.channels; ++i) {\n var cd = pizChannelData[i]\n\n for (var j = 0; j < pizChannelData[i].size; ++j) {\n wav2Decode(outBuffer, cd.start + j, cd.nx, cd.size, cd.ny, cd.nx * cd.size, maxValue)\n }\n }\n\n // Expand the pixel data to their original range\n applyLut(lut, outBuffer, outBufferEnd)\n\n // Rearrange the pixel data into the format expected by the caller.\n var tmpOffset = 0\n var tmpBuffer = new Uint8Array(outBuffer.buffer.byteLength)\n for (var y = 0; y < info.lines; y++) {\n for (var c = 0; c < info.channels; c++) {\n var cd = pizChannelData[c]\n\n var n = cd.nx * cd.size\n var cp = new Uint8Array(outBuffer.buffer, cd.end * INT16_SIZE, n * INT16_SIZE)\n\n tmpBuffer.set(cp, tmpOffset)\n tmpOffset += n * INT16_SIZE\n cd.end += n\n }\n }\n\n return new DataView(tmpBuffer.buffer)\n }\n\n function uncompressPXR(info) {\n var compressed = info.array.slice(info.offset.value, info.offset.value + info.size)\n var rawBuffer = unzlibSync(compressed)\n\n const sz = info.lines * info.channels * info.width\n const tmpBuffer = info.type == 1 ? new Uint16Array(sz) : new Uint32Array(sz)\n\n let tmpBufferEnd = 0\n let writePtr = 0\n const ptr = new Array(4)\n\n for (let y = 0; y < info.lines; y++) {\n for (let c = 0; c < info.channels; c++) {\n let pixel = 0\n\n switch (info.type) {\n case 1:\n ptr[0] = tmpBufferEnd\n ptr[1] = ptr[0] + info.width\n tmpBufferEnd = ptr[1] + info.width\n\n for (let j = 0; j < info.width; ++j) {\n const diff = (rawBuffer[ptr[0]++] << 8) | rawBuffer[ptr[1]++]\n\n pixel += diff\n\n tmpBuffer[writePtr] = pixel\n writePtr++\n }\n\n break\n\n case 2:\n ptr[0] = tmpBufferEnd\n ptr[1] = ptr[0] + info.width\n ptr[2] = ptr[1] + info.width\n tmpBufferEnd = ptr[2] + info.width\n\n for (let j = 0; j < info.width; ++j) {\n const diff = (rawBuffer[ptr[0]++] << 24) | (rawBuffer[ptr[1]++] << 16) | (rawBuffer[ptr[2]++] << 8)\n\n pixel += diff\n\n tmpBuffer[writePtr] = pixel\n writePtr++\n }\n\n break\n }\n }\n }\n\n return new DataView(tmpBuffer.buffer)\n }\n\n function uncompressDWA(info) {\n var inDataView = info.viewer\n var inOffset = { value: info.offset.value }\n var outBuffer = new Uint8Array(info.width * info.lines * (info.channels * info.type * INT16_SIZE))\n\n // Read compression header information\n var dwaHeader = {\n version: parseInt64(inDataView, inOffset),\n unknownUncompressedSize: parseInt64(inDataView, inOffset),\n unknownCompressedSize: parseInt64(inDataView, inOffset),\n acCompressedSize: parseInt64(inDataView, inOffset),\n dcCompressedSize: parseInt64(inDataView, inOffset),\n rleCompressedSize: parseInt64(inDataView, inOffset),\n rleUncompressedSize: parseInt64(inDataView, inOffset),\n rleRawSize: parseInt64(inDataView, inOffset),\n totalAcUncompressedCount: parseInt64(inDataView, inOffset),\n totalDcUncompressedCount: parseInt64(inDataView, inOffset),\n acCompression: parseInt64(inDataView, inOffset),\n }\n\n if (dwaHeader.version < 2) {\n throw 'EXRLoader.parse: ' + EXRHeader.compression + ' version ' + dwaHeader.version + ' is unsupported'\n }\n\n // Read channel ruleset information\n var channelRules = new Array()\n var ruleSize = parseUint16(inDataView, inOffset) - INT16_SIZE\n\n while (ruleSize > 0) {\n var name = parseNullTerminatedString(inDataView.buffer, inOffset)\n var value = parseUint8(inDataView, inOffset)\n var compression = (value >> 2) & 3\n var csc = (value >> 4) - 1\n var index = new Int8Array([csc])[0]\n var type = parseUint8(inDataView, inOffset)\n\n channelRules.push({\n name: name,\n index: index,\n type: type,\n compression: compression,\n })\n\n ruleSize -= name.length + 3\n }\n\n // Classify channels\n var channels = EXRHeader.channels\n var channelData = new Array(info.channels)\n\n for (var i = 0; i < info.channels; ++i) {\n var cd = (channelData[i] = {})\n var channel = channels[i]\n\n cd.name = channel.name\n cd.compression = UNKNOWN\n cd.decoded = false\n cd.type = channel.pixelType\n cd.pLinear = channel.pLinear\n cd.width = info.width\n cd.height = info.lines\n }\n\n var cscSet = {\n idx: new Array(3),\n }\n\n for (var offset = 0; offset < info.channels; ++offset) {\n var cd = channelData[offset]\n\n for (var i = 0; i < channelRules.length; ++i) {\n var rule = channelRules[i]\n\n if (cd.name == rule.name) {\n cd.compression = rule.compression\n\n if (rule.index >= 0) {\n cscSet.idx[rule.index] = offset\n }\n\n cd.offset = offset\n }\n }\n }\n\n // Read DCT - AC component data\n if (dwaHeader.acCompressedSize > 0) {\n switch (dwaHeader.acCompression) {\n case STATIC_HUFFMAN:\n var acBuffer = new Uint16Array(dwaHeader.totalAcUncompressedCount)\n hufUncompress(\n info.array,\n inDataView,\n inOffset,\n dwaHeader.acCompressedSize,\n acBuffer,\n dwaHeader.totalAcUncompressedCount,\n )\n break\n\n case DEFLATE:\n var compressed = info.array.slice(inOffset.value, inOffset.value + dwaHeader.totalAcUncompressedCount)\n var data = unzlibSync(compressed)\n var acBuffer = new Uint16Array(data.buffer)\n inOffset.value += dwaHeader.totalAcUncompressedCount\n break\n }\n }\n\n // Read DCT - DC component data\n if (dwaHeader.dcCompressedSize > 0) {\n var zlibInfo = {\n array: info.array,\n offset: inOffset,\n size: dwaHeader.dcCompressedSize,\n }\n var dcBuffer = new Uint16Array(uncompressZIP(zlibInfo).buffer)\n inOffset.value += dwaHeader.dcCompressedSize\n }\n\n // Read RLE compressed data\n if (dwaHeader.rleRawSize > 0) {\n var compressed = info.array.slice(inOffset.value, inOffset.value + dwaHeader.rleCompressedSize)\n var data = unzlibSync(compressed)\n var rleBuffer = decodeRunLength(data.buffer)\n\n inOffset.value += dwaHeader.rleCompressedSize\n }\n\n // Prepare outbuffer data offset\n var outBufferEnd = 0\n var rowOffsets = new Array(channelData.length)\n for (var i = 0; i < rowOffsets.length; ++i) {\n rowOffsets[i] = new Array()\n }\n\n for (var y = 0; y < info.lines; ++y) {\n for (var chan = 0; chan < channelData.length; ++chan) {\n rowOffsets[chan].push(outBufferEnd)\n outBufferEnd += channelData[chan].width * info.type * INT16_SIZE\n }\n }\n\n // Lossy DCT decode RGB channels\n lossyDctDecode(cscSet, rowOffsets, channelData, acBuffer, dcBuffer, outBuffer)\n\n // Decode other channels\n for (var i = 0; i < channelData.length; ++i) {\n var cd = channelData[i]\n\n if (cd.decoded) continue\n\n switch (cd.compression) {\n case RLE:\n var row = 0\n var rleOffset = 0\n\n for (var y = 0; y < info.lines; ++y) {\n var rowOffsetBytes = rowOffsets[i][row]\n\n for (var x = 0; x < cd.width; ++x) {\n for (var byte = 0; byte < INT16_SIZE * cd.type; ++byte) {\n outBuffer[rowOffsetBytes++] = rleBuffer[rleOffset + byte * cd.width * cd.height]\n }\n\n rleOffset++\n }\n\n row++\n }\n\n break\n\n case LOSSY_DCT: // skip\n\n default:\n throw 'EXRLoader.parse: unsupported channel compression'\n }\n }\n\n return new DataView(outBuffer.buffer)\n }\n\n function parseNullTerminatedString(buffer, offset) {\n var uintBuffer = new Uint8Array(buffer)\n var endOffset = 0\n\n while (uintBuffer[offset.value + endOffset] != 0) {\n endOffset += 1\n }\n\n var stringValue = new TextDecoder().decode(uintBuffer.slice(offset.value, offset.value + endOffset))\n\n offset.value = offset.value + endOffset + 1\n\n return stringValue\n }\n\n function parseFixedLengthString(buffer, offset, size) {\n var stringValue = new TextDecoder().decode(new Uint8Array(buffer).slice(offset.value, offset.value + size))\n\n offset.value = offset.value + size\n\n return stringValue\n }\n\n function parseRational(dataView, offset) {\n var x = parseInt32(dataView, offset)\n var y = parseUint32(dataView, offset)\n\n return [x, y]\n }\n\n function parseTimecode(dataView, offset) {\n var x = parseUint32(dataView, offset)\n var y = parseUint32(dataView, offset)\n\n return [x, y]\n }\n\n function parseInt32(dataView, offset) {\n var Int32 = dataView.getInt32(offset.value, true)\n\n offset.value = offset.value + INT32_SIZE\n\n return Int32\n }\n\n function parseUint32(dataView, offset) {\n var Uint32 = dataView.getUint32(offset.value, true)\n\n offset.value = offset.value + INT32_SIZE\n\n return Uint32\n }\n\n function parseUint8Array(uInt8Array, offset) {\n var Uint8 = uInt8Array[offset.value]\n\n offset.value = offset.value + INT8_SIZE\n\n return Uint8\n }\n\n function parseUint8(dataView, offset) {\n var Uint8 = dataView.getUint8(offset.value)\n\n offset.value = offset.value + INT8_SIZE\n\n return Uint8\n }\n\n const parseInt64 = function (dataView, offset) {\n let int\n\n if ('getBigInt64' in DataView.prototype) {\n int = Number(dataView.getBigInt64(offset.value, true))\n } else {\n int = dataView.getUint32(offset.value + 4, true) + Number(dataView.getUint32(offset.value, true) << 32)\n }\n\n offset.value += ULONG_SIZE\n\n return int\n }\n\n function parseFloat32(dataView, offset) {\n var float = dataView.getFloat32(offset.value, true)\n\n offset.value += FLOAT32_SIZE\n\n return float\n }\n\n function decodeFloat32(dataView, offset) {\n return DataUtils.toHalfFloat(parseFloat32(dataView, offset))\n }\n\n // https://stackoverflow.com/questions/5678432/decompressing-half-precision-floats-in-javascript\n function decodeFloat16(binary) {\n var exponent = (binary & 0x7c00) >> 10,\n fraction = binary & 0x03ff\n\n return (\n (binary >> 15 ? -1 : 1) *\n (exponent\n ? exponent === 0x1f\n ? fraction\n ? NaN\n : Infinity\n : Math.pow(2, exponent - 15) * (1 + fraction / 0x400)\n : 6.103515625e-5 * (fraction / 0x400))\n )\n }\n\n function parseUint16(dataView, offset) {\n var Uint16 = dataView.getUint16(offset.value, true)\n\n offset.value += INT16_SIZE\n\n return Uint16\n }\n\n function parseFloat16(buffer, offset) {\n return decodeFloat16(parseUint16(buffer, offset))\n }\n\n function parseChlist(dataView, buffer, offset, size) {\n var startOffset = offset.value\n var channels = []\n\n while (offset.value < startOffset + size - 1) {\n var name = parseNullTerminatedString(buffer, offset)\n var pixelType = parseInt32(dataView, offset)\n var pLinear = parseUint8(dataView, offset)\n offset.value += 3 // reserved, three chars\n var xSampling = parseInt32(dataView, offset)\n var ySampling = parseInt32(dataView, offset)\n\n channels.push({\n name: name,\n pixelType: pixelType,\n pLinear: pLinear,\n xSampling: xSampling,\n ySampling: ySampling,\n })\n }\n\n offset.value += 1\n\n return channels\n }\n\n function parseChromaticities(dataView, offset) {\n var redX = parseFloat32(dataView, offset)\n var redY = parseFloat32(dataView, offset)\n var greenX = parseFloat32(dataView, offset)\n var greenY = parseFloat32(dataView, offset)\n var blueX = parseFloat32(dataView, offset)\n var blueY = parseFloat32(dataView, offset)\n var whiteX = parseFloat32(dataView, offset)\n var whiteY = parseFloat32(dataView, offset)\n\n return {\n redX: redX,\n redY: redY,\n greenX: greenX,\n greenY: greenY,\n blueX: blueX,\n blueY: blueY,\n whiteX: whiteX,\n whiteY: whiteY,\n }\n }\n\n function parseCompression(dataView, offset) {\n var compressionCodes = [\n 'NO_COMPRESSION',\n 'RLE_COMPRESSION',\n 'ZIPS_COMPRESSION',\n 'ZIP_COMPRESSION',\n 'PIZ_COMPRESSION',\n 'PXR24_COMPRESSION',\n 'B44_COMPRESSION',\n 'B44A_COMPRESSION',\n 'DWAA_COMPRESSION',\n 'DWAB_COMPRESSION',\n ]\n\n var compression = parseUint8(dataView, offset)\n\n return compressionCodes[compression]\n }\n\n function parseBox2i(dataView, offset) {\n var xMin = parseUint32(dataView, offset)\n var yMin = parseUint32(dataView, offset)\n var xMax = parseUint32(dataView, offset)\n var yMax = parseUint32(dataView, offset)\n\n return { xMin: xMin, yMin: yMin, xMax: xMax, yMax: yMax }\n }\n\n function parseLineOrder(dataView, offset) {\n var lineOrders = ['INCREASING_Y']\n\n var lineOrder = parseUint8(dataView, offset)\n\n return lineOrders[lineOrder]\n }\n\n function parseV2f(dataView, offset) {\n var x = parseFloat32(dataView, offset)\n var y = parseFloat32(dataView, offset)\n\n return [x, y]\n }\n\n function parseV3f(dataView, offset) {\n var x = parseFloat32(dataView, offset)\n var y = parseFloat32(dataView, offset)\n var z = parseFloat32(dataView, offset)\n\n return [x, y, z]\n }\n\n function parseValue(dataView, buffer, offset, type, size) {\n if (type === 'string' || type === 'stringvector' || type === 'iccProfile') {\n return parseFixedLengthString(buffer, offset, size)\n } else if (type === 'chlist') {\n return parseChlist(dataView, buffer, offset, size)\n } else if (type === 'chromaticities') {\n return parseChromaticities(dataView, offset)\n } else if (type === 'compression') {\n return parseCompression(dataView, offset)\n } else if (type === 'box2i') {\n return parseBox2i(dataView, offset)\n } else if (type === 'lineOrder') {\n return parseLineOrder(dataView, offset)\n } else if (type === 'float') {\n return parseFloat32(dataView, offset)\n } else if (type === 'v2f') {\n return parseV2f(dataView, offset)\n } else if (type === 'v3f') {\n return parseV3f(dataView, offset)\n } else if (type === 'int') {\n return parseInt32(dataView, offset)\n } else if (type === 'rational') {\n return parseRational(dataView, offset)\n } else if (type === 'timecode') {\n return parseTimecode(dataView, offset)\n } else if (type === 'preview') {\n offset.value += size\n return 'skipped'\n } else {\n offset.value += size\n return undefined\n }\n }\n\n function parseHeader(dataView, buffer, offset) {\n const EXRHeader = {}\n\n if (dataView.getUint32(0, true) != 20000630) {\n // magic\n throw \"THREE.EXRLoader: provided file doesn't appear to be in OpenEXR format.\"\n }\n\n EXRHeader.version = dataView.getUint8(4)\n\n const spec = dataView.getUint8(5) // fullMask\n\n EXRHeader.spec = {\n singleTile: !!(spec & 2),\n longName: !!(spec & 4),\n deepFormat: !!(spec & 8),\n multiPart: !!(s