All formats

ImageIO

LanguageJava (part of the JDK, java.desktop module)
LicenseGPL v2 with Classpath Exception (OpenJDK)
Repositorygithub.com/openjdk/jdk
Documentationjavax.imageio API, BMP metadata format
Depends onnothing (built into the JDK)
Read / writeyes, 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#

Java
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:

Java
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#

Java
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:

Java
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#

Java
BufferedImage image = ImageIO.read(new File("in.bmp"));
ImageIO.write(image, "png", new File("out.png"));

Tips#