]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/jpg/jpegdump.c
cwfs: back to previous version
[plan9front.git] / sys / src / cmd / jpg / jpegdump.c
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 }