Skip to content

Instantly share code, notes, and snippets.

@simon04
Last active March 27, 2018 14:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simon04/a663647b9649193c82c1929c30ddbecc to your computer and use it in GitHub Desktop.
Save simon04/a663647b9649193c82c1929c30ddbecc to your computer and use it in GitHub Desktop.
PngjWriter

Java's ImageIO PNGImageWriter is slow in Java <9 (see also JDK-6488522). This snipped uses PNGJ to encode a BufferedImage. Requires Java 8 for the Stream API.

import ar.com.hjg.pngj.FilterType;
import ar.com.hjg.pngj.ImageInfo;
import ar.com.hjg.pngj.ImageLineByte;
import ar.com.hjg.pngj.PngWriter;
import ar.com.hjg.pngj.PngjException;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.SinglePixelPackedSampleModel;
import java.io.OutputStream;
/**
* Writes {@link BufferedImage} using PNGJ {@link PngWriter}.
*/
class PngjWriter {
private PngjWriter() {
}
/**
* Writes the image {@code bi} to {@code os} using PNGJ {@link PngWriter}.
* @param bi the image to write
* @param os the stream to write to
*/
static void writeARGB(BufferedImage bi, OutputStream os) {
if (bi.getType() != BufferedImage.TYPE_INT_ARGB) {
throw new PngjException("This method expects BufferedImage.TYPE_INT_ARGB");
}
writeARGB(bi.getRaster(), os);
}
private static void writeARGB(Raster raster, OutputStream os) {
final SinglePixelPackedSampleModel sampleModel = (SinglePixelPackedSampleModel) raster.getSampleModel();
final DataBuffer dataBuffer = raster.getDataBuffer();
if (dataBuffer.getNumBanks() != 1) {
throw new PngjException("This method expects one bank");
}
final ImageInfo info = new ImageInfo(raster.getWidth(), raster.getHeight(), 8, true);
final PngWriter writer = new PngWriter(os, info);
writer.setCompLevel(5);
writer.setFilterType(FilterType.FILTER_ADAPTIVE_FAST);
for (int row = 0; row < info.rows; row++) {
final byte[] bytes = new byte[4 * info.cols];
int i = 0;
for (int col = 0; col < info.cols; col++) {
final int sample = dataBuffer.getElem(sampleModel.getOffset(col, row));
bytes[i++] = (byte) ((sample & 0xFF0000) >> 16); //R
bytes[i++] = (byte) ((sample & 0xFF00) >> 8); //G
bytes[i++] = (byte) (sample & 0xFF); //B
bytes[i++] = (byte) ((sample & 0xFF000000) >> 24); //A
}
writer.writeRow(new ImageLineByte(info, bytes), row);
}
writer.end();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment