PngSurface.java
package io.brunoborges.jairosvg.surface;
import java.io.IOException;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.MemoryCacheImageOutputStream;
/**
* PNG output surface.
*/
public final class PngSurface extends Surface {
private static final ImageWriter PNG_WRITER;
static {
var writers = ImageIO.getImageWritersByFormatName("PNG");
if (!writers.hasNext()) {
throw new ExceptionInInitializerError("No PNG ImageWriter found");
}
PNG_WRITER = writers.next();
}
private int compressionLevel = 6; // Match CairoSVG/libpng default (Z_DEFAULT_COMPRESSION)
/**
* Set PNG compression level (0-9). 0 = no compression (fastest), 9 = max
* compression (smallest). Default is 6, matching CairoSVG/libpng.
*/
public void setCompressionLevel(int level) {
if (level < 0 || level > 9) {
throw new IllegalArgumentException("PNG compression level must be 0-9, got: " + level);
}
this.compressionLevel = level;
}
/**
* Write a BufferedImage as PNG to the given ImageOutputStream.
*/
static void writePng(java.awt.image.BufferedImage img, javax.imageio.stream.ImageOutputStream ios)
throws IOException {
writePng(img, ios, -1);
}
static void writePng(java.awt.image.BufferedImage img, javax.imageio.stream.ImageOutputStream ios,
int compressionLevel) throws IOException {
synchronized (PNG_WRITER) {
try {
PNG_WRITER.setOutput(ios);
ImageWriteParam param = null;
if (compressionLevel >= 0) {
param = PNG_WRITER.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
// PNG plugin maps quality 0.0 = max compression, 1.0 = no compression
param.setCompressionQuality(1.0f - (compressionLevel / 9.0f));
}
PNG_WRITER.write(null, new IIOImage(img, null, null), param);
} finally {
PNG_WRITER.reset();
}
}
}
@Override
public void finish() throws IOException {
super.finish();
if (output != null && image != null) {
try (var ios = new MemoryCacheImageOutputStream(output)) {
writePng(image, ios, compressionLevel);
}
}
}
}