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
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.
2.
3.