jpegdump.c (7181B)
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> 9 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])) 17 18 FILE *infile; 19 char *fname; 20 21 /* Routines to print error messages of varying severity */ 22 23 /* externally visible variables */ 24 int warncnt; 25 char *myname; 26 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 } 36 37 static void introduction (void) { 38 warncnt++; 39 fflush (stdout); 40 if (myname != NULL) 41 fprintf (stderr, "%s: ", myname); 42 } 43 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 } 53 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 } 64 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 } 75 76 int toption = 0; 77 int dqt[16][64]; 78 79 int get1 (void) { 80 unsigned char x; 81 if (fread(&x, 1, 1, infile) == 0) 82 quit ("unexpected EOF"); 83 return x; 84 } 85 86 int get2 (void) { 87 int x; 88 89 x = get1() << 8; 90 return x | get1(); 91 } 92 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 } 100 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 }; 119 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); 137 } 138 } 139 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"); 147 } 148 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; 168 } 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; 177 } 178 } 179 if(nok >= sizeof buf) 180 if(nbuf > 0){ 181 if(!first && nbuf == nok) 182 printf(" "); 183 printf("%.*s", nbuf, buf); 184 } 185 } 186 187 void get_dac (int kind) { 188 eatmarker (kind); 189 } 190 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]); 203 } 204 return p ? 65 : 129; 205 } 206 207 void get_dqt (int kind) { 208 int length; 209 length = get2() - 2; 210 while (length > 0) 211 length -= get1dqt(); 212 } 213 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; 225 } 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]); 232 } 233 return l; 234 } 235 236 void get_dht (int kind) { 237 int length; 238 length = get2() - 2; 239 while (length > 0) 240 length -= get1dht(); 241 } 242 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); 252 } 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); 257 } 258 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]); 268 } 269 eatarg0; 270 } 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); 327 } 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; 339 } 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; 344 } 345 goto marker; 346 } 347 }