Blob


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>
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]))
17 FILE *infile;
18 char *fname;
20 /* Routines to print error messages of varying severity */
22 /* externally visible variables */
23 int warncnt;
24 char *myname;
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 }
36 static void introduction (void) {
37 warncnt++;
38 fflush (stdout);
39 if (myname != NULL)
40 fprintf (stderr, "%s: ", myname);
41 }
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 }
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 }
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 }
75 int toption = 0;
76 int dqt[16][64];
78 int get1 (void) {
79 unsigned char x;
80 if (fread(&x, 1, 1, infile) == 0)
81 quit ("unexpected EOF");
82 return x;
83 }
85 int get2 (void) {
86 int x;
88 x = get1() << 8;
89 return x | get1();
90 }
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 }
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 };
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);
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");
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;
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;
178 if(nok >= sizeof buf)
179 if(nbuf > 0){
180 if(!first && nbuf == nok)
181 printf(" ");
182 printf("%.*s", nbuf, buf);
186 void get_dac (int kind) {
187 eatmarker (kind);
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]);
203 return p ? 65 : 129;
206 void get_dqt (int kind) {
207 int length;
208 length = get2() - 2;
209 while (length > 0)
210 length -= get1dqt();
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;
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]);
232 return l;
235 void get_dht (int kind) {
236 int length;
237 length = get2() - 2;
238 while (length > 0)
239 length -= get1dht();
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);
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);
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]);
268 eatarg0;
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);
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;
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;
344 goto marker;