decode2D method

void decode2D(
  1. InputBuffer out,
  2. InputBuffer compData,
  3. int startX,
  4. int height,
  5. int tiffT4Options,
)

Implementation

void decode2D(InputBuffer out, InputBuffer compData, int startX, int height,
    int tiffT4Options) {
  data = compData;
  compression = 3;

  bitPointer = 0;
  bytePointer = 0;

  final scanlineStride = (width + 7) ~/ 8;

  int? a0, a1, b1, b2;
  final b = List<int?>.filled(2, null);
  int entry, code, bits;
  bool isWhite;
  var currIndex = 0;
  List<int?>? temp;

  // fillBits - dealt with this in readEOL
  // 1D/2D encoding - dealt with this in readEOL

  // uncompressedMode - haven't dealt with this yet.

  oneD = (tiffT4Options & 0x01);
  uncompressedMode = ((tiffT4Options & 0x02) >> 1);
  fillBits = ((tiffT4Options & 0x04) >> 2);

  // The data must start with an EOL code
  if (_readEOL() != 1) {
    throw ImageException('TIFFFaxDecoder3');
  }

  var lineOffset = 0;
  int? bitOffset;

  // Then the 1D encoded scanline data will occur, changing elements
  // array gets set.
  _decodeNextScanline(out, lineOffset, startX);
  lineOffset += scanlineStride;

  for (var lines = 1; lines < height; lines++) {
    // Every line must begin with an EOL followed by a bit which
    // indicates whether the following scanline is 1D or 2D encoded.
    if (_readEOL() == 0) {
      // 2D encoded scanline follows

      // Initialize previous scanlines changing elements, and
      // initialize current scanline's changing elements array
      temp = prevChangingElems;
      prevChangingElems = currChangingElems;
      currChangingElems = temp;
      currIndex = 0;

      // a0 has to be set just before the start of this scanline.
      a0 = -1;
      isWhite = true;
      bitOffset = startX;

      lastChangingElement = 0;

      while (bitOffset! < width) {
        // Get the next changing element
        _getNextChangingElement(a0, isWhite, b);

        b1 = b[0];
        b2 = b[1];

        // Get the next seven bits
        entry = _nextLesserThan8Bits(7);

        // Run these through the 2DCodes table
        entry = (TWO_D_CODES[entry] & 0xff);

        // Get the code and the number of bits used up
        code = (entry & 0x78) >> 3;
        bits = entry & 0x07;

        if (code == 0) {
          if (!isWhite) {
            _setToBlack(out, lineOffset, bitOffset, b2! - bitOffset);
          }
          bitOffset = a0 = b2;

          // Set pointer to consume the correct number of bits.
          _updatePointer(7 - bits);
        } else if (code == 1) {
          // Horizontal
          _updatePointer(7 - bits);

          // identify the next 2 codes.
          int number;
          if (isWhite) {
            number = _decodeWhiteCodeWord();
            bitOffset += number;
            currChangingElems![currIndex++] = bitOffset;

            number = _decodeBlackCodeWord();
            _setToBlack(out, lineOffset, bitOffset, number);
            bitOffset += number;
            currChangingElems![currIndex++] = bitOffset;
          } else {
            number = _decodeBlackCodeWord();
            _setToBlack(out, lineOffset, bitOffset, number);
            bitOffset += number;
            currChangingElems![currIndex++] = bitOffset;

            number = _decodeWhiteCodeWord();
            bitOffset += number;
            currChangingElems![currIndex++] = bitOffset;
          }

          a0 = bitOffset;
        } else if (code <= 8) {
          // Vertical
          a1 = b1! + (code - 5);

          currChangingElems![currIndex++] = a1;

          // We write the current color till a1 - 1 pos,
          // since a1 is where the next color starts
          if (!isWhite) {
            _setToBlack(out, lineOffset, bitOffset, a1 - bitOffset);
          }
          bitOffset = a0 = a1;
          isWhite = !isWhite;

          _updatePointer(7 - bits);
        } else {
          throw ImageException('TIFFFaxDecoder4');
        }
      }

      // Add the changing element beyond the current scanline for the
      // other color too
      currChangingElems![currIndex++] = bitOffset;
      changingElemSize = currIndex;
    } else {
      // 1D encoded scanline follows
      _decodeNextScanline(out, lineOffset, startX);
    }

    lineOffset += scanlineStride;
  }
}