ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/lib/readxbitmap.b/
implement RImagefile;
include "sys.m";
sys: Sys;
include "draw.m";
draw: Draw;
include "bufio.m";
bufio: Bufio;
Iobuf: import bufio;
include "imagefile.m";
init(iomod: Bufio)
{
if(sys == nil)
sys = load Sys Sys->PATH;
bufio = iomod;
}
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);
}
read(fd: ref Iobuf): (ref Rawimage, string)
{
width, height, fnd: int;
(fnd, width) = get_define(fd);
if(fnd)
(fnd, height) = get_define(fd);
if(!fnd)
return (nil, "xbitmap doesn't start with width and height");
if(height <= 0 || width <= 0)
return (nil, "xbitmap has bad width or height");
# now, optional x_hot, y_hot
(fnd, nil) = get_define(fd);
if(fnd)
(fnd, nil) = get_define(fd);
# now expect 'static char x...x_bits[] = {'
if(!get_to_char(fd, '{'))
return (nil, "xbitmap premature eof");
bytesperline := (width+7) / 8;
pixels := array[width*height] of byte;
pixi := 0;
for(i := 0; i < height; i++) {
for(j := 0; j < bytesperline; j++) {
(vfnd, v) := get_hexbyte(fd);
if(!vfnd)
return (nil, "xbitmap premature eof");
kend := 7;
if(j == bytesperline-1)
kend = (width-1)%8;
for(k := 0; k <= kend; k++) {
if(v & (1<<k))
pixels[pixi] = byte 0;
else
pixels[pixi] = byte 1;
pixi++;
}
}
}
cmap := array[6] of {byte 0, byte 0, byte 0,
byte 255, byte 255, byte 255};
chans := array[1] of {pixels};
ans := ref Rawimage(Draw->Rect((0,0),(width,height)), cmap, 0, byte 0, 1, chans, CRGB1, 0);
return (ans, "");
}
# get a line, which should be of form
# '#define fieldname val'
# and return (found, integer rep of val)
get_define(fd: ref Iobuf) : (int, int)
{
c := fd.getc();
if(c != '#') {
fd.ungetc();
return (0, 0);
}
line := fd.gets('\n');
for(i := len line -1; i >= 0; i--)
if(line[i] == ' ')
break;
val := int line[i+1:];
return (1, val);
}
# read fd until get char cterm; return 1 if found
get_to_char(fd: ref Iobuf, cterm: int) : int
{
for(;;) {
c := fd.getc();
if(c < 0)
return c;
if(c == cterm)
return 1;
}
}
# read fd until get xDD, were DD are hex digits.
# return (found, value of DD as integer)
get_hexbyte(fd: ref Iobuf) : (int, int)
{
if(!get_to_char(fd, 'x'))
return (0, 0);
n1 := hexdig(fd.getc());
n2 := hexdig(fd.getc());
if(n1 < 0 || n2 < 0)
return (0, 0);
return (1, (n1<<4) | n2);
}
hexdig(c: int) : int
{
if('0' <= c && c <= '9')
c -= '0';
else if('a' <= c && c <= 'f')
c += 10 - 'a';
else if('A' <= c && c <= 'F')
c += 10 - 'A';
else
c = -1;
return c;
}