Delphi Xe10 实现的LZW解压缩算法

由于最近因为工作需要使用到LZW解压缩算法,找遍全网也没有发现DELPHI的版本,痛苦之下留下一个

印记,献给有类似需要的人

unit LzwDecompression;

interface
  uses
    Winapi.Windows,System.SysUtils,  System.Classes;
  function LZWDecode(pin,pout:pbyte):Integer;
implementation
const
  INIT_BITS=9;
  TABLE_SIZE= 18041;
  MAX_BITS = 14;
  HASHING_SHIFT = MAX_BITS-8;
  CLEAR_TABLE   =  256;
  TERMINATOR = 257;
  FIRST_CODE=258;
  CHECK_TIME = 100;
var
    currnt_code:PINT;
    prefix_code:array [0..3999] of NativeUInt;
    append_char:array [0..3999] of byte;
    decode_stack:array [0..3999] of byte;
    bytes_out:LongWord;
    checkpoint:LongWord = CHECK_TIME;
    num_bits:Cardinal = INIT_BITS;
    max_code:Cardinal = 0;
    end_flag:Cardinal=0;
    input_bit_count:Cardinal = 0;
    input_bit_buffer:Cardinal = 0;
function maxval(n:integer):Integer;
 begin
   result:= (1 shl n) -1;
 end;
function input_code(var input:PByte):Cardinal;
var
  return_value,input_bit_buf:Cardinal;
begin
  while input_bit_count <=24 do
  begin
    input_bit_buf := input^;
    Inc(input);
    input_bit_buf:=input_bit_buf shl (24-input_bit_count);
    input_bit_buffer:= input_bit_buffer or input_bit_buf;
    Inc(input_bit_count,8);
  end;
  return_value:=input_bit_buffer shr (32-num_bits);
  input_bit_buffer := input_bit_buffer shl num_bits;
  input_bit_count := input_bit_count - num_bits;
  result:=return_value;
end;
function decode_string(buffer:pbyte;code:Cardinal):pbyte;
var
  i:Integer;
begin
  i:=0;
  while code>255 do
  begin
    buffer^ :=append_char[code];
    Inc(buffer);
    code := prefix_code[code];
    inc(i);
    if i>=4000 then
    begin
      raise Exception.Create('内存越界');
      Exit;
    end;
  end;
  buffer^ := byte(code);
  Result :=(buffer);
end;

function LZWDecode(pin,pout:pbyte):Integer;
var
  temppstr:PByte;
  next_code:Cardinal;
  new_code,old_code:Cardinal;
  character:Integer;
  clear_flag:Boolean;
  s:string;
begin
  currnt_code:=GetMemory(TABLE_SIZE*SIZEOF(INTEGER));
  FillChar(append_char,SizeOf(append_char),0);
  FillChar(prefix_code,SizeOf(prefix_code),0);
  next_code:=FIRST_CODE;
  new_code:=0;
  clear_flag:=True;
  bytes_out:=0;
  character:=0;
  old_code:=0;
  max_code:= maxval(num_bits);
  while (new_code <> TERMINATOR) do
  begin
    new_code:=input_code(pin);
    if clear_flag then
    begin
      clear_flag:=False;
      old_code:=new_code;
      character:=old_code;
      if old_code>255 then
       pout^:=byte(old_code)
      else
       pout^:=old_code;
      s:=s+char(pout^);
      Inc(pout);
      Inc(bytes_out);
      Continue;
    end;
    if new_code = CLEAR_TABLE then
    begin
      clear_flag:=True;
      num_bits:=INIT_BITS;
      next_code:=FIRST_CODE;
      max_code:=maxval(num_bits);
      Continue;
    end;
    if new_code >= next_code then
    begin
      decode_stack[0]:=Byte(character);
      temppstr:=@decode_stack[0];
      Inc(temppstr);
      temppstr:=decode_string(temppstr,old_code);
    end
    else
    begin
      temppstr:=@decode_stack[0];
      temppstr:=decode_string(temppstr,new_code);
    end;
    character:=byte(temppstr^);
    while temppstr >= pbyte(@decode_stack[0]) do
    begin
      pout^:=Byte(temppstr^);
      Inc(bytes_out);
      s:=s+char(pout^);
      Inc(pout);
      Dec(temppstr);
    end;
    if next_code<=Cardinal(max_code) then
    begin
      prefix_code[next_code] := old_code;
      append_char[next_code] := character;
      Inc(next_code);
      if (next_code = max_code) and (num_bits <MAX_BITS) then
      begin
        Inc(num_bits);
        max_code:=maxval(num_bits);
      end;
    end;
    old_code:=new_code;
  end;
  result:=bytes_out-2;
  FreeMem(currnt_code);
end;
end.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值