diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/lib/readpicfile.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/lib/readpicfile.b')
| -rw-r--r-- | appl/lib/readpicfile.b | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/appl/lib/readpicfile.b b/appl/lib/readpicfile.b new file mode 100644 index 00000000..a8983d24 --- /dev/null +++ b/appl/lib/readpicfile.b @@ -0,0 +1,164 @@ +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); +} |
