Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compression of PNG using JAI (Java Advanced Imaging)

I am using javax.imageio API and JAI for compressing different types of images. It works fine for JPEG using JPEGImageWriter and GIF using GIFImageWriter. But it is not supporting for PNG compression using PNGImageWriter which throws an exception like compression type is not set or "No valid compression", etc. So I used this below ImageWriter for PNG. It works but image quality is too bad.

Can anyone suggest how to use PNGImageWriter for PNG compression and which JAR contains it?

File input = new File("test.png");

InputStream is = new FileInputStream(input);
BufferedImage image = ImageIO.read(is);

File compressedImageFile = new File(input.getName());

OutputStream os =new FileOutputStream(compressedImageFile);

Iterator<ImageWriter>writers = 
        ImageIO.getImageWritersByFormatName("jpg"); // here "png" does not work
ImageWriter writer = (ImageWriter) writers.next();

ImageOutputStream ios = ImageIO.createImageOutputStream(os);
writer.setOutput(ios);

ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.5f);

writer.write(null, new IIOImage(image, null, null), param);
like image 942
Gnaniyar Zubair Avatar asked Jul 02 '14 18:07

Gnaniyar Zubair


People also ask

What compression is used in PNG?

PNG uses DEFLATE, a non-patented lossless data compression algorithm involving a combination of LZ77 and Huffman coding.

Does image compression reduce quality PNG?

In contrast, PNG files benefit from lossless compression. This means no data is lost when the image is compressed — the quality stays the same no matter how many times you edit and save the file.

What is Jai codec?

Overview. An important adjunct to the Java Advanced Imaging (JAI) API is a set of image encoder/decoder (codec) classes, which have been packaged with JAI since the release of JAI 1.0. The encoders and decoders for several popular image storage formats have been implemented.


1 Answers

It seems the default com.sun.imageio.plugins.png.PNGImageWriter that is bundled with the JRE does not support setting compression. This is kind of surprising, as the format obviously supports compression. However, the PNGImageWriter always writes compressed.

You can see from the source code that it uses:

Deflater def = new Deflater(Deflater.BEST_COMPRESSION);

Which will give you good, but slow compression. It might be good enough for you, but for some cases it might be better to use faster compression and larger files.

To fix your code, so that it would work with any format name, change the lines:

ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.5f);

to:

ImageWriteParam param = writer.getDefaultWriteParam();

if (param.canWriteCompressed()) { 
    // NOTE: Any method named [set|get]Compression.* throws UnsupportedOperationException if false
    param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
    param.setCompressionQuality(0.5f);
}

It will still write compressed PNGs.

If you need more control over the PNG compression, like setting compression or filter used, you need to find an ImageWriter that supports it. As you mention JAI, I think the CLibPNGImageWriter that is part of jai-imageio.jar or jai-imageio-tools.jar supports setting compression. You just need to look through the ImageWriters iterator, to see if you have it installed:

Iterator<ImageWriter>writers = ImageIO.getImageWritersByFormatName("png");
ImageWriter writer = null;

while (writers.hasNext()) {
    ImageWriter candidate = writers.next();

    if (candidate.getClass().getSimpleName().equals("CLibPNGImageWriter")) {
        writer = candidate; // This is the one we want
        break;
    }
    else if (writer == null) {
        writer = candidate; // Any writer is better than no writer ;-)
    }
}

With the correct ImageWriter, your code should work as expected.

like image 195
Harald K Avatar answered Sep 20 '22 05:09

Harald K