LZW Compression Support

概要

HotPDF は LZWDecode フィルターを使うレガシー PDF ストリームをデコードでき、そのフィルターと共に使われることが多い TIFF / PNG プレディクターも逆算できます

主な特徴

  • PDF EarlyChange=1 / EarlyChange=0 のコード幅遷移
  • MSB / LSB の両フィル順
  • クリアコードリセット、end-of-information、KwKwK 展開の処理
  • 2 つ目の結果文字列を構築せず TStream へ直接出力
  • 設定可能な出力上限と、オプションの厳格な初期クリア / end-of-information チェック
  • コンポーネントあたり 1 / 2 / 4 / 8 / 16 ビットの TIFF Predictor 2
  • PNG の None、Sub、Up、Average、Paeth の各行フィルター
  • コード幅、辞書成長、リセット、展開、出力バイトのデコードごとの統計

型

  • TPDFLZWDecompressor は再利用可能なデコーダークラスです
  • TPDFLZWCompressor は対応するエンコーダークラスです
  • TPDFLZWParms は PDF プレディクターのジオメトリを運びます
  • TPDFLZWFillOrder が foTop / foBottom のビット順を選びます
  • EHPDFLZWError が不正入力、未対応ジオメトリ、設定上限超過を報告します

設定プロパティ

  • FillOrder が圧縮ビット順を選びます
  • EarlyChange が PDF の辞書幅遷移ルールを選び、既定は True です
  • InitialCodeSize は 2〜9 を受け付け、PDF では既定 9 です
  • 縮小されたアルファベットでは、圧縮前のすべてのバイトが 1 shl (InitialCodeSize - 1) 未満でなければなりません。この範囲外のバイトがある場合、圧縮は出力を書き込む前に EHPDFLZWError を発生させます
  • MaxOutputBytes は設定した上限を超える前に過度な展開を止めます。0 は無制限です
  • RequireInitialClear は最初のコードに辞書リセットを要求します
  • RequireEndOfInformation は終端子なしで終わるストリームを拒否します

メソッド

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 は不正入力に対して EHPDFLZWError を発生させます
  • TryDecompress は False を返し、理由を LastError で公開します
  • DecompressToStream と DecompressStream は書き出されたデコード済みバイト数を返します
  • DecompressStream は現在の入力位置から読み、シーク可能なストリームでは既定でその位置を復元します

基本的な LZW 展開

TPDFLZWCompressor.CompressToStream と CompressStream は書き込まれたエンコード済みバイト数を返します。空の入力に対してもクリアコードと end-of-information コードを含み、既定の PDF 設定では空の入力に 3 バイトを書き込みます

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;

ストリーム出力と診断

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=1 はデコード済みバイトをそのまま返します
  • Predictor=2 は TIFF の水平差分を逆算します
  • Predictor=10..15 は各行の先頭に格納された PNG フィルタータグを逆算します
  • Colors、BitsPerComponent、Columns が正確な行ジオメトリを定義します
  • ExpandedTo8Bit と ColorSpace はソース互換のために残されています

デコード統計

  • CodesRead、ClearCodesRead、DictionaryAdds
  • KwKwKExpansions、PeakCodeSize、PeakDictionarySize
  • OutputBytes と EndedWithEndOfInformation

エラー処理

  • 次の辞書エントリを超えるコードは拒否されます
  • 壊れたプレフィックスチェーンと不正な最初のコードは拒否されます
  • RequireEndOfInformation 有効時は、切り詰められた入力を拒否します
  • 出力の展開はフレーズを Emit する前に毎回チェックされます
  • プレディクターの行は完全で、有効なジオメトリと PNG 行タグを使う必要があります

関連項目