Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/cmd/postscript/g3p9bit/g3p9bit.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
 
4
enum
5
{
6
	ERR,
7
	EOL,
8
	MAKE,
9
	TERM,
10
};
11
 
12
enum
13
{
14
	White,
15
	Black,
16
};
17
 
18
typedef struct Tab
19
{
20
	ushort	run;
21
	ushort	bits;
22
	int		code;
23
} Tab;
24
 
25
Tab	wtab[8192];
26
Tab	btab[8192];
27
uchar	bitrev[256];
28
uchar	bitnonrev[256];
29
 
30
int	readrow(uchar *rev, int*);
31
void	initwbtab(void);
32
void	sync(uchar*);
33
int	readfile(int, char*, char*);
34
 
35
int		nbytes;
36
uchar	*bytes;
37
uchar	*pixels;
38
uchar	*buf;
39
int		y;
40
uint		bitoffset;
41
uint		word24;
42
 
43
enum
44
{
45
	Bytes	= 1024*1024,
46
	Lines	= 1410,	/* 1100 for A4, 1410 for B4 */
47
	Dots		= 1728,
48
};
49
 
50
void
51
error(char *fmt, ...)
52
{
53
	char buf[256];
54
	va_list arg;
55
 
56
	if(fmt){
57
		va_start(arg, fmt);
58
		vseprint(buf, buf+sizeof buf, fmt, arg);
59
		va_end(arg);
60
		fprint(2, "g3: %s\n", buf);
61
	}
62
	exits(fmt);
63
}
64
 
65
void
66
usage(void)
67
{
68
	fprint(2, "usage: g3p9bit [-gy] file\n");
69
	exits("usage");
70
}
71
 
72
void
73
main(int argc, char **argv)
74
{
75
	int y, fd, n, m;
76
	char *t;
77
	char *file, err[ERRMAX], tbuf[5*12+1];
78
	int gray=0;
79
	int yscale=1;
80
 
81
	ARGBEGIN{
82
	case 'g':
83
		/* do simulated 2bit gray to compress x */
84
		gray++;
85
		break;
86
	case 'y':
87
		/* double each scan line to double the y resolution */
88
		yscale=2;
89
		break;
90
	default:
91
		usage();
92
	}ARGEND
93
 
94
	if(argc > 1)
95
		usage();
96
 
97
	initwbtab();
98
	buf = malloc(1024*1024);
99
	t = malloc((Dots/8)*Lines);
100
	if(buf==nil || t==nil)
101
		error("malloc failed: %r\n");
102
	pixels = (uchar*)t;
103
 
104
	file = "<stdin>";
105
	fd = 0;
106
	if(argc > 0){
107
		file = argv[0];
108
		fd = open(file, OREAD);
109
		if(fd < 0)
110
			error("can't open %s", file);
111
	}
112
	y = readfile(fd, file, err);
113
	if(y < 0)
114
		error(err);
115
	sprint(tbuf, "%11d %11d %11d %11d %11d ", gray, 0, 0, Dots/(gray+1), y*yscale);
116
	write(1, tbuf, 5*12);
117
	n = (Dots/8)*y*yscale;
118
	/* write in pieces; brazil pipes work badly with huge counts */
119
	while(n > 0){
120
		if(yscale > 1)	/* write one scan line */
121
			m = Dots/8;
122
		else{	/* write lots */
123
			m = n;
124
			if(m > 8192)
125
				m = 8192;
126
		}
127
		for(y=0; y<yscale; y++){
128
			if(write(1, t, m) != m)
129
				error("write error");
130
			n -= m;
131
		}
132
		t += m;
133
	}
134
	if(err[0])
135
		error(err);
136
	error(nil);
137
}
138
 
139
enum{
140
	Hvres,
141
	Hbaud,
142
	Hwidth,
143
	Hlength,
144
	Hcomp,
145
	HenabECM,
146
	HenabBFT,
147
	Hmsperscan,
148
};
149
 
150
int	defhdr[8] = {
151
	0,		/* 98 lpi */
152
	0,		/* 2400 baud */
153
	0,		/* 1728 pixels in 215mm */
154
	0,		/* A4, 297mm */
155
	0,		/* 1-D modified huffman */
156
	0,		/* disable ECM */
157
	0,		/* disable BFT */
158
	3,		/* 10 ms per scan */
159
};
160
 
161
int
162
crackhdr(uchar *ap, int *hdr)
163
{
164
	char *p, *q;
165
	int i;
166
 
167
	p = (char*)ap;
168
	q = p;
169
	for(i=0; i<8; i++){
170
		if(*p<'0' || '9'<*p)
171
			return -1;
172
		hdr[i] = strtol(p, &q, 0);
173
		p = q+1;
174
	}
175
	return p-(char*)ap;
176
}
177
 
178
int
179
readfile(int f, char *file, char *err)
180
{
181
	int i, r, lines;
182
	uchar *rev;
183
	int hdr[8];
184
 
185
	err[0] = 0;
186
	memset(pixels, 0, (Dots/8) * Lines);
187
	nbytes = readn(f, buf, 1024*1024);
188
	if(nbytes==1024*1024 || nbytes<=100){
189
    bad:
190
		sprint(err, "g3: file improper size or format: %s", file);
191
		return -1;
192
	}
193
	bytes = buf;
194
	if(bytes[0]=='I' && bytes[1]=='I' && bytes[2]=='*'){	/* dumb PC format */
195
		bytes += 0xf3;
196
		nbytes -= 0xf3;
197
		rev = bitrev;
198
		memmove(hdr, defhdr, sizeof defhdr);
199
	}else if(bytes[0] == 0 && strcmp((char*)bytes+1, "PC Research, Inc") == 0){	/* digifax format */
200
		memmove(hdr, defhdr, sizeof defhdr);
201
		if(bytes[45] == 0x40 && bytes[29] == 1)	/* high resolution */
202
			hdr[Hvres] = 1;
203
		else
204
			hdr[Hvres] = 0;
205
		/* hdr[26] | (hdr[27]<<8) is page number */
206
 
207
		bytes += 64;
208
		nbytes -= 64;
209
		rev = bitnonrev;
210
	}else{
211
		while(nbytes > 2){
212
			if(bytes[0]=='\n'){
213
				if(strncmp((char*)bytes+1, "FDCS=", 5) == 0){
214
					i = crackhdr(bytes+6, hdr);
215
					if(i < 0){
216
						sprint(err, "g3: bad FDCS in header: %s", file);
217
						return -1;
218
					}
219
					if(hdr[Hwidth] != 0){
220
						sprint(err, "g3: unsupported width: %s", file);
221
						return -1;
222
					}
223
					if(hdr[Hcomp] != 0){
224
						sprint(err, "g3: unsupported compression: %s", file);
225
						return -1;
226
					}
227
					bytes += i+1;
228
					nbytes -= i+1;
229
					continue;
230
				}
231
				if(bytes[1] == '\n'){
232
					bytes += 2;
233
					nbytes -= 2;
234
					break;
235
				}
236
			}
237
			bytes++;
238
			nbytes--;
239
		}
240
		if(nbytes < 2)
241
			goto bad;
242
		rev = bitnonrev;
243
	}
244
	bitoffset = 24;
245
	word24 = 0;
246
	sync(rev);
247
	lines = Lines;
248
	if(hdr[Hvres] == 1)
249
		lines *= 2;
250
	for(y=0; y<lines; y++){
251
		r = readrow(rev, hdr);
252
		if(r < 0)
253
			break;
254
		if(r == 0)
255
			sync(rev);
256
	}
257
	if(hdr[Hvres] == 1)
258
		y /= 2;
259
//	if(y < 100)
260
//		goto bad;
261
	return y;
262
}
263
 
264
int
265
readrow(uchar *rev, int *hdr)
266
{
267
	int bo, state;
268
	Tab *tab, *t;
269
	int x, oldx, x2, oldx2, dx, xx;
270
	uint w24;
271
	uchar *p, *q;
272
 
273
	state = White;
274
	oldx = 0;
275
	bo = bitoffset;
276
	w24 = word24;
277
	x = y;
278
	if(hdr[Hvres] == 1)	/* high resolution */
279
		x /= 2;
280
	p = pixels + x*Dots/8;
281
	x = 0;
282
 
283
loop:
284
	if(x > Dots)
285
		return 0;
286
	if(state == White)
287
		tab = wtab;
288
	else
289
		tab = btab;
290
	if(bo > (24-13)) {
291
		do {
292
			if(nbytes <= 0)
293
				return -1;
294
			w24 = (w24<<8) | rev[*bytes];
295
			bo -= 8;
296
			bytes++;
297
			nbytes--;
298
		} while(bo >= 8);
299
	}
300
 
301
	t = tab + ((w24 >> (24-13-bo)) & 8191);
302
	x += t->run;
303
	bo += t->bits;
304
	if(t->code == TERM){
305
		if(state == White)
306
			oldx = x;
307
		else{
308
			oldx2 = oldx;
309
			x2 = x;
310
			xx = oldx2&7;
311
			q = p+oldx2/8;
312
			if(x2/8 == oldx2/8)	/* all in one byte, but if((x2&7)==0), do harder case */
313
				*q |= (0xFF>>xx) & (0xFF<<(8-(x2&7)));
314
			else{
315
				dx = x2 - oldx2;
316
				/* leading edge */
317
				if(xx){
318
					*q++ |= 0xFF>>xx;
319
					dx -= 8-xx;
320
				}
321
				/* middle */
322
				while(dx >= 8){
323
					*q++ = 0xFF;
324
					dx -= 8;
325
				}
326
				/* trailing edge */
327
				if(dx)
328
					*q |= 0xFF<<(8-dx);
329
			}
330
		}
331
		state ^= White^Black;
332
		goto loop;
333
	}
334
	if(t->code == ERR){
335
		bitoffset = bo;
336
		word24 = w24;
337
		return 0;
338
	}
339
	if(t->code == EOL){
340
		bitoffset = bo;
341
		word24 = w24;
342
		return 1;
343
	}
344
	goto loop;
345
}
346
 
347
 
348
void
349
sync(uchar *rev)
350
{
351
	Tab *t;
352
	int c;
353
 
354
	c = 0;
355
loop:
356
	if(bitoffset > (24-13)) {
357
		do {
358
			if(nbytes <= 0)
359
				return;
360
			word24 = (word24<<8) | rev[*bytes];
361
			bitoffset -= 8;
362
			bytes++;
363
			nbytes--;
364
		} while(bitoffset >= 8);
365
	}
366
	t = wtab + ((word24 >> (24-13-bitoffset)) & 8191);
367
	if(t->code != EOL) {
368
		bitoffset++;
369
		c++;
370
		goto loop;
371
	}
372
	bitoffset += t->bits;
373
}
374
 
375
typedef struct File
376
{
377
	char	*val;
378
	int	code;
379
}File;
380
 
381
File ibtab[] = {
382
#include "btab"
383
{nil, 0}
384
};
385
 
386
File iwtab[] = {
387
#include "wtab"
388
{nil, 0}
389
};
390
 
391
int
392
binary(char *s)
393
{
394
	int n;
395
 
396
	n = 0;
397
	while(*s)
398
		n = n*2 + *s++-'0';
399
	return n;
400
}
401
 
402
void
403
tabinit(File *file, Tab *tab)
404
{
405
	int i, j, v, r, l;
406
	char *b;
407
 
408
	for(v=0; v<8192; v++) {
409
		tab[v].run = 0;
410
		tab[v].bits = 1;
411
		tab[v].code = ERR;
412
	}
413
	for(i=0; b=file[i].val; i++){
414
		l = strlen(b);
415
		v = binary(b);
416
		r = file[i].code;
417
		if(l > 13)
418
			fprint(2, "g3: oops1 l = %d %s\n", l, b);
419
 
420
		v = v<<(13-l);
421
		for(j=0; j<(1<<((13-l))); j++) {
422
			if(tab[v].code != ERR)
423
				fprint(2, "g3: oops2 %d %s\n", r, b);
424
			tab[v].run = r;
425
			tab[v].bits = l;
426
			tab[v].code = TERM;
427
			if(r < 0) {
428
				tab[v].run = 0;
429
				tab[v].code = EOL;
430
				if(r < -1) {
431
					tab[v].bits = 1;
432
					tab[v].code = MAKE;
433
				}
434
			}
435
			if(r >= 64) {
436
				tab[v].code = MAKE;
437
			}
438
			v++;
439
		}
440
	}
441
 
442
	for(i=0; i<256; i++)
443
		for(j=0; j<8; j++)
444
			if(i & (1<<j))
445
				bitrev[i] |= 0x80 >> j;
446
	for(i=0; i<256; i++)
447
		bitnonrev[i] = i;
448
}
449
 
450
void
451
initwbtab(void)
452
{
453
	tabinit(iwtab, wtab);
454
	tabinit(ibtab, btab);
455
}