rsvk/Component/FileStrucAriDecoderUnit.pas

150 lines
3.6 KiB
Plaintext

unit FileStrucAriDecoderUnit;
{-------------------------------------------------------------------------------
File Structured Arithmetic Decoder Unit
---------------------------------------
reSource v2.6
Copyright (C) 1998-2001 Victor Kasenda / gruv
http://go.to/gruv
email: vickas@singnet.com.sg
Desc:
Derives from Structured arithmetic decoder to allow it to write to files.
Handles the input from the archive file by implementing InputBit/InputBits.
To use:
Create the class.
Call DecodeBlock.
Free.
DecodeBlock
Wrapper proc.
Decode from file to block. returns the block length in block_length.
-------------------------------------------------------------------------------}
(**) interface (**)
uses Classes,
StructsUnit,
StrucAriDecoderUnit, GroupAriModelUnit, ArchiveFileUnit;
type
TFileStrucAriDecoder = class(TStrucAriDecoder)
protected
ArchiveFile: TArchiveFile;
function InputBit: byte; override;
function InputBits( count: byte ): longint; override;
public
constructor Create;
destructor Destroy; override;
procedure DecodeBlock(_ArchiveFile: TArchiveFile; block: PBlock; var block_length: integer);
end;
(**) implementation (**)
constructor TFileStrucAriDecoder.Create;
begin
inherited Create;
end;
destructor TFileStrucAriDecoder.Destroy;
begin
inherited Destroy;
end;
function TFileStrucAriDecoder.InputBit: byte;
begin
result := ArchiveFile.InputBit;
end;
function TFileStrucAriDecoder.InputBits( count: byte ): longint;
begin
result := ArchiveFile.InputBits(count);
end;
procedure TFileStrucAriDecoder.DecodeBlock(_ArchiveFile: TArchiveFile; block: PBlock; var block_length: integer);
var
i, j: longint;
symbol: integer;
mask: integer;
run_length: integer;
begin
ArchiveFile := _ArchiveFile;
ArchiveFile.BeginBitReadAccess;
StartDecoding;
i := 0;
DecodeSymbol(symbol);
while (symbol <> EOF_SYMBOL) do
begin
{Convert the symbols to ascii
symbols 0 and 1 represent runs of 0s.
symbols 2 - 256 represent ascii 1-255 repectively.
symbol 257 is the EOB}
if (symbol <= 1) then
begin
{expand runs}
{successive 0s have weights 1, 2, 4, 8, 16, ..., while
successive 1s have weights 2, 4, 8, 16, 32, ... .}
{read in symbols and get run length.
start off with the currently read symbol}
run_length := 0;
mask := 1;
repeat
if (symbol = 0) then
inc(run_length, mask)
else
inc(run_length, (mask shl 1));
mask := mask shl 1;
DecodeSymbol(symbol);
until (symbol > 1) or (symbol = EOF_SYMBOL);
{expand run and update i}
for j := 1 to run_length do
begin
block^[i] := 0;
inc(i);
end;
{DEBUG: Test no run expansion.
1 should not appear because MTF_1 is symbol_2}
{Assert(symbol <> 1, 'No run expansion but symbol_1 appeared.');
block^[i] := 0;
DecodeSymbol(symbol);
inc(i);}
{symbol has been filled with a value greater than 1 or it is EOF_SYMBOL
i is positioned to the next pos to fill}
end
else
begin
{decrement symbol value by 1 to get the ascii}
block^[i] := byte(symbol-1);
inc(i);
DecodeSymbol(symbol);
end;
end;
block_length := i;
{DEBUG: If there is no run_length compression, then the block_length should be
blocksize for all except the last block.}
//Assert(block_length = BLOCKSIZE, 'block_length <> BlockSize');
DoneDecoding;
ArchiveFile.EndBitReadAccess;
end;
end.