function decodeTextRegion()

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;
}