#99 Article 929 Posted at 1995/10/15 20:08:42 by えす (MAP2303) [Q.ML1]

Subject: ML1で質問です。

ごめんください、えす です。
  ml1 データの形式について教えて下さいませ。
  以下のようなプログラム組んだんですが、正常に読んでくれません。

  症状は、しばらく読みすすむと、あらたなデータの開始場所(長さ、色、連鎖と
 なっている所)で色データが違ってしまっています。長さも、正常何箇所か次のポ
 インタとなる点を飛ばしているようです。ひょっとして、長さだけの問題かもしれ
 ません。
  ある程度読み進まないと起こらないため、テスト用に作るような簡単なデータで
 は正常に表示できます(^^;
  きちっとした絵を解析するのってたいへんで、、、。しおしおです。

--------------------------------------------------------------------------
program ml1toppm;

uses dos;

const
  bit     : array [0..8] of word =
             ($01,$02,$04,$08,$10,$20,$40,$80,$100);
  wyleseg : array [1..13] of word =
             (0,2,6,14,30,62,126,254,510,1022,2046,4094,8190);

type
  datatype = object
               d : ^byte;                 {現在、データ(=d^)の }
               c : byte;                   {      c bit目を注目している。}
               function wyleread:word;
               function bitread(n:byte):longint;
               procedure rensaread(xy : word; color:word);
             end;
  headertype = record
               ver : array [1..4] of byte;
               year : byte;
               month : byte;
               day : byte;
               hour : byte;
               minite : byte;
               second : byte;
               x1 : word;
               y1 : word;
               x2 : word;
               y2 : word;
               handle : array [1..12] of char;
               fsize : word;
               machine : array [1..16] of char;
               editor : array [1..16] of char;
               comment : array [1..32] of char;
             end;

var
  header : headertype;
  pixel  : array [0..15999] of word;
  infile : file;
  filename : string;

function datatype.bitread(n:byte):longint;  { (d^,c) から n [bit] 読む。}
var                                         { d,c は進む。 }
  a,i,j : byte;
  r : longint;
begin
  i := 0;
  r := 0;
  while (i < n) do begin
    j := i;
    if (i = 0) then begin
      a := (d^ and (bit[c+1] -1));
      inc(i,c+1);
    end else begin
      a := d^;
      inc(i,8);
    end;
    if (i > n) then begin
      c := i-n-1;
      a := (a shr (c+1));
      inc(r,a);
    end else begin
      inc(longint(d),1);
      c := 7;
      inc(r,a shl (n-i));
    end;
  end;
  bitread := r;
end;

function datatype.wyleread:word;     { (d^,c) から wyle符号のデータを読む。 }
var                                  { d,c は進む。 }
  i : byte;
  r : word;
begin
  i:=1;
  while ((d^ and bit[c]) <> 0) do begin
    inc(c,-1);
    if (c=255) then begin
      inc(longint(d),1);
      c := 7;
    end;
    inc(i,1);
  end;
  inc(c,-1);
  if (c=255) then begin
    inc(longint(d),1);
    c:=7;
  end;
  r := bitread(i);
  r := wyleseg[i] + r;
  wyleread := r;
end;

procedure datatype.rensaread(xy : word; color : word);
var                            { (d^,c)から連鎖を読んで、pixelにセットする。}
  w : word;                    { d,c は移動する。 xy は移動しない。 }
  dx : shortint;
begin
  repeat
    if (xy = 6881) then
      xy := xy;
    if (xy > 15999) then
      exit;
    dx := 0;
    w := bitread(1);
    if (w = 0) then begin
      dx := 0;
    end else begin
      w := bitread(2);
      case (w) of
        0 : dx := +1;
        1 : dx := -1;
        2 : dx := -127;
        3 : begin
          if (bitread(1) = 0) then
            dx := +2
          else
            dx := -2;
        end;
      end;
    end;

    if (dx <> -127) then
      pixel[xy + dx] := color;
    inc(xy,160+dx);
  until (dx = -127);
end;

procedure exchange(var x : word);
begin
  x := (x shl 8) or (x shr 8);
end;

{ ################################ main ####################### }
var
  data    : datatype;
  l,i,j,xy: word;
  fgc     : word;
  s       : string;
  mode    : byte;
  color   : array [0..127] of word;
  p       : pointer;

begin
  filename := 'test.ml1';
  assign(infile,filename);
  reset(infile,1);

  blockread(infile,header,96);
  with header do begin
    exchange(x1);
    exchange(y1);
    exchange(x2);
    exchange(y2);
    exchange(fsize);
  end;

  getmem(data.d,header.fsize - 96);
  p := data.d;
  blockread(infile,data.d^,header.fsize -96,i);
  data.c := 7;

  mode := data.bitread(2);
  if (mode > 2) then error('this mode is not supported.');
  case mode of
    0   : begin
            for i:=0 to 127 do
              color[i] := (data.bitread(10));
          end;

    1,2 : begin
            j := data.bitread(7);
            for i:=0 to j do begin
              l := data.bitread(7);
              color[i] := word(data.bitread(10));
            end;
          end;
  end;

  for xy:=0 to 15999 do
    pixel[xy]:=$FFFF;

  xy := 0;

  with data do begin
    repeat
      l := wyleread+1;
        case mode of
          0,1 : fgc := bitread(7);
          2   : fgc := wyleread;
        end;
        pixel[xy] := fgc;
        inc(l,-1);
        i := bitread(1);
        if (i = 1) then
          rensaread(xy+160,fgc);
        inc(xy,1);
      while (l > 0) do begin
        if (pixel[xy] = $FFFF) then
          pixel[xy] := fgc
        else
          fgc := pixel[xy];
        inc(xy,1);
        inc(l,-1);
      end;
    until (xy>15999);
  end;

  freemem(p, header.fsize - 96);
  close(infile);
end.
--------------------------------------------------------------------------

                            えす。