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 streamsEarlyChange=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 settingsTPDFLZWParms carries PDF predictor geometry
  • TPDFLZWFillOrder: Enumeration for bit order processingTPDFLZWFillOrder selects foTop or foBottom bit order
  • EarlyChange: Controls early code size changesEHPDFLZWError reports malformed input, unsupported geometry, and configured-limit failures

Methods:

  • Decompress(Input: AnsiString): AnsiString - Basic decompressionFillOrder selects the compressed bit order
  • Decompress(Input: AnsiString; Parms: TPDFLZWParms): AnsiString - Decompression with PDF parametersEarlyChange 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 rowColors, BitsPerComponent, and Columns define the exact row geometry
  • ExpandedTo8Bit: Whether to expand to 8-bit componentsExpandedTo8Bit and ColorSpace remain available for source compatibility

Algorithm Details

  • CodesRead, ClearCodesRead, and DictionaryAdds
  • Variable Code Length: Supports code lengths from 9 to 12 bitsKwKwKExpansions, PeakCodeSize, and PeakDictionarySize
  • Clear Code Handling: Proper handling of clear and end-of-information codesOutputBytes 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