in src/main/java/org/apache/xmlgraphics/image/codec/png/PNGImageEncoder.java [361:467]
private void encodePass(OutputStream os, Raster ras,
int xOffset, int yOffset,
int xSkip, int ySkip)
throws IOException {
int minX = ras.getMinX();
int minY = ras.getMinY();
int width = ras.getWidth();
int height = ras.getHeight();
xOffset *= numBands;
xSkip *= numBands;
int samplesPerByte = 8 / bitDepth;
int numSamples = width * numBands;
int[] samples = new int[numSamples];
int pixels = (numSamples - xOffset + xSkip - 1) / xSkip;
int bytesPerRow = pixels * numBands;
if (bitDepth < 8) {
bytesPerRow = (bytesPerRow + samplesPerByte - 1) / samplesPerByte;
} else if (bitDepth == 16) {
bytesPerRow *= 2;
}
if (bytesPerRow == 0) {
return;
}
currRow = new byte[bytesPerRow + bpp];
prevRow = new byte[bytesPerRow + bpp];
filteredRows = new byte[5][bytesPerRow + bpp];
int maxValue = (1 << bitDepth) - 1;
for (int row = minY + yOffset; row < minY + height; row += ySkip) {
ras.getPixels(minX, row, width, 1, samples);
if (compressGray) {
int shift = 8 - bitDepth;
for (int i = 0; i < width; i++) {
samples[i] >>= shift;
}
}
int count = bpp; // leave first 'bpp' bytes zero
int pos = 0;
int tmp = 0;
switch (bitDepth) {
case 1: case 2: case 4:
// Image can only have a single band
int mask = samplesPerByte - 1;
for (int s = xOffset; s < numSamples; s += xSkip) {
int val = clamp(samples[s] >> bitShift, maxValue);
tmp = (tmp << bitDepth) | val;
if (pos++ == mask) {
currRow[count++] = (byte)tmp;
tmp = 0;
pos = 0;
}
}
// Left shift the last byte
if (pos != 0) {
tmp <<= (samplesPerByte - pos) * bitDepth;
currRow[count++] = (byte)tmp;
}
break;
case 8:
for (int s = xOffset; s < numSamples; s += xSkip) {
for (int b = 0; b < numBands; b++) {
currRow[count++] =
(byte)clamp(samples[s + b] >> bitShift, maxValue);
}
}
break;
case 16:
for (int s = xOffset; s < numSamples; s += xSkip) {
for (int b = 0; b < numBands; b++) {
int val = clamp(samples[s + b] >> bitShift, maxValue);
currRow[count++] = (byte)(val >> 8);
currRow[count++] = (byte)(val & 0xff);
}
}
break;
}
// Perform filtering
int filterType = param.filterRow(currRow, prevRow,
filteredRows,
bytesPerRow, bpp);
os.write(filterType);
os.write(filteredRows[filterType], bpp, bytesPerRow);
// Swap current and previous rows
byte[] swap = currRow;
currRow = prevRow;
prevRow = swap;
}
}