TL;DR
Java’s built-in ImageIO often falls short with modern formats like AVIF, HEIC, and WebP and lacks the reliability needed for production-grade TIFF handling. This post explores four key solutions:
- Sticking with the ImageIO basics
- Extending it with a plugin such as TwelveMonkeys
- Utilizing an Open Source alternative such as Apache Commons Imaging
- Upgrading to a commercial alternative such as JDeli for full modern format support and performance
Why do Images cause problems for Java Developers?
Images cause problems for Java developers because many common image formats are not fully supported by Java’s built-in ImageIO library. Support for some formats (such as TIFF) has actually deteriorated since Java 8. Modern formats like HEIC, AVIF and WebP are not supported at all.
In addition, many third-party alternatives are just Java wrappers around non-Java code, which introduces memory and security issues. Others require extensive code changes to adopt.
What options are there for supporting Image files in Java?
There are four main options for reading and writing images in Java:
- Built-in support – ImageIO is built into Java and part of core version
- Plugins – Software (such as TwelveMonkeys) which extends ImageIO with additional format support, generally requiring no code changes
- Open Source libraries – Apache Commons Imaging is an example of an open source standalone library with strong metadata handling.
- Commercial libraries – JDeli is a commercial library which can replace ImageIO and add support for AVIF, HEIC and WebP.
Some libraries (such as JDeli) can function as either a plugin or a complete replacement for ImageIO.
In this post we cover all options, with code examples and an honest comparison to help you choose the right one.
How Java handles images: BufferedImage
Java represents all images as a single object type: BufferedImage. Regardless of the original format — JPEG, PNG, TIFF, WebP — once an image is read into memory, you work with it as a BufferedImage. All the complexity of different image formats is hidden; you get direct access to pixels, colour information, and built-in transformations.
The key requirement becomes how to read and write them into Java BufferedImage objects. Sometimes you may also want to convert them between image file formats directly.
Option 1: ImageIO (built into Java)
ImageIO is Java’s built-in image framework, available since Java 1.4. No dependencies required.
How to read an image with ImageIO
- Create a File handle, InputStream or URL pointing to the raw image.
- Call
ImageIO.read()to read it into a BufferedImage.
File file = new File("/path/to/image.png");
BufferedImage image = ImageIO.read(file);
How to write an image with ImageIO
- Create a File or OutputStream object.
- Pass the image, format string and File into the write method.
File file = new File("/path/to/output.png");
ImageIO.write(bufferedImage, "PNG", file);
What ImageIO supports out of the box
BMP, GIF, JPEG, PNG, TIFF.
Where ImageIO falls short
- No support for AVIF, HEIC or JPEG 2000 or WebP
- TIFF support has deteriorated since Java 8 — complex variants frequently fail
ImageIO.read()returnsnullfor unsupported formats rather than throwing an exception, which causes NullPointerExceptions downstream- Poor memory efficiency on large images
- No resilience on malformed or corrupt files
- Lack of control when writing out images
Verdict: Fine for JPEG and PNG in controlled environments. Not suitable for production systems handling varied or user-supplied image formats.
Option 2: TwelveMonkeys (Open Source ImageIO plugin)
TwelveMonkeys is an open source library that extends ImageIO by registering additional format support as plugins. Its key advantage: you do not need to change your existing ImageIO code. Add the dependency and ImageIO automatically gains the new format support.
Adding TwelveMonkeys (Maven)
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>3.10.1</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.10.1</version>
</dependency>
Reading and writing with TwelveMonkeys
No code changes needed — TwelveMonkeys registers itself automatically on the classpath.
// Identical to standard ImageIO code
File file = new File("/path/to/image.tiff");
BufferedImage image = ImageIO.read(file);
What TwelveMonkeys adds
TIFF (significantly improved over Java’s native support), JPEG 2000, PSD, HDR, ICNS, PCX, TGA, and more.
TwelveMonkeys limitations
- Still bound by ImageIO’s underlying architecture and its failure modes
- No WebP write, HEIC or AVIF support
- Community-supported only — no commercial SLA
Verdict: The best zero-effort upgrade for existing ImageIO codebases. Excellent if your format requirements fall within its coverage. Not a solution for HEIC, AVIF or WebP write.
Option 3: Apache Commons Imaging (Open Source standalone library)
Apache Commons Imaging is a standalone pure-Java image library — not an ImageIO plugin. It does not depend on the ImageIO architecture at all, which gives it independence but means you cannot use it as a drop-in replacement for existing ImageIO code.
Adding Apache Commons Imaging (Maven)
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-imaging</artifactId>
<version>1.0.0-alpha5</version>
</dependency>
How to read an image with Apache Commons Imaging
File file = new File("/path/to/image.tiff");
BufferedImage image = Imaging.getBufferedImage(file);
How to write an image with Apache Commons Imaging
File outputFile = new File("/path/to/output.png");
Imaging.writeImage(bufferedImage, outputFile, ImageFormats.PNG);
Apache Commons Imaging strengths
- Strong metadata handling — EXIF, IPTC, XMP
- Good colour space support and format detection
- Pure Java — no JNI, no native dependencies, no security issues from wrapped C/C++ code
Apache Commons Imaging limitations
- Slow development cadence — long gaps between releases
- No WebP, HEIC or AVIF support
- Generally slower performance than commercial alternatives on large images
- Not a drop-in for existing ImageIO code — requires API changes
Verdict: A solid open source choice when metadata handling matters or you want independence from the ImageIO architecture. Not the answer for modern image formats.
Option 4: JDeli (Commercial)
We created JDeli to be a pure, complete Java implementation with no known security issues. It can be used as an ImageIO plugin — so existing code keeps working — and also has its own API for more control. It supports modern formats including AVIF, HEIC and WebP.
Adding JDeli (Maven)
- Add JDeli to your class or module path. (Download the trial jar.)
- Install jar into your local maven repository
- Then add JDeli as a dependency to your pom file
mvn install:install-file -Dfile= -DgroupId=com.idrsolutions -Dpackaging=jar -DartifactId=jdeli -Dversion=1.0
<dependency>
<groupId>com.idrsolutions</groupId>
<artifactId>jdeli</artifactId>
<version>1.0</version>
</dependency>
How to read an image with JDeli
- Add JDeli to your class or module path. (Download the trial jar.)
- Create a File or InputStream pointing to the raw image. You can also use a
byte[]containing the image data. - Read the image into a BufferedImage.
File file = new File("/path/to/image.heic");
BufferedImage image = JDeli.read(file);
How to write an image with JDeli
- Add JDeli to your class or module path. (Download the trial jar.)
- Create a File or OutputStream object.
- Pass the image, format and File into the write method.
File file = new File("/path/to/output.webp");
JDeli.write(bufferedImage, "webp", file);
// Type-safe version
JDeli.write(bufferedImage, OutputFormat.WEBP, file);
// Pass in encoder options for full control over output
WebpEncoderOptions options = new WebpEncoderOptions();
options.setQuality(90);
JDeli.write(bufferedImage, options, file);
Using JDeli as an ImageIO plugin
Add JDeli to your classpath and existing ImageIO code automatically gains JDeli’s extended format support — no changes required.
// Standard ImageIO call — now reads HEIC, AVIF, WebP etc with JDeli on the classpath
BufferedImage image = ImageIO.read(new File("/path/to/image.avif"));
JDeli format support
AVIF, HEIC, WebP, JPEG 2000, TIFF (including complex variants), JPEG, PNG, BMP, GIF, DICOM and more. See the full format list.
JDeli limitations
- Commercial licence required — pricing here
- Cost may not be justified for simple use cases that ImageIO handles adequately
Verdict: The most capable option for production systems handling varied, modern or user-supplied image formats. The commercial cost is the only meaningful trade-off.
Java image library comparison
| ImageIO | TwelveMonkeys | Apache Commons Imaging | JDeli | |
|---|---|---|---|---|
| Cost | Free | Free | Free | Commercial |
| Format breadth | ★★ | ★★★★ | ★★★ | ★★★★★ |
| WebP write | ❌ | ❌ | ❌ | ✅ |
| HEIC support | ❌ | ❌ | ❌ | ✅ |
| AVIF support | ❌ | ❌ | ❌ | ✅ |
| Drop-in for ImageIO | — | ✅ | ❌ | ✅ |
| Performance | ★★★ | ★★★ | ★★ | ★★★★★ |
| Error resilience | ★★ | ★★★ | ★★★ | ★★★★★ |
| Pure Java | ✅ | ✅ | ✅ | ✅ |
| Commercial support | ❌ | ❌ | ❌ | ✅ |
Which Java image library should you use?
- Use ImageIO if you are working exclusively with JPEG and PNG in a controlled environment with no plans to extend format support.
- Use TwelveMonkeys if you have existing ImageIO code and need to add TIFF or extended format support with minimal changes. Lowest-friction open source upgrade.
- Use Apache Commons Imaging if you need strong metadata handling (EXIF, IPTC) and want independence from the ImageIO architecture.
- Use JDeli if you are building a production system that needs to handle modern formats (HEIC, AVIF, WebP), complex TIFF variants, or user-supplied images of unknown provenance — or if performance on large images matters.
Other useful image links
- JDeli documentation and tutorials
- Speed comparisons of Java image libraries: ImageIO, JAI and JDeli
- Replacing ImageIO with the JDeli image library
- Image conversion in Java
- Working with images in Java
As experienced Java developers, we help you work with images in Java and bring over a decade of hands-on experience with many image file formats.
Are you a Java Developer working with Image files?
// Read an image
BufferedImage bufferedImage = JDeli.read(avifImageFile);
// Write an image
JDeli.write(bufferedImage, "avif", outputStreamOrFile);// Read an image
BufferedImage bufferedImage = JDeli.read(dicomImageFile);// Read an image
BufferedImage bufferedImage = JDeli.read(heicImageFile);
// Write an image
JDeli.write(bufferedImage, "heic", outputStreamOrFile);// Read an image
BufferedImage bufferedImage = JDeli.read(jpegImageFile);
// Write an image
JDeli.write(bufferedImage, "jpeg", outputStreamOrFile);
// Read an image
BufferedImage bufferedImage = JDeli.read(jpeg2000ImageFile);
// Write an image
JDeli.write(bufferedImage, "jpx", outputStreamOrFile);
// Write an image
JDeli.write(bufferedImage, "pdf", outputStreamOrFile);
// Read an image
BufferedImage bufferedImage = JDeli.read(pngImageFile);
// Write an image
JDeli.write(bufferedImage, "png", outputStreamOrFile);
// Read an image
BufferedImage bufferedImage = JDeli.read(tiffImageFile);
// Write an image
JDeli.write(bufferedImage, "tiff", outputStreamOrFile);
// Read an image
BufferedImage bufferedImage = JDeli.read(webpImageFile);
// Write an image
JDeli.write(bufferedImage, "webp", outputStreamOrFile);
What is JDeli?
JDeli is a commercial Java Image library that is used to read, write, convert, manipulate and process many different image formats.
Why use JDeli?
To handle many well known formats such as JPEG, PNG, TIFF as well as newer formats like AVIF, HEIC and JPEG XL in java with no calls to any external system or third party library.
What licenses are available?
We have 3 licenses available:
Server for on premises and cloud servers, Distribution for use in a named end user applications, and Custom for more demanding requirements.
How does JDeli compare?
We work hard to make sure JDeli performance is better than or similar to other java image libraries. Check out our benchmarks to see just how well JDeli performs.


What if my images were JPG?
Works the same. Java will still read. We have articles on https://blog.idrsolutions.com/2017/02/how-to-read-jpeg-images-in-java/ and https://blog.idrsolutions.com/2015/04/how-to-write-jpeg-images-in-java/
Can we adjust angle of image with this library?
Yes. Have a look at https://www.idrsolutions.com/docs/jdeli/tutorials/image-processing/rotate-an-image
Can we mask certain fields from the image?
You can process the image in lots of ways. We provide lots of processing options or you can write your own in Java. I am not clear what you mean by fields – this is an image. Can you explain further?