Saving a BufferedImage as a PNG, JPEG etc
Having created a BufferedImage to represent
a graphic image in Java and set pixels on that image
as appropriate, a common next step is to want to save that image to disk in a common
image format such as JPEG, PNG etc.
Saving a BufferedImage as a PNG
You can easily save a BufferedImage in one of these formats thanks to
the static utility method ImageIO.write(). To save a BufferedImage
as a PNG file, the following will suffice:
BufferedImage img = ...
File f = new File("MyFile.png");
ImageIO.write(img, "PNG", f);
Saving a BufferedImage as a JPEG
The procedure for writing an image file as a JPEG is similar:
BufferedImage img = ...
File f = new File("MyFile.jpg");
ImageIO.write(img, "JPEG", f);
(You can also specify "JPG" instead of "JPEG".)
Which format should I use: PNG or JPEG?
In general, the choice depends on (a) whether you need your image to include
transparency information, and (b) whether or not it matters if pixels in the saved
image differ slightly from the original in order to give greater compression.
- JPEG is a format primarily designed for photographs and similar
images, where preservation of the precise details of sharp outlines is not crucial.
It is a so-called lossy compression algorithm: small detail, usually imperceptible
for the purposes of viewing a photograph, is lost, but with the benefit of smaller
image files. JPEG does not support transparency, so if your BufferedImage
includes transparency, this information will be lost when you save it to a JPEG file.
- The PNG format is a lossless format: precise details of each
individual pixel will be retained, at the expense of a larger file. (The file is still
compressed, however.) It also supports transparency. The PNG format is
more suited to cases where either (a) transparency is needed, or (b) you are dealing
with an image that isn't a 'normal photograph' and where precise details of outlines
of shapes need to be retained. For example, it is well suited to cartoon or
technical drawings, scanned text etc.
Saving a BufferedImage in other formats
A couple of other formats are supported by the JDK as standard. You can
save a BufferedImage as a GIF by specifying "GIF" as the format name to
ImageIO.write(). Note that this will create a 256-colour indexed image.
In other words, if your image contains more than 256 individual colours, then
its quality will be degraded as each colour other than the 256 most common will be
mapped to its closest neighbour of the most common 256.
Due to this limitation, along with the fact that PNG offers a patent-free alternative
to GIF, it is recommended only to use the GIF format when you have no alternative.
The BMP and WBMP formats are also supported as standard. The BMP format is
lossless but typically results in larger files than other formats.
Error handling
As you might expect, ImageIO.write() will
throw an
IOException should an I/O error occur while writing the image. A quirk of this method,
however, is that there are some types of error that do not actually throw an exception.
This can occur if:
- you request an unsupported image file type;
- the plugin that deals with saving in the particular file type in question
encounters some internal error.
In these latter cases, ImageIO.write() may instead return a value of false
(instead of the usual value of true which it is common to ignore) to indicate failure.
So if you are being ultra-careful, it is safer to do the following "just in case":
BufferedImage img = ...
File f = new File("MyFile.jpg");
if (!ImageIO.write(img, "JPEG", f)) {
throw new RuntimeException("Unexpected error writing image");
}
This won't solve the underlying problem, but it will prevent your program 'failing silently'
at some point in the future and wasting your time with a lot of head-scratching trying to
figure out what went wrong.