LZW-Komprimierungsunterstützung

Übersicht

HotPDF dekodiert ältere PDF-Streams mit dem LZWDecode-Filter und kann die üblicherweise mit diesem Filter gepaarten TIFF- oder PNG-Predictoren zurückrechnen

Hauptmerkmale

  • Codebreiten-Übergänge mit PDF EarlyChange=1 und EarlyChange=0
  • Bitfüllreihenfolge vom höchst- und vom niederwertigsten Bit her
  • Behandlung von Clear-Code-Reset, End-of-Information und KwKwK-Expansion
  • Direkte Ausgabe in einen TStream, ohne einen zweiten Ergebnis-String aufzubauen
  • Konfigurierbare Ausgabelimits sowie optionale strenge Prüfungen von Initial-Clear und End-of-Information
  • TIFF Predictor 2 mit 1, 2, 4, 8 oder 16 Bit pro Komponente
  • PNG-Zeilenfilter None, Sub, Up, Average und Paeth
  • Statistiken pro Dekodierung für Codebreiten, Wörterbuchwachstum, Resets, Expansionen und Ausgabe-Bytes

Typen

  • TPDFLZWDecompressor ist die wiederverwendbare Dekodierer-Klasse
  • TPDFLZWCompressor ist die passende Enkodierer-Klasse
  • TPDFLZWParms trägt die PDF-Predictor-Geometrie
  • TPDFLZWFillOrder wählt die Bitreihenfolge foTop oder foBottom
  • EHPDFLZWError meldet fehlerhafte Eingaben, nicht unterstützte Geometrie und Verstöße gegen konfigurierte Limits

Konfigurationseigenschaften

  • FillOrder wählt die Bitreihenfolge der komprimierten Daten
  • EarlyChange wählt die PDF-Übergangsregel für Wörterbuchbreiten und steht standardmäßig auf True
  • InitialCodeSize akzeptiert Werte von 2 bis 9 und steht für PDF standardmäßig auf 9
  • Für reduzierte Alphabete muss jedes unkomprimierte Byte kleiner als 1 shl (InitialCodeSize - 1) sein; die Komprimierung löst EHPDFLZWError aus, bevor sie Ausgabe schreibt, wenn ein Byte außerhalb dieses Bereichs liegt
  • MaxOutputBytes stoppt übermäßige Expansion, bevor das konfigurierte Limit überschritten wird; null bedeutet unbegrenzt
  • RequireInitialClear verlangt, dass der erste Code das Wörterbuch zurücksetzt
  • RequireEndOfInformation weist einen Stream zurück, der ohne seinen Terminator endet

Methoden:

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 löst bei ungültiger Eingabe EHPDFLZWError aus
  • TryDecompress liefert False und stellt den Grund über LastError bereit
  • DecompressToStream und DecompressStream liefern die Anzahl der geschriebenen dekodierten Bytes
  • DecompressStream liest ab der aktuellen Eingabeposition und stellt diese standardmäßig wieder her, wenn der Stream seekbar ist

Einfache LZW-Dekomprimierung

TPDFLZWCompressor.CompressToStream und CompressStream liefern die Anzahl der geschriebenen kodierten Bytes, einschließlich Clear-Code und End-of-Information-Code bei leerer Eingabe; die Standard-PDF-Konfiguration schreibt für eine leere Eingabe 3 Bytes

uses
  HPDFLZW;

procedure DecompressLZWData;
var
  Decompressor: TPDFLZWDecompressor;
  CompressedData: AnsiString;
  DecompressedData: AnsiString;
begin
  Decompressor := TPDFLZWDecompressor.Create;
  try
    Decompressor.FillOrder := foTop;
    Decompressor.EarlyChange := True;
    Decompressor.MaxOutputBytes := 64 * 1024 * 1024;
    DecompressedData := Decompressor.Decompress(CompressedData);
    ProcessDecompressedData(DecompressedData);
  finally
    Decompressor.Free;
  end;
end;

Stream-Ausgabe und Diagnostik

procedure DecodeLZWToStream(const CompressedData: AnsiString;
  Destination: TStream);
var
  Decompressor: TPDFLZWDecompressor;
begin
  Decompressor := TPDFLZWDecompressor.Create;
  try
    Decompressor.RequireInitialClear := True;
    Decompressor.RequireEndOfInformation := True;
    Decompressor.DecompressToStream(CompressedData, Destination);
    LogDecodeStatistics(
      Decompressor.CodesRead,
      Decompressor.PeakCodeSize,
      Decompressor.PeakDictionarySize,
      Decompressor.OutputBytes);
  finally
    Decompressor.Free;
  end;
end;

Predictor-Parameter

  • Predictor=1 liefert die dekodierten Bytes unverändert zurück
  • Predictor=2 rechnet die horizontale TIFF-Differenzbildung zurück
  • Predictor=10..15 rechnet das PNG-Filter-Tag zurück, das am Anfang jeder Zeile steht
  • Colors, BitsPerComponent und Columns definieren die exakte Zeilengeometrie
  • ExpandedTo8Bit und ColorSpace bleiben aus Kompatibilitätsgründen verfügbar

Dekodier-Statistiken

  • CodesRead, ClearCodesRead und DictionaryAdds
  • KwKwKExpansions, PeakCodeSize und PeakDictionarySize
  • OutputBytes und EndedWithEndOfInformation

Fehlerbehandlung

  • Codes jenseits des nächsten Wörterbucheintrags werden zurückgewiesen
  • Abgebrochene Präfixketten und ein ungültiger erster Code werden zurückgewiesen
  • Abgeschnittene Eingaben werden zurückgewiesen, wenn RequireEndOfInformation aktiviert ist
  • Die Ausgabeexpansion wird geprüft, bevor jede Phrase ausgegeben wird
  • Predictor-Zeilen müssen vollständig sein und eine gültige Geometrie sowie ein gültiges PNG-Zeilen-Tag verwenden

Siehe auch