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();