@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
JavaScript
/**
* @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);