All formats

TwelveMonkeys ImageIO

LanguageJava 8 or later
LicenseBSD-3-Clause
Repositorygithub.com/haraldk/TwelveMonkeys
DocumentationJPEG plugin wiki, README
Depends onTwelveMonkeys common and imageio-core/metadata modules (pulled in by Maven)
Read / writeyes / yes; JFIF, Exif, CMYK, YCCK, lossless JPEG (read), JFIF/JFXX/Exif thumbnails

TwelveMonkeys is a collection of plugins for javax.imageio. Its JPEG plugin registers itself ahead of the JDK’s reader, so existing ImageIO.read(file) calls start working on files the JDK rejects:

It also reads JFIF, JFXX and Exif thumbnails and can write CMYK JPEGs. For encoding ordinary RGB images it delegates to the JDK writer. It doesn’t apply the Exif orientation; read the tag with metadata-extractor. The project also has plugins for TIFF, PSD, WebP (read), BMP, ICO, PICT, SVG and others.

Installation#

Maven:

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

Gradle:

implementation("com.twelvemonkeys.imageio:imageio-jpeg:3.15.3")

Basic usage: read any JPEG with ImageIO#

No code changes: with the JAR on the classpath, the standard API uses the plugin.

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

public class ReadCmyk {
    public static void main(String[] args) throws IOException {
        // works for CMYK / YCCK files that throw "Unsupported Image Type" with the plain JDK
        BufferedImage image = ImageIO.read(new File("cmyk.jpg"));
        System.out.println(image.getWidth() + " x " + image.getHeight() + ", type " + image.getType());
        ImageIO.write(image, "jpg", new File("rgb.jpg"));
    }
}

How to check that the TwelveMonkeys JPEG reader is used#

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

Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JPEG");
while (readers.hasNext()) {
    System.out.println(readers.next().getClass().getName());
}
// first line: com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader

How to read the embedded thumbnail of a JPEG#

Exif and JFIF thumbnails load without decoding the full image, which is fast for photo browsers:

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("photo.jpg"))) {
    ImageReader reader = ImageIO.getImageReaders(in).next();
    try {
        reader.setInput(in);
        if (reader.getNumThumbnails(0) > 0) {
            BufferedImage thumb = reader.readThumbnail(0, 0);
            ImageIO.write(thumb, "jpg", new File("thumb.jpg"));
        }
    } finally {
        reader.dispose();
    }
}

How to use TwelveMonkeys in a web application#

ImageIO’s plugin registry is global to the JVM and doesn’t see JARs in WEB-INF/lib reliably. Add the servlet module and its context listener, which loads plugins on startup and unloads them on redeploy:

XML
<dependency>
    <groupId>com.twelvemonkeys.servlet</groupId>
    <artifactId>servlet</artifactId>
    <version>3.15.3</version>
    <classifier>jakarta</classifier>  <!-- omit for javax.servlet -->
</dependency>
XML
<listener>
    <listener-class>com.twelvemonkeys.servlet.image.IIOProviderContextListener</listener-class>
</listener>

In Spring Boot and other fat-JAR applications the plugins are found without the listener.

Tips#