plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }