168 lines
4.5 KiB
ObjectPascal

(* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TurboPower Abbrevia
*
* The Initial Developer of the Original Code is Craig Peterson
*
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Craig Peterson <capeterson@users.sourceforge.net>
*
* ***** END LICENSE BLOCK ***** *)
{*********************************************************}
{* ABBREVIA: AbPPMd.pas *}
{*********************************************************}
{* ABBREVIA: PPMd decompression *}
{*********************************************************}
unit AbPPMd;
{$I AbDefine.inc}
interface
uses
Classes;
procedure DecompressPPMd(aSrc, aDes: TStream);
implementation
uses
AbCrtl,
SysUtils,
AbExcept;
// Compiled with:
// Release: bcc32 -q -c *.c
// Debug: bcc32 -q -c -v -y *.c
{ Linker derectives ======================================================== }
// Don't re-order these; it will cause linker errors
{$IF DEFINED(WIN32)}
{$L Win32\PPMdVariantI.obj}
{$L Win32\PPMdContext.obj}
{$L Win32\PPMdSubAllocatorVariantI.obj}
{$L Win32\CarrylessRangeCoder.obj}
{$ELSEIF DEFINED(WIN64)}
{$L Win64\PPMdVariantI.obj}
{$L Win64\PPMdContext.obj}
{$L Win64\PPMdSubAllocatorVariantI.obj}
{$L Win64\CarrylessRangeCoder.obj}
{$IFEND}
{ CarrylessRangeCoder.h ==================================================== }
type
PInStream = ^TInStream;
TInStream = record
nextByte: function(Self: PInStream): Byte; cdecl;
// Private data
stream: TStream;
InPos: Integer;
InCount: Integer;
InBuf: array[0..4097] of Byte;
end;
{ -------------------------------------------------------------------------- }
function TInStream_NextByte(Self: PInStream): Byte; cdecl;
begin
if Self.InPos = Self.InCount then begin
Self.InCount := Self.stream.Read(Self.InBuf, SizeOf(Self.InBuf));
if Self.InCount = 0 then
raise EAbReadError.Create;
Self.InPos := 0;
end;
Result := Self.InBuf[Self.InPos];
Inc(Self.InPos);
end;
{ -------------------------------------------------------------------------- }
function TInStream_Create(aStream: TStream): PInStream;
begin
GetMem(Result, SizeOf(TInStream));
Result.nextByte := TInStream_NextByte;
Result.stream := aStream;
Result.InPos := 0;
Result.InCount := 0;
end;
{ PPMdVariantI.h =========================================================== }
type
PPMdModelVariantI = Pointer;
function CreatePPMdModelVariantI(const input: TInStream;
suballocsize, maxorder, restoration: Integer): PPMdModelVariantI; cdecl; external;
procedure FreePPMdModelVariantI(Self: PPMdModelVariantI); cdecl; external;
function NextPPMdVariantIByte(Self: PPMdModelVariantI): Integer; cdecl; external;
{ Decompression routines =================================================== }
procedure DecompressPPMd(aSrc, aDes: TStream);
const
OutBufSize = 4096;
var
nextByte: Integer;
params: word;
ppmd: PPMdModelVariantI;
Src: PInStream;
OutBuf: PByteArray;
OutPos: Integer;
begin
Src := TInStream_Create(aSrc);
try
GetMem(OutBuf, OutBufSize);
try
OutPos := 0;
ASrc.ReadBuffer(Params, SizeOf(Params));// Pkzip stream header
ppmd := CreatePPMdModelVariantI(Src^,
(((Params shr 4) and $FF) + 1) shl 20,// sub-allocator size
(Params and $0F) + 1, // model order
Params shr 12); // model restoration method
try
while True do begin
nextByte := NextPPMdVariantIByte(ppmd);
if nextByte < 0 then Break;
OutBuf[OutPos] := Byte(nextByte);
Inc(OutPos);
if OutPos = OutBufSize then begin
aDes.WriteBuffer(OutBuf^, OutBufSize);
OutPos := 0;
end;
end;
if OutPos > 0 then
aDes.WriteBuffer(OutBuf^, OutPos);
finally
FreePPMdModelVariantI(ppmd);
end;
finally
FreeMem(OutBuf);
end;
finally
FreeMem(Src);
end;
end;
end.