我该怎么用这个过程啊?
sdenf 2004-11-11 11:05:04 我在网上找到了这个,但我不知道我该怎么用啊?
该怎么引入一段数据流让它解压出来呢?解压以后的数据我怎么得到呢?
求大侠救救命,我DELPHI是赶鸭子上架啊
const // LZW encoding and decoding support
NoLZWCode = 4096;
type
PByte = ^Byte;
TByteStream = array[0..MaxInt - 1] of Byte;
PByteStream = ^TByteStream;
// abstract decoder class to define the base functionality of an encoder/decoder
TDecoder = class
public
procedure Decode(var Source: Pointer; Dest: Pointer; PackedSize, UnpackedSize: Integer); virtual; abstract;
procedure Encode(Source, Dest: Pointer; var FByteCounts: Cardinal); virtual; abstract;
end;
// Note: We need a different LZW decoder class for GIF because the bit order is reversed compared to that
// of TIFF and the code size increment is handled slightly different.
TGIFLZW = class(TDecoder)
private
FCodeSize: Cardinal;
FCodeMask: Cardinal;
FFreeCode: Cardinal;
FOldCode: Cardinal;
FPrefix: array[0..4095] of Cardinal; // LZW prefix
FSuffix, // LZW suffix
FStack: array [0..4095] of Byte; // stack
FStackPointer: PByte;
FTarget: PByte;
FFirstChar: Byte; // buffer for decoded byte
FClearCode,
FEOICode: Word;
function DecodeLZW(Code: Cardinal): Boolean;
public
InitialCodeSize: Byte; // must be set before decoding is started!
procedure Decode(var Source: Pointer; Dest: Pointer; PackedSize, UnpackedSize: Integer); override;
procedure Encode(Source, Dest: Pointer; var FByteCounts: Cardinal); override;
end;
implementation
function TGIFLZW.DecodeLZW(Code: Cardinal): Boolean;
var
InCode: Cardinal; // buffer for passed code
begin
// handling of clear codes
if Code = FClearCode then
begin
// reset of all variables
FCodeSize := InitialCodeSize + 1;
FCodeMask := (1 shl FCodeSize) - 1;
FFreeCode := FClearCode + 2;
FOldCode := NoLZWCode;
Result := True;
Exit;
end;
// check whether it is a valid, already registered code
if Code > FFreeCode then
raise Exception.Create('GIF LZW: invalid opcode.');
// handling for the first LZW code: print and keep it
if FOldCode = NoLZWCode then
begin
FFirstChar := FSuffix[Code];
FTarget^ := FFirstChar;
Inc(FTarget);
FOldCode := Code;
Result := True;
Exit;
end;
// keep the passed LZW code
InCode := Code;
// the first LZW code is always smaller than FFirstCode
if Code = FFreeCode then
begin
FStackPointer^ := FFirstChar;
Inc(FStackPointer);
Code := FOldCode;
end;
// loop to put decoded bytes onto the stack
while Code > FClearCode do
begin
FStackPointer^ := FSuffix[Code];
Inc(FStackPointer);
Code := FPrefix[Code];
end;
// place new code into code table
FFirstChar := FSuffix[Code];
FStackPointer^ := FFirstChar;
Inc(FStackPointer);
FPrefix[FFreeCode] := FOldCode;
FSuffix[FFreeCode] := FFirstChar;
// increase code size if necessary
if (FFreeCode = FCodeMask) and
(FCodeSize < 12) then
begin
Inc(FCodeSize);
FCodeMask := (1 shl FCodeSize) - 1;
end;
if FFreeCode < 4095 then Inc(FFreeCode);
// put decoded bytes (from the stack) into the target buffer
FOldCode := InCode;
repeat
Dec(FStackPointer);
FTarget^ := FStackPointer^;
Inc(FTarget);
until FStackPointer = @FStack;
Result := True;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TGIFLZW.Decode(var Source: Pointer; Dest: Pointer; PackedSize, UnpackedSize: Integer);
var
I: Integer;
Data, // current data
Bits, // counter for bit management
Code: Cardinal; // current code value
SourcePtr: PByte;
begin
FTarget := Dest;
SourcePtr := Source;
// initialize parameter
FCodeSize := InitialCodeSize + 1;
FClearCode := 1 shl InitialCodeSize;
FEOICode := FClearCode + 1;
FFreeCode := FClearCode + 2;
FOldCode := NoLZWCode;
FCodeMask := (1 shl FCodeSize) - 1;
// init code table
for I := 0 to FClearCode - 1 do
begin
FPrefix[I] := NoLZWCode;
FSuffix[I] := I;
end;
// initialize stack
FStackPointer := @FStack;
Data := 0;
Bits := 0;
while PackedSize > 0 do
begin
// read code from bit stream
Inc(Data, SourcePtr^ shl Bits);
Inc(Bits, 8);
while Bits >= FCodeSize do
begin
// current code
Code := Data and FCodeMask;
// prepare next run
Data := Data shr FCodeSize;
Dec(Bits, FCodeSize);
// EOICode -> decoding finished, check also for badly written codes and
// terminate the loop as soon as the target is filled up
if (Code = FEOICode) or
((PChar(FTarget) - PChar(Dest)) >= UnpackedSize) then Exit;
if not DecodeLZW(Code) then Break;
end;
Inc(SourcePtr);
Dec(PackedSize);
end;
end;