150 lines
3.6 KiB
Plaintext
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.
|