ImageIO
| Language | Java (part of the JDK, java.desktop module) |
|---|---|
| License | GPL v2 with Classpath Exception (OpenJDK) |
| Repository | github.com/openjdk/jdk |
| Documentation | javax.imageio API, BMP metadata format |
| Depends on | nothing (built into the JDK) |
| Read / write | yes, 1-32 bit, RLE4, RLE8, bit fields / yes, 1-24 bit, RLE4, RLE8, bit fields; no alpha |
ImageIO is the image I/O API of the Java standard library. Its BMP plugin reads palette, 16, 24 and 32-bit BMP files, including RLE compression, OS/2 headers and V4/V5 headers, and writes uncompressed, RLE and bit field files. ImageIO.read returns a BufferedImage you can draw on with Graphics2D.
The BMP writer only accepts images with 1 or 3 bands: an image with alpha (TYPE_INT_ARGB, typical after reading a PNG) makes ImageIO.write return false without an exception. Convert to RGB first, as shown below. For a few more variants and ICO/CUR files, add the TwelveMonkeys plugin.
Installation#
Nothing to install: javax.imageio is in every JDK. In a modular project add requires java.desktop; to module-info.java.
Basic usage: read and write a BMP#
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class BmpExample {
public static void main(String[] args) throws IOException {
BufferedImage image = ImageIO.read(new File("in.bmp"));
if (image == null) {
throw new IOException("not a supported image");
}
System.out.println(image.getWidth() + " x " + image.getHeight()
+ ", " + image.getColorModel().getPixelSize() + " bits per pixel");
image.setRGB(0, 0, 0xFF0000); // top-left pixel red
if (!ImageIO.write(image, "bmp", new File("out.bmp"))) {
throw new IOException("no BMP writer for this image type");
}
}
}
How to save a PNG with transparency as BMP#
ImageIO.write(image, "bmp", file) returns false for images with alpha. Draw onto a TYPE_INT_RGB image first:
import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
BufferedImage src = ImageIO.read(new File("in.png"));
BufferedImage rgb = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = rgb.createGraphics();
g.setColor(Color.WHITE); // background for transparent pixels
g.fillRect(0, 0, rgb.getWidth(), rgb.getHeight());
g.drawImage(src, 0, 0, null);
g.dispose();
ImageIO.write(rgb, "bmp", new File("out.bmp"));
How to get BMP width and height without decoding#
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.io.File;
try (ImageInputStream in = ImageIO.createImageInputStream(new File("in.bmp"))) {
ImageReader reader = ImageIO.getImageReadersByFormatName("bmp").next();
try {
reader.setInput(in);
System.out.println(reader.getWidth(0) + " x " + reader.getHeight(0));
} finally {
reader.dispose();
}
}
How to write an RLE-compressed BMP#
RLE8 works with 8-bit palette images (TYPE_BYTE_INDEXED), RLE4 with 4-bit ones:
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.File;
BufferedImage indexed = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED);
indexed.getGraphics().drawImage(src, 0, 0, null);
ImageWriter writer = ImageIO.getImageWritersByFormatName("bmp").next();
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionType("BI_RLE8"); // BI_RGB, BI_RLE8, BI_RLE4, BI_BITFIELDS
try (ImageOutputStream out = ImageIO.createImageOutputStream(new File("rle.bmp"))) {
writer.setOutput(out);
writer.write(null, new IIOImage(indexed, null, null), param);
} finally {
writer.dispose();
}
How to convert BMP to PNG#
BufferedImage image = ImageIO.read(new File("in.bmp"));
ImageIO.write(image, "png", new File("out.png"));
Tips#
ImageIO.readreturnsnull(not an exception) when no reader recognizes the file.TYPE_BYTE_BINARYimages are written as 1-bit BMP andTYPE_BYTE_INDEXEDimages as 8-bit palette BMP.ImageIO.getWriterFormatNames()lists the formats your JDK can write.