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.
Last active
March 27, 2018 14:28
-
-
Save simon04/a663647b9649193c82c1929c30ddbecc to your computer and use it in GitHub Desktop.
PngjWriter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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