Bethan Palmer Bethan is a Java developer and a Java Champion. She has spoken at conferences including JavaOne/Code One, DevFest and NetBeans days. She has a degree in English Literature.

How to read and write images in Java (Tutorial)

5 min read

image formats java

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

 
image formats java
 

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 to read and write images in Java

 

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

  1. Create a File handle, InputStream or URL pointing to the raw image.
  2. 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

  1. Create a File or OutputStream object.
  2. 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() returns null for 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)

  1. Add JDeli to your class or module path. (Download the trial jar.)
  2. Install jar into your local maven repository
  3. mvn install:install-file -Dfile= -DgroupId=com.idrsolutions -Dpackaging=jar -DartifactId=jdeli -Dversion=1.0
  4. Then add JDeli as a dependency to your pom file
  5. <dependency>
    <groupId>com.idrsolutions</groupId>
    <artifactId>jdeli</artifactId>
    <version>1.0</version>
    </dependency>

 

How to read an image with JDeli

  1. Add JDeli to your class or module path. (Download the trial jar.)
  2. Create a File or InputStream pointing to the raw image. You can also use a byte[] containing the image data.
  3. Read the image into a BufferedImage.


 

How to write an image with JDeli

  1. Add JDeli to your class or module path. (Download the trial jar.)
  2. Create a File or OutputStream object.
  3. Pass the image, format and File into the write method.


 

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.


 

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

ImageIOTwelveMonkeysApache Commons ImagingJDeli
CostFreeFreeFreeCommercial
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

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?

Bethan Palmer Bethan is a Java developer and a Java Champion. She has spoken at conferences including JavaOne/Code One, DevFest and NetBeans days. She has a degree in English Literature.

6 Replies to “How to read and write images in Java (Tutorial)”

    1. 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?

Comments are closed.