diff options
Diffstat (limited to 'src/cmd/jpg/jpegdump.c')
-rw-r--r-- | src/cmd/jpg/jpegdump.c | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/src/cmd/jpg/jpegdump.c b/src/cmd/jpg/jpegdump.c new file mode 100644 index 00000000..0b132cb7 --- /dev/null +++ b/src/cmd/jpg/jpegdump.c @@ -0,0 +1,346 @@ +/* jpeg parser by tom szymanski */ +#include <stddef.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <ctype.h> + +/* subroutines done by macros */ +#define min(A,B) ((A)<(B) ? (A) : (B)) +#define max(A,B) ((A)>(B) ? (A) : (B)) +#define maxeql(A,B) if (A < (B)) A = (B); +#define mineql(A,B) if (A > (B)) A = (B); +#define eatarg0 (argc--, argv++) +#define arrayLength(A) ((sizeof A)/ (sizeof A[0])) + +FILE *infile; +char *fname; + +/* Routines to print error messages of varying severity */ + +/* externally visible variables */ +int warncnt; +char *myname; + +void getname (char *arg) { + /* Save name of invoking program for use by error routines */ + register char *p; + p = strrchr (arg, '/'); + if (p == NULL) + myname = arg; + else + myname = ++p; +} + +static void introduction (void) { + warncnt++; + fflush (stdout); + if (myname != NULL) + fprintf (stderr, "%s: ", myname); +} + +void warn (char *fmt, ...) { + va_list args; + introduction (); + va_start (args, fmt); + vfprintf (stderr, fmt, args); + va_end (args); + fputc ('\n', stderr); + fflush (stderr); +} + +void quit (char *fmt, ...) { + va_list args; + introduction (); + va_start (args, fmt); + vfprintf (stderr, fmt, args); + va_end (args); + fputc ('\n', stderr); + fflush (stderr); + exit (1); +} + +void fatal (char *fmt, ...) { + va_list args; + introduction (); + va_start (args, fmt); + vfprintf (stderr, fmt, args); + va_end (args); + fprintf (stderr, "\nbetter get help!\n"); + fflush (stderr); + abort (); +} + +int toption = 0; +int dqt[16][64]; + +int get1 (void) { + unsigned char x; + if (fread(&x, 1, 1, infile) == 0) + quit ("unexpected EOF"); + return x; +} + +int get2 (void) { + int x; + + x = get1() << 8; + return x | get1(); +} + +void eatmarker (int kind) { + int l, c; + l = get2(); + printf ("%02x len=%d\n", kind, l); + for (l -= 2; l > 0; l--) + get1(); +} + +char *sofName[16] = { + "Baseline sequential DCT - Huffman coding", + "Extended sequential DCT - Huffman coding", + "Progressive DCT - Huffman coding", + "Lossless - Huffman coding", + "4 is otherwise used", + "Sequential DCT - differential Huffman coding", + "Progressive DCT - differential Huffman coding", + "Lossless - differential Huffman coding", + "8 is reserved", + "Extended Sequential DCT - arithmetic coding", + "Progressive DCT - arithmetic coding", + "Lossless - arithmetic coding", + "c is otherwise used", + "Sequential DCT - differential arithmetic coding", + "Progressive DCT - differential arithmetic coding", + "Lossless - differential arithmetic coding", +}; + +void get_sof (int kind) { + int i, length, height, width, precision, ncomponents; + int id, sf, tab; + length = get2(); + precision = get1(); + height = get2(); + width = get2(); + ncomponents = get1(); + printf ("SOF%d:\t%s\n", kind - 0xc0, sofName[kind - 0xc0]); + printf ("\t%d wide, %d high, %d deep, %d components\n", + width, height, precision, ncomponents); + for (i = 0; i < ncomponents; i++) { + id = get1(); + sf = get1(); + tab = get1(); + printf ("\tcomponent %d: %d hsample, %d vsample, quantization table %d\n", + id, sf >> 4, sf & 0xf, tab); + } +} + +void get_com (int kind) { + int l, c; + l = get2(); + printf ("COM len=%d '", l); + for (l -= 2; l > 0; l--) + putchar (c = get1()); + printf ("'\n"); +} + +void get_app (int kind) { + int l, c, first; + char buf[6]; + int nbuf, nok; + l = get2(); + printf ("APP%d len=%d\n", kind - 0xe0, l); + nbuf = 0; + nok = 0; + first = 1; + /* dump printable strings in comment */ + for (l -= 2; l > 0; l--){ + c = get1(); + if(isprint(c)){ + if(nbuf >= sizeof buf){ + if(!first && nbuf == nok) + printf(" "); + printf("%.*s", nbuf, buf); + nbuf = 0; + first = 0; + } + buf[nbuf++] = c; + nok++; + }else{ + if(nok >= sizeof buf) + if(nbuf > 0) + printf("%.*s", nbuf, buf); + nbuf = 0; + nok = 0; + } + } + if(nok >= sizeof buf) + if(nbuf > 0){ + if(!first && nbuf == nok) + printf(" "); + printf("%.*s", nbuf, buf); + } +} + +void get_dac (int kind) { + eatmarker (kind); +} + +int get1dqt (void) { + int t, p, i, *tab; + t = get1(); + p = t >> 4; + t = t & 0xf; + printf ("DQT:\tp = %d, table = %d\n", p, t); + tab = &dqt[t][0]; + for (i = 0; i < 64; i++) + tab[i] = p ? get2() : get1(); + if (toption) { + for (i = 0; i < 64; i++) + printf ("\t%q[%02d] = %d\n", i, tab[i]); + } + return p ? 65 : 129; +} + +void get_dqt (int kind) { + int length; + length = get2() - 2; + while (length > 0) + length -= get1dqt(); +} + +int get1dht (void) { + int l, tcth, p, i, j, v[16], vv[16][256]; + tcth = get1(); + printf ("DHT:\tclass = %d, table = %d\n", tcth >> 4, tcth & 0xf); + for (i = 0; i < 16; i++) + v[i] = get1(); + l = 17; + for (i = 0; i < 16; i++) + for (j = 0; j < v[i]; j++) { + vv[i][j] = get1(); + l += 1; + } + if (toption) { + for (i = 0; i < 16; i++) + printf ("\t%l[%02d] = %d\n", i+1, v[i]); + for (i = 0; i < 16; i++) + for (j = 0; j < v[i]; j++) + printf ("\t%v[%02d,%02d] = %d\n", i+1, j+1, vv[i][j]); + } + return l; +} + +void get_dht (int kind) { + int length; + length = get2() - 2; + while (length > 0) + length -= get1dht(); +} + +void get_sos (int kind) { + int i, length, ncomponents, id, dcac, ahal; + length = get2(); + ncomponents = get1(); + printf ("SOS:\t%d components\n", ncomponents); + for (i = 0; i < ncomponents; i++) { + id = get1(); + dcac = get1(); + printf ("\tcomponent %d: %d DC, %d AC\n", id, dcac >> 4, dcac & 0xf); + } + printf ("\tstart spectral %d\n", get1()); + printf ("\tend spectral %d\n", get1()); + ahal = get1(); + printf ("\tah = %d, al = %d\n", ahal >> 4, ahal &0xf); +} + +main (int argc, char *argv[]) { + int l, stuff, i, j, c; + while (argc > 1 && argv[1][0] == '-') { + switch (argv[1][1]) { + case 't': + toption = 1; + break; + default: + warn ("bad option '%c'", argv[1][1]); + } + eatarg0; + } + fname = argv[1]; + infile = fopen (fname, "r"); + if (infile == NULL) + quit ("can't open %s\n", fname); + Start: +// if (get1() != 0xff || get1() != 0xd8) +// quit ("not JFIF"); +// printf ("SOI\n"); +// get_app (0xe0); + for (;;) { + c = get1(); + if (c != 0xff) + quit ("expected marker, got %2x", c); + do { + c = get1(); + } while (c == 0xff); +marker: + switch (c) { + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcd: case 0xce: case 0xcf: + get_sof (c); + break; + case 0xc4: + get_dht (c); + break; + case 0xcc: + get_dac (c); + break; + case 0xd8: + printf ("SOI\n"); + break; + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + get_app(c); + break; + case 0xda: + get_sos (c); + goto newentropy; + case 0xdb: + get_dqt (c); + break; + case 0xfe: + get_com (c); + break; + case 0xd9: + printf ("EOI\n"); + if((c=getc(infile)) == EOF) + exit(0); + ungetc(c, infile); + goto Start; + default: + eatmarker (c); + } + continue; +newentropy: + l = stuff = 0; +entropy: + while ((c = get1()) != 0xff) + l += 1; + while (c == 0xff) + c = get1(); + if (c == 0) { + stuff += 1; + goto entropy; + } + printf ("sequence length %d with %d stuffs\n", l, stuff); + if (0xd0 <= c && c <= 0xd7) { + printf ("restart %d\n", c - 0xd0); + goto newentropy; + } + goto marker; + } +} |