gis-tools-ts
Version:
A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.
163 lines • 5.86 kB
JavaScript
import { U32I32F32 } from '../util';
import { ArithmeticBitModel, ArithmeticModel } from '.';
const I32_MIN = -2147483648; // ((I32)0x80000000)
const I32_MAX = 2147483647; // ((I32)0x7FFFFFFF)
/**
* https://github.com/LASzip/LASzip/blob/master/src/integercompressor.cpp
*/
export class IntegerCompressor {
dec;
bits;
contexts;
bitsHigh;
range;
#k = 0;
#corrBits;
#corrRange;
corrMin;
corrMax;
#mBits = [];
#mCorrector = [];
/**
* @param dec - the arithmetic decoder
* @param bits - the number of bits
* @param contexts - the number of contexts
* @param bitsHigh - the number of bits for the high bits
* @param range - the range
*/
constructor(dec, bits = 16, // U32
contexts = 1, // U32
bitsHigh = 8, // U32
range = 0) {
this.dec = dec;
this.bits = bits;
this.contexts = contexts;
this.bitsHigh = bitsHigh;
this.range = range;
if (this.range !== 0) {
// the corrector's significant bits and range
this.#corrBits = 0;
this.#corrRange = this.range;
while (this.range !== 0) {
this.range = this.range >> 1;
this.#corrBits++;
}
if (this.#corrRange === 1 << (this.#corrBits - 1)) {
this.#corrBits--;
}
// the corrector must fall into this interval
this.corrMin = -Math.trunc(this.#corrRange / 2);
this.corrMax = this.corrMin + this.#corrRange - 1;
}
else if (this.bits !== 0 && this.bits < 32) {
this.#corrBits = this.bits;
this.#corrRange = 1 << this.bits;
// the corrector must fall into this interval
this.corrMin = -Math.trunc(this.#corrRange / 2);
this.corrMax = this.corrMin + this.#corrRange - 1;
}
else {
this.#corrBits = 32;
this.#corrRange = 0;
// the corrector must fall into this interval
this.corrMin = I32_MIN;
this.corrMax = I32_MAX;
}
}
/**
* Get the K value in the Compressor
* @returns - the current k value
*/
getK() {
return this.#k;
}
/** Initialize the decompressor */
initDecompressor() {
let i;
// maybe create the models
if (this.#mBits.length === 0) {
this.#mBits = new Array(this.contexts);
for (i = 0; i < this.contexts; i++) {
this.#mBits[i] = new ArithmeticModel(this.#corrBits + 1, false);
}
this.#mCorrector = new Array(this.#corrBits + 1);
this.#mCorrector[0] = new ArithmeticBitModel();
for (i = 1; i <= this.#corrBits; i++) {
if (i <= this.bitsHigh) {
this.#mCorrector[i] = new ArithmeticModel(1 << i, false);
}
else {
this.#mCorrector[i] = new ArithmeticModel(1 << this.bitsHigh, false);
}
}
}
// certainly init the models
for (i = 0; i < this.contexts; i++)
this.#mBits[i].init();
for (i = 0; i <= this.#corrBits; i++)
this.#mCorrector[i].init();
}
/**
* @param pred - the predicted value
* @param context - the context
* @returns - the decompressed value
*/
decompress(pred, context = { value: 0 }) {
const real = new U32I32F32(pred + this.readCorrector(this.#mBits[context.value]), 'i32');
if (real.i32 < 0)
real.i32 += this.#corrRange;
else if (real.u32 >= this.#corrRange)
real.i32 -= this.#corrRange;
return real.i32;
}
/**
* @param mBits - the arithmetic model
* @returns - the corrector
*/
readCorrector(mBits) {
let c; // I32
// decode within which interval the corrector is falling
this.#k = this.dec.decodeSymbol(mBits);
// decode the exact location of the corrector within the interval
if (this.#k !== 0) {
// then c is either smaller than 0 or bigger than 1
if (this.#k < 32) {
if (this.#k <= this.bitsHigh) {
// for small k we can do this in one step
// decompress c with the range coder
c = this.dec.decodeSymbol(this.#mCorrector[this.#k]);
}
else {
// for larger k we need to do this in two steps
const k1 = this.#k - this.bitsHigh;
// decompress higher bits with table
c = this.dec.decodeSymbol(this.#mCorrector[this.#k]);
// read lower bits raw
const c1 = this.dec.readBits(k1);
// put the corrector back together
c = (c << k1) | c1;
}
// translate c back into its correct interval
if (c >= 1 << (this.#k - 1)) {
// if c is in the interval [ 2^(k-1) ... + 2^k - 1 ]
// so we translate c back into the interval [ 2^(k-1) + 1 ... 2^k ] by adding 1
c += 1;
}
else {
// otherwise c is in the interval [ 0 ... + 2^(k-1) - 1 ]
// so we translate c back into the interval [ - (2^k - 1) ... - (2^(k-1)) ] by subtracting (2^k - 1)
c -= (1 << this.#k) - 1;
}
}
else {
c = this.corrMin;
}
}
else {
// then c is either 0 or 1
c = this.dec.decodeBit(this.#mCorrector[0]);
}
return c;
}
}
//# sourceMappingURL=integerCompressor.js.map