s2-tools
Version:
A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.
96 lines • 3.57 kB
JavaScript
/**
* Decode a block using the specified predictor
* @param row - the row to decode
* @param stride - the number of bytes per row
*/
function decodeRowAcc(row, stride) {
let length = row.length - stride;
let offset = 0;
do {
for (let i = stride; i > 0; i--) {
row[offset + stride] += row[offset];
offset++;
}
length -= stride;
} while (length > 0);
}
/**
* Decode a floating point block using the specified predictor
* @param row - the row to decode
* @param stride - the number of bytes per row
* @param bytesPerSample - the number of bytes per sample
*/
function decodeRowFloatingPoint(row, stride, bytesPerSample) {
let index = 0;
let count = row.length;
const wc = count / bytesPerSample;
while (count > stride) {
for (let i = stride; i > 0; --i) {
row[index + stride] += row[index];
++index;
}
count -= stride;
}
const copy = row.slice();
for (let i = 0; i < wc; ++i) {
for (let b = 0; b < bytesPerSample; ++b) {
row[bytesPerSample * i + b] = copy[(bytesPerSample - b - 1) * wc + i];
}
}
}
/**
* Apply the specified predictor to a block
* @param block - the block to modify
* @param predictor - the predictor
* @param width - the block width
* @param height - the block height
* @param bitsPerSample - the number of bits per sample
* @param planarConfiguration - the planar configuration
* @returns - the modified block
*/
export function applyPredictor(block, predictor, width, height, bitsPerSample, planarConfiguration) {
if (predictor === 0 || predictor === 1) {
return block;
}
for (let i = 0; i < bitsPerSample.length; ++i) {
if (bitsPerSample[i] % 8 !== 0) {
throw new Error('When decoding with predictor, only multiple of 8 bits are supported.');
}
if (bitsPerSample[i] !== bitsPerSample[0]) {
throw new Error('When decoding with predictor, all samples must have the same size.');
}
}
const bytesPerSample = bitsPerSample[0] / 8;
const stride = planarConfiguration === 2 ? 1 : bitsPerSample.length;
for (let i = 0; i < height; ++i) {
// Last strip will be truncated if height % stripHeight != 0
if (i * stride * width * bytesPerSample >= block.byteLength) {
break;
}
let row;
if (predictor === 2) {
// horizontal prediction
switch (bitsPerSample[0]) {
case 8:
row = new Uint8Array(block, i * stride * width * bytesPerSample, stride * width * bytesPerSample);
break;
case 16:
row = new Uint16Array(block, i * stride * width * bytesPerSample, (stride * width * bytesPerSample) / 2);
break;
case 32:
row = new Uint32Array(block, i * stride * width * bytesPerSample, (stride * width * bytesPerSample) / 4);
break;
default:
throw new Error(`Predictor 2 not allowed with ${bitsPerSample[0]} bits per sample.`);
}
decodeRowAcc(row, stride);
}
else if (predictor === 3) {
// horizontal floating point
row = new Uint8Array(block, i * stride * width * bytesPerSample, stride * width * bytesPerSample);
decodeRowFloatingPoint(row, stride, bytesPerSample);
}
}
return block;
}
//# sourceMappingURL=predictor.js.map