ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/lib/readpicfile.b/
implement RImagefile;
include "sys.m";
sys: Sys;
include "draw.m";
include "bufio.m";
bufio: Bufio;
Iobuf: import bufio;
include "imagefile.m";
Header: adt
{
fd: ref Iobuf;
ch: chan of (ref Rawimage, string);
# variables in i/o routines
buf: array of byte;
bufi: int;
nbuf: int;
TYPE: string;
CHAN: string;
NCHAN: string;
CMAP: int;
dx: int;
dy: int;
};
NBUF: con 8*1024;
init(iomod: Bufio)
{
if(sys == nil)
sys = load Sys Sys->PATH;
bufio = iomod;
}
read(fd: ref Iobuf): (ref Rawimage, string)
{
# spawn a subprocess so I/O errors can clean up easily
ch := chan of (ref Rawimage, string);
spawn readslave(fd, ch);
return <-ch;
}
readmulti(fd: ref Iobuf): (array of ref Rawimage, string)
{
(i, err) := read(fd);
if(i != nil){
a := array[1] of { i };
return (a, err);
}
return (nil, err);
}
readslave(fd: ref Iobuf, ch: chan of (ref Rawimage, string))
{
(header, err) := header(fd, ch);
if(header == nil){
ch <-= (nil, err);
exit;
}
ch <-= image(header);
}
readerror(): string
{
return sys->sprint("ReadPIC: read error: %r");
}
header(fd: ref Iobuf, ch: chan of (ref Rawimage, string)): (ref Header, string)
{
h := ref Header;
h.fd = fd;
h.ch = ch;
h.CMAP = 0;
h.dx = 0;
h.dy = 0;
cantparse := "ReadPIC: can't parse header";
for(;;){
s := fd.gets('\n');
if(s==nil || s[len s-1]!='\n')
return (nil, cantparse);
if(s == "\n")
break;
addfield(h, s[0:len s-1]);
}
if(h.dx<=0 || h.dy<=0)
return (nil, "ReadPIC: empty picture or WINDOW not set");
return (h, nil);
}
addfield(h: ref Header, s: string)
{
baddata := "ReadPIC: not a PIC header";
for(i:=0; i<len s; i++){
if(s[i] == '=')
break;
if(s[i]==0 || s[i]>16r7f){
h.ch <-= (nil, baddata);
exit;
}
}
if(i == len s){
h.ch <-= (nil, baddata);
exit;
}
case s[0:i]{
"TYPE" =>
h.TYPE = s[i+1:];
"CHAN" =>
h.CHAN = s[i+1:];
"NCHAN" =>
h.NCHAN = s[i+1:];
"CMAP" =>
h.CMAP = 1;
"WINDOW" =>
(n, l) := sys->tokenize(s[i+1:], " ");
if(n != 4){
h.ch <-= (nil, "ReadPIC: bad WINDOW specification");
exit;
}
x0 := int hd l;
l = tl l;
y0 := int hd l;
l = tl l;
h.dx = int hd l - x0;
l = tl l;
h.dy = int hd l - y0;
}
}
image(h: ref Header): (ref Rawimage, string)
{
if(h.TYPE!="dump" || h.CHAN!="rgb" || h.NCHAN!="3" || h.CMAP)
return (nil, "ReadPIC: can't handle this type of picture");
i := ref Rawimage;
i.r = ((0,0), (h.dx, h.dy));
i.cmap = nil;
i.transp = 0;
i.trindex = byte 0;
i.nchans = int h.NCHAN;
i.chans = array[i.nchans] of array of byte;
for(j:=0; j<i.nchans; j++)
i.chans[j] = array[h.dx*h.dy] of byte;
i.chandesc = CRGB;
n := h.dx*h.dy;
b := array[i.nchans*n] of byte;
if(h.fd.read(b, len b) != len b)
return (nil, "ReadPIC: file too short");
l := 0;
for(j=0; j<n; j++)
for(k:=0; k<i.nchans; k++)
i.chans[k][j] = b[l++];
return (i, nil);
}