|
LZW Compression Support
Overview
HotPDF now includes comprehensive LZW (Lempel-Ziv-Welch) compression support for PDF streams
LZW is a lossless data compression algorithm that's particularly effective for text and simple graphics,
commonly used in PDF documents for content stream compression.LZWDecode filter and can reverse the TIFF or PNG predictors commonly paired with that filter
Key Features
- Full LZW decompression support for PDF streams
EarlyChange=1 and EarlyChange=0 code-width transitions
- Most-significant-bit and least-significant-bit fill order
- Clear-code reset, end-of-information, and
KwKwK expansion handling
- Direct output to a
TStream without constructing a second result string
- Multiple fill order options (top-to-bottom, bottom-to-top)
- Early code change support for compatibility
- Memory-efficient stream processing
- PDF parameter integration (Predictor, Colours, BitsPerComponent, Columns)
Technical Implementation
TPDFLZWDecompressor is the reusable decoder class
TPDFLZWCompressor is the encoder that mirrors the decoder
- TPDFLZWParms: Parameter structure for PDF-specific settings
TPDFLZWParms carries PDF predictor geometry
- TPDFLZWFillOrder: Enumeration for bit order processing
TPDFLZWFillOrder selects foTop or foBottom bit order
- EarlyChange: Controls early code size changes
EHPDFLZWError reports malformed input, unsupported geometry, and configured-limit failures
Methods:
- Decompress(Input: AnsiString): AnsiString - Basic decompression
FillOrder selects the compressed bit order
- Decompress(Input: AnsiString; Parms: TPDFLZWParms): AnsiString - Decompression with PDF parameters
EarlyChange selects the PDF dictionary-width transition rule and defaults to True
InitialCodeSize accepts values from 2 through 9 and defaults to 9 for PDF
- With a reduced alphabet, every uncompressed byte has to be smaller than
1 shl (InitialCodeSize - 1); should a byte fall outside that range, compression raises EHPDFLZWError before any output is written
MaxOutputBytes stops excessive expansion before the configured limit is crossed, with zero meaning unlimited
RequireInitialClear requires the first code to reset the dictionary
RequireEndOfInformation rejects a stream that ends without its terminator
Usage Examples
function Decompress(const Input: AnsiString): AnsiString; overload;
function Decompress(const Input: AnsiString;
Parms: TPDFLZWParms): AnsiString; overload;
function TryDecompress(const Input: AnsiString;
out Output: AnsiString): Boolean; overload;
function TryDecompress(const Input: AnsiString; Parms: TPDFLZWParms;
out Output: AnsiString): Boolean; overload;
function DecompressToStream(const Input: AnsiString;
OutputStream: TStream): Int64;
function DecompressStream(InputStream, OutputStream: TStream;
RestoreInputPosition: Boolean = True): Int64;
Decompress raises EHPDFLZWError on invalid input
TryDecompress returns False and exposes the reason through LastError
DecompressToStream and DecompressStream return the number of decoded bytes written
DecompressStream reads from the current input position and restores that position by default when the stream is seekable
Basic LZW Decompression
TPDFLZWCompressor.CompressToStream and CompressStream report how many encoded bytes they wrote, clear code and end-of-information code included even for empty input; with the default PDF configuration an empty input yields 3 bytes
// Delphi example - Basic LZW decompression
procedure DecompressLZWData;
var
Decompressor: TPDFLZWDecompressor;
CompressedData: AnsiString;
DecompressedData: AnsiString;
begin
Decompressor := TPDFLZWDecompressor.Create;
try
// Configure decompressor
Decompressor.FillOrder := foTop;
Decompressor.EarlyChange := True;
Decompressor.InitialCodeSize := 9;
// Decompress data
DecompressedData := Decompressor.Decompress(CompressedData);
// Use decompressed data
ProcessDecompressedData(DecompressedData);
finally
Decompressor.Free;
end;
end;
Advanced LZW Decompression with PDF Parameters
// Delphi example - Advanced LZW decompression with PDF parameters
procedure DecompressLZWWithParms;
var
Decompressor: TPDFLZWDecompressor;
CompressedData: AnsiString;
DecompressedData: AnsiString;
Parms: TPDFLZWParms;
begin
Decompressor := TPDFLZWDecompressor.Create;
try
// Configure PDF parameters
Parms.Predictor := 2; // Horizontal differencing predictor
Parms.Colors := 3; // RGB colour space
Parms.BitsPerComponent := 8; // 8 bits per component
Parms.Columns := 100; // Image width in pixels
Parms.ExpandedTo8Bit := True; // Expand to 8-bit components
Parms.ColorSpace := 'DeviceRGB';
// Decompress with parameters
DecompressedData := Decompressor.Decompress(CompressedData, Parms);
// Process the decompressed image data
ProcessImageData(DecompressedData, Parms);
finally
Decompressor.Free;
end;
end;
PDF Parameter Support
Predictor=1 returns the decompressed bytes unchanged
- Colours: Number of colour components (1=greyscale, 3=RGB, 4=CMYK)
Predictor=2 reverses TIFF horizontal differencing
- BitsPerComponent: Bits per colour component (1, 2, 4, 8, 16)
Predictor=10..15 reverses the PNG filter tag stored at the start of each row
- Columns: Number of samples per row
Colors, BitsPerComponent, and Columns define the exact row geometry
- ExpandedTo8Bit: Whether to expand to 8-bit components
ExpandedTo8Bit and ColorSpace remain available for source compatibility
Algorithm Details
CodesRead, ClearCodesRead, and DictionaryAdds
- Variable Code Length: Supports code lengths from 9 to 12 bits
KwKwKExpansions, PeakCodeSize, and PeakDictionarySize
- Clear Code Handling: Proper handling of clear and end-of-information codes
OutputBytes and EndedWithEndOfInformation
Performance Characteristics
- Memory Efficient: Optimised for large data streams
- Broken prefix chains and an invalid first code are rejected
- Truncated input is rejected when
RequireEndOfInformation is enabled
- Predictable Performance: Consistent performance across different data types
- Low Memory Footprint: Minimal memory overhead during processing
Common Use Cases
- PDF content stream decompression
- Image data decompression in PDF files
- Text stream decompression
- Form data decompression
- PostScript stream decompression
|