Поддержка сжатия LZW

Обзор

HotPDF декодирует legacy-потоки PDF, использующие LZWDecode фильтр, и умеет обращать вспять TIFF- или PNG-предикторы, обычно идущие с этим фильтром в паре

Ключевые возможности

  • PDF EarlyChange=1 и EarlyChange=0 переходы ширины кода
  • Порядок заполнения битов от старшего к младшему и от младшего к старшему
  • Сброс по clear-коду, конец информации и KwKwK обработка расширения
  • Прямой вывод в TStream без построения второй результирующей строки
  • Настраиваемые пределы вывода и опциональные строгие проверки начального clear и конца информации
  • TIFF Predictor 2 при 1, 2, 4, 8 или 16 битах на компоненту
  • Строчные фильтры PNG None, Sub, Up, Average и Paeth
  • Статистика по каждой распаковке: ширины кодов, рост словаря, сбросы, расширения и выходные байты

Типы

  • TPDFLZWDecompressor — переиспользуемый класс декодера
  • TPDFLZWCompressor — соответствующий класс кодировщика
  • TPDFLZWParms переносит геометрию PDF-предиктора
  • TPDFLZWFillOrder выбирает foTop или foBottom порядок битов
  • EHPDFLZWError сообщает о повреждённом входе, неподдерживаемой геометрии и превышении настроенных пределов

Свойства конфигурации

  • FillOrder выбирает порядок битов сжатых данных
  • EarlyChange выбирает правило перехода ширины словаря PDF и по умолчанию берёт True
  • InitialCodeSize принимает значения от 2 до 9 и по умолчанию равен 9 для PDF
  • Для уменьшенных алфавитов каждый несжатый байт должен быть меньше 1 shl (InitialCodeSize - 1); при сжатии EHPDFLZWError выбрасывается до записи вывода, если байт вне этого диапазона
  • MaxOutputBytes останавливает чрезмерное расширение до пересечения настроенного предела; ноль означает без ограничений
  • 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 читает с текущей входной позиции и по умолчанию восстанавливает её, когда поток seekable

Базовая распаковка LZW

TPDFLZWCompressor.CompressToStream и CompressStream возвращают число записанных закодированных байтов, включая код очистки и код конца информации для пустого входа; конфигурация 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 включён
  • Расширение вывода проверяется перед выводом каждой фразы
  • Строки предиктора должны быть полными и иметь корректную геометрию и тег PNG-строки

См. также