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;
  }
Exemplo n.º 2
0
  /**
   * Prepare this {@link ScanlineReader} for reading new scanlines of specified width and with
   * specified number of samples-per-pixel and bits-per-sample.
   */
  public void prepare(int width, int spp, int bps) {
    final int n = bps >> 3;

    // Update the current ScanlineWrapper:
    // bps = 1,2,4 --> bps >> 3 = 0
    // bps = 8     --> bps >> 3 = 1
    // bps = 16    --> bps >> 3 = 2
    wrapper = wrappers[n];
    wrapper.prepare(bps);

    // For reconstruction of a byte of the pixel X the corresponding
    // byte in the pixel immediately before X should be used. But when
    // the bitdepth is less than 8, then simply use the previous byte.
    this.delta = (bps < 8) ? 1 : (spp * n);

    this.width = width;
    this.numScanlinesRead = 0;
    this.ftype = FILTER_INVALID;
    this.offset = 0;

    // Calculate the sanline's length in bytes
    final int numbits = spp * bps * width;
    this.length = (numbits >> 3);
    if ((numbits & 0x07) != 0) {
      // numbits is not a multiple of 8,
      // one additional byte is needed!
      ++length;
    }

    // Update the buffers for scanlines
    if (buffer.length < length) {
      buffer = new byte[length];
      scanlines[0] = new int[length];
      scanlines[1] = new int[length];
    }
  }