decodeT6 method

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

Implementation

void decodeT6(InputBuffer out, InputBuffer compData, int startX, int height,
    int tiffT6Options) {
  data = compData;
  compression = 4;

  bitPointer = 0;
  bytePointer = 0;

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

  int? a0, a1, b1, b2;
  int entry, code, bits;
  bool isWhite;
  int currIndex;
  List<int?>? temp;

  // Return values from getNextChangingElement
  final b = List<int?>.filled(2, null);

  uncompressedMode = ((tiffT6Options & 0x02) >> 1);

  // Local cached reference
  var cce = currChangingElems!;

  // Assume invisible preceding row of all white pixels and insert
  // both black and white changing elements beyond the end of this
  // imaginary scanline.
  changingElemSize = 0;
  cce[changingElemSize++] = width;
  cce[changingElemSize++] = width;

  var lineOffset = 0;
  int? bitOffset;

  for (var lines = 0; lines < height; lines++) {
    // a0 has to be set just before the start of the scanline.
    a0 = -1;
    isWhite = true;

    // Assign the changing elements of the previous scanline to
    // prevChangingElems and start putting this new scanline's
    // changing elements into the currChangingElems.
    temp = prevChangingElems;
    prevChangingElems = currChangingElems;
    cce = (currChangingElems = temp)!;
    currIndex = 0;

    // Start decoding the scanline at startX in the raster
    bitOffset = startX;

    // Reset search start position for getNextChangingElement
    lastChangingElement = 0;

    // Till one whole scanline is decoded
    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) {
        // Pass
        // We always assume WhiteIsZero format for fax.
        if (!isWhite) {
          _setToBlack(out, lineOffset, bitOffset, b2! - bitOffset);
        }
        bitOffset = a0 = b2;

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

        // identify the next 2 alternating color codes.
        int number;
        if (isWhite) {
          // Following are white and black runs
          number = _decodeWhiteCodeWord();
          bitOffset += number;
          cce[currIndex++] = bitOffset;

          number = _decodeBlackCodeWord();
          _setToBlack(out, lineOffset, bitOffset, number);
          bitOffset += number;
          cce[currIndex++] = bitOffset;
        } else {
          // First a black run and then a white run follows
          number = _decodeBlackCodeWord();
          _setToBlack(out, lineOffset, bitOffset, number);
          bitOffset += number;
          cce[currIndex++] = bitOffset;

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

        a0 = bitOffset;
      } else if (code <= 8) {
        // Vertical
        a1 = b1! + (code - 5);
        cce[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 if (code == 11) {
        if (_nextLesserThan8Bits(3) != 7) {
          throw ImageException('TIFFFaxDecoder5');
        }

        var zeros = 0;
        var exit = false;

        while (!exit) {
          while (_nextLesserThan8Bits(1) != 1) {
            zeros++;
          }

          if (zeros > 5) {
            // Exit code

            // Zeros before exit code
            zeros = zeros - 6;

            if (!isWhite && (zeros > 0)) {
              cce[currIndex++] = bitOffset;
            }

            // Zeros before the exit code
            bitOffset = bitOffset! + zeros;
            if (zeros > 0) {
              // Some zeros have been written
              isWhite = true;
            }

            // Read in the bit which specifies the color of
            // the following run
            if (_nextLesserThan8Bits(1) == 0) {
              if (!isWhite) {
                cce[currIndex++] = bitOffset;
              }
              isWhite = true;
            } else {
              if (isWhite) {
                cce[currIndex++] = bitOffset;
              }
              isWhite = false;
            }

            exit = true;
          }

          if (zeros == 5) {
            if (!isWhite) {
              cce[currIndex++] = bitOffset;
            }
            bitOffset = bitOffset! + zeros;

            // Last thing written was white
            isWhite = true;
          } else {
            bitOffset = bitOffset! + zeros;

            cce[currIndex++] = bitOffset;
            _setToBlack(out, lineOffset, bitOffset, 1);
            ++bitOffset;

            // Last thing written was black
            isWhite = false;
          }
        }
      } else {
        throw ImageException('TIFFFaxDecoder5 $code');
      }
    }

    // Add the changing element beyond the current scanline for the
    // other color too
    cce[currIndex++] = bitOffset;

    // Number of changing elements in this scanline.
    changingElemSize = currIndex;

    lineOffset += scanlineStride;
  }
}