|
| 1 | +# Brotli Compression Strategy for iText |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +This module provides a Brotli compression implementation for PDF streams in iText. Brotli is a modern compression |
| 6 | +algorithm that typically provides better compression ratios than traditional Flate/Deflate compression, especially for |
| 7 | +text-heavy content. |
| 8 | + |
| 9 | +## Important Notice |
| 10 | + |
| 11 | +**EXPERIMENTAL FEATURE**: Brotli compression for PDF streams is currently experimental and is not part of the official |
| 12 | +PDF specification. PDF documents compressed using Brotli may not be compatible with other PDF processors or readers. Use |
| 13 | +this feature with caution and only when you control both the generation and consumption of the PDF documents. |
| 14 | + |
| 15 | +## Features |
| 16 | + |
| 17 | +- Implementation of iText's `IStreamCompressionStrategy` interface |
| 18 | +- Automatic compression level mapping from iText's 0-9 scale to Brotli's 0-11 scale |
| 19 | +- Better compression ratios compared to Flate compression for most text content |
| 20 | +- Seamless integration with iText's PDF generation workflow |
| 21 | + |
| 22 | +## Requirements |
| 23 | + |
| 24 | +- iText 9.5.0 or later |
| 25 | + |
| 26 | +## Installation |
| 27 | + |
| 28 | +`brotli-compressor` is experimental so the artifacts are only available on iText's artifactory. |
| 29 | + |
| 30 | +Add the following dependency and config to your Maven project: |
| 31 | + |
| 32 | +```xml |
| 33 | +<repositories> |
| 34 | + <repository> |
| 35 | + <id>itext-releases</id> |
| 36 | + <name>iText Repository - releases</name> |
| 37 | + <url>https://repo.itextsupport.com/releases</url> |
| 38 | + </repository> |
| 39 | +</repositories> |
| 40 | + |
| 41 | +<dependency> |
| 42 | + <groupId>com.itextpdf</groupId> |
| 43 | + <artifactId>brotli-compressor</artifactId> |
| 44 | + <version>{itext.version.bigger.then.9.5.0}</version> |
| 45 | +</dependency> |
| 46 | +``` |
| 47 | + |
| 48 | + |
| 49 | + |
| 50 | +## Usage |
| 51 | + |
| 52 | +To use Brotli compression for PDF streams, register the `BrotliStreamCompressionStrategy` with your PDF document: |
| 53 | + |
| 54 | +```java |
| 55 | +import com.itextpdf.BrotliStreamCompressionStrategy; |
| 56 | +import com.itextpdf.kernel.pdf.DocumentProperties; |
| 57 | +import com.itextpdf.kernel.pdf.IStreamCompressionStrategy; |
| 58 | +import com.itextpdf.kernel.pdf.PdfDocument; |
| 59 | +import com.itextpdf.kernel.pdf.PdfWriter; |
| 60 | + |
| 61 | +// Create a PDF document with Brotli compression |
| 62 | +DocumentProperties properties = new DocumentProperties(); |
| 63 | +properties.registerDependency(IStreamCompressionStrategy .class, new BrotliStreamCompressionStrategy()); |
| 64 | + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outputStream), properties); |
| 65 | + |
| 66 | +// Continue with normal PDF generation |
| 67 | +// All streams will be compressed using Brotli |
| 68 | +``` |
| 69 | + |
| 70 | +## Compression Levels |
| 71 | + |
| 72 | +The Brotli compression strategy automatically maps iText compression levels to Brotli levels: |
| 73 | + |
| 74 | +- iText levels: 0 (no compression) to 9 (best compression) |
| 75 | +- Brotli levels: 0 to 11 |
| 76 | +- Mapping formula: `brotliLevel = round(iTextLevel * (11.0 / 9.0))` |
| 77 | +- Default level: 6 (used when the input level is out of range) |
| 78 | + |
| 79 | +You can set the compression level on the PDF writer: |
| 80 | + |
| 81 | +```java |
| 82 | + |
| 83 | +DocumentProperties properties = new DocumentProperties(); |
| 84 | +properties.registerDependency(IStreamCompressionStrategy .class, new BrotliStreamCompressionStrategy()); |
| 85 | + |
| 86 | +PdfWriter writer = new PdfWriter(outputStream); |
| 87 | +writer.setCompressionLevel(9); // Maximum compression |
| 88 | + |
| 89 | +PdfDocument pdfDoc = new PdfDocument(writer, properties); |
| 90 | + |
| 91 | +``` |
| 92 | + |
| 93 | +## Decompression |
| 94 | + |
| 95 | +Supported out of the box in the iText kernel module |
| 96 | + |
| 97 | +The filter supports: |
| 98 | + |
| 99 | +- Standard Brotli decompression |
| 100 | +- Optional Brotli dictionary streams (specified via decode parameters) |
| 101 | +- Memory limits awareness through iText's MemoryLimitsAwareHandler |
| 102 | + |
| 103 | +## Compatibility Warning |
| 104 | + |
| 105 | +PDF documents using Brotli compression (`/BrotliDecode` filter) are currently not compliant with the official PDF |
| 106 | +specification (ISO 32000). These documents may: |
| 107 | + |
| 108 | +- Fail to open in standard PDF readers (Adobe Acrobat, Preview, etc.) |
| 109 | +- Not render correctly in web browsers |
| 110 | +- Be rejected by PDF validation tools |
| 111 | +- Not be processable by third-party PDF libraries |
| 112 | + |
| 113 | +This compression method should only be used in controlled environments where: |
| 114 | + |
| 115 | +- You generate and consume the PDF documents within your own system |
| 116 | +- You have verified compatibility with your specific PDF processing pipeline |
| 117 | +- You can handle potential incompatibilities with external tools |
| 118 | + |
| 119 | +## Brotli (brotli4j) Support in GraalVM Native Image |
| 120 | + |
| 121 | +This project uses **brotli4j**, which relies on a native Brotli library. When building a **GraalVM native image**, the |
| 122 | +native library is **not included automatically** and must be configured explicitly. |
| 123 | + |
| 124 | +### Native Image Configuration |
| 125 | + |
| 126 | +Add the following options to your `native-image` buildargs: |
| 127 | + |
| 128 | +```bash |
| 129 | +#add all the runtimes you are deploying to, iText test env does these so we have added these as a example |
| 130 | +-H:IncludeResources=lib/windows-x86_64/brotli.dll |
| 131 | +-H:IncludeResources=lib/linux-aarch64/libbrotli.so |
| 132 | + |
| 133 | +--initialize-at-run-time=com.aayushatharva.brotli4j.Brotli4jLoader |
| 134 | +``` |
0 commit comments