Exemplo n.º 1
0
  /**
   * Read and decompress a new scanline from the specified {@link Inflater}. If more data is needed,
   * then {@code null} is returned.
   */
  public ScanlineWrapper readNext(Inflater inflater) throws IOException {
    try {
      // Decompress the filter-type first, that is
      // contained as first byte in a scanline
      if (ftype == FILTER_INVALID) {
        inflater.inflate(buffer, 0, 1);
        ftype = buffer[0];
      }

      // Decompress one scanline, skipping the already read bytes
      final int numBytesRequired = length - offset;
      final int numBytesInflated = inflater.inflate(buffer, offset, numBytesRequired);
      if (numBytesInflated != numBytesRequired) {
        // A full scanline could not be read or decompressed, save
        // the position inside the buffer and wait for more input
        offset = numBytesInflated;
        return null;
      } else offset = 0;
    } catch (DataFormatException dfe) {
      // Rethrow as IOException
      throw new IOException(dfe);
    }

    // Ensure a valid filter-type!
    if (ftype < FILTER_NONE || ftype > FILTER_PAETH)
      throw new IOException("Invalid filter type found: " + ftype);

    // Reconstruct the decompressed scanline using its filter
    final int[] curline = this.getCurScanline();
    final int[] preline = this.getPreScanline();
    final IScanlineFilter filter = LUT_FILTERS[ftype];
    filter.reconstruct(curline, preline, buffer, length, delta);

    // Prepare for next reconstruction
    ftype = FILTER_INVALID;

    // Swap the scanlines!
    curid = 1 - curid;
    ++numScanlinesRead;

    // Return the reconstructed scanline
    wrapper.setScanline(curline, 0, width);
    return wrapper;
  }