連長圧縮 ランレングス圧縮

 データーの圧縮方法の一つで、一つの値と、その値が連続している数データーを圧縮する方法です。
モノクロ画像の圧縮や、ファックスデーターの送信に使われています、ファックスの場合、白か黒のデーターしかなく一番適した圧縮方法です。
グレースケールや、カラー画象の場合は、連続したデーターが少ないので、この方法は適していません。
文章は、殆ど連続したデーターは無く、逆にデーターが増えてしまいます。

例えば
    AAAAAAAABBBBBCCCCCCCCCDDDD    を圧縮すると  
    A8B5C9D4                    の様になります。

 パソコンのデーターはバイト単位8ビットのなっているので、8ビットのコードと、8ビットで表すことの出来る数1~255ので表現されます。
連続したしたデーターが255個を超える場合は、A255A23 (数値は1バイト(8ビット)の値) の様になります。 

 プログラムは、入力ファイルとして、in.txt 圧縮ファイルとして comp.txt 展開ファイルは out.txt となっています。
実行ファイルと同じ場所に置くことでファイルにアクセスできます。
ファイルの指定をしたい場合は、TOpenDialog、TSaveDialogを追加して下さい。



プログラム

unit main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
var
  infile, outfile : Thandle;    // 入力ファイル, 出力ファイル

// 圧縮
procedure encode;
var
  ir, x : byte;
  c, gets, puts  : integer;
  n  : byte;
  cf : double;
begin
  gets := 0;
  puts := 0;
  c := fileread(infile, ir, 1);           // 一バイト読み込み
  if c <= 0 then exit;                    // 読み込めなかったら終了
  inc(gets);
  repeat
    n := 0;
    x := ir;
    while n < 255 do begin               // 個数の最大値は8bit 255 $FF 越えたら1から
      inc(n);                            // 前の読み込みに対するカウント
      c := fileread(infile, ir, 1);      // 一バイト読み込み
      if c <= 0 then break;              // 読み込めなかったらブレーク
      inc(gets);
      if ir <> x then break;             // 前と違ったらブレーク
    end;
    if filewrite(outfile, x, 1) <= 0 then break;  // 値書き込み
    inc(puts);
    if filewrite(outfile, n, 1) <= 0 then break;  // 個数書き込み
    inc(puts);
  until c <= 0;
  Form1.Memo1.Lines.Append('読み込んだバイト数= ' + intTostr(gets));
  Form1.Memo1.Lines.Append('書きこんだバイト数= ' + intTostr(puts));
  cf := (puts / gets) * 1000;
  cf := round(cf);
  cf := cf / 1000;
  Form1.Memo1.Lines.Append('圧縮率 = ' + floatTostr(cf));
end;

// 復元
procedure decode;
var
  c, i, gets, puts  :integer;
  n, ir : byte;
begin
  gets := 0;
  puts := 0;
  repeat
    c := fileread(infile, ir, 1);       // 一バイト読み込み 値
    if c <= 0 then break;
    inc(gets);
    c := fileread(infile, n, 1);        // 一バイト読み込み 個数
    if c <= 0 then break;
    inc(gets);
    for i := 1 to n do begin            // 個数分同じ値書き込み
      c := filewrite(outfile, ir, 1);
      if c <= 0 then break;
      inc(puts);
    end;
  until c <= 0;
  Form1.Memo1.Lines.Append('読み込んだバイト数= ' + intTostr(gets));
  Form1.Memo1.Lines.Append('書きこんだバイト数= ' + intTostr(puts));
end;

// 圧縮
procedure TForm1.Button1Click(Sender: TObject);
var
  comp, text  : string;
begin
  text  := 'in.txt';          // 入力ファイル名
  comp := 'comp.txt';         // 圧縮ファイル名 
  infile := fileopen(text, fmOpenRead);          // 入力ファイルopen
  if infile = INVALID_HANDLE_VALUE then begin
    application.MessageBox('入力ファイル開けません。','注意',0);
    exit;
  end;
  outfile := filecreate(comp, fmOpenWrite, 0);  // 出力ファイル作成 既存のファイルがあったらopen 
  if outfile = INVALID_HANDLE_VALUE then begin
    application.MessageBox('圧縮先ファイル開けません。','注意',0);
    fileclose(infile);
    exit;
  end;
  memo1.Clear;
  encode;
  fileclose(infile);
  fileclose(outfile);
end;

// 展開
procedure TForm1.Button2Click(Sender: TObject);
var
  comp, text  : string;
begin
  comp := 'comp.txt';         // 圧縮ファイル名 
  text  := 'out.txt';         // 出力ファイル名
  infile := fileopen(comp, fmOpenRead);          // 圧縮ファイルopen
  if infile = INVALID_HANDLE_VALUE then begin
    application.MessageBox('圧縮ファイル開けません。','注意',0);
    exit;
  end;
  outfile := filecreate(text, fmOpenWrite, 0);  // 出力ファイル作成 既存のファイルがあったらopen 
  if outfile = INVALID_HANDLE_VALUE then begin
    application.MessageBox('出力先ファイル開けません。','注意',0);
    fileclose(infile);
    exit;
  end;
  memo1.Clear;
  decode;
  fileclose(infile);
  fileclose(outfile);
end;

end.


download Run_Length_Encoding.zip

  三角関数、逆三角関数、その他関数 に戻る