Subversion Repositories planix.SVN

Rev

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

Rev Author Line No. Line
2 - 1
/* jpeg parser by tom szymanski */
2
#include <stddef.h>
3
#include <stdlib.h>
4
#include <stdio.h>
5
#include <string.h>
6
#include <math.h>
7
#include <ctype.h>
8
 
9
/* subroutines done by macros */
10
#define min(A,B)	((A)<(B) ? (A) : (B))
11
#define max(A,B)	((A)>(B) ? (A) : (B))
12
#define maxeql(A,B)	if (A < (B)) A = (B);
13
#define mineql(A,B)	if (A > (B)) A = (B);
14
#define eatarg0		(argc--, argv++)
15
#define arrayLength(A) ((sizeof A)/ (sizeof A[0]))
16
 
17
FILE *infile;
18
char *fname;
19
 
20
/* Routines to print error messages of varying severity */
21
 
22
/* externally visible variables */
23
int   warncnt;
24
char *myname;
25
 
26
void getname (char *arg) {
27
	/* Save name of invoking program for use by error routines */
28
	register char *p;
29
	p = strrchr (arg, '/');
30
	if (p == NULL)
31
		myname = arg;
32
	else
33
		myname = ++p;
34
}
35
 
36
static void introduction (void) {
37
	warncnt++;
38
	fflush (stdout);
39
	if (myname != NULL)
40
		fprintf (stderr, "%s: ", myname);
41
}
42
 
43
void warn (char *fmt, ...) {
44
	va_list args;
45
	introduction ();
46
	va_start (args, fmt);
47
	vfprintf (stderr, fmt, args);
48
	va_end (args);
49
	fputc ('\n', stderr);
50
	fflush (stderr);
51
}
52
 
53
void quit (char *fmt, ...) {
54
	va_list args;
55
	introduction ();
56
	va_start (args, fmt);
57
	vfprintf (stderr, fmt, args);
58
	va_end (args);
59
	fputc ('\n', stderr);
60
	fflush (stderr);
61
	exit (1);
62
}
63
 
64
void fatal (char *fmt, ...) {
65
	va_list args;
66
	introduction ();
67
	va_start (args, fmt);
68
	vfprintf (stderr, fmt, args);
69
	va_end (args);
70
	fprintf (stderr, "\nbetter get help!\n");
71
	fflush (stderr);
72
	abort ();
73
}
74
 
75
int toption = 0;
76
int dqt[16][64];
77
 
78
int get1 (void) {
79
	unsigned char x;
80
	if (fread(&x, 1, 1, infile) == 0)
81
		quit ("unexpected EOF");
82
	return x;
83
}
84
 
85
int get2 (void) {
86
	int x;
87
 
88
	x = get1() << 8;
89
	return x | get1();
90
}
91
 
92
void eatmarker (int kind) {
93
	int l, c;
94
	l = get2();
95
	printf ("%02x len=%d\n", kind, l);
96
	for (l -= 2; l > 0; l--)
97
		get1();
98
}
99
 
100
char *sofName[16] = {
101
	"Baseline sequential DCT - Huffman coding",
102
	"Extended sequential DCT - Huffman coding",
103
	"Progressive DCT - Huffman coding",
104
	"Lossless - Huffman coding",
105
	"4 is otherwise used",
106
	"Sequential DCT - differential Huffman coding",
107
	"Progressive DCT - differential Huffman coding",
108
	"Lossless - differential Huffman coding",
109
	"8 is reserved",
110
	"Extended Sequential DCT - arithmetic coding",
111
	"Progressive DCT - arithmetic coding",
112
	"Lossless - arithmetic coding",
113
	"c is otherwise used",
114
	"Sequential DCT - differential arithmetic coding",
115
	"Progressive DCT - differential arithmetic coding",
116
	"Lossless - differential arithmetic coding",
117
};
118
 
119
void get_sof (int kind) {
120
	int i, length, height, width, precision, ncomponents;
121
	int id, sf, tab;
122
	length = get2();
123
	precision = get1();
124
	height = get2();
125
	width = get2();
126
	ncomponents = get1();
127
	printf ("SOF%d:\t%s\n", kind - 0xc0, sofName[kind - 0xc0]);
128
	printf ("\t%d wide, %d high, %d deep, %d components\n",
129
		width, height, precision, ncomponents);
130
	for (i = 0; i < ncomponents; i++) {
131
		id = get1();
132
		sf = get1();
133
		tab = get1();
134
		printf ("\tcomponent %d: %d hsample, %d vsample, quantization table %d\n",
135
			id, sf >> 4, sf & 0xf, tab);
136
	}		
137
}
138
 
139
void get_com (int kind) {
140
	int l, c;
141
	l = get2();
142
	printf ("COM len=%d '", l);
143
	for (l -= 2; l > 0; l--)
144
		putchar (c = get1());
145
	printf ("'\n");
146
}
147
 
148
void get_app (int kind) {
149
	int l, c, first;
150
	char buf[6];
151
	int nbuf, nok;
152
	l = get2();
153
	printf ("APP%d len=%d\n", kind - 0xe0, l);
154
	nbuf = 0;
155
	nok = 0;
156
	first = 1;
157
	/* dump printable strings in comment */
158
	for (l -= 2; l > 0; l--){
159
		c = get1();
160
		if(isprint(c)){
161
			if(nbuf >= sizeof buf){
162
				if(!first && nbuf == nok)
163
					printf(" ");
164
				printf("%.*s", nbuf, buf);
165
				nbuf = 0;
166
				first = 0;
167
			}
168
			buf[nbuf++] = c;
169
			nok++;
170
		}else{
171
			if(nok >= sizeof buf)
172
				if(nbuf > 0)
173
					printf("%.*s", nbuf, buf);
174
			nbuf = 0;
175
			nok = 0;
176
		}
177
	}
178
	if(nok >= sizeof buf)
179
		if(nbuf > 0){
180
			if(!first && nbuf == nok)
181
				printf(" ");
182
			printf("%.*s", nbuf, buf);
183
		}
184
}
185
 
186
void get_dac (int kind) {
187
	eatmarker (kind);
188
}
189
 
190
int get1dqt (void) {
191
	int t, p, i, *tab;
192
	t = get1();
193
	p = t >> 4;
194
	t = t & 0xf;
195
	printf ("DQT:\tp = %d, table = %d\n", p, t);
196
	tab = &dqt[t][0];
197
	for (i = 0; i < 64; i++)
198
		tab[i] = p ? get2() : get1();
199
	if (toption) {
200
		for (i = 0; i < 64; i++)
201
			printf ("\t%q[%02d] = %d\n", i, tab[i]);
202
	}
203
	return p ? 65 : 129;
204
}
205
 
206
void get_dqt (int kind) {
207
	int length;
208
	length = get2() - 2;
209
	while (length > 0)
210
		length -= get1dqt();
211
}
212
 
213
int get1dht (void) {
214
	int l, tcth, p, i, j, v[16], vv[16][256];
215
	tcth = get1();
216
	printf ("DHT:\tclass = %d, table = %d\n", tcth >> 4, tcth & 0xf);
217
	for (i = 0; i < 16; i++)
218
		v[i] = get1();
219
	l = 17;
220
	for (i = 0; i < 16; i++)
221
		for (j = 0; j < v[i]; j++) {
222
			vv[i][j] = get1();
223
			l += 1;
224
		}
225
	if (toption) {
226
		for (i = 0; i < 16; i++)
227
			printf ("\t%l[%02d] = %d\n", i+1, v[i]);
228
		for (i = 0; i < 16; i++)
229
			for (j = 0; j < v[i]; j++)
230
				printf ("\t%v[%02d,%02d] = %d\n", i+1, j+1, vv[i][j]);
231
	}
232
	return l;
233
}
234
 
235
void get_dht (int kind) {
236
	int length;
237
	length = get2() - 2;
238
	while (length > 0)
239
		length -= get1dht();
240
}
241
 
242
void get_sos (int kind) {
243
	int i, length, ncomponents, id, dcac, ahal;
244
	length = get2();
245
	ncomponents = get1();
246
	printf ("SOS:\t%d components\n", ncomponents);
247
	for (i = 0; i < ncomponents; i++) {
248
		id = get1();
249
		dcac = get1();
250
		printf ("\tcomponent %d: %d DC, %d AC\n", id, dcac >> 4, dcac & 0xf);
251
	}
252
	printf ("\tstart spectral %d\n", get1());
253
	printf ("\tend spectral %d\n", get1());
254
	ahal = get1();
255
	printf ("\tah = %d, al = %d\n", ahal >> 4, ahal &0xf);
256
}
257
 
258
main (int argc, char *argv[]) {
259
	int l, stuff, i, j, c;
260
	while (argc > 1 && argv[1][0] == '-') {
261
		switch (argv[1][1]) {
262
		case 't':
263
			toption = 1;
264
			break;
265
		default:
266
			warn ("bad option '%c'", argv[1][1]);
267
		}
268
		eatarg0;
269
	}
270
	fname = argv[1];
271
	infile = fopen (fname, "r");
272
	if (infile == NULL)
273
		quit ("can't open %s\n", fname);
274
    Start:
275
//	if (get1() != 0xff || get1() != 0xd8)
276
//		quit ("not JFIF");
277
//	printf ("SOI\n");
278
//	get_app (0xe0);
279
	for (;;) {
280
		c = get1();
281
		if (c != 0xff)
282
			quit ("expected marker, got %2x", c);
283
		do {
284
			c = get1();
285
		} while (c == 0xff);
286
marker:
287
		switch (c) {
288
		case 0xc0: case 0xc1: case 0xc2: case 0xc3:
289
		case 0xc5: case 0xc6: case 0xc7:
290
		case 0xc8: case 0xc9: case 0xca: case 0xcb:
291
		case 0xcd: case 0xce: case 0xcf:
292
			get_sof (c);
293
			break;
294
		case 0xc4:
295
			get_dht (c);
296
			break;
297
		case 0xcc:
298
			get_dac (c);
299
			break;
300
		case 0xd8:
301
			printf ("SOI\n");
302
			break;
303
		case 0xe0: case 0xe1: case 0xe2: case 0xe3: 
304
		case 0xe4: case 0xe5: case 0xe6: case 0xe7: 
305
		case 0xe8: case 0xe9: case 0xea: case 0xeb: 
306
		case 0xec: case 0xed: case 0xee: case 0xef: 
307
			get_app(c);
308
			break;
309
		case 0xda:
310
			get_sos (c);
311
			goto newentropy;
312
		case 0xdb:
313
			get_dqt (c);
314
			break;
315
		case 0xfe:
316
			get_com (c);
317
			break;
318
		case 0xd9:
319
			printf ("EOI\n");
320
			if((c=getc(infile)) == EOF)
321
				exit(0);
322
			ungetc(c, infile);
323
			goto Start;
324
		default:
325
			eatmarker (c);
326
		}
327
		continue;
328
newentropy:
329
		l = stuff = 0;
330
entropy:
331
		while ((c = get1()) != 0xff)
332
			l += 1;
333
		while (c == 0xff)
334
			c = get1();
335
		if (c == 0) {
336
			stuff += 1;
337
			goto entropy;
338
		}
339
		printf ("sequence length %d with %d stuffs\n", l, stuff);
340
		if (0xd0 <= c && c <= 0xd7) {
341
			printf ("restart %d\n", c - 0xd0);
342
			goto newentropy;
343
		}
344
		goto marker;
345
	}
346
}