in src/core/jbig2.js [775:949]
function decodeTextRegion(
huffman,
refinement,
width,
height,
defaultPixelValue,
numberOfSymbolInstances,
stripSize,
inputSymbols,
symbolCodeLength,
transposed,
dsOffset,
referenceCorner,
combinationOperator,
huffmanTables,
refinementTemplateIndex,
refinementAt,
decodingContext,
logStripSize,
huffmanInput
) {
if (huffman && refinement) {
throw new Jbig2Error("refinement with Huffman is not supported");
}
// Prepare bitmap
const bitmap = [];
let i, row;
for (i = 0; i < height; i++) {
row = new Uint8Array(width);
if (defaultPixelValue) {
row.fill(defaultPixelValue);
}
bitmap.push(row);
}
const decoder = decodingContext.decoder;
const contextCache = decodingContext.contextCache;
let stripT = huffman
? -huffmanTables.tableDeltaT.decode(huffmanInput)
: -decodeInteger(contextCache, "IADT", decoder); // 6.4.6
let firstS = 0;
i = 0;
while (i < numberOfSymbolInstances) {
const deltaT = huffman
? huffmanTables.tableDeltaT.decode(huffmanInput)
: decodeInteger(contextCache, "IADT", decoder); // 6.4.6
stripT += deltaT;
const deltaFirstS = huffman
? huffmanTables.tableFirstS.decode(huffmanInput)
: decodeInteger(contextCache, "IAFS", decoder); // 6.4.7
firstS += deltaFirstS;
let currentS = firstS;
do {
let currentT = 0; // 6.4.9
if (stripSize > 1) {
currentT = huffman
? huffmanInput.readBits(logStripSize)
: decodeInteger(contextCache, "IAIT", decoder);
}
const t = stripSize * stripT + currentT;
const symbolId = huffman
? huffmanTables.symbolIDTable.decode(huffmanInput)
: decodeIAID(contextCache, decoder, symbolCodeLength);
const applyRefinement =
refinement &&
(huffman
? huffmanInput.readBit()
: decodeInteger(contextCache, "IARI", decoder));
let symbolBitmap = inputSymbols[symbolId];
let symbolWidth = symbolBitmap[0].length;
let symbolHeight = symbolBitmap.length;
if (applyRefinement) {
const rdw = decodeInteger(contextCache, "IARDW", decoder); // 6.4.11.1
const rdh = decodeInteger(contextCache, "IARDH", decoder); // 6.4.11.2
const rdx = decodeInteger(contextCache, "IARDX", decoder); // 6.4.11.3
const rdy = decodeInteger(contextCache, "IARDY", decoder); // 6.4.11.4
symbolWidth += rdw;
symbolHeight += rdh;
symbolBitmap = decodeRefinement(
symbolWidth,
symbolHeight,
refinementTemplateIndex,
symbolBitmap,
(rdw >> 1) + rdx,
(rdh >> 1) + rdy,
false,
refinementAt,
decodingContext
);
}
let increment = 0;
if (!transposed) {
if (referenceCorner > 1) {
currentS += symbolWidth - 1;
} else {
increment = symbolWidth - 1;
}
} else if (!(referenceCorner & 1)) {
currentS += symbolHeight - 1;
} else {
increment = symbolHeight - 1;
}
const offsetT = t - (referenceCorner & 1 ? 0 : symbolHeight - 1);
const offsetS = currentS - (referenceCorner & 2 ? symbolWidth - 1 : 0);
let s2, t2, symbolRow;
if (transposed) {
// Place Symbol Bitmap from T1,S1
for (s2 = 0; s2 < symbolHeight; s2++) {
row = bitmap[offsetS + s2];
if (!row) {
continue;
}
symbolRow = symbolBitmap[s2];
// To ignore Parts of Symbol bitmap which goes
// outside bitmap region
const maxWidth = Math.min(width - offsetT, symbolWidth);
switch (combinationOperator) {
case 0: // OR
for (t2 = 0; t2 < maxWidth; t2++) {
row[offsetT + t2] |= symbolRow[t2];
}
break;
case 2: // XOR
for (t2 = 0; t2 < maxWidth; t2++) {
row[offsetT + t2] ^= symbolRow[t2];
}
break;
default:
throw new Jbig2Error(
`operator ${combinationOperator} is not supported`
);
}
}
} else {
for (t2 = 0; t2 < symbolHeight; t2++) {
row = bitmap[offsetT + t2];
if (!row) {
continue;
}
symbolRow = symbolBitmap[t2];
switch (combinationOperator) {
case 0: // OR
for (s2 = 0; s2 < symbolWidth; s2++) {
row[offsetS + s2] |= symbolRow[s2];
}
break;
case 2: // XOR
for (s2 = 0; s2 < symbolWidth; s2++) {
row[offsetS + s2] ^= symbolRow[s2];
}
break;
default:
throw new Jbig2Error(
`operator ${combinationOperator} is not supported`
);
}
}
}
i++;
const deltaS = huffman
? huffmanTables.tableDeltaS.decode(huffmanInput)
: decodeInteger(contextCache, "IADS", decoder); // 6.4.8
if (deltaS === null) {
break; // OOB
}
currentS += increment + deltaS + dsOffset;
} while (true);
}
return bitmap;
}