xref: /inferno-os/appl/lib/readxbitmap.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1implement RImagefile;
2
3include "sys.m";
4	sys: Sys;
5
6include "draw.m";
7	draw: Draw;
8
9include "bufio.m";
10	bufio: Bufio;
11	Iobuf: import bufio;
12
13include "imagefile.m";
14
15init(iomod: Bufio)
16{
17	if(sys == nil)
18		sys = load Sys Sys->PATH;
19	bufio = iomod;
20}
21
22readmulti(fd: ref Iobuf): (array of ref Rawimage, string)
23{
24	(i, err) := read(fd);
25	if(i != nil){
26		a := array[1] of { i };
27		return (a, err);
28	}
29	return (nil, err);
30}
31
32read(fd: ref Iobuf): (ref Rawimage, string)
33{
34	width, height, fnd: int;
35	(fnd, width) = get_define(fd);
36	if(fnd)
37		(fnd, height) = get_define(fd);
38	if(!fnd)
39		return (nil, "xbitmap doesn't start with width and height");
40	if(height <= 0 || width <= 0)
41		return (nil, "xbitmap has bad width or height");
42	# now, optional x_hot, y_hot
43	(fnd, nil) = get_define(fd);
44	if(fnd)
45		(fnd, nil) = get_define(fd);
46	# now expect 'static char x...x_bits[] = {'
47	if(!get_to_char(fd, '{'))
48		return (nil, "xbitmap premature eof");
49
50	bytesperline := (width+7) / 8;
51	pixels := array[width*height] of byte;
52	pixi := 0;
53	for(i := 0; i < height; i++) {
54		for(j := 0; j < bytesperline; j++) {
55			(vfnd, v) := get_hexbyte(fd);
56			if(!vfnd)
57				return (nil,  "xbitmap premature eof");
58			kend := 7;
59			if(j == bytesperline-1)
60				kend = (width-1)%8;
61			for(k := 0; k <= kend; k++) {
62				if(v & (1<<k))
63					pixels[pixi] = byte 0;
64				else
65					pixels[pixi] = byte 1;
66				pixi++;
67			}
68		}
69	}
70	cmap := array[6] of {byte 0, byte 0, byte 0,
71			byte 255, byte 255, byte 255};
72	chans := array[1] of {pixels};
73	ans := ref Rawimage(Draw->Rect((0,0),(width,height)), cmap, 0, byte 0, 1, chans, CRGB1, 0);
74	return (ans, "");
75}
76
77# get a line, which should be of form
78#	'#define fieldname val'
79# and return (found, integer rep of val)
80get_define(fd: ref Iobuf) : (int, int)
81{
82	c := fd.getc();
83	if(c != '#') {
84		fd.ungetc();
85		return (0, 0);
86	}
87	line := fd.gets('\n');
88	for(i := len line -1; i >= 0; i--)
89		if(line[i] == ' ')
90			break;
91	val := int line[i+1:];
92	return (1, val);
93}
94
95# read fd until get char cterm; return 1 if found
96get_to_char(fd: ref Iobuf, cterm: int) : int
97{
98	for(;;) {
99		c := fd.getc();
100		if(c < 0)
101			return c;
102		if(c == cterm)
103			return 1;
104	}
105}
106
107# read fd until get xDD, were DD are hex digits.
108# return (found, value of DD as integer)
109get_hexbyte(fd: ref Iobuf) : (int, int)
110{
111	if(!get_to_char(fd, 'x'))
112		return (0, 0);
113	n1 := hexdig(fd.getc());
114	n2 := hexdig(fd.getc());
115	if(n1 < 0 || n2 < 0)
116		return (0, 0);
117	return (1, (n1<<4) | n2);
118}
119
120hexdig(c: int) : int
121{
122	if('0' <= c && c <= '9')
123		c -= '0';
124	else if('a' <= c && c <= 'f')
125		c += 10 - 'a';
126	else if('A' <= c && c <= 'F')
127		c += 10 - 'A';
128	else
129		c = -1;
130	return c;
131}
132