Listing 19


//das Listing verdeutlicht eine Möglichkeit Daten nach dem RLE
//(run length encoding = Lauflängencodierung) Verfahren zu komprimieren

unit RLE;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Button3: TButton;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function RunLengthCompress(s: string): string;
var cv, vv, po, co: Word;

begin //Längenbyte: 0-127 -> x gleiche Zeichen; 128-255 -> x ungleiche Zeichen folgen

if Length(s)<3 then begin result:=s; Exit; end;

cv:=1; vv:=1; result:='';
while cv<=Length(s) do
begin

   if s[cv]=Copy(s, cv+1, 1) then
   begin
      if cv-vv>0 then
      begin
         co:=cv-vv;
         while co>127 do begin result:=result+chr(127+128)+Copy(s, vv, 127); co:=co-127; vv:=vv+127; end;
         result:=result+chr(co+128)+Copy(s, vv, co);
         vv:=cv;
      end;

      //cv und cv+1 gleich -> mind. 2 gleiche Zeichen gefunden
      for po:=cv+1 to Length(s) do
         if s[po]<>Copy(s, po+1, 1) then
         begin
            co:=po-vv+1;
            while co>127 do begin result:=result+chr(127)+s[cv]; co:=co-127; vv:=vv+127; end;
            result:=result+chr(co)+s[cv];
            cv:=po;
            vv:=po+1;
            Break;
         end;
   end;

   if (cv=Length(s)) and (vv<=Length(s)) then
   begin
      co:=cv-vv+1;
      while co>127 do begin result:=result+chr(127+128)+Copy(s, vv, 127); co:=co-127; vv:=vv+127; end;
      result:=result+chr(co+128)+Copy(s, vv, co);
   end;

   inc(cv);
end;

end;

function RunLengthDeCompress(s: string): string;
var cv, vv, co: Word;

begin

result:='';

if Length(s)<2 then begin result:=s; Exit; end;

cv:=1;
while cv<=Length(s) do
begin
   co:=ord(s[cv]);

   if co<128 then
   begin
      if co=0 then begin inc(cv); Continue; end;

      for vv:=1 to co do
         result:=result+s[cv+1];

      cv:=cv+2;
   end
   else
   begin
      co:=co-128;

      for vv:=cv+1 to cv+co do
         result:=result+s[vv];

      cv:=cv+(co+1);
   end;

end;

end;

procedure TForm1.Button1Click(Sender: TObject);
var fo, fs: file;
    fsize: Integer;
    ofn, sfn, s: string;
    c: array[1..High(Word)] of Char;

begin
caption:='Kompression ...';

ofn:=Edit1.Text;
sfn:=ChangeFileExt(Edit1.Text, '.cmp');

AssignFile(fo, ofn);
{$I-}
Reset(fo, 1);
{$I+}

AssignFile(fs, sfn);
{$I-}
Rewrite(fs, 1);
{$I+}

if IOResult = 0 then
begin
//Achtung: das Beispiel kann nur Dateigrößen <= High(Word) bearbeiten !!!
fsize:=FileSize(fo);
BlockRead(fo, c, fsize);

s:=c;
s:=RunLengthCompress(Copy(s, 1, fsize));
BlockWrite(fs, s[1], Length(s));
end;

CloseFile(fo);
CloseFile(fs);

caption:='OK';
end;

procedure TForm1.Button2Click(Sender: TObject);
var fo, fs: file;
    fsize: Integer;
    ofn, sfn, s: string;
    c: array[1..High(Word)] of Char;

begin
caption:='Dekompression ...';

ofn:=ChangeFileExt(Edit1.Text, '.cmp');
sfn:=ChangeFileExt(Edit1.Text, 'Kopie'+ExtractFileExt(Edit1.Text));

AssignFile(fo, ofn);
{$I-}
Reset(fo, 1);
{$I+}

AssignFile(fs, sfn);
{$I-}
Rewrite(fs, 1);
{$I+}

if IOResult = 0 then
begin
fsize:=FileSize(fo);
BlockRead(fo, c, fsize);

s:=c;
s:=RunLengthDeCompress(Copy(s, 1, fsize));
BlockWrite(fs, s[1], Length(s));
end;

CloseFile(fo);
CloseFile(fs);

caption:='OK';
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
if OpenDialog1.execute then
   Edit1.Text:=OpenDialog1.FileName;
end;

end.

Zurück zur Hauptseite