Remove the closure from BitModel
in the src/core/jpx.js
file
This commit is contained in:
parent
b0a1af306d
commit
88616f77ae
611
src/core/jpx.js
611
src/core/jpx.js
@ -1738,381 +1738,380 @@ class InclusionTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Section D. Coefficient bit modeling
|
// Section D. Coefficient bit modeling
|
||||||
const BitModel = (function BitModelClosure() {
|
class BitModel {
|
||||||
const UNIFORM_CONTEXT = 17;
|
static UNIFORM_CONTEXT = 17;
|
||||||
const RUNLENGTH_CONTEXT = 18;
|
|
||||||
|
static RUNLENGTH_CONTEXT = 18;
|
||||||
|
|
||||||
// Table D-1
|
// Table D-1
|
||||||
// The index is binary presentation: 0dddvvhh, ddd - sum of Di (0..4),
|
// The index is binary presentation: 0dddvvhh, ddd - sum of Di (0..4),
|
||||||
// vv - sum of Vi (0..2), and hh - sum of Hi (0..2)
|
// vv - sum of Vi (0..2), and hh - sum of Hi (0..2)
|
||||||
const LLAndLHContextsLabel = new Uint8Array([
|
static LLAndLHContextsLabel = new Uint8Array([
|
||||||
0, 5, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 1, 6, 8, 0, 3, 7, 8, 0, 4,
|
0, 5, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 1, 6, 8, 0, 3, 7, 8, 0, 4,
|
||||||
7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6,
|
7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6,
|
||||||
8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8,
|
8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8,
|
||||||
]);
|
]);
|
||||||
const HLContextLabel = new Uint8Array([
|
|
||||||
|
static HLContextLabel = new Uint8Array([
|
||||||
0, 3, 4, 0, 5, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 1, 3, 4, 0, 6, 7, 7, 0, 8,
|
0, 3, 4, 0, 5, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 1, 3, 4, 0, 6, 7, 7, 0, 8,
|
||||||
8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3,
|
8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3,
|
||||||
4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8,
|
4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8,
|
||||||
]);
|
]);
|
||||||
const HHContextLabel = new Uint8Array([
|
|
||||||
|
static HHContextLabel = new Uint8Array([
|
||||||
0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, 4, 5, 5, 0, 5,
|
0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, 4, 5, 5, 0, 5,
|
||||||
5, 5, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 8, 8,
|
5, 5, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 8, 8,
|
||||||
8, 0, 8, 8, 8, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8,
|
8, 0, 8, 8, 8, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// eslint-disable-next-line no-shadow
|
constructor(width, height, subband, zeroBitPlanes, mb) {
|
||||||
class BitModel {
|
this.width = width;
|
||||||
constructor(width, height, subband, zeroBitPlanes, mb) {
|
this.height = height;
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
|
|
||||||
let contextLabelTable;
|
let contextLabelTable;
|
||||||
if (subband === "HH") {
|
if (subband === "HH") {
|
||||||
contextLabelTable = HHContextLabel;
|
contextLabelTable = BitModel.HHContextLabel;
|
||||||
} else if (subband === "HL") {
|
} else if (subband === "HL") {
|
||||||
contextLabelTable = HLContextLabel;
|
contextLabelTable = BitModel.HLContextLabel;
|
||||||
} else {
|
} else {
|
||||||
contextLabelTable = LLAndLHContextsLabel;
|
contextLabelTable = BitModel.LLAndLHContextsLabel;
|
||||||
}
|
|
||||||
this.contextLabelTable = contextLabelTable;
|
|
||||||
|
|
||||||
const coefficientCount = width * height;
|
|
||||||
|
|
||||||
// coefficients outside the encoding region treated as insignificant
|
|
||||||
// add border state cells for significanceState
|
|
||||||
this.neighborsSignificance = new Uint8Array(coefficientCount);
|
|
||||||
this.coefficentsSign = new Uint8Array(coefficientCount);
|
|
||||||
let coefficentsMagnitude;
|
|
||||||
if (mb > 14) {
|
|
||||||
coefficentsMagnitude = new Uint32Array(coefficientCount);
|
|
||||||
} else if (mb > 6) {
|
|
||||||
coefficentsMagnitude = new Uint16Array(coefficientCount);
|
|
||||||
} else {
|
|
||||||
coefficentsMagnitude = new Uint8Array(coefficientCount);
|
|
||||||
}
|
|
||||||
this.coefficentsMagnitude = coefficentsMagnitude;
|
|
||||||
this.processingFlags = new Uint8Array(coefficientCount);
|
|
||||||
|
|
||||||
const bitsDecoded = new Uint8Array(coefficientCount);
|
|
||||||
if (zeroBitPlanes !== 0) {
|
|
||||||
for (let i = 0; i < coefficientCount; i++) {
|
|
||||||
bitsDecoded[i] = zeroBitPlanes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.bitsDecoded = bitsDecoded;
|
|
||||||
|
|
||||||
this.reset();
|
|
||||||
}
|
}
|
||||||
|
this.contextLabelTable = contextLabelTable;
|
||||||
|
|
||||||
setDecoder(decoder) {
|
const coefficientCount = width * height;
|
||||||
this.decoder = decoder;
|
|
||||||
|
// coefficients outside the encoding region treated as insignificant
|
||||||
|
// add border state cells for significanceState
|
||||||
|
this.neighborsSignificance = new Uint8Array(coefficientCount);
|
||||||
|
this.coefficentsSign = new Uint8Array(coefficientCount);
|
||||||
|
let coefficentsMagnitude;
|
||||||
|
if (mb > 14) {
|
||||||
|
coefficentsMagnitude = new Uint32Array(coefficientCount);
|
||||||
|
} else if (mb > 6) {
|
||||||
|
coefficentsMagnitude = new Uint16Array(coefficientCount);
|
||||||
|
} else {
|
||||||
|
coefficentsMagnitude = new Uint8Array(coefficientCount);
|
||||||
}
|
}
|
||||||
|
this.coefficentsMagnitude = coefficentsMagnitude;
|
||||||
|
this.processingFlags = new Uint8Array(coefficientCount);
|
||||||
|
|
||||||
reset() {
|
const bitsDecoded = new Uint8Array(coefficientCount);
|
||||||
// We have 17 contexts that are accessed via context labels,
|
if (zeroBitPlanes !== 0) {
|
||||||
// plus the uniform and runlength context.
|
for (let i = 0; i < coefficientCount; i++) {
|
||||||
this.contexts = new Int8Array(19);
|
bitsDecoded[i] = zeroBitPlanes;
|
||||||
|
}
|
||||||
// Contexts are packed into 1 byte:
|
|
||||||
// highest 7 bits carry the index, lowest bit carries mps
|
|
||||||
this.contexts[0] = (4 << 1) | 0;
|
|
||||||
this.contexts[UNIFORM_CONTEXT] = (46 << 1) | 0;
|
|
||||||
this.contexts[RUNLENGTH_CONTEXT] = (3 << 1) | 0;
|
|
||||||
}
|
}
|
||||||
|
this.bitsDecoded = bitsDecoded;
|
||||||
|
|
||||||
setNeighborsSignificance(row, column, index) {
|
this.reset();
|
||||||
const neighborsSignificance = this.neighborsSignificance;
|
}
|
||||||
const width = this.width,
|
|
||||||
height = this.height;
|
|
||||||
const left = column > 0;
|
|
||||||
const right = column + 1 < width;
|
|
||||||
let i;
|
|
||||||
|
|
||||||
if (row > 0) {
|
setDecoder(decoder) {
|
||||||
i = index - width;
|
this.decoder = decoder;
|
||||||
if (left) {
|
}
|
||||||
neighborsSignificance[i - 1] += 0x10;
|
|
||||||
}
|
|
||||||
if (right) {
|
|
||||||
neighborsSignificance[i + 1] += 0x10;
|
|
||||||
}
|
|
||||||
neighborsSignificance[i] += 0x04;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row + 1 < height) {
|
reset() {
|
||||||
i = index + width;
|
// We have 17 contexts that are accessed via context labels,
|
||||||
if (left) {
|
// plus the uniform and runlength context.
|
||||||
neighborsSignificance[i - 1] += 0x10;
|
this.contexts = new Int8Array(19);
|
||||||
}
|
|
||||||
if (right) {
|
|
||||||
neighborsSignificance[i + 1] += 0x10;
|
|
||||||
}
|
|
||||||
neighborsSignificance[i] += 0x04;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Contexts are packed into 1 byte:
|
||||||
|
// highest 7 bits carry the index, lowest bit carries mps
|
||||||
|
this.contexts[0] = (4 << 1) | 0;
|
||||||
|
this.contexts[BitModel.UNIFORM_CONTEXT] = (46 << 1) | 0;
|
||||||
|
this.contexts[BitModel.RUNLENGTH_CONTEXT] = (3 << 1) | 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
setNeighborsSignificance(row, column, index) {
|
||||||
|
const neighborsSignificance = this.neighborsSignificance;
|
||||||
|
const width = this.width,
|
||||||
|
height = this.height;
|
||||||
|
const left = column > 0;
|
||||||
|
const right = column + 1 < width;
|
||||||
|
let i;
|
||||||
|
|
||||||
|
if (row > 0) {
|
||||||
|
i = index - width;
|
||||||
if (left) {
|
if (left) {
|
||||||
neighborsSignificance[index - 1] += 0x01;
|
neighborsSignificance[i - 1] += 0x10;
|
||||||
}
|
}
|
||||||
if (right) {
|
if (right) {
|
||||||
neighborsSignificance[index + 1] += 0x01;
|
neighborsSignificance[i + 1] += 0x10;
|
||||||
}
|
}
|
||||||
neighborsSignificance[index] |= 0x80;
|
neighborsSignificance[i] += 0x04;
|
||||||
}
|
}
|
||||||
|
|
||||||
runSignificancePropagationPass() {
|
if (row + 1 < height) {
|
||||||
const decoder = this.decoder;
|
i = index + width;
|
||||||
const width = this.width,
|
if (left) {
|
||||||
height = this.height;
|
neighborsSignificance[i - 1] += 0x10;
|
||||||
const coefficentsMagnitude = this.coefficentsMagnitude;
|
}
|
||||||
const coefficentsSign = this.coefficentsSign;
|
if (right) {
|
||||||
const neighborsSignificance = this.neighborsSignificance;
|
neighborsSignificance[i + 1] += 0x10;
|
||||||
const processingFlags = this.processingFlags;
|
}
|
||||||
const contexts = this.contexts;
|
neighborsSignificance[i] += 0x04;
|
||||||
const labels = this.contextLabelTable;
|
}
|
||||||
const bitsDecoded = this.bitsDecoded;
|
|
||||||
const processedInverseMask = ~1;
|
|
||||||
const processedMask = 1;
|
|
||||||
const firstMagnitudeBitMask = 2;
|
|
||||||
|
|
||||||
for (let i0 = 0; i0 < height; i0 += 4) {
|
if (left) {
|
||||||
for (let j = 0; j < width; j++) {
|
neighborsSignificance[index - 1] += 0x01;
|
||||||
let index = i0 * width + j;
|
}
|
||||||
for (let i1 = 0; i1 < 4; i1++, index += width) {
|
if (right) {
|
||||||
const i = i0 + i1;
|
neighborsSignificance[index + 1] += 0x01;
|
||||||
if (i >= height) {
|
}
|
||||||
break;
|
neighborsSignificance[index] |= 0x80;
|
||||||
}
|
}
|
||||||
// clear processed flag first
|
|
||||||
processingFlags[index] &= processedInverseMask;
|
|
||||||
|
|
||||||
if (coefficentsMagnitude[index] || !neighborsSignificance[index]) {
|
runSignificancePropagationPass() {
|
||||||
continue;
|
const decoder = this.decoder;
|
||||||
}
|
const width = this.width,
|
||||||
|
height = this.height;
|
||||||
|
const coefficentsMagnitude = this.coefficentsMagnitude;
|
||||||
|
const coefficentsSign = this.coefficentsSign;
|
||||||
|
const neighborsSignificance = this.neighborsSignificance;
|
||||||
|
const processingFlags = this.processingFlags;
|
||||||
|
const contexts = this.contexts;
|
||||||
|
const labels = this.contextLabelTable;
|
||||||
|
const bitsDecoded = this.bitsDecoded;
|
||||||
|
const processedInverseMask = ~1;
|
||||||
|
const processedMask = 1;
|
||||||
|
const firstMagnitudeBitMask = 2;
|
||||||
|
|
||||||
const contextLabel = labels[neighborsSignificance[index]];
|
for (let i0 = 0; i0 < height; i0 += 4) {
|
||||||
const decision = decoder.readBit(contexts, contextLabel);
|
for (let j = 0; j < width; j++) {
|
||||||
if (decision) {
|
let index = i0 * width + j;
|
||||||
const sign = this.decodeSignBit(i, j, index);
|
for (let i1 = 0; i1 < 4; i1++, index += width) {
|
||||||
coefficentsSign[index] = sign;
|
const i = i0 + i1;
|
||||||
coefficentsMagnitude[index] = 1;
|
if (i >= height) {
|
||||||
this.setNeighborsSignificance(i, j, index);
|
break;
|
||||||
processingFlags[index] |= firstMagnitudeBitMask;
|
|
||||||
}
|
|
||||||
bitsDecoded[index]++;
|
|
||||||
processingFlags[index] |= processedMask;
|
|
||||||
}
|
}
|
||||||
|
// clear processed flag first
|
||||||
|
processingFlags[index] &= processedInverseMask;
|
||||||
|
|
||||||
|
if (coefficentsMagnitude[index] || !neighborsSignificance[index]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contextLabel = labels[neighborsSignificance[index]];
|
||||||
|
const decision = decoder.readBit(contexts, contextLabel);
|
||||||
|
if (decision) {
|
||||||
|
const sign = this.decodeSignBit(i, j, index);
|
||||||
|
coefficentsSign[index] = sign;
|
||||||
|
coefficentsMagnitude[index] = 1;
|
||||||
|
this.setNeighborsSignificance(i, j, index);
|
||||||
|
processingFlags[index] |= firstMagnitudeBitMask;
|
||||||
|
}
|
||||||
|
bitsDecoded[index]++;
|
||||||
|
processingFlags[index] |= processedMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
decodeSignBit(row, column, index) {
|
decodeSignBit(row, column, index) {
|
||||||
const width = this.width,
|
const width = this.width,
|
||||||
height = this.height;
|
height = this.height;
|
||||||
const coefficentsMagnitude = this.coefficentsMagnitude;
|
const coefficentsMagnitude = this.coefficentsMagnitude;
|
||||||
const coefficentsSign = this.coefficentsSign;
|
const coefficentsSign = this.coefficentsSign;
|
||||||
let contribution, sign0, sign1, significance1;
|
let contribution, sign0, sign1, significance1;
|
||||||
let contextLabel, decoded;
|
let contextLabel, decoded;
|
||||||
|
|
||||||
// calculate horizontal contribution
|
// calculate horizontal contribution
|
||||||
significance1 = column > 0 && coefficentsMagnitude[index - 1] !== 0;
|
significance1 = column > 0 && coefficentsMagnitude[index - 1] !== 0;
|
||||||
if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) {
|
if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) {
|
||||||
sign1 = coefficentsSign[index + 1];
|
sign1 = coefficentsSign[index + 1];
|
||||||
if (significance1) {
|
if (significance1) {
|
||||||
sign0 = coefficentsSign[index - 1];
|
|
||||||
contribution = 1 - sign1 - sign0;
|
|
||||||
} else {
|
|
||||||
contribution = 1 - sign1 - sign1;
|
|
||||||
}
|
|
||||||
} else if (significance1) {
|
|
||||||
sign0 = coefficentsSign[index - 1];
|
sign0 = coefficentsSign[index - 1];
|
||||||
contribution = 1 - sign0 - sign0;
|
contribution = 1 - sign1 - sign0;
|
||||||
} else {
|
} else {
|
||||||
contribution = 0;
|
contribution = 1 - sign1 - sign1;
|
||||||
}
|
}
|
||||||
const horizontalContribution = 3 * contribution;
|
} else if (significance1) {
|
||||||
|
sign0 = coefficentsSign[index - 1];
|
||||||
|
contribution = 1 - sign0 - sign0;
|
||||||
|
} else {
|
||||||
|
contribution = 0;
|
||||||
|
}
|
||||||
|
const horizontalContribution = 3 * contribution;
|
||||||
|
|
||||||
// calculate vertical contribution and combine with the horizontal
|
// calculate vertical contribution and combine with the horizontal
|
||||||
significance1 = row > 0 && coefficentsMagnitude[index - width] !== 0;
|
significance1 = row > 0 && coefficentsMagnitude[index - width] !== 0;
|
||||||
if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) {
|
if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) {
|
||||||
sign1 = coefficentsSign[index + width];
|
sign1 = coefficentsSign[index + width];
|
||||||
if (significance1) {
|
if (significance1) {
|
||||||
sign0 = coefficentsSign[index - width];
|
|
||||||
contribution = 1 - sign1 - sign0 + horizontalContribution;
|
|
||||||
} else {
|
|
||||||
contribution = 1 - sign1 - sign1 + horizontalContribution;
|
|
||||||
}
|
|
||||||
} else if (significance1) {
|
|
||||||
sign0 = coefficentsSign[index - width];
|
sign0 = coefficentsSign[index - width];
|
||||||
contribution = 1 - sign0 - sign0 + horizontalContribution;
|
contribution = 1 - sign1 - sign0 + horizontalContribution;
|
||||||
} else {
|
} else {
|
||||||
contribution = horizontalContribution;
|
contribution = 1 - sign1 - sign1 + horizontalContribution;
|
||||||
}
|
}
|
||||||
|
} else if (significance1) {
|
||||||
if (contribution >= 0) {
|
sign0 = coefficentsSign[index - width];
|
||||||
contextLabel = 9 + contribution;
|
contribution = 1 - sign0 - sign0 + horizontalContribution;
|
||||||
decoded = this.decoder.readBit(this.contexts, contextLabel);
|
} else {
|
||||||
} else {
|
contribution = horizontalContribution;
|
||||||
contextLabel = 9 - contribution;
|
|
||||||
decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1;
|
|
||||||
}
|
|
||||||
return decoded;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
runMagnitudeRefinementPass() {
|
if (contribution >= 0) {
|
||||||
const decoder = this.decoder;
|
contextLabel = 9 + contribution;
|
||||||
const width = this.width,
|
decoded = this.decoder.readBit(this.contexts, contextLabel);
|
||||||
height = this.height;
|
} else {
|
||||||
const coefficentsMagnitude = this.coefficentsMagnitude;
|
contextLabel = 9 - contribution;
|
||||||
const neighborsSignificance = this.neighborsSignificance;
|
decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1;
|
||||||
const contexts = this.contexts;
|
}
|
||||||
const bitsDecoded = this.bitsDecoded;
|
return decoded;
|
||||||
const processingFlags = this.processingFlags;
|
}
|
||||||
const processedMask = 1;
|
|
||||||
const firstMagnitudeBitMask = 2;
|
|
||||||
const length = width * height;
|
|
||||||
const width4 = width * 4;
|
|
||||||
|
|
||||||
for (let index0 = 0, indexNext; index0 < length; index0 = indexNext) {
|
runMagnitudeRefinementPass() {
|
||||||
indexNext = Math.min(length, index0 + width4);
|
const decoder = this.decoder;
|
||||||
for (let j = 0; j < width; j++) {
|
const width = this.width,
|
||||||
for (let index = index0 + j; index < indexNext; index += width) {
|
height = this.height;
|
||||||
// significant but not those that have just become
|
const coefficentsMagnitude = this.coefficentsMagnitude;
|
||||||
if (
|
const neighborsSignificance = this.neighborsSignificance;
|
||||||
!coefficentsMagnitude[index] ||
|
const contexts = this.contexts;
|
||||||
(processingFlags[index] & processedMask) !== 0
|
const bitsDecoded = this.bitsDecoded;
|
||||||
) {
|
const processingFlags = this.processingFlags;
|
||||||
continue;
|
const processedMask = 1;
|
||||||
}
|
const firstMagnitudeBitMask = 2;
|
||||||
|
const length = width * height;
|
||||||
|
const width4 = width * 4;
|
||||||
|
|
||||||
let contextLabel = 16;
|
for (let index0 = 0, indexNext; index0 < length; index0 = indexNext) {
|
||||||
if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) {
|
indexNext = Math.min(length, index0 + width4);
|
||||||
processingFlags[index] ^= firstMagnitudeBitMask;
|
for (let j = 0; j < width; j++) {
|
||||||
// first refinement
|
for (let index = index0 + j; index < indexNext; index += width) {
|
||||||
const significance = neighborsSignificance[index] & 127;
|
// significant but not those that have just become
|
||||||
contextLabel = significance === 0 ? 15 : 14;
|
if (
|
||||||
}
|
!coefficentsMagnitude[index] ||
|
||||||
|
(processingFlags[index] & processedMask) !== 0
|
||||||
const bit = decoder.readBit(contexts, contextLabel);
|
) {
|
||||||
coefficentsMagnitude[index] =
|
continue;
|
||||||
(coefficentsMagnitude[index] << 1) | bit;
|
|
||||||
bitsDecoded[index]++;
|
|
||||||
processingFlags[index] |= processedMask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let contextLabel = 16;
|
||||||
|
if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) {
|
||||||
|
processingFlags[index] ^= firstMagnitudeBitMask;
|
||||||
|
// first refinement
|
||||||
|
const significance = neighborsSignificance[index] & 127;
|
||||||
|
contextLabel = significance === 0 ? 15 : 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bit = decoder.readBit(contexts, contextLabel);
|
||||||
|
coefficentsMagnitude[index] =
|
||||||
|
(coefficentsMagnitude[index] << 1) | bit;
|
||||||
|
bitsDecoded[index]++;
|
||||||
|
processingFlags[index] |= processedMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
runCleanupPass() {
|
runCleanupPass() {
|
||||||
const decoder = this.decoder;
|
const decoder = this.decoder;
|
||||||
const width = this.width,
|
const width = this.width,
|
||||||
height = this.height;
|
height = this.height;
|
||||||
const neighborsSignificance = this.neighborsSignificance;
|
const neighborsSignificance = this.neighborsSignificance;
|
||||||
const coefficentsMagnitude = this.coefficentsMagnitude;
|
const coefficentsMagnitude = this.coefficentsMagnitude;
|
||||||
const coefficentsSign = this.coefficentsSign;
|
const coefficentsSign = this.coefficentsSign;
|
||||||
const contexts = this.contexts;
|
const contexts = this.contexts;
|
||||||
const labels = this.contextLabelTable;
|
const labels = this.contextLabelTable;
|
||||||
const bitsDecoded = this.bitsDecoded;
|
const bitsDecoded = this.bitsDecoded;
|
||||||
const processingFlags = this.processingFlags;
|
const processingFlags = this.processingFlags;
|
||||||
const processedMask = 1;
|
const processedMask = 1;
|
||||||
const firstMagnitudeBitMask = 2;
|
const firstMagnitudeBitMask = 2;
|
||||||
const oneRowDown = width;
|
const oneRowDown = width;
|
||||||
const twoRowsDown = width * 2;
|
const twoRowsDown = width * 2;
|
||||||
const threeRowsDown = width * 3;
|
const threeRowsDown = width * 3;
|
||||||
let iNext;
|
let iNext;
|
||||||
for (let i0 = 0; i0 < height; i0 = iNext) {
|
for (let i0 = 0; i0 < height; i0 = iNext) {
|
||||||
iNext = Math.min(i0 + 4, height);
|
iNext = Math.min(i0 + 4, height);
|
||||||
const indexBase = i0 * width;
|
const indexBase = i0 * width;
|
||||||
const checkAllEmpty = i0 + 3 < height;
|
const checkAllEmpty = i0 + 3 < height;
|
||||||
for (let j = 0; j < width; j++) {
|
for (let j = 0; j < width; j++) {
|
||||||
const index0 = indexBase + j;
|
const index0 = indexBase + j;
|
||||||
// using the property: labels[neighborsSignificance[index]] === 0
|
// using the property: labels[neighborsSignificance[index]] === 0
|
||||||
// when neighborsSignificance[index] === 0
|
// when neighborsSignificance[index] === 0
|
||||||
const allEmpty =
|
const allEmpty =
|
||||||
checkAllEmpty &&
|
checkAllEmpty &&
|
||||||
processingFlags[index0] === 0 &&
|
processingFlags[index0] === 0 &&
|
||||||
processingFlags[index0 + oneRowDown] === 0 &&
|
processingFlags[index0 + oneRowDown] === 0 &&
|
||||||
processingFlags[index0 + twoRowsDown] === 0 &&
|
processingFlags[index0 + twoRowsDown] === 0 &&
|
||||||
processingFlags[index0 + threeRowsDown] === 0 &&
|
processingFlags[index0 + threeRowsDown] === 0 &&
|
||||||
neighborsSignificance[index0] === 0 &&
|
neighborsSignificance[index0] === 0 &&
|
||||||
neighborsSignificance[index0 + oneRowDown] === 0 &&
|
neighborsSignificance[index0 + oneRowDown] === 0 &&
|
||||||
neighborsSignificance[index0 + twoRowsDown] === 0 &&
|
neighborsSignificance[index0 + twoRowsDown] === 0 &&
|
||||||
neighborsSignificance[index0 + threeRowsDown] === 0;
|
neighborsSignificance[index0 + threeRowsDown] === 0;
|
||||||
let i1 = 0,
|
let i1 = 0,
|
||||||
index = index0;
|
index = index0;
|
||||||
let i = i0,
|
let i = i0,
|
||||||
sign;
|
sign;
|
||||||
if (allEmpty) {
|
if (allEmpty) {
|
||||||
const hasSignificantCoefficent = decoder.readBit(
|
const hasSignificantCoefficent = decoder.readBit(
|
||||||
contexts,
|
contexts,
|
||||||
RUNLENGTH_CONTEXT
|
BitModel.RUNLENGTH_CONTEXT
|
||||||
);
|
);
|
||||||
if (!hasSignificantCoefficent) {
|
if (!hasSignificantCoefficent) {
|
||||||
bitsDecoded[index0]++;
|
bitsDecoded[index0]++;
|
||||||
bitsDecoded[index0 + oneRowDown]++;
|
bitsDecoded[index0 + oneRowDown]++;
|
||||||
bitsDecoded[index0 + twoRowsDown]++;
|
bitsDecoded[index0 + twoRowsDown]++;
|
||||||
bitsDecoded[index0 + threeRowsDown]++;
|
bitsDecoded[index0 + threeRowsDown]++;
|
||||||
continue; // next column
|
continue; // next column
|
||||||
}
|
}
|
||||||
i1 =
|
i1 =
|
||||||
(decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) |
|
(decoder.readBit(contexts, BitModel.UNIFORM_CONTEXT) << 1) |
|
||||||
decoder.readBit(contexts, UNIFORM_CONTEXT);
|
decoder.readBit(contexts, BitModel.UNIFORM_CONTEXT);
|
||||||
if (i1 !== 0) {
|
if (i1 !== 0) {
|
||||||
i = i0 + i1;
|
i = i0 + i1;
|
||||||
index += i1 * width;
|
index += i1 * width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sign = this.decodeSignBit(i, j, index);
|
||||||
|
coefficentsSign[index] = sign;
|
||||||
|
coefficentsMagnitude[index] = 1;
|
||||||
|
this.setNeighborsSignificance(i, j, index);
|
||||||
|
processingFlags[index] |= firstMagnitudeBitMask;
|
||||||
|
|
||||||
|
index = index0;
|
||||||
|
for (let i2 = i0; i2 <= i; i2++, index += width) {
|
||||||
|
bitsDecoded[index]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1++;
|
||||||
|
}
|
||||||
|
for (i = i0 + i1; i < iNext; i++, index += width) {
|
||||||
|
if (
|
||||||
|
coefficentsMagnitude[index] ||
|
||||||
|
(processingFlags[index] & processedMask) !== 0
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contextLabel = labels[neighborsSignificance[index]];
|
||||||
|
const decision = decoder.readBit(contexts, contextLabel);
|
||||||
|
if (decision === 1) {
|
||||||
sign = this.decodeSignBit(i, j, index);
|
sign = this.decodeSignBit(i, j, index);
|
||||||
coefficentsSign[index] = sign;
|
coefficentsSign[index] = sign;
|
||||||
coefficentsMagnitude[index] = 1;
|
coefficentsMagnitude[index] = 1;
|
||||||
this.setNeighborsSignificance(i, j, index);
|
this.setNeighborsSignificance(i, j, index);
|
||||||
processingFlags[index] |= firstMagnitudeBitMask;
|
processingFlags[index] |= firstMagnitudeBitMask;
|
||||||
|
|
||||||
index = index0;
|
|
||||||
for (let i2 = i0; i2 <= i; i2++, index += width) {
|
|
||||||
bitsDecoded[index]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
i1++;
|
|
||||||
}
|
|
||||||
for (i = i0 + i1; i < iNext; i++, index += width) {
|
|
||||||
if (
|
|
||||||
coefficentsMagnitude[index] ||
|
|
||||||
(processingFlags[index] & processedMask) !== 0
|
|
||||||
) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const contextLabel = labels[neighborsSignificance[index]];
|
|
||||||
const decision = decoder.readBit(contexts, contextLabel);
|
|
||||||
if (decision === 1) {
|
|
||||||
sign = this.decodeSignBit(i, j, index);
|
|
||||||
coefficentsSign[index] = sign;
|
|
||||||
coefficentsMagnitude[index] = 1;
|
|
||||||
this.setNeighborsSignificance(i, j, index);
|
|
||||||
processingFlags[index] |= firstMagnitudeBitMask;
|
|
||||||
}
|
|
||||||
bitsDecoded[index]++;
|
|
||||||
}
|
}
|
||||||
|
bitsDecoded[index]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkSegmentationSymbol() {
|
|
||||||
const decoder = this.decoder;
|
|
||||||
const contexts = this.contexts;
|
|
||||||
const symbol =
|
|
||||||
(decoder.readBit(contexts, UNIFORM_CONTEXT) << 3) |
|
|
||||||
(decoder.readBit(contexts, UNIFORM_CONTEXT) << 2) |
|
|
||||||
(decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) |
|
|
||||||
decoder.readBit(contexts, UNIFORM_CONTEXT);
|
|
||||||
if (symbol !== 0xa) {
|
|
||||||
throw new JpxError("Invalid segmentation symbol");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return BitModel;
|
checkSegmentationSymbol() {
|
||||||
})();
|
const decoder = this.decoder;
|
||||||
|
const contexts = this.contexts;
|
||||||
|
const symbol =
|
||||||
|
(decoder.readBit(contexts, BitModel.UNIFORM_CONTEXT) << 3) |
|
||||||
|
(decoder.readBit(contexts, BitModel.UNIFORM_CONTEXT) << 2) |
|
||||||
|
(decoder.readBit(contexts, BitModel.UNIFORM_CONTEXT) << 1) |
|
||||||
|
decoder.readBit(contexts, BitModel.UNIFORM_CONTEXT);
|
||||||
|
if (symbol !== 0xa) {
|
||||||
|
throw new JpxError("Invalid segmentation symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Section F, Discrete wavelet transformation
|
// Section F, Discrete wavelet transformation
|
||||||
class Transform {
|
class Transform {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user