Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <draw.h>
5
#include <ctype.h>
6
#include "imagefile.h"
7
 
8
Rawimage *readppm(Biobuf*, Rawimage*);
9
 
10
/*
11
 * fetch a non-comment character.
12
 */
13
static
14
int
15
Bgetch(Biobufhdr *b)
16
{
17
	int c;
18
 
19
	for(;;) {
20
		c = Bgetc(b);
21
		if(c == '#') {
22
			while((c = Bgetc(b)) != Beof && c != '\n')
23
				;
24
		}
25
		return c;
26
	}		
27
}
28
 
29
/*
30
 * fetch a nonnegative decimal integer.
31
 */
32
static
33
int
34
Bgetint(Biobufhdr *b)
35
{
36
	int c;
37
	int i;
38
 
39
	while((c = Bgetch(b)) != Beof && !isdigit(c))
40
		;
41
	if(c == Beof)
42
		return -1;
43
 
44
	i = 0;
45
	do { 
46
		i = i*10 + (c-'0');
47
	} while((c = Bgetch(b)) != Beof && isdigit(c));
48
 
49
	return i;
50
}
51
 
52
static
53
int
54
Bgetdecimalbit(Biobufhdr *b)
55
{
56
	int c;
57
	while((c = Bgetch(b)) != Beof && c != '0' && c != '1')
58
		;
59
	if(c == Beof)
60
		return -1;
61
	return c == '1';
62
}
63
 
64
static int bitc, nbit;
65
 
66
static
67
int
68
Bgetbit(Biobufhdr *b)
69
{
70
	if(nbit == 0) {
71
		nbit = 8;
72
		bitc = Bgetc(b);
73
		if(bitc == -1)
74
			return -1;
75
	}
76
	nbit--;
77
	return (bitc >> nbit) & 0x1;
78
}
79
 
80
static
81
void
82
Bflushbit(Biobufhdr*)
83
{
84
	nbit = 0;
85
}
86
 
87
 
88
Rawimage**
89
readpixmap(int fd, int colorspace)
90
{
91
	Rawimage **array, *a;
92
	Biobuf b;
93
	char buf[ERRMAX];
94
	int i;
95
	char *e;
96
 
97
	USED(colorspace);
98
	if(Binit(&b, fd, OREAD) < 0)
99
		return nil;
100
 
101
	werrstr("");
102
	e = "out of memory";
103
	if((array = malloc(sizeof *array)) == nil)
104
		goto Error;
105
	if((array[0] = malloc(sizeof *array[0])) == nil)
106
		goto Error;
107
	memset(array[0], 0, sizeof *array[0]);
108
 
109
	for(i=0; i<3; i++)
110
		array[0]->chans[i] = nil;
111
 
112
	e = "bad file format";
113
	switch(Bgetc(&b)) {
114
	case 'P':
115
		Bungetc(&b);
116
		a = readppm(&b, array[0]);
117
		break;
118
	default:
119
		a = nil;
120
		break;
121
	}
122
	if(a == nil)
123
		goto Error;
124
	array[0] = a;
125
 
126
	return array;
127
 
128
Error:
129
	if(array)
130
		free(array[0]);
131
	free(array);
132
 
133
	errstr(buf, sizeof buf);
134
	if(buf[0] == 0)
135
		strcpy(buf, e);
136
	errstr(buf, sizeof buf);
137
 
138
	return nil;
139
}
140
 
141
typedef struct Pix	Pix;
142
struct Pix {
143
	char magic;
144
	int	maxcol;
145
	int	(*fetch)(Biobufhdr*);
146
	int	nchan;
147
	int	chandesc;
148
	int	invert;
149
	void	(*flush)(Biobufhdr*);
150
};
151
 
152
static Pix pix[] = {
153
	{ '1', 1, Bgetdecimalbit, 1, CY, 1, nil },	/* portable bitmap */
154
	{ '4', 1, Bgetbit, 1, CY, 1, Bflushbit },	/* raw portable bitmap */
155
	{ '2', 0, Bgetint, 1, CY, 0, nil },	/* portable greymap */
156
	{ '5', 0, Bgetc, 1, CY, 0, nil },	/* raw portable greymap */
157
	{ '3', 0, Bgetint, 3, CRGB, 0, nil },	/* portable pixmap */
158
	{ '6', 0, Bgetc, 3, CRGB, 0, nil },	/* raw portable pixmap */
159
	{ 0 },
160
};
161
 
162
Rawimage*
163
readppm(Biobuf *b, Rawimage *a)
164
{
165
	int i, ch, wid, ht, r, c;
166
	int maxcol, nchan, invert;
167
	int (*fetch)(Biobufhdr*);
168
	uchar *rgb[3];
169
	char buf[ERRMAX];
170
	char *e;
171
	Pix *p;
172
 
173
	e = "bad file format";
174
	if(Bgetc(b) != 'P')
175
		goto Error;
176
 
177
	c = Bgetc(b);
178
	for(p=pix; p->magic; p++)
179
		if(p->magic == c)
180
			break;
181
	if(p->magic == 0)
182
		goto Error;
183
 
184
 
185
	wid = Bgetint(b);
186
	ht = Bgetint(b);
187
	if(wid <= 0 || ht <= 0)
188
		goto Error;
189
	a->r = Rect(0,0,wid,ht);
190
 
191
	maxcol = p->maxcol;
192
	if(maxcol == 0) {
193
		maxcol = Bgetint(b);
194
		if(maxcol <= 0)
195
			goto Error;
196
	}
197
 
198
	e = "out of memory";
199
	for(i=0; i<p->nchan; i++)
200
		if((rgb[i] = a->chans[i] = malloc(wid*ht)) == nil)
201
			goto Error;
202
	a->nchans = p->nchan;
203
	a->chanlen = wid*ht;
204
	a->chandesc = p->chandesc;
205
 
206
	e = "error reading file";
207
 
208
	fetch = p->fetch;
209
	nchan = p->nchan;
210
	invert = p->invert;
211
	for(r=0; r<ht; r++) {
212
		for(c=0; c<wid; c++) {
213
			for(i=0; i<nchan; i++) {
214
				if((ch = (*fetch)(b)) < 0)
215
					goto Error;
216
				if(invert)
217
					ch = maxcol - ch;
218
				*rgb[i]++ = (ch * 255)/maxcol;
219
			}
220
		}
221
		if(p->flush)
222
			(*p->flush)(b);
223
	}
224
 
225
	return a;
226
 
227
Error:
228
	errstr(buf, sizeof buf);
229
	if(buf[0] == 0)
230
		strcpy(buf, e);
231
	errstr(buf, sizeof buf);
232
 
233
	for(i=0; i<3; i++)
234
		free(a->chans[i]);
235
	free(a->cmap);
236
	return nil;
237
}