URI:
       tjpegdump.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tjpegdump.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 }