ry-vue-map
Version:
ry公共组件库
1,297 lines (1,196 loc) • 91.6 kB
JavaScript
((typeof self !== 'undefined' ? self : this)["webpackJsonpryui"] = (typeof self !== 'undefined' ? self : this)["webpackJsonpryui"] || []).push([[7],{
/***/ "6372":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return LercDecoder; });
/* harmony import */ var pako__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("acff");
/* harmony import */ var lerc__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("7558");
/* harmony import */ var lerc__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(lerc__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _basedecoder_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("b3f7");
/* harmony import */ var _globals_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("aba6");
class LercDecoder extends _basedecoder_js__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"] {
constructor(fileDirectory) {
super();
this.planarConfiguration = typeof fileDirectory.PlanarConfiguration !== 'undefined' ? fileDirectory.PlanarConfiguration : 1;
this.samplesPerPixel = typeof fileDirectory.SamplesPerPixel !== 'undefined' ? fileDirectory.SamplesPerPixel : 1;
this.addCompression = fileDirectory.LercParameters[_globals_js__WEBPACK_IMPORTED_MODULE_3__[/* LercParameters */ "c"].AddCompression];
}
decodeBlock(buffer) {
switch (this.addCompression) {
case _globals_js__WEBPACK_IMPORTED_MODULE_3__[/* LercAddCompression */ "b"].None:
break;
case _globals_js__WEBPACK_IMPORTED_MODULE_3__[/* LercAddCompression */ "b"].Deflate:
buffer = Object(pako__WEBPACK_IMPORTED_MODULE_0__[/* inflate */ "a"])(new Uint8Array(buffer)).buffer; // eslint-disable-line no-param-reassign, prefer-destructuring
break;
default:
throw new Error(`Unsupported LERC additional compression method identifier: ${this.addCompression}`);
}
const lercResult = lerc__WEBPACK_IMPORTED_MODULE_1___default.a.decode(buffer, { returnPixelInterleavedDims: this.planarConfiguration === 1 });
const lercData = lercResult.pixels[0];
return lercData.buffer;
}
}
/***/ }),
/***/ "7558":
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* jshint forin: false, bitwise: false */
/*
Copyright 2015-2021 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
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.
A copy of the license and additional notices are located with the
source distribution at:
http://github.com/Esri/lerc/
Contributors: Johannes Schmid, (LERC v1)
Chayanika Khatua, (LERC v1)
Wenxue Ju (LERC v1, v2.x)
*/
/* Copyright 2015-2021 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 */
/**
* a module for decoding LERC blobs
* @module Lerc
*/
(function() {
//this decoder supports all lerc versions, each version has its own class (LercDecode and Lerc2Decode).
//the exported module handles format variation autoamtically.
//the original LercDecode for Version 1
var LercDecode = (function() {
// Note: currently, this module only has an implementation for decoding LERC data, not encoding. The name of
// the class was chosen to be future proof.
var CntZImage = {};
CntZImage.defaultNoDataValue = -3.4027999387901484e+38; // smallest Float32 value
/**
* Decode a LERC byte stream and return an object containing the pixel data and some required and optional
* information about it, such as the image's width and height.
*
* @param {ArrayBuffer} input The LERC input byte stream
* @param {object} [options] Decoding options, containing any of the following properties:
* @config {number} [inputOffset = 0]
* Skip the first inputOffset bytes of the input byte stream. A valid LERC file is expected at that position.
* @config {Uint8Array} [encodedMask = null]
* If specified, the decoder will not read mask information from the input and use the specified encoded
* mask data instead. Mask header/data must not be present in the LERC byte stream in this case.
* @config {number} [noDataValue = LercCode.defaultNoDataValue]
* Pixel value to use for masked pixels.
* @config {ArrayBufferView|Array} [pixelType = Float32Array]
* The desired type of the pixelData array in the return value. Note that it is the caller's responsibility to
* provide an appropriate noDataValue if the default pixelType is overridden.
* @config {boolean} [returnMask = false]
* If true, the return value will contain a maskData property of type Uint8Array which has one element per
* pixel, the value of which is 1 or 0 depending on whether that pixel's data is present or masked. If the
* input LERC data does not contain a mask, maskData will not be returned.
* @config {boolean} [returnEncodedMask = false]
* If true, the return value will contain a encodedMaskData property, which can be passed into encode() as
* encodedMask.
* @config {boolean} [returnFileInfo = false]
* If true, the return value will have a fileInfo property that contains metadata obtained from the
* LERC headers and the decoding process.
* @config {boolean} [computeUsedBitDepths = false]
* If true, the fileInfo property in the return value will contain the set of all block bit depths
* encountered during decoding. Will only have an effect if returnFileInfo option is true.
* @returns {{width, height, pixelData, minValue, maxValue, noDataValue, maskData, encodedMaskData, fileInfo}}
*/
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: 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) {
// block is either uncompressed or bit-stuffed (encodings 0 and 1)
if (block.encoding === 0) {
// block is uncompressed
blockData = block.rawData;
} else {
// block is bit-stuffed
unstuff(block.stuffedData, block.bitsPerPixel, block.numValidPixels, block.offset, scale, blockDataBuffer, data.pixels.maxValue);
blockData = blockDataBuffer;
}
blockPtr = 0;
}
else if (block.encoding === 2) {
// block is all 0
constValue = 0;
}
else {
// block has constant value (encoding === 3)
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)) {
// read next byte from mask
maskByte = maskBitset[outPtr >> 3];
}
if (maskByte & 128) {
// pixel data present
if (resultMask) {
resultMask[outPtr] = 1;
}
currentValue = (block.encoding < 2) ? blockData[blockPtr++] : constValue;
minValue = minValue > currentValue ? currentValue : minValue;
resultPixels[outPtr++] = currentValue;
} else {
// pixel data not present
if (resultMask) {
resultMask[outPtr] = 0;
}
resultPixels[outPtr++] = noDataValue;
}
maskByte <<= 1;
}
outPtr += outStride;
}
} else {
// mask not present, simply copy block over
if (block.encoding < 2) {
// duplicating this code block for performance reasons
// blockData case:
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 {
// constValue case:
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: resultPixels,
resultMask: resultMask,
minValue: 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 = {};
// File header
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;
// Mask Header
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;
// Mask Data
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) { // Special case, all nodata
data.mask.bitset = new Uint8Array(Math.ceil(data.width * data.height / 8));
}
}
// Pixel Header
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;
// the number of blocks specified in the header does not take into account the blocks at the end of
// each row/column with a special width/height that make the image complete in case the width is not
// evenly divisible by the number of blocks.
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++) {
// Block
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);
// get rid of trailing bytes that are already part of next block
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);
}
//pixel values may exceed max due to quantization
dest[o] = n < nmax ? offset + n * scale : maxValue;
}
return dest;
};
return CntZImage;
})();
//version 2. Supports 2.1, 2.2, 2.3
var Lerc2Decode = (function() {
"use strict";
// Note: currently, this module only has an implementation for decoding LERC data, not encoding. The name of
// the class was chosen to be future proof, following LercDecode.
/*****************************************
* private static class bitsutffer used by Lerc2Decode
*******************************************/
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;
// get rid of trailing bytes that are already part of next block
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];//offset + lutArr[n] * scale;
}
}
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);
}
//pixel values may exceed max due to quantization
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 = [];
// get rid of trailing bytes that are already part of next block
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.push(n);
dest[o] = n < nmax ? offset + n * scale : maxValue;
}
dest.unshift(offset);//1st one
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) {
//no unsigned left shift
n = ((buffer >>> bitPos) & bitMask);
bitsLeft -= bitsPerPixel;
bitPos += bitsPerPixel;
} else {
missingBits = (bitsPerPixel - bitsLeft);
n = (buffer >>> bitPos) & bitMask;//((buffer & bitMask) << missingBits) & bitMask;
buffer = src[i++];
bitsLeft = 32 - missingBits;
n |= (buffer & ((1 << missingBits) - 1)) << (bitsPerPixel - missingBits);
bitPos = missingBits;
}
//pixel values may exceed max due to quantization
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) {
//no unsigned left shift
n = ((buffer >>> bitPos) & bitMask);
bitsLeft -= bitsPerPixel;
bitPos += bitsPerPixel;
} else {
missingBits = (bitsPerPixel - bitsLeft);
n = (buffer >>> bitPos) & bitMask;//((buffer & bitMask) << missingBits) & bitMask;
buffer = src[i++];
bitsLeft = 32 - missingBits;
n |= (buffer & ((1 << missingBits) - 1)) << (bitsPerPixel - missingBits);
bitPos = missingBits;
}
//dest.push(n);
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;
// get rid of trailing bytes that are already part of next block
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;
//micro-optimizations
for (o = 0; o < numPixels; o++) {
if (bitsLeft === 0) {
buffer = src[i++];
bitsLeft = 32;
bitPos = 0;
}
if (bitsLeft >= bitsPerPixel) {
//no unsigned left shift
n = ((buffer >>> bitPos) & bitMask);
bitsLeft -= bitsPerPixel;
bitPos += bitsPerPixel;
} else {
missingBits = (bitsPerPixel - bitsLeft);
n = (buffer >>> bitPos) & bitMask;//((buffer & bitMask) << missingBits) & bitMask;
buffer = src[i++];
bitsLeft = 32 - missingBits;
n |= (buffer & ((1 << missingBits) - 1)) << (bitsPerPixel - missingBits);
bitPos = missingBits;
}
dest[o] = n;
}
return dest;
}
};
/*****************************************
*private static class used by Lerc2Decode
******************************************/
var Lerc2Helpers = {
HUFFMAN_LUT_BITS_MAX: 12, //use 2^12 lut, treat it like constant
computeChecksumFletcher32: function(input) {
var sum1 = 0xffff, sum2 = 0xffff;
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 & 0xffff) + (sum1 >>> 16);
sum2 = (sum2 & 0xffff) + (sum2 >>> 16);
}
// add the straggler byte if it exists
if (len & 1) {
sum2 += sum1 += (input[i] << 8);
}
// second reduction step to reduce sums to 16 bits
sum1 = (sum1 & 0xffff) + (sum1 >>> 16);
sum2 = (sum2 & 0xffff) + (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); //nrows
ptr += 4;
}
//keys start from here
view = new DataView(input, ptr, 12);
headerInfo.height = view.getUint32(0, true); //nrows
headerInfo.width = view.getUint32(4, true); //ncols
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;
// Mask Data
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 (data.mask.numBytes > 0 && data.mask.numBytes< data.numValidPixel) {
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, useBSQForOutputDim) {
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;
//data.pixels.numBytes = numBytes;
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) {
if (useBSQForOutputDim) {
data.pixels.resultPixels = Lerc2Helpers.swapDimensionOrder(rawData, numPixels, numDims, OutPixelTypeArray, true);
}
else {
data.pixels.resultPixels = rawData;
}
}
else //mask
{
data.pixels.resultPixels = new OutPixelTypeArray(numPixels * numDims);
var z = 0, k = 0, i = 0, nStart = 0;
if (numDims > 1) {
if (useBSQForOutputDim) {
for (k = 0; k < numPixels; k++) {
if (mask[k]) {
nStart = k;
for (i = 0; i < numDims; i++, nStart+=numPixels) {
data.pixels.resultPixels[nStart] = rawData[z++];
}
}
}
}
else {
for (k = 0; k < numPixels; k++) {
if (mask[k]) {
nStart = k * numDims;
for (i = 0; i < numDims; i++) {
data.pixels.resultPixels[nStart + i] = rawData[z++];
}
}
}
}
}
else {
for (k = 0; k < numPixels; k++) {
if (mask[k]) {
data.pixels.resultPixels[k] = rawData[z++];
}
}
}
}
ptr += numBytes;
data.ptr = ptr; //return data;
return true;
},
readHuffmanTree: function(input, data) {
var BITS_MAX = this.HUFFMAN_LUT_BITS_MAX; //8 is slow for the large test image
//var size_max = 1 << BITS_MAX;
/* ************************
* reading code table
*************************/
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 = []; //size
var i, j, k, len;
for (i = i0; i < i1; i++) {
j = i - (i < size ? 0 : size);//wrap around
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); //must start from x*4
var bitPos = 0, word, srcPtr = 0;
word = stuffedData[0];
for (i = i0; i < i1; i++) {
j = i - (i < size ? 0 : size);//wrap around
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);
}
}
}
//finished reading code table
/* ************************
* building lut
*************************/
var numBitsLUT = 0, numBitsLUTQick = 0;
var tree = new TreeNode();
for (i = 0; i < codeTable.length; i++) {
if (codeTable[i] !== undefined) {
numBitsLUT = Math.max(numBitsLUT, codeTable[i].first);
}
}
if (numBitsLUT >= BITS_MAX) {
numBitsLUTQick = BITS_MAX;
}
else {
numBitsLUTQick = numBitsLUT;
}
// for debugging purpose
// 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);//wrap around
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 {
//build tree
code = codeTable[j].second;
node = tree;
for (jj = len - 1; jj >= 0; jj--) {
currentBit = code >>> jj & 1; //no left shift as length could be 30,31
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: decodeLut,
numBitsLUTQick: numBitsLUTQick,
numBitsLUT: numBitsLUT,
tree: tree,
stuffedData: stuffedData,
srcPtr: srcPtr,
bitPos: bitPos
};
},
readHuffman: function(input, data, OutPixelTypeArray, useBSQForOutputDim) {
var headerInfo = data.headerInfo;
var numDims = headerInfo.numDims;
var height = data.headerInfo.height;
var width = data.headerInfo.width;
var numPixels = width * height;
//var size_max = 1 << BITS_MAX;
/* ************************
* reading huffman structure info
*************************/
var huffmanInfo = this.readHuffmanTree(input, data);
var decodeLut = huffmanInfo.decodeLut;
var tree = huffmanInfo.tree;
//stuffedData includes huffman headers
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;
/*************************
* decode
***************************/
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;
// TODO: reevaluate the need to keep inlined decoding code as IE support is phasing out
if (numDims < 2 || deltaEncode) {
for (iDim = 0; iDim < numDims; iDim++) {
if (numDims > 1) {
//get the mem block of current dimension
resultPixels = new OutPixelTypeArray(resultPixelsAllDim.buffer, numPixels * iDim, numPixels);
prevVal = 0;
}
if (data.headerInfo.numValidPixel === width * height) { //all valid
for (k = 0, i = 0; i < height; i++) {
for (j = 0; j < width; j++, k++) {
val = 0;
valTmp = (word << bitPos) >>> (32 - numBitsLUTQick);
valTmpQuick = valTmp;// >>> deltaBits;
if (32 - bitPos < numBitsLUTQick) {
valTmp |= ((stuffedData[srcPtr + 1]) >>> (64 - bitPos - numBitsLUTQick));
valTmpQuick = valTmp;// >>> deltaBits;
}
if (decodeLut[valTmpQuick]) // if there, move the correct number of bits and done
{
val = decodeLut[valTmpQuick][1];
bitPos += decodeLut[valTmpQuick][0];
}
else {
valTmp = (word << bitPos) >>> (32 - numBitsLUT);
valTmpQuick = valTmp;// >>> deltaBits;
if (32 - bitPos < numBitsLUT) {
valTmp |= ((stuffedData[srcPtr + 1]) >>> (64 - bitPos - numBitsLUT));
valTmpQuick = valTmp;// >>> deltaBits;
}
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; // use overflow
}
else if (i > 0) {
delta += resultPixels[k - width];
}
else {
delta += prevVal;
}
delta &= 0xFF; //overflow
resultPixels[k] = delta;//overflow
prevVal = delta;
}
else {
resultPixels[k] = delta;
}
}
}
}
else { //not all valid, use mask
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;// >>> deltaBits;
if (32 - bitPos < numBitsLUTQick) {
valTmp |= ((stuffedData[srcPtr + 1]) >>> (64 - bitPos - numBitsLUTQick));
valTmpQuick = valTmp;// >>> deltaBits;
}
if (decodeLut[valTmpQuick]) // if there, move the correct number of bits and done
{
val = decodeLut[valTmpQuick][1];
bitPos += decodeLut[valTmpQuick][0];
}
else {
valTmp = (word << bitPos) >>> (32 - numBitsLUT);
valTmpQuick = valTmp;// >>> deltaBits;
if (32 - bitPos < numBitsLUT) {
valTmp |= ((stuffedData[srcPtr + 1]) >>> (64 - bitPos - numBitsLUT));
valTmpQuick = valTmp;// >>> deltaBits;
}
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) {
b