All formats

TwelveMonkeys ImageIO

LanguageJava 8 or later
LicenseBSD 3-Clause
Repositorygithub.com/haraldk/TwelveMonkeys
DocumentationBMP plugin wiki, README
Depends onTwelveMonkeys imageio-core and common-* modules (pulled in by Maven)
Read / writeyes, all known Windows and OS/2 versions, RLE4, RLE8, embedded PNG and JPEG / yes, 32-bit with alpha from TYPE_4BYTE_ABGR images

TwelveMonkeys is a collection of plugins for javax.imageio. Once the jar is on the classpath, the standard ImageIO.read call uses it, so existing code gets better format support without changes. Its imageio-bmp module reads every BMP variant, including the ones the JDK reader rejects, and adds ICO (icons) and CUR (cursors), which store images as BMP data.

Use it when you process BMP files from many sources (scanners, old software, icon extraction). Its BMP writer is limited: it only accepts 4-byte ABGR images and writes them as 32-bit; other image types still go to the JDK writer. The project also has plugins for JPEG (CMYK), TIFF, WebP, PSD, PICT, SGI and more.

Installation#

Maven:

XML
<dependency>
    <groupId>com.twelvemonkeys.imageio</groupId>
    <artifactId>imageio-bmp</artifactId>
    <version>3.15.3</version>
</dependency>

Gradle:

implementation 'com.twelvemonkeys.imageio:imageio-bmp:3.15.3'

In web applications, also register com.twelvemonkeys.servlet.image.IIOProviderContextListener (artifact com.twelvemonkeys.servlet:servlet) so plugins load and unload with the application.

Basic usage: read a BMP#

Nothing changes in your code; ImageIO finds the plugin through the service loader:

Java
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class ReadBmp {
    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()
                + ", alpha: " + image.getColorModel().hasAlpha());
        ImageIO.write(image, "png", new File("out.png"));
    }
}

How to check that the TwelveMonkeys reader is used#

Java
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import java.util.Iterator;

Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("bmp");
while (readers.hasNext()) {
    System.out.println(readers.next().getClass().getName());
    // com.twelvemonkeys.imageio.plugins.bmp.BMPImageReader comes first
}

How to write a 32-bit BMP with alpha#

The JDK writer refuses images with alpha. TwelveMonkeys writes TYPE_4BYTE_ABGR images as 32-bit BMP:

Java
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;

BufferedImage src = ImageIO.read(new File("in.png"));
BufferedImage abgr = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
abgr.getGraphics().drawImage(src, 0, 0, null);
if (!ImageIO.write(abgr, "bmp", new File("alpha.bmp"))) {
    throw new IllegalStateException("no BMP writer");
}

How to read all images from an ICO file#

An ICO file holds the same icon in several sizes. ImageIO.read returns only the first; use an ImageReader to get all of them:

Java
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.image.BufferedImage;
import java.io.File;

try (ImageInputStream in = ImageIO.createImageInputStream(new File("app.ico"))) {
    ImageReader reader = ImageIO.getImageReadersByFormatName("ico").next();
    reader.setInput(in);
    int count = reader.getNumImages(true);
    for (int i = 0; i < count; i++) {
        BufferedImage icon = reader.read(i);
        System.out.println(icon.getWidth() + " x " + icon.getHeight());
    }
    reader.dispose();
}

Tips#