Realisierung eines Interfaces zur brotli Library von Google, aktuelle Releases auch der Windows DLL's stehen unter https://github.com/google/brotli/releases zur Verfügung.
Sicherlich ist es nur eine minimale Realisierung ohne die Klassen mit all ihren Methoden, aber zum einfachen Gebrauch reicht es schon und vor allem zum Test und für einen Vergleich mit GZip.
Ich habe den BROTLI_DEFAULT_QUALITY Wert auf 5 gesetzt nicht auf 11 wie in vielen anderen Realisierungen, dadurch ergibt sich ein Vergleichbarer Wert mit GZip, je nach Dateigröße eine etwas bessere Komprimierung in einer angemessenen Zeit. Setzt man diesen Wert auf 11, erhält man kein brauchbares Ergenis denn die benötigte Zeit ist zumindest für eine dynamische Komprimierung unbrauchbar.
brotli.pas Pascal (5,34 kByte) 24.06.2018 12:33
unit Brotli;
{$mode objfpc} {$H+}
interface
uses
Classes, SysUtils;
const
BROTLI_DEFAULT_QUALITY = 5 ; BROTLI_MIN_QUALITY = 0 ;
BROTLI_MAX_QUALITY = 11 ;
BROTLI_DEFAULT_MODE = 0 ;
BROTLI_MODE_GENERIC = 0 ; BROTLI_MODE_TEXT = 1 ; BROTLI_MODE_FONT = 2 ; BROTLI_DEFAULT_WINDOW = 22 ;
BROTLI_MIN_WINDOW_BITS = 10 ;
BROTLI_MAX_WINDOW_BITS = 24 ;
BROTLI_DECODER_RESULT_ERROR = 0 ;
BROTLI_DECODER_RESULT_SUCCESS = 1 ;
BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT = 2 ;
BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT = 3 ;
function brotliEncodeStream (inStream, outStream: TMemoryStream; mode: LongInt = BROTLI_DEFAULT_MODE): boolean;
function brotliDecodeStream (inStream, outStream: TMemoryStream): boolean;
function BrotliCompress (const aFile: string ): boolean;
function BrotliUncompress (const aFile: string ): boolean;
implementation
const
BROTLIENC_DLL = 'libbrotlienc.dll' ;
BROTLIDEC_DLL = 'libbrotlidec.dll' ;
var
BrotliEncHandle: TLibHandle = 0 ;
BrotliDecHandle: TLibHandle = 0 ;
function BrotliEncoderCompress (quality: longint; lgwin: longint; mode: LongInt;
input_size: LongWord; const input_buffer: pointer; var encoded_size: LongWord; encoded_buffer: pointer): boolean;
stdcall ; external BROTLIENC_DLL name 'BrotliEncoderCompress' ;
function BrotliDecoderDecompress (encoded_size: LongWord; const encoded_buffer: pointer; var decoded_size: LongWord; decoded_buffer: pointer): LongInt;
stdcall ; external BROTLIDEC_DLL name 'BrotliDecoderDecompress' ;
function brotliEncodeStream (inStream, outStream: TMemoryStream; mode: LongInt = BROTLI_DEFAULT_MODE): boolean;
var outSize: LongWord;
begin
result := false ;
outStream.SetSize(inStream.Size);
outSize := outStream.Size;
inStream.Position := 0 ; outStream.Position := 0 ; result := BrotliEncoderCompress (BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, mode, inStream.size, inStream.Memory, outSize, outStream.Memory);
if result then
begin
inStream.Position := 0 ; outStream.Position := 0 ; outStream.Size := outSize;
end ;
end ;
function brotliDecodeStream (inStream, outStream: TMemoryStream): boolean;
var
outSize: LongWord;
btResult: LongInt;
begin
result := false ;
outStream.SetSize(inStream.Size* 10);
outSize := outStream.Size;
inStream.Position := 0 ; outStream.Position := 0 ; btResult := BrotliDecoderDecompress (inStream.size, inStream.Memory, outSize, outStream.Memory);
result := btResult = BROTLI_DECODER_RESULT_SUCCESS;
if result then
begin
inStream.Position := 0 ; outStream.Position := 0 ; outStream.Size := outSize;
end ;
end ;
function BrotliCompress (const aFile: string ): boolean;
var inStream, outStream: TMemoryStream;
begin
result := false ;
if FileExists(aFile) then
begin
inStream := TMemoryStream.Create;
try
inStream.LoadFromFile(aFile);
outStream := TMemoryStream.Create;
try
if brotliEncodeStream (inStream, outStream, BROTLI_MODE_TEXT) then
begin
outStream.SaveToFile(aFile + '.br' );
result := true ;
end ;
finally
outStream.Free;
end ;
finally
inStream.Free;
end ;
end ;
end ;
function BrotliUncompress (const aFile: string ): boolean;
var inStream, outStream: TMemoryStream;
begin
result := false ;
if FileExists(aFile) then
begin
inStream := TMemoryStream.Create;
try
inStream.LoadFromFile(aFile);
outStream := TMemoryStream.Create;
try
if brotliDecodeStream (inStream, outStream) then
begin
outStream.SaveToFile(ChangeFileExt(aFile, '' ));
result := true ;
end ;
finally
outStream.Free;
end ;
finally
inStream.Free;
end ;
end ;
end ;
initialization
BrotliEncHandle := LoadLibrary(PChar(BROTLIENC_DLL));
BrotliDecHandle := LoadLibrary(PChar(BROTLIDEC_DLL));
finalization
if BrotliEncHandle <> 0 then
begin
FreeLibrary(BrotliEncHandle);
BrotliEncHandle := 0 ;
end ;
if BrotliDecHandle <> 0 then
begin
FreeLibrary(BrotliDecHandle);
BrotliDecHandle := 0 ;
end ;
end .
Beispiel:
brotliExample.lpr Pascal (578 Bytes) 24.06.2018 12:33
program brotli_example;
{$mode objfpc} {$H+}
uses
Classes, SysUtils, brotli;
var
StartTime, EndTime: QWord;
begin
StartTime := GetTickCount64();
BrotliCompress(ExtractFilePath(ParamStr(0 )) + 'test.dat' );
EndTime := GetTickCount64();
WriteLn('Brotli compress TickCount: ' + IntToStr(EndTime - StartTime) + ' ms' );
StartTime := GetTickCount64();
BrotliUncompress(ExtractFilePath(ParamStr(0 )) + 'test.dat.br' );
EndTime := GetTickCount64();
WriteLn('Brotli uncompress TickCount: ' + IntToStr(EndTime - StartTime) + ' ms' );
ReadLn();
end .