aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/jpg/jpegdump.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/jpg/jpegdump.c')
-rw-r--r--src/cmd/jpg/jpegdump.c346
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;
+ }
+}