this.bytesPerPixel = (this.encodeAlpha) ? 4 : 3;
    final Deflater scrunch = new Deflater(this.compressionLevel);
    final ByteArrayOutputStream outBytes = new ByteArrayOutputStream(1024);
    final DeflaterOutputStream compBytes = new DeflaterOutputStream(outBytes, scrunch);
    try
    {
      int startRow = 0;       // starting row to process this time through
      //noinspection SuspiciousNameCombination
      int rowsLeft = this.height;  // number of rows remaining to write
      while (rowsLeft > 0)
      {
        final int nRows = Math.max(Math.min(32767 / (this.width * (this.bytesPerPixel + 1)), rowsLeft), 1);
        final int[] pixels = new int[this.width * nRows];
        final PixelGrabber pg = new PixelGrabber(this.image, 0, startRow,
            this.width, nRows, pixels, 0, this.width);
        try
        {
          pg.grabPixels();
        }
        catch (Exception e)
        {
          logger.error("interrupted waiting for pixels!", e);
          return false;
        }
        if ((pg.getStatus() & ImageObserver.ABORT) != 0)
        {
          logger.error("image fetch aborted or errored");
          return false;
        }
        /*
        * Create a data chunk. scanLines adds "nRows" for
        * the filter bytes.
        */
        final byte[] scanLines = new byte[this.width * nRows * this.bytesPerPixel + nRows];
        if (this.filter == PngEncoder.FILTER_SUB)
        {
          this.leftBytes = new byte[16];
        }
        if (this.filter == PngEncoder.FILTER_UP)
        {
          this.priorRow = new byte[this.width * this.bytesPerPixel];
        }
        int scanPos = 0;
        int startPos = 1;
        for (int i = 0; i < this.width * nRows; i++)
        {
          if (i % this.width == 0)
          {
            scanLines[scanPos++] = (byte) this.filter;
            startPos = scanPos;
          }
          scanLines[scanPos++] = (byte) ((pixels[i] >> 16) & 0xff);
          scanLines[scanPos++] = (byte) ((pixels[i] >> 8) & 0xff);
          scanLines[scanPos++] = (byte) ((pixels[i]) & 0xff);
          if (this.encodeAlpha)
          {
            scanLines[scanPos++] = (byte) ((pixels[i] >> 24)
                & 0xff);
          }
          if ((i % this.width == this.width - 1)
              && (this.filter != PngEncoder.FILTER_NONE))
          {
            if (this.filter == PngEncoder.FILTER_SUB)
            {
              filterSub(scanLines, startPos, this.width);
            }
            if (this.filter == PngEncoder.FILTER_UP)
            {
              filterUp(scanLines, startPos, this.width);
            }
          }
        }
        /*
        * Write these lines to the output area
        */
        compBytes.write(scanLines, 0, scanPos);
        startRow += nRows;
        rowsLeft -= nRows;
      }
      compBytes.close();
      /*
      * Write the compressed bytes
      */
      final byte[] compressedLines = outBytes.toByteArray();