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