A common complaint from Java developers when using ImageIO in Java is that it is both slow to write out images, and that the images it produces are not well optimised and have large file sizes.
In a previous article I wrote about how to reduce image file size and recommend using PNGQuant, but how can you improve the speed at which images get written out?
One simple thing you can do if you are not already is to use a BufferedOutputStream, though the improvement is mostly negligible.
Another possibility is to write out JPEG files rather than PNG files which is faster in Java, but as JPEG does not support transparency, this becomes a bug if your images contain colors with alpha.
You could use a third party library such as PngEncoder by ObjectPlanet, which claims to be 5 times faster for a standard truecolour image and almost 7 times faster for a truecolour image with alpha (though I did not see improvements quite that large when experimenting).
Finally, a technique that I would recommend is to write images out on a separate thread, though this may not fit your use case. The key here is that ImageIO.write() is largely bound by IO and as such, whilst writing out images, your CPU is spending most of the time simply waiting for the disk to write the image out. This is time that your CPU could spend doing other tasks, such as generating the next image that needs to be written out. In our PDF to HTML5 converter we have exactly this scenario, where rather than waiting for the image to be written out we could spend that time decoding and converting the rest of the PDF file. This is a technique we have been using since our September 2014 release.
A problem with this solution is that ImageIO is not thread safe, which is why I recommend using an ExecutorService with a single thread. In order for your application to end successfully, you will need to wait for any images to finish being output.
If you have any suggestions for how to improve the performance of ImageIO.write(), please feel free to share it in the comments.
In the end we gave up with trying to patch ImageIO and wrote our own ImageIO replacement from scratch. Lots of other developers seemed to have the problems so we made this commercially available as the JDeli Image library. You can find out more on the JDeli page.