UNPKG

@cesium/engine

Version:

CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.

1,197 lines (1,194 loc) 92.3 kB
/** * @license * Cesium - https://github.com/CesiumGS/cesium * Version 1.132 * * Copyright 2011-2022 Cesium Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Columbus View (Pat. Pend.) * * Portions licensed separately. * See https://github.com/CesiumGS/cesium/blob/main/LICENSE.md for full licensing details. */ import { EllipsoidalOccluder_default, TerrainEncoding_default } from "./chunk-23FRF5ZP.js"; import { createTaskProcessorWorker_default } from "./chunk-DPFAUGBE.js"; import { WebMercatorProjection_default } from "./chunk-4NRFVAG2.js"; import { OrientedBoundingBox_default } from "./chunk-HHHBRTSW.js"; import "./chunk-K5VGMGFM.js"; import "./chunk-DAHXCIOX.js"; import { AxisAlignedBoundingBox_default } from "./chunk-AABNX23Q.js"; import "./chunk-25USKS4R.js"; import "./chunk-RZJA77TX.js"; import { BoundingSphere_default } from "./chunk-GO3IRH6U.js"; import { Matrix4_default, Rectangle_default, Transforms_default } from "./chunk-WUMTX3FI.js"; import "./chunk-FQNSMOZT.js"; import { Cartesian2_default, Cartesian3_default, Ellipsoid_default } from "./chunk-E6NMEKSS.js"; import { Math_default } from "./chunk-Y3PM6G2V.js"; import "./chunk-DXYAD4ED.js"; import { RuntimeError_default } from "./chunk-Q2QXUN33.js"; import { DeveloperError_default } from "./chunk-SOYVF5RC.js"; import { __commonJS, __toESM, defined_default } from "./chunk-EV4PBU7O.js"; // node_modules/lerc/LercDecode.js var require_LercDecode = __commonJS({ "node_modules/lerc/LercDecode.js"(exports, module) { /* Copyright 2015-2018 Esri. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 @preserve */ (function() { var LercDecode = function() { var CntZImage = {}; CntZImage.defaultNoDataValue = -34027999387901484e22; CntZImage.decode = function(input, options) { options = options || {}; var skipMask = options.encodedMaskData || options.encodedMaskData === null; var parsedData = parse(input, options.inputOffset || 0, skipMask); var noDataValue = options.noDataValue !== null ? options.noDataValue : CntZImage.defaultNoDataValue; var uncompressedData = uncompressPixelValues( parsedData, options.pixelType || Float32Array, options.encodedMaskData, noDataValue, options.returnMask ); var result = { width: parsedData.width, height: parsedData.height, pixelData: uncompressedData.resultPixels, minValue: uncompressedData.minValue, maxValue: parsedData.pixels.maxValue, noDataValue }; if (uncompressedData.resultMask) { result.maskData = uncompressedData.resultMask; } if (options.returnEncodedMask && parsedData.mask) { result.encodedMaskData = parsedData.mask.bitset ? parsedData.mask.bitset : null; } if (options.returnFileInfo) { result.fileInfo = formatFileInfo(parsedData); if (options.computeUsedBitDepths) { result.fileInfo.bitDepths = computeUsedBitDepths(parsedData); } } return result; }; var uncompressPixelValues = function(data, TypedArrayClass, maskBitset, noDataValue, storeDecodedMask) { var blockIdx = 0; var numX = data.pixels.numBlocksX; var numY = data.pixels.numBlocksY; var blockWidth = Math.floor(data.width / numX); var blockHeight = Math.floor(data.height / numY); var scale = 2 * data.maxZError; var minValue = Number.MAX_VALUE, currentValue; maskBitset = maskBitset || (data.mask ? data.mask.bitset : null); var resultPixels, resultMask; resultPixels = new TypedArrayClass(data.width * data.height); if (storeDecodedMask && maskBitset) { resultMask = new Uint8Array(data.width * data.height); } var blockDataBuffer = new Float32Array(blockWidth * blockHeight); var xx, yy; for (var y = 0; y <= numY; y++) { var thisBlockHeight = y !== numY ? blockHeight : data.height % numY; if (thisBlockHeight === 0) { continue; } for (var x = 0; x <= numX; x++) { var thisBlockWidth = x !== numX ? blockWidth : data.width % numX; if (thisBlockWidth === 0) { continue; } var outPtr = y * data.width * blockHeight + x * blockWidth; var outStride = data.width - thisBlockWidth; var block = data.pixels.blocks[blockIdx]; var blockData, blockPtr, constValue; if (block.encoding < 2) { if (block.encoding === 0) { blockData = block.rawData; } else { unstuff(block.stuffedData, block.bitsPerPixel, block.numValidPixels, block.offset, scale, blockDataBuffer, data.pixels.maxValue); blockData = blockDataBuffer; } blockPtr = 0; } else if (block.encoding === 2) { constValue = 0; } else { constValue = block.offset; } var maskByte; if (maskBitset) { for (yy = 0; yy < thisBlockHeight; yy++) { if (outPtr & 7) { maskByte = maskBitset[outPtr >> 3]; maskByte <<= outPtr & 7; } for (xx = 0; xx < thisBlockWidth; xx++) { if (!(outPtr & 7)) { maskByte = maskBitset[outPtr >> 3]; } if (maskByte & 128) { if (resultMask) { resultMask[outPtr] = 1; } currentValue = block.encoding < 2 ? blockData[blockPtr++] : constValue; minValue = minValue > currentValue ? currentValue : minValue; resultPixels[outPtr++] = currentValue; } else { if (resultMask) { resultMask[outPtr] = 0; } resultPixels[outPtr++] = noDataValue; } maskByte <<= 1; } outPtr += outStride; } } else { if (block.encoding < 2) { for (yy = 0; yy < thisBlockHeight; yy++) { for (xx = 0; xx < thisBlockWidth; xx++) { currentValue = blockData[blockPtr++]; minValue = minValue > currentValue ? currentValue : minValue; resultPixels[outPtr++] = currentValue; } outPtr += outStride; } } else { minValue = minValue > constValue ? constValue : minValue; for (yy = 0; yy < thisBlockHeight; yy++) { for (xx = 0; xx < thisBlockWidth; xx++) { resultPixels[outPtr++] = constValue; } outPtr += outStride; } } } if (block.encoding === 1 && blockPtr !== block.numValidPixels) { throw "Block and Mask do not match"; } blockIdx++; } } return { resultPixels, resultMask, minValue }; }; var formatFileInfo = function(data) { return { "fileIdentifierString": data.fileIdentifierString, "fileVersion": data.fileVersion, "imageType": data.imageType, "height": data.height, "width": data.width, "maxZError": data.maxZError, "eofOffset": data.eofOffset, "mask": data.mask ? { "numBlocksX": data.mask.numBlocksX, "numBlocksY": data.mask.numBlocksY, "numBytes": data.mask.numBytes, "maxValue": data.mask.maxValue } : null, "pixels": { "numBlocksX": data.pixels.numBlocksX, "numBlocksY": data.pixels.numBlocksY, "numBytes": data.pixels.numBytes, "maxValue": data.pixels.maxValue, "noDataValue": data.noDataValue } }; }; var computeUsedBitDepths = function(data) { var numBlocks = data.pixels.numBlocksX * data.pixels.numBlocksY; var bitDepths = {}; for (var i = 0; i < numBlocks; i++) { var block = data.pixels.blocks[i]; if (block.encoding === 0) { bitDepths.float32 = true; } else if (block.encoding === 1) { bitDepths[block.bitsPerPixel] = true; } else { bitDepths[0] = true; } } return Object.keys(bitDepths); }; var parse = function(input, fp, skipMask) { var data = {}; var fileIdView = new Uint8Array(input, fp, 10); data.fileIdentifierString = String.fromCharCode.apply(null, fileIdView); if (data.fileIdentifierString.trim() !== "CntZImage") { throw "Unexpected file identifier string: " + data.fileIdentifierString; } fp += 10; var view = new DataView(input, fp, 24); data.fileVersion = view.getInt32(0, true); data.imageType = view.getInt32(4, true); data.height = view.getUint32(8, true); data.width = view.getUint32(12, true); data.maxZError = view.getFloat64(16, true); fp += 24; if (!skipMask) { view = new DataView(input, fp, 16); data.mask = {}; data.mask.numBlocksY = view.getUint32(0, true); data.mask.numBlocksX = view.getUint32(4, true); data.mask.numBytes = view.getUint32(8, true); data.mask.maxValue = view.getFloat32(12, true); fp += 16; if (data.mask.numBytes > 0) { var bitset = new Uint8Array(Math.ceil(data.width * data.height / 8)); view = new DataView(input, fp, data.mask.numBytes); var cnt = view.getInt16(0, true); var ip = 2, op = 0; do { if (cnt > 0) { while (cnt--) { bitset[op++] = view.getUint8(ip++); } } else { var val = view.getUint8(ip++); cnt = -cnt; while (cnt--) { bitset[op++] = val; } } cnt = view.getInt16(ip, true); ip += 2; } while (ip < data.mask.numBytes); if (cnt !== -32768 || op < bitset.length) { throw "Unexpected end of mask RLE encoding"; } data.mask.bitset = bitset; fp += data.mask.numBytes; } else if ((data.mask.numBytes | data.mask.numBlocksY | data.mask.maxValue) === 0) { data.mask.bitset = new Uint8Array(Math.ceil(data.width * data.height / 8)); } } view = new DataView(input, fp, 16); data.pixels = {}; data.pixels.numBlocksY = view.getUint32(0, true); data.pixels.numBlocksX = view.getUint32(4, true); data.pixels.numBytes = view.getUint32(8, true); data.pixels.maxValue = view.getFloat32(12, true); fp += 16; var numBlocksX = data.pixels.numBlocksX; var numBlocksY = data.pixels.numBlocksY; var actualNumBlocksX = numBlocksX + (data.width % numBlocksX > 0 ? 1 : 0); var actualNumBlocksY = numBlocksY + (data.height % numBlocksY > 0 ? 1 : 0); data.pixels.blocks = new Array(actualNumBlocksX * actualNumBlocksY); var blockI = 0; for (var blockY = 0; blockY < actualNumBlocksY; blockY++) { for (var blockX = 0; blockX < actualNumBlocksX; blockX++) { var size = 0; var bytesLeft = input.byteLength - fp; view = new DataView(input, fp, Math.min(10, bytesLeft)); var block = {}; data.pixels.blocks[blockI++] = block; var headerByte = view.getUint8(0); size++; block.encoding = headerByte & 63; if (block.encoding > 3) { throw "Invalid block encoding (" + block.encoding + ")"; } if (block.encoding === 2) { fp++; continue; } if (headerByte !== 0 && headerByte !== 2) { headerByte >>= 6; block.offsetType = headerByte; if (headerByte === 2) { block.offset = view.getInt8(1); size++; } else if (headerByte === 1) { block.offset = view.getInt16(1, true); size += 2; } else if (headerByte === 0) { block.offset = view.getFloat32(1, true); size += 4; } else { throw "Invalid block offset type"; } if (block.encoding === 1) { headerByte = view.getUint8(size); size++; block.bitsPerPixel = headerByte & 63; headerByte >>= 6; block.numValidPixelsType = headerByte; if (headerByte === 2) { block.numValidPixels = view.getUint8(size); size++; } else if (headerByte === 1) { block.numValidPixels = view.getUint16(size, true); size += 2; } else if (headerByte === 0) { block.numValidPixels = view.getUint32(size, true); size += 4; } else { throw "Invalid valid pixel count type"; } } } fp += size; if (block.encoding === 3) { continue; } var arrayBuf, store8; if (block.encoding === 0) { var numPixels = (data.pixels.numBytes - 1) / 4; if (numPixels !== Math.floor(numPixels)) { throw "uncompressed block has invalid length"; } arrayBuf = new ArrayBuffer(numPixels * 4); store8 = new Uint8Array(arrayBuf); store8.set(new Uint8Array(input, fp, numPixels * 4)); var rawData = new Float32Array(arrayBuf); block.rawData = rawData; fp += numPixels * 4; } else if (block.encoding === 1) { var dataBytes = Math.ceil(block.numValidPixels * block.bitsPerPixel / 8); var dataWords = Math.ceil(dataBytes / 4); arrayBuf = new ArrayBuffer(dataWords * 4); store8 = new Uint8Array(arrayBuf); store8.set(new Uint8Array(input, fp, dataBytes)); block.stuffedData = new Uint32Array(arrayBuf); fp += dataBytes; } } } data.eofOffset = fp; return data; }; var unstuff = function(src, bitsPerPixel, numPixels, offset, scale, dest, maxValue) { var bitMask = (1 << bitsPerPixel) - 1; var i = 0, o; var bitsLeft = 0; var n, buffer; var nmax = Math.ceil((maxValue - offset) / scale); var numInvalidTailBytes = src.length * 4 - Math.ceil(bitsPerPixel * numPixels / 8); src[src.length - 1] <<= 8 * numInvalidTailBytes; for (o = 0; o < numPixels; o++) { if (bitsLeft === 0) { buffer = src[i++]; bitsLeft = 32; } if (bitsLeft >= bitsPerPixel) { n = buffer >>> bitsLeft - bitsPerPixel & bitMask; bitsLeft -= bitsPerPixel; } else { var missingBits = bitsPerPixel - bitsLeft; n = (buffer & bitMask) << missingBits & bitMask; buffer = src[i++]; bitsLeft = 32 - missingBits; n += buffer >>> bitsLeft; } dest[o] = n < nmax ? offset + n * scale : maxValue; } return dest; }; return CntZImage; }(); var Lerc2Decode = function() { "use strict"; var BitStuffer = { //methods ending with 2 are for the new byte order used by Lerc2.3 and above. //originalUnstuff is used to unpack Huffman code table. code is duplicated to unstuffx for performance reasons. unstuff: function(src, dest, bitsPerPixel, numPixels, lutArr, offset, scale, maxValue) { var bitMask = (1 << bitsPerPixel) - 1; var i = 0, o; var bitsLeft = 0; var n, buffer, missingBits, nmax; var numInvalidTailBytes = src.length * 4 - Math.ceil(bitsPerPixel * numPixels / 8); src[src.length - 1] <<= 8 * numInvalidTailBytes; if (lutArr) { for (o = 0; o < numPixels; o++) { if (bitsLeft === 0) { buffer = src[i++]; bitsLeft = 32; } if (bitsLeft >= bitsPerPixel) { n = buffer >>> bitsLeft - bitsPerPixel & bitMask; bitsLeft -= bitsPerPixel; } else { missingBits = bitsPerPixel - bitsLeft; n = (buffer & bitMask) << missingBits & bitMask; buffer = src[i++]; bitsLeft = 32 - missingBits; n += buffer >>> bitsLeft; } dest[o] = lutArr[n]; } } else { nmax = Math.ceil((maxValue - offset) / scale); for (o = 0; o < numPixels; o++) { if (bitsLeft === 0) { buffer = src[i++]; bitsLeft = 32; } if (bitsLeft >= bitsPerPixel) { n = buffer >>> bitsLeft - bitsPerPixel & bitMask; bitsLeft -= bitsPerPixel; } else { missingBits = bitsPerPixel - bitsLeft; n = (buffer & bitMask) << missingBits & bitMask; buffer = src[i++]; bitsLeft = 32 - missingBits; n += buffer >>> bitsLeft; } dest[o] = n < nmax ? offset + n * scale : maxValue; } } }, unstuffLUT: function(src, bitsPerPixel, numPixels, offset, scale, maxValue) { var bitMask = (1 << bitsPerPixel) - 1; var i = 0, o = 0, missingBits = 0, bitsLeft = 0, n = 0; var buffer; var dest = []; var numInvalidTailBytes = src.length * 4 - Math.ceil(bitsPerPixel * numPixels / 8); src[src.length - 1] <<= 8 * numInvalidTailBytes; var nmax = Math.ceil((maxValue - offset) / scale); for (o = 0; o < numPixels; o++) { if (bitsLeft === 0) { buffer = src[i++]; bitsLeft = 32; } if (bitsLeft >= bitsPerPixel) { n = buffer >>> bitsLeft - bitsPerPixel & bitMask; bitsLeft -= bitsPerPixel; } else { missingBits = bitsPerPixel - bitsLeft; n = (buffer & bitMask) << missingBits & bitMask; buffer = src[i++]; bitsLeft = 32 - missingBits; n += buffer >>> bitsLeft; } dest[o] = n < nmax ? offset + n * scale : maxValue; } dest.unshift(offset); return dest; }, unstuff2: function(src, dest, bitsPerPixel, numPixels, lutArr, offset, scale, maxValue) { var bitMask = (1 << bitsPerPixel) - 1; var i = 0, o; var bitsLeft = 0, bitPos = 0; var n, buffer, missingBits; if (lutArr) { for (o = 0; o < numPixels; o++) { if (bitsLeft === 0) { buffer = src[i++]; bitsLeft = 32; bitPos = 0; } if (bitsLeft >= bitsPerPixel) { n = buffer >>> bitPos & bitMask; bitsLeft -= bitsPerPixel; bitPos += bitsPerPixel; } else { missingBits = bitsPerPixel - bitsLeft; n = buffer >>> bitPos & bitMask; buffer = src[i++]; bitsLeft = 32 - missingBits; n |= (buffer & (1 << missingBits) - 1) << bitsPerPixel - missingBits; bitPos = missingBits; } dest[o] = lutArr[n]; } } else { var nmax = Math.ceil((maxValue - offset) / scale); for (o = 0; o < numPixels; o++) { if (bitsLeft === 0) { buffer = src[i++]; bitsLeft = 32; bitPos = 0; } if (bitsLeft >= bitsPerPixel) { n = buffer >>> bitPos & bitMask; bitsLeft -= bitsPerPixel; bitPos += bitsPerPixel; } else { missingBits = bitsPerPixel - bitsLeft; n = buffer >>> bitPos & bitMask; buffer = src[i++]; bitsLeft = 32 - missingBits; n |= (buffer & (1 << missingBits) - 1) << bitsPerPixel - missingBits; bitPos = missingBits; } dest[o] = n < nmax ? offset + n * scale : maxValue; } } return dest; }, unstuffLUT2: function(src, bitsPerPixel, numPixels, offset, scale, maxValue) { var bitMask = (1 << bitsPerPixel) - 1; var i = 0, o = 0, missingBits = 0, bitsLeft = 0, n = 0, bitPos = 0; var buffer; var dest = []; var nmax = Math.ceil((maxValue - offset) / scale); for (o = 0; o < numPixels; o++) { if (bitsLeft === 0) { buffer = src[i++]; bitsLeft = 32; bitPos = 0; } if (bitsLeft >= bitsPerPixel) { n = buffer >>> bitPos & bitMask; bitsLeft -= bitsPerPixel; bitPos += bitsPerPixel; } else { missingBits = bitsPerPixel - bitsLeft; n = buffer >>> bitPos & bitMask; buffer = src[i++]; bitsLeft = 32 - missingBits; n |= (buffer & (1 << missingBits) - 1) << bitsPerPixel - missingBits; bitPos = missingBits; } dest[o] = n < nmax ? offset + n * scale : maxValue; } dest.unshift(offset); return dest; }, originalUnstuff: function(src, dest, bitsPerPixel, numPixels) { var bitMask = (1 << bitsPerPixel) - 1; var i = 0, o; var bitsLeft = 0; var n, buffer, missingBits; var numInvalidTailBytes = src.length * 4 - Math.ceil(bitsPerPixel * numPixels / 8); src[src.length - 1] <<= 8 * numInvalidTailBytes; for (o = 0; o < numPixels; o++) { if (bitsLeft === 0) { buffer = src[i++]; bitsLeft = 32; } if (bitsLeft >= bitsPerPixel) { n = buffer >>> bitsLeft - bitsPerPixel & bitMask; bitsLeft -= bitsPerPixel; } else { missingBits = bitsPerPixel - bitsLeft; n = (buffer & bitMask) << missingBits & bitMask; buffer = src[i++]; bitsLeft = 32 - missingBits; n += buffer >>> bitsLeft; } dest[o] = n; } return dest; }, originalUnstuff2: function(src, dest, bitsPerPixel, numPixels) { var bitMask = (1 << bitsPerPixel) - 1; var i = 0, o; var bitsLeft = 0, bitPos = 0; var n, buffer, missingBits; for (o = 0; o < numPixels; o++) { if (bitsLeft === 0) { buffer = src[i++]; bitsLeft = 32; bitPos = 0; } if (bitsLeft >= bitsPerPixel) { n = buffer >>> bitPos & bitMask; bitsLeft -= bitsPerPixel; bitPos += bitsPerPixel; } else { missingBits = bitsPerPixel - bitsLeft; n = buffer >>> bitPos & bitMask; buffer = src[i++]; bitsLeft = 32 - missingBits; n |= (buffer & (1 << missingBits) - 1) << bitsPerPixel - missingBits; bitPos = missingBits; } dest[o] = n; } return dest; } }; var Lerc2Helpers = { HUFFMAN_LUT_BITS_MAX: 12, //use 2^12 lut, treat it like constant computeChecksumFletcher32: function(input) { var sum1 = 65535, sum2 = 65535; var len = input.length; var words = Math.floor(len / 2); var i = 0; while (words) { var tlen = words >= 359 ? 359 : words; words -= tlen; do { sum1 += input[i++] << 8; sum2 += sum1 += input[i++]; } while (--tlen); sum1 = (sum1 & 65535) + (sum1 >>> 16); sum2 = (sum2 & 65535) + (sum2 >>> 16); } if (len & 1) { sum2 += sum1 += input[i] << 8; } sum1 = (sum1 & 65535) + (sum1 >>> 16); sum2 = (sum2 & 65535) + (sum2 >>> 16); return (sum2 << 16 | sum1) >>> 0; }, readHeaderInfo: function(input, data) { var ptr = data.ptr; var fileIdView = new Uint8Array(input, ptr, 6); var headerInfo = {}; headerInfo.fileIdentifierString = String.fromCharCode.apply(null, fileIdView); if (headerInfo.fileIdentifierString.lastIndexOf("Lerc2", 0) !== 0) { throw "Unexpected file identifier string (expect Lerc2 ): " + headerInfo.fileIdentifierString; } ptr += 6; var view = new DataView(input, ptr, 8); var fileVersion = view.getInt32(0, true); headerInfo.fileVersion = fileVersion; ptr += 4; if (fileVersion >= 3) { headerInfo.checksum = view.getUint32(4, true); ptr += 4; } view = new DataView(input, ptr, 12); headerInfo.height = view.getUint32(0, true); headerInfo.width = view.getUint32(4, true); ptr += 8; if (fileVersion >= 4) { headerInfo.numDims = view.getUint32(8, true); ptr += 4; } else { headerInfo.numDims = 1; } view = new DataView(input, ptr, 40); headerInfo.numValidPixel = view.getUint32(0, true); headerInfo.microBlockSize = view.getInt32(4, true); headerInfo.blobSize = view.getInt32(8, true); headerInfo.imageType = view.getInt32(12, true); headerInfo.maxZError = view.getFloat64(16, true); headerInfo.zMin = view.getFloat64(24, true); headerInfo.zMax = view.getFloat64(32, true); ptr += 40; data.headerInfo = headerInfo; data.ptr = ptr; var checksum, keyLength; if (fileVersion >= 3) { keyLength = fileVersion >= 4 ? 52 : 48; checksum = this.computeChecksumFletcher32(new Uint8Array(input, ptr - keyLength, headerInfo.blobSize - 14)); if (checksum !== headerInfo.checksum) { throw "Checksum failed."; } } return true; }, checkMinMaxRanges: function(input, data) { var headerInfo = data.headerInfo; var OutPixelTypeArray = this.getDataTypeArray(headerInfo.imageType); var rangeBytes = headerInfo.numDims * this.getDataTypeSize(headerInfo.imageType); var minValues = this.readSubArray(input, data.ptr, OutPixelTypeArray, rangeBytes); var maxValues = this.readSubArray(input, data.ptr + rangeBytes, OutPixelTypeArray, rangeBytes); data.ptr += 2 * rangeBytes; var i, equal = true; for (i = 0; i < headerInfo.numDims; i++) { if (minValues[i] !== maxValues[i]) { equal = false; break; } } headerInfo.minValues = minValues; headerInfo.maxValues = maxValues; return equal; }, readSubArray: function(input, ptr, OutPixelTypeArray, numBytes) { var rawData; if (OutPixelTypeArray === Uint8Array) { rawData = new Uint8Array(input, ptr, numBytes); } else { var arrayBuf = new ArrayBuffer(numBytes); var store8 = new Uint8Array(arrayBuf); store8.set(new Uint8Array(input, ptr, numBytes)); rawData = new OutPixelTypeArray(arrayBuf); } return rawData; }, readMask: function(input, data) { var ptr = data.ptr; var headerInfo = data.headerInfo; var numPixels = headerInfo.width * headerInfo.height; var numValidPixel = headerInfo.numValidPixel; var view = new DataView(input, ptr, 4); var mask = {}; mask.numBytes = view.getUint32(0, true); ptr += 4; if ((0 === numValidPixel || numPixels === numValidPixel) && 0 !== mask.numBytes) { throw "invalid mask"; } var bitset, resultMask; if (numValidPixel === 0) { bitset = new Uint8Array(Math.ceil(numPixels / 8)); mask.bitset = bitset; resultMask = new Uint8Array(numPixels); data.pixels.resultMask = resultMask; ptr += mask.numBytes; } else if (mask.numBytes > 0) { bitset = new Uint8Array(Math.ceil(numPixels / 8)); view = new DataView(input, ptr, mask.numBytes); var cnt = view.getInt16(0, true); var ip = 2, op = 0, val = 0; do { if (cnt > 0) { while (cnt--) { bitset[op++] = view.getUint8(ip++); } } else { val = view.getUint8(ip++); cnt = -cnt; while (cnt--) { bitset[op++] = val; } } cnt = view.getInt16(ip, true); ip += 2; } while (ip < mask.numBytes); if (cnt !== -32768 || op < bitset.length) { throw "Unexpected end of mask RLE encoding"; } resultMask = new Uint8Array(numPixels); var mb = 0, k = 0; for (k = 0; k < numPixels; k++) { if (k & 7) { mb = bitset[k >> 3]; mb <<= k & 7; } else { mb = bitset[k >> 3]; } if (mb & 128) { resultMask[k] = 1; } } data.pixels.resultMask = resultMask; mask.bitset = bitset; ptr += mask.numBytes; } data.ptr = ptr; data.mask = mask; return true; }, readDataOneSweep: function(input, data, OutPixelTypeArray) { var ptr = data.ptr; var headerInfo = data.headerInfo; var numDims = headerInfo.numDims; var numPixels = headerInfo.width * headerInfo.height; var imageType = headerInfo.imageType; var numBytes = headerInfo.numValidPixel * Lerc2Helpers.getDataTypeSize(imageType) * numDims; var rawData; var mask = data.pixels.resultMask; if (OutPixelTypeArray === Uint8Array) { rawData = new Uint8Array(input, ptr, numBytes); } else { var arrayBuf = new ArrayBuffer(numBytes); var store8 = new Uint8Array(arrayBuf); store8.set(new Uint8Array(input, ptr, numBytes)); rawData = new OutPixelTypeArray(arrayBuf); } if (rawData.length === numPixels * numDims) { data.pixels.resultPixels = rawData; } else { data.pixels.resultPixels = new OutPixelTypeArray(numPixels * numDims); var z = 0, k = 0, i = 0, nStart = 0; if (numDims > 1) { for (i = 0; i < numDims; i++) { nStart = i * numPixels; for (k = 0; k < numPixels; k++) { if (mask[k]) { data.pixels.resultPixels[nStart + k] = rawData[z++]; } } } } else { for (k = 0; k < numPixels; k++) { if (mask[k]) { data.pixels.resultPixels[k] = rawData[z++]; } } } } ptr += numBytes; data.ptr = ptr; return true; }, readHuffmanTree: function(input, data) { var BITS_MAX = this.HUFFMAN_LUT_BITS_MAX; var view = new DataView(input, data.ptr, 16); data.ptr += 16; var version = view.getInt32(0, true); if (version < 2) { throw "unsupported Huffman version"; } var size = view.getInt32(4, true); var i0 = view.getInt32(8, true); var i1 = view.getInt32(12, true); if (i0 >= i1) { return false; } var blockDataBuffer = new Uint32Array(i1 - i0); Lerc2Helpers.decodeBits(input, data, blockDataBuffer); var codeTable = []; var i, j, k, len; for (i = i0; i < i1; i++) { j = i - (i < size ? 0 : size); codeTable[j] = { first: blockDataBuffer[i - i0], second: null }; } var dataBytes = input.byteLength - data.ptr; var dataWords = Math.ceil(dataBytes / 4); var arrayBuf = new ArrayBuffer(dataWords * 4); var store8 = new Uint8Array(arrayBuf); store8.set(new Uint8Array(input, data.ptr, dataBytes)); var stuffedData = new Uint32Array(arrayBuf); var bitPos = 0, word, srcPtr = 0; word = stuffedData[0]; for (i = i0; i < i1; i++) { j = i - (i < size ? 0 : size); len = codeTable[j].first; if (len > 0) { codeTable[j].second = word << bitPos >>> 32 - len; if (32 - bitPos >= len) { bitPos += len; if (bitPos === 32) { bitPos = 0; srcPtr++; word = stuffedData[srcPtr]; } } else { bitPos += len - 32; srcPtr++; word = stuffedData[srcPtr]; codeTable[j].second |= word >>> 32 - bitPos; } } } var numBitsLUT = 0, numBitsLUTQick = 0; var tree = new TreeNode(); for (i = 0; i < codeTable.length; i++) { if (codeTable[i] !== void 0) { numBitsLUT = Math.max(numBitsLUT, codeTable[i].first); } } if (numBitsLUT >= BITS_MAX) { numBitsLUTQick = BITS_MAX; } else { numBitsLUTQick = numBitsLUT; } if (numBitsLUT >= 30) { console.log("WARning, large NUM LUT BITS IS " + numBitsLUT); } var decodeLut = [], entry, code, numEntries, jj, currentBit, node; for (i = i0; i < i1; i++) { j = i - (i < size ? 0 : size); len = codeTable[j].first; if (len > 0) { entry = [len, j]; if (len <= numBitsLUTQick) { code = codeTable[j].second << numBitsLUTQick - len; numEntries = 1 << numBitsLUTQick - len; for (k = 0; k < numEntries; k++) { decodeLut[code | k] = entry; } } else { code = codeTable[j].second; node = tree; for (jj = len - 1; jj >= 0; jj--) { currentBit = code >>> jj & 1; if (currentBit) { if (!node.right) { node.right = new TreeNode(); } node = node.right; } else { if (!node.left) { node.left = new TreeNode(); } node = node.left; } if (jj === 0 && !node.val) { node.val = entry[1]; } } } } } return { decodeLut, numBitsLUTQick, numBitsLUT, tree, stuffedData, srcPtr, bitPos }; }, readHuffman: function(input, data, OutPixelTypeArray) { var headerInfo = data.headerInfo; var numDims = headerInfo.numDims; var height = data.headerInfo.height; var width = data.headerInfo.width; var numPixels = width * height; var huffmanInfo = this.readHuffmanTree(input, data); var decodeLut = huffmanInfo.decodeLut; var tree = huffmanInfo.tree; var stuffedData = huffmanInfo.stuffedData; var srcPtr = huffmanInfo.srcPtr; var bitPos = huffmanInfo.bitPos; var numBitsLUTQick = huffmanInfo.numBitsLUTQick; var numBitsLUT = huffmanInfo.numBitsLUT; var offset = data.headerInfo.imageType === 0 ? 128 : 0; var node, val, delta, mask = data.pixels.resultMask, valTmp, valTmpQuick, currentBit; var i, j, k, ii; var prevVal = 0; if (bitPos > 0) { srcPtr++; bitPos = 0; } var word = stuffedData[srcPtr]; var deltaEncode = data.encodeMode === 1; var resultPixelsAllDim = new OutPixelTypeArray(numPixels * numDims); var resultPixels = resultPixelsAllDim; var iDim; for (iDim = 0; iDim < headerInfo.numDims; iDim++) { if (numDims > 1) { resultPixels = new OutPixelTypeArray(resultPixelsAllDim.buffer, numPixels * iDim, numPixels); prevVal = 0; } if (data.headerInfo.numValidPixel === width * height) { for (k = 0, i = 0; i < height; i++) { for (j = 0; j < width; j++, k++) { val = 0; valTmp = word << bitPos >>> 32 - numBitsLUTQick; valTmpQuick = valTmp; if (32 - bitPos < numBitsLUTQick) { valTmp |= stuffedData[srcPtr + 1] >>> 64 - bitPos - numBitsLUTQick; valTmpQuick = valTmp; } if (decodeLut[valTmpQuick]) { val = decodeLut[valTmpQuick][1]; bitPos += decodeLut[valTmpQuick][0]; } else { valTmp = word << bitPos >>> 32 - numBitsLUT; valTmpQuick = valTmp; if (32 - bitPos < numBitsLUT) { valTmp |= stuffedData[srcPtr + 1] >>> 64 - bitPos - numBitsLUT; valTmpQuick = valTmp; } node = tree; for (ii = 0; ii < numBitsLUT; ii++) { currentBit = valTmp >>> numBitsLUT - ii - 1 & 1; node = currentBit ? node.right : node.left; if (!(node.left || node.right)) { val = node.val; bitPos = bitPos + ii + 1; break; } } } if (bitPos >= 32) { bitPos -= 32; srcPtr++; word = stuffedData[srcPtr]; } delta = val - offset; if (deltaEncode) { if (j > 0) { delta += prevVal; } else if (i > 0) { delta += resultPixels[k - width]; } else { delta += prevVal; } delta &= 255; resultPixels[k] = delta; prevVal = delta; } else { resultPixels[k] = delta; } } } } else { for (k = 0, i = 0; i < height; i++) { for (j = 0; j < width; j++, k++) { if (mask[k]) { val = 0; valTmp = word << bitPos >>> 32 - numBitsLUTQick; valTmpQuick = valTmp; if (32 - bitPos < numBitsLUTQick) { valTmp |= stuffedData[srcPtr + 1] >>> 64 - bitPos - numBitsLUTQick; valTmpQuick = valTmp; } if (decodeLut[valTmpQuick]) { val = decodeLut[valTmpQuick][1]; bitPos += decodeLut[valTmpQuick][0]; } else { valTmp = word << bitPos >>> 32 - numBitsLUT; valTmpQuick = valTmp; if (32 - bitPos < numBitsLUT) { valTmp |= stuffedData[srcPtr + 1] >>> 64 - bitPos - numBitsLUT; valTmpQuick = valTmp; } node = tree; for (ii = 0; ii < numBitsLUT; ii++) { currentBit = valTmp >>> numBitsLUT - ii - 1 & 1; node = currentBit ? node.right : node.left; if (!(node.left || node.right)) { val = node.val; bitPos = bitPos + ii + 1; break; } } } if (bitPos >= 32) { bitPos -= 32; srcPtr++; word = stuffedData[srcPtr]; } delta = val - offset; if (deltaEncode) { if (j > 0 && mask[k - 1]) { delta += prevVal; } else if (i > 0 && mask[k - width]) { delta += resultPixels[k - width]; } else { delta += prevVal; } delta &= 255; resultPixels[k] = delta; prevVal = delta; } else { resultPixels[k] = delta; } } } } } data.ptr = data.ptr + (srcPtr + 1) * 4 + (bitPos > 0 ? 4 : 0); } data.pixels.resultPixels = resultPixelsAllDim; }, decodeBits: function(input, data, blockDataBuffer, offset, iDim) { { var headerInfo = data.headerInfo; var fileVersion = headerInfo.fileVersion; var blockPtr = 0; var view = new DataView(input, data.ptr, 5); var headerByte = view.getUint8(0); blockPtr++; var bits67 = headerByte >> 6; var n = bits67 === 0 ? 4 : 3 - bits67; var doLut = (headerByte & 32) > 0 ? true : false; var numBits = headerByte & 31; var numElements = 0; if (n === 1) { numElements = view.getUint8(blockPtr); blockPtr++; } else if (n === 2) { numElements = view.getUint16(blockPtr, true); blockPtr += 2; } else if (n === 4) { numElements = view.getUint32(blockPtr, true); blockPtr += 4; } else { throw "Invalid valid pixel count type"; } var scale = 2 * headerInfo.maxZError; var stuffedData, arrayBuf, store8, dataBytes, dataWords; var lutArr, lutData, lutBytes, lutBitsPerElement, bitsPerPixel; var zMax = headerInfo.numDims > 1 ? headerInfo.maxValues[iDim] : headerInfo.zMax; if (doLut) { data.counter.lut++; lutBytes = view.getUint8(blockPtr); lutBitsPerElement = numBits; blockPtr++; dataBytes = Math.ceil((lutBytes - 1) * numBits / 8); dataWords = Math.ceil(dataBytes / 4); arrayBuf = new ArrayBuffer(dataWords * 4); store8 = new Uint8Array(arrayBuf); data.ptr += blockPtr; store8.set(new Uint8Array(input, data.ptr, dataBytes)); lutData = new Uint32Array(arrayBuf); data.ptr += dataBytes; bitsPerPixel = 0; while (lutBytes - 1 >>> bitsPerPixel) { bitsPerPixel++; } dataBytes = Math.ceil(numElements * bitsPerPixel / 8); dataWords = Math.ceil(dataBytes / 4); arrayBuf = new ArrayBuffer(dataWords * 4); store8 = new Uint8Array(arrayBuf); store8.set(new Uint8Array(input, data.ptr, dataBytes)); stuffedData = new Uint32Array(arrayBuf); data.ptr += dataBytes; if (fileVersion >= 3) { lutArr = BitStuffer.unstuffLUT2(lutData, numBits, lutBytes - 1, offset, scale, zMax); } else { lutArr = BitStuffer.unstuffLUT(lutData, numBits, lutBytes - 1, offset, scale, zMax); } if (fileVersion >= 3) { BitStuffer.unstuff2(stuffedData, blockDataBuffer, bitsPerPixel, numElements, lutArr); } else { BitStuffer.unstuff(stuffedData, blockDataBuffer, bitsPerPixel, numElements, lutArr); } } else { data.counter.bitstuffer++; bitsPerPixel = numBits; data.ptr += blockPtr; if (bitsPerPixel > 0) { dataBytes = Math.ceil(numElements * bitsPerPixel / 8); dataWords = Math.ceil(dataBytes / 4); arrayBuf = new ArrayBuffer(dataWords * 4); store8 = new Uint8Array(arrayBuf); store8.set(new Uint8Array(input, data.ptr, dataBytes)); stuffedData = new Uint32Array(arrayBuf); data.ptr += dataBytes; if (fileVersion >= 3) { if (offset == null) { BitStuffer.originalUnstuff2(stuffedData, blockDataBuffer, bitsPerPixel, numElements); } else { BitStuffer.unstuff2(stuffedData, blockDataBuffer, bitsPerPixel, numElements, false, offset, scale, zMax); } } else { if (offset == null) { BitStuffer.originalUnstuff(stuffedData, blockDataBuffer, bitsPerPixel, numElements);