Java PNG Library — Read, Write & Convert PNG Files

Read, write, convert, and process PNG images in pure Java. No native code. Drop-in ImageIO replacement. Commercial license with dedicated support.

JDeli is a commercial, pure-Java image library that reads, writes, and converts PNG files with no native code or third-party dependencies. It works as a drop-in ImageIO replacement. Add one JAR, get better PNG handling in your existing code.

Quick Start

Get running in 30 seconds. Add the dependency, write one line, convert any PNG.

// Add IDR Solutions repository to your pom.xml
<repositories>
   <repository>
       <id>IDRsolutions</id>
       <name>IDR Solutions</name>
       <url>https://maven.idrsolutions.com</url>
   </repository>
</repositories>

// Add JDeli as a dependency
<dependencies>
    <dependency>
        <groupId>com.idrsolutions</groupId>
        <artifactId>jdeli</artifactId>
        <version>{YYYY.MM}</version>
    </dependency>
</dependencies>
// Add IDR Solutions repository to your build.gradle
repositories {
    maven {
        url = "https://maven.idrsolutions.com"
        name = "IDRsolutions"
        credentials(PasswordCredentials)
    }
}

// Add JDeli as a dependency
dependencies {
    implementation "com.idrsolutions:jdeli:{version}"
}

PNG Code Examples for Java

Copy-paste solutions to the exact problems Java developers search for.

// Read a PNG with alpha into a BufferedImage
BufferedImage image = JDeli.read(pngFile);

// Detect if the image has alpha
boolean hasAlpha = image.getColorModel().hasAlpha();
// Type 2 = TYPE_INT_ARGB when PNG contains transparency
int imageType = image.getType();
// Write a BufferedImage to PNG with compression options
final PngEncoderOptions options = new PngEncoderOptions();

// Choose compression: ZLIB_BETTER_COMPRESSION | ZLIB_BETTER_SPEED | QUANTISED8BIT | NONE
options.setCompressionFormat(PngCompressionFormat.ZLIB_BETTER_COMPRESSION);

JDeli.write(myBufferedImage, options, outputFile);

// Or use QUANTISED8BIT for indexed 8-bit color — much smaller file size
options.setCompressionFormat(PngCompressionFormat.QUANTISED8BIT);

JDeli.write(myBufferedImage, options, outputFile);
// Convert PNG to JPEG with background fill for alpha
BufferedImage png = JDeli.read(pngFile);

// JPEG has no alpha — composite onto a white background
BufferedImage rgb = new BufferedImage(
    png.getWidth(), png.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = rgb.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, rgb.getWidth(), rgb.getHeight());
g.drawImage(png, 0, 0, null);
g.dispose();

JDeli.write(rgb, "jpeg", outputFile);
// Resize a PNG to fit within target dimensions (preserves aspect ratio)
ImageProcessingOperations operations = new ImageProcessingOperations();
operations.resizeToFit(targetWidth, targetHeight);

JDeli.convert(inputFile, outputFile, operations);

// Or generate a thumbnail
ImageProcessingOperations thumbOps = new ImageProcessingOperations();
thumbOps.thumbnail(150, 150);

JDeli.convert(inputFile, outputFile, thumbOps);
// Strip PNG metadata by reading and re-writing
BufferedImage image = JDeli.read(inputFile);

// Write back — produces a clean PNG without the original ancillary chunks
PngEncoderOptions options = new PngEncoderOptions();
JDeli.write(image, options, outputFile);
// Read a 16-bit PNG — JDeli supports 1, 2, 4, 8 and 16-bit per sample
BufferedImage image = JDeli.read(new File("16bit-photo.png"));

// Or use PngDecoder directly
PngDecoder decoder = new PngDecoder();
BufferedImage image = decoder.read(pngData);

Java PNG Library Comparison

An honest comparison. Where alternatives are equal or better, we say so.

Feature JDeli Java ImageIO (JDK) Apache Commons Imaging TwelveMonkeys
PNG Read ✅ Yes ✅ Yes ✅ Yes ⚠️ Defers to JDK
PNG Write ✅ Yes ✅ Yes ✅ Yes ⚠️ Defers to JDK
Cross-format convert ✅ One-line API ⚠️ Manual read/write ⚠️ Manual read/write ⚠️ Manual read/write
Native dependencies ❌ None (pure Java) ⚠️ Uses native memory via JNI ❌ None (pure Java) ❌ None (pure Java)
License Commercial (paid) JDK license (free) Apache 2.0 (free) BSD 3-clause (free)
Max bit depth 1–16 bit 8-bit / 16-bit 8-bit Same as JDK
ICC colour profiles ✅ Read and apply ⚠️ Inconsistent handling ✅ Supported Same as JDK
ImageIO compatible ✅ Drop-in plugin ✅ (it is ImageIO) ❌ Own API ✅ ImageIO plugin
Image processing ✅ Resize, crop, rotate, etc. ❌ Read/write only ❌ Read/write only ⚠️ Resample only
Streaming / large images Heap-based (configurable) Native memory (hard to control) Heap-based Same as JDK
Commercial support ✅ Dedicated team, bug fixes in days ❌ JDK issue tracker ❌ Community only ❌ Community only
Other image formats 15+ (AVIF, HEIC, JPEG XL, WebP…) 5 (JPEG, PNG, BMP, GIF, TIFF) ~15 (no AVIF, HEIC, WebP) ~15 (no AVIF, HEIC)

Key takeaway: ImageIO ships free with the JDK but relies on native code and offers limited control. Apache Commons Imaging is pure Java but slow and unoptimised. TwelveMonkeys deliberately does not add PNG support because the JDK's built-in reader is "good enough as-is" for basic use. JDeli fills the gap when you need a broad-format, high-performance, commercially-supported library with an ImageIO-compatible API.

PNG Benchmarks

Measured with JMH on GitHub. Run them yourself — the code is public and the tests work on the trial version.

Throughput mode, 25 measurement iterations, units in operations per second — higher is better. JDeli, ImageIO, and Apache Commons Imaging compared at equivalent quality settings.

PNG Reading (ops/s)

Library Throughput (ops/s) Error
JDeli 2160.496 ± 43.874
Apache Commons Imaging 1151.556 ± 12.405
Java ImageIO 296.915 ± 12.564

JDeli decodes PNG roughly 7x faster than ImageIO and nearly 2x faster than Apache Commons Imaging.

PNG Writing (ops/s)

Library / Mode Throughput (ops/s) Error
JDeli — fast 13.061 ± 0.026
JDeli — uncompressed 12.985 ± 0.088
JDeli — compressed 5.402 ± 0.027
JDeli — default 5.383 ± 0.033
JDeli — quantised 1.192 ± 0.001
ImageIO — fast 5.597 ± 0.014
ImageIO — default 4.819 ± 0.010
ImageIO — max compression 3.512 ± 0.008
Apache Commons Imaging 5.100 ± 0.018

Writing is more nuanced. JDeli's fast and uncompressed modes are roughly 2.4x faster than ImageIO's default writer. At matched default settings the three libraries sit close together, and ImageIO's fast mode slightly edges JDeli's default. JDeli's quantised mode is the slowest to encode — the tradeoff is a much smaller output file (see below).

Output Size & Quality (166 files)

Library / Mode Total Size Unreadable Output Avg SSIM Similarity
JDeli — default 2.62 MB 0 1.0 Identical or virtually identical
JDeli — compressed 2.62 MB 0 1.0 Identical or virtually identical
JDeli — fast 2.74 MB 0 1.0 Identical or virtually identical
JDeli — uncompressed 2.74 MB 0 1.0 Identical or virtually identical
JDeli — quantised 0.514 MB 0 0.9926 Identical or virtually identical
ImageIO — default 2.64 MB 0 1.0 Identical or virtually identical
ImageIO — fast 2.74 MB 0 1.0 Identical or virtually identical
ImageIO — max compression 2.62 MB 0 1.0 Identical or virtually identical
Apache Commons Imaging 2.61 MB 0 0.9673 Very similar (high quality)

Every library produced readable output for all 166 files. JDeli and ImageIO are pixel-perfect (SSIM 1.0); Apache is marginally lower. The standout is JDeli's quantised mode, which shrinks the set to 0.514 MB — about a fifth of the size of the others — while staying visually near-identical (SSIM 0.9926). That is the mode to reach for when file size matters more than encode speed.

PNG Format Support in Depth

Colour Profiles & Colour Spaces

JDeli reads ICC colour profiles embedded in the iCCP chunk and applies them during decoding. This matters when PNGs are created in colour-managed workflows (Photoshop, Lightroom, medical imaging) — the colours you see in Java match what the author intended. ImageIO's handling of iCCP is inconsistent across JDK versions, often producing colour shifts on Linux that don't appear on Windows.

Gamma Correction

The gAMA chunk specifies the intended display gamma. JDeli accurately reads this value, ensuring brightness and contrast are correct. Many Java libraries ignore the gamma chunk entirely, leading to images that look washed out or too dark depending on the source.

Bit Depths & Colour Types

PNG supports greyscale (1/2/4/8/16-bit), indexed colour (1/2/4/8-bit palette), truecolour (8/16-bit RGB), greyscale+alpha, and truecolour+alpha. JDeli reads all standard bit depths — 1, 2, 4, 8 and 16 bits per sample — plus interlacing and filtering, so 16-bit medical, scientific, and HDR PNGs are handled natively.

Interlacing (Adam7)

PNG supports Adam7 interlacing, which allows progressive rendering. JDeli reads interlaced PNGs correctly. When writing, JDeli produces non-interlaced PNGs (the standard choice for server-side processing where progressive display is unnecessary).

Chunk Handling

PNG stores data in chunks. The critical chunks — IHDR (header), PLTE (palette), IDAT (image data), and IEND (end marker) — carry everything needed to reconstruct the image, and JDeli decodes all of them. The format also allows optional ancillary chunks that carry metadata such as text annotations (tEXt, iTXt, zTXt), pixel density (pHYs), and timestamps (tIME).

Compression & Quantisation

JDeli offers four PNG compression modes: ZLIB_BETTER_COMPRESSION (default, smallest files), ZLIB_BETTER_SPEED (fastest encoding), QUANTISED8BIT (converts to 8-bit indexed palette — dramatically smaller files for UI assets), and NONE (uncompressed, fastest, largest). The optimizeBasedOnColors flag analyses colour content to pick optimal encoding automatically.

Why Use JDeli over ImageIO for PNG?

The JDK's built-in PNG support works for basic reading and writing. But it has real gaps that show up in production.

Inconsistent ICC colour profile handling

Java's colour management has documented cross-platform and cross-version inconsistencies — most notably the switch from KCMS to LittleCMS as the default engine. The result is that the same PNG with an embedded iCCP profile can render with different colours on Windows vs Linux, or between JDK versions. JDeli reads and applies iCCP profiles consistently across platforms.

No built-in conversion or processing

ImageIO can read a PNG and write a PNG. Converting PNG to JPEG means reading into a BufferedImage, handling the alpha channel yourself (the JPEG writer is notorious for the red/pink tint when alpha is left in), then writing with a separate writer. There is no built-in resize, crop, or rotate either — that is all manual Java2D work. JDeli converts in one line and includes image processing operations.

Slow PNG encoding

The JDK's PNG writer is not optimized for throughput — slow enough that a dedicated backport exists purely to improve PNG write performance on Java 7/8. On large images or batch workloads, encoding becomes the bottleneck. JDeli's PNG encoder is written from scratch for speed.

Limited metadata access

Reading PNG text chunks, resolution data, or other metadata through ImageIO's IIOMetadata API means navigating an org.w3c.dom.Node tree (the javax_imageio_png_1.0 format) by hand — a clunky API developers widely complain about. JDeli exposes metadata through a straightforward API.

Little control over compression

The standard PNG writer gives you a single coarse quality setting and no control over filter strategy or palette reduction. JDeli exposes explicit compression modes — ZLIB_BETTER_COMPRESSION, ZLIB_BETTER_SPEED, QUANTISED8BIT (8-bit indexed for much smaller files), and NONE — so you can trade size against speed deliberately.

Bugs sit in the JDK for years

ImageIO PNG issues go through the OpenJDK bug tracker, where they can sit unresolved for years, and you only get fixes when you upgrade the whole JDK. JDeli is actively maintained with a release every 6 weeks, and format bugs are typically fixed within days of a reproducible report.

Read, Write and Convert PNG files in pure Java with JDeli

JDeli helps unlock the potential of the file format with a few lines of Java code:

// Read PNG files

JDeli.read(File pngFile);

JDeli.read(byte[] pngData);

JDeli.read(InputStream pngStream);
// Write PNG files

JDeli.write(myBufferedImage, "png");
// Convert to and from PNG files
JDeli.convert(File inFile, File outFile);

JDeli.convert(InputStream inStream, OutputStream outStream, String format);

byte[] outputData=JDeli.convert(byte[] inputData, String format);

Trusted by Companies around the World

Abacus logo
Citi logo
Clearsense logo
Honeywell logo
Los Alamos National Lab logo
Mercedes-Benz Bank logo

JDeli handles not only HEIC but other types of file formats as well.

- Joselito M. (Senior Applications Developer at Omaha National)

Frequently Asked Questions

Can JDeli replace ImageIO for PNG?

Yes. JDeli provides an ImageIO plugin that works transparently with existing javax.imageio code. Add the jdeli-imageio JAR to your classpath and your existing ImageIO.read() / ImageIO.write() calls use JDeli's PNG implementation — no code changes required.

How do I set PNG compression level in JDeli?

Use PngEncoderOptions and call setCompressionFormat(). Options: ZLIB_BETTER_COMPRESSION (default, smallest files), ZLIB_BETTER_SPEED (faster encoding), QUANTISED8BIT (indexed 8-bit palette for dramatically smaller files), and NONE (no compression).

Does JDeli handle PNG transparency (alpha channel)?

Yes. JDeli reads and writes PNGs with full alpha channel support, including RGBA true colour and palette-based transparency (tRNS chunk). When converting to a format without alpha (like JPEG), composite the alpha onto a background colour first — see the code recipe above.

Is JDeli thread-safe?

Yes. JDeli's read(), write(), and convert() methods are stateless static calls. Each invocation creates its own internal state. You can call them concurrently from multiple threads without synchronisation.

What license does JDeli use?

JDeli is a commercial library with three tiers: Server (on-premises/cloud), Distribution (embedded in end-user apps), and Custom. A 30-day trial is available with the full feature set and no watermarks on output. See pricing for details.

Why use JDeli for PNG image support?

1.

Adds PNG to ImageIO so works with existing code

2.

Uses no native code or third party libraries

3.

Optimised Java code for maximum performance

Try JDeli for Free