Java Compression Library
Compress and decompress image data in pure Java. Supports Flate, LZW, DCT, Brotli, CCITT, JBIG2, JPX, RLE and more with no native dependencies.
JDeli provides 10 filters for compressing & decompressing image data in pure Java (Java 17+) with no native or third-party dependencies. It handles Ascii85, AsciiHex, Brotli, CCITT, DCT, Flate, JBIG2, JPX, LZW, and RLE through a single static API.
Input can be a byte arrays directly, or InputStreams and OutputStreams for larger data. See the full filter documentation for the complete API reference.
Compress data in Java with two lines of code
These examples use Flate (Deflate), the most commonly used lossless compression filter for image streams.
// Compress a byte array using Flate (Deflate)
FlateFilterOptions options = new FlateFilterOptions();
options.setMode(FilterOptions.FilterMode.COMPRESS);
byte[] compressed = JDeli.filter(rawData, options);
// Decompress back to the original data
FlateFilterOptions decompressOptions = new FlateFilterOptions();
decompressOptions.setMode(FilterOptions.FilterMode.DECOMPRESS);
byte[] original = JDeli.filter(compressed, decompressOptions);// Compress an InputStream to an OutputStream
FlateFilterOptions options = new FlateFilterOptions();
options.setMode(FilterOptions.FilterMode.COMPRESS);
JDeli.filter(inputStream, options, outputStream);
// Decompress an InputStream to an OutputStream
FlateFilterOptions decompressOptions = new FlateFilterOptions();
decompressOptions.setMode(FilterOptions.FilterMode.DECOMPRESS);
JDeli.filter(inputStream, decompressOptions, outputStream);How to compress image data in Java
- Add the JDeli JAR to your project classpath, or add it as a Maven or Gradle dependency.
- Choose the compression filter that matches your data type. Flate works for most use cases; LZW is common for TIFF and GIF data; DCT handles JPEG streams. See the filter comparison table below for the full list.
- Create the corresponding FilterOptions object and call
setMode(FilterOptions.FilterMode.COMPRESS). - Pass your data and options to
JDeli.filter(). Use thebyte[]overload for small data or theInputStream/OutputStreamoverload for large files. - To decompress, change the mode to
FilterOptions.FilterMode.DECOMPRESSand call the same method.
For PNG-specific compression (reducing PNG file sizes without quality loss), see How to compress PNG files with PngCompressor.
All compression and decompression filters
// Compress byte[]
ASCII85FilterOptions options = new ASCII85FilterOptions();
options.setMode(FilterOptions.FilterMode.COMPRESS);
byte[] compressed = JDeli.filter(rawData, options);
// Decompress byte[]
ASCII85FilterOptions options = new ASCII85FilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
byte[] decompressed = JDeli.filter(rawData, options);
// Compress InputStream
ASCII85FilterOptions options = new ASCII85FilterOptions();
options.setMode(FilterOptions.FilterMode.COMPRESS);
JDeli.filter(inputStream, options, outputStream);
// Decompress InputStream
ASCII85FilterOptions options = new ASCII85FilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
JDeli.filter(inputStream, options, outputStream);// Compress byte[]
ASCIIHexFilterOptions options = new ASCIIHexFilterOptions();
options.setMode(FilterOptions.FilterMode.COMPRESS);
byte[] compressed = JDeli.filter(rawData, options);
// Decompress byte[]
ASCIIHexFilterOptions options = new ASCIIHexFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
byte[] decompressed = JDeli.filter(rawData, options);
// Compress InputStream
ASCIIHexFilterOptions options = new ASCIIHexFilterOptions();
options.setMode(FilterOptions.FilterMode.COMPRESS);
JDeli.filter(inputStream, options, outputStream);
// Decompress InputStream
ASCIIHexFilterOptions options = new ASCIIHexFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
JDeli.filter(inputStream, options, outputStream);// Decompress byte[]
BrotliFilterOptions options = new BrotliFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
byte[] decompressed = JDeli.filter(rawData, options);
// Decompress InputStream
BrotliFilterOptions options = new BrotliFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
JDeli.filter(inputStream, options, outputStream);// Decompress byte[]
CCITTFilterOptions options = new CCITTFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
byte[] decompressed = JDeli.filter(rawData, options);
// Decompress InputStream
CCITTFilterOptions options = new CCITTFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
JDeli.filter(inputStream, options, outputStream);// Decompress byte[]
DCTFilterOptions options = new DCTFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
byte[] decompressed = JDeli.filter(rawData, options);
// Decompress InputStream
DCTFilterOptions options = new DCTFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
JDeli.filter(inputStream, options, outputStream);// Compress byte[]
FlateFilterOptions options = new FlateFilterOptions();
options.setMode(FilterOptions.FilterMode.COMPRESS);
byte[] compressed = JDeli.filter(rawData, options);
// Decompress byte[]
FlateFilterOptions options = new FlateFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
byte[] decompressed = JDeli.filter(rawData, options);
// Compress InputStream
FlateFilterOptions options = new FlateFilterOptions();
options.setMode(FilterOptions.FilterMode.COMPRESS);
JDeli.filter(inputStream, options, outputStream);
// Decompress InputStream
FlateFilterOptions options = new FlateFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
JDeli.filter(inputStream, options, outputStream);// Decompress byte[]
JBIG2FilterOptions options = new JBIG2FilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
byte[] decompressed = JDeli.filter(rawData, options);
// Decompress InputStream
JBIG2FilterOptions options = new JBIG2FilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
JDeli.filter(inputStream, options, outputStream);// Decompress byte[]
JPXFilterOptions options = new JPXFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
byte[] decompressed = JDeli.filter(rawData, options);
// Decompress InputStream
JPXFilterOptions options = new JPXFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
JDeli.filter(inputStream, options, outputStream);// Compress byte[]
LZWFilterOptions options = new LZWFilterOptions();
options.setMode(FilterOptions.FilterMode.COMPRESS);
byte[] compressed = JDeli.filter(rawData, options);
// Decompress byte[]
LZWFilterOptions options = new LZWFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
byte[] decompressed = JDeli.filter(rawData, options);
// Compress InputStream
LZWFilterOptions options = new LZWFilterOptions();
options.setMode(FilterOptions.FilterMode.COMPRESS);
JDeli.filter(inputStream, options, outputStream);
// Decompress InputStream
LZWFilterOptions options = new LZWFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
JDeli.filter(inputStream, options, outputStream);// Compress byte[]
RLEFilterOptions options = new RLEFilterOptions();
options.setMode(FilterOptions.FilterMode.COMPRESS);
byte[] compressed = JDeli.filter(rawData, options);
// Decompress byte[]
RLEFilterOptions options = new RLEFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
byte[] decompressed = JDeli.filter(rawData, options);
// Compress InputStream
RLEFilterOptions options = new RLEFilterOptions();
options.setMode(FilterOptions.FilterMode.COMPRESS);
JDeli.filter(inputStream, options, outputStream);
// Decompress InputStream
RLEFilterOptions options = new RLEFilterOptions();
options.setMode(FilterOptions.FilterMode.DECOMPRESS);
JDeli.filter(inputStream, options, outputStream);Which compression filter should you use?
JDeli supports 10 filters. The right choice depends on your image format and whether you need lossless or lossy compression.
| Filter | Best for | Modes | Learn more |
|---|---|---|---|
| Ascii85 | Encodes binary image data as printable ASCII text | Compress, Decompress | Tutorial |
| AsciiHex | Encodes binary image data as hexadecimal text | Compress, Decompress | Tutorial |
| Brotli | High-ratio lossless compression | Decompress | Tutorial |
| CCITT | Bilevel (black and white) fax-style image compression | Decompress | Tutorial |
| DCT | Lossy compression for JPEG image data | Decompress | Tutorial |
| Flate | General-purpose lossless compression for image streams | Compress, Decompress | Tutorial |
| JBIG2 | High-ratio compression for scanned bilevel document images | Decompress | Tutorial |
| JPX | JPEG 2000 wavelet-based image compression | Decompress | Tutorial |
| LZW | Lossless compression used in TIFF and GIF image formats | Compress, Decompress | Tutorial |
| RLE | Run-length encoding for data with long repeated byte sequences | Compress, Decompress | Tutorial |
"I was looking specifically for a Java-based compression technique, I'm happy because it's taking up less space on the server."
- Kevin Lauder (ISC Engineering Senior Manager)
Common issues when compressing data in Java
Compressing already-compressed data increases size. Applying Flate to data that is already Flate-compressed will not reduce it further. The framing overhead usually makes the output slightly larger than the input. Compress once.
DCT is lossy. Each compress-decompress cycle with DCT (JPEG) degrades image quality. If you need to round-trip image data without loss, use Flate or LZW instead.
CCITT and JBIG2 expect bilevel images. These filters are designed for 1-bit black-and-white image data. Passing colour or grayscale data will produce incorrect output. Check your image colour model before choosing a filter.
Use streams for large data.
The byte[] overload of JDeli.filter() loads everything into heap
memory. For large image streams, use the InputStream/OutputStream version to
avoid OutOfMemoryError.
Frequently asked questions
What image formats does JDeli support?
JDeli reads AVIF, BMP, GIF, HEIC, JPEG, JPEG 2000, JPEG XL, PNG, TIFF, and WebP. It writes AVIF, BMP, GIF, HEIC, JPEG, JPEG 2000, PNG, TIFF, and WebP. For data-level compression, it supports 10 filters: Ascii85, AsciiHex, Brotli, CCITT, DCT, Flate, JBIG2, JPX, LZW, and RLE. See the full format list.
Does JDeli require native libraries or DLLs?
No. JDeli is written entirely in Java with no native code, no JNI, and no third-party dependencies. It runs on any platform that supports Java 8 or later.
Can I use JDeli as a drop-in replacement for ImageIO?
Yes. JDeli includes an ImageIO plugin that works
transparently with existing javax.imageio code, adding support for formats
like AVIF, HEIC, JPEG XL, and WebP that standard ImageIO does not handle.
How does JDeli's performance compare to alternatives?
JDeli's encoders and decoders are up to 3x faster than ImageIO and other Java image libraries in independent benchmarks. See the performance comparison for detailed numbers.
JDeli is the only Java library to include all these features...
Drop-in replacement for ImageIO
- Works transparently with existing code
- No DLLs or 3rd party code used
- Any feature can be enabled/disabled
Convert image formats
- Direct conversion
- Translate any supported formats
- Process/modify image during conversion
Compress/Decompress Data
- Ascii85, AsciiHex, Brotli
- CCITT, DCT, Flate, JPX
- JBIG2, LZW, RLE
Why use JDeli when there are Open-source image libraries?
Written in 100% pure Java so no native dependencies or command-line tools.
Works with any existing Java codebase as an ImageIO plugin
Provides significant performance benefits and lower memory usage for batch operations.
Makes no calls to any external system or third party library.
Fast response time on official support, frequent updates, and commercial licensing
Trusted by Companies around the World
Extend Java capabilities
(works with your existing code!)
1.
2.
3.
Try JDeli for Free
How do you achieve such good performance? So many companies attempting writing image codecs in Java end up in far slower performance or claim better performance requires native code.
- David E. (Lead developer and founder of jAlbum)
Key Benefits
High Performance
JDeli encoders and decoders are faster than alternatives, making JDeli perfect for applications where performance matters.
File Security
The software runs securely on your servers. It makes no callback or access to the cloud so critical customer data is always secure.
Simple installation
Provides a simple set of static methods to decompress/compress data streams and implements Input/OutputStream implementations
Ongoing development
Nightly and stable builds with regular new features and an expanding range of compression formats supported.
Premium support
Support is provided quickly and directly by our in-house JDeli Developers on email or via our online portal.
No third party libraries
JDeli does not use any third-party or system dependencies, avoiding security flaws in other software and JVM crashes from statically linked libraries.
We replaced all our various image processing code with JDeli, which allowed us to smoothly migrate to Java 11. The support from IDR solutions is just great. Whenever we came across a strange image from our customers which JDeli couldn't read properly, IDR fixed it in less than a day.
- Developer in SME Financial Services Company
Straightforward Pricing That Works for You
| Server License | Product License | Custom License | |
|---|---|---|---|
| Price | $1,600 USD/ year per server | $5,400 USD/ year per application | $15,000 USD/ year |
| Usage | Run on cloud or on premise server with up to 12 cores | Use JDeli in a named end user application | Use JDeli in a named end user application or Microservice |
| License | Standard shrink-wrapped EULA license | Standard shrink-wrapped EULA license | Option to customise EULA license |
| Non-Production Test and Development Servers |
Included | Included | Included |
| Included Support | Standard support via email/service portal | Standard support via email/service portal | Premium support via email/service portal/ Zoom |
| New Releases Access | ✓ | ✓ | ✓ |
| High priority tickets | Up to 3 high priority support tickets | Up to 3 high priority support tickets | Up to 12 high priority support tickets |
| Source Code Access | - | - | ✓ |
| Free Consultancy | - | - | Up to 5 hours free consultancy or development time |
| Development plan update Call | - | - | Quarterly |
Not ready to buy? You may also Try JDeli for Free or Ask a Question