parse.c

00001 /*
00002    Raw Photo Parser
00003    Copyright 2004 by Dave Coffin, dcoffin a cybercom o net
00004 
00005    This program extracts thumbnail images (preferably JPEGs)
00006    from any raw digital camera formats that have them, and
00007    shows table contents.
00008 
00009    $Revision: 1.42 $
00010    $Date: 2005/06/27 20:22:12 $
00011  */
00012 
00013 #include <stdio.h>
00014 #include <string.h>
00015 #include <stdlib.h>
00016 #include <ctype.h>
00017 
00018 #ifdef WIN32
00019 #include <winsock2.h>
00020 typedef __int64 INT64;
00021 #else
00022 #include <netinet/in.h>
00023 typedef long long INT64;
00024 #endif
00025 
00026 /*
00027    TIFF and CIFF data blocks can be quite large.
00028    Display only the first DLEN bytes.
00029  */
00030 #ifndef DLEN
00031 #define DLEN 768
00032 #endif
00033 
00034 typedef unsigned char uchar;
00035 //typedef unsigned short ushort;
00036 
00037 FILE *ifp;
00038 short order;
00039 char *fname;
00040 char make[128], model[128], model2[128], thumb_head[128];
00041 int width, height, offset, length, bps, is_dng;
00042 int thumb_offset, thumb_length, thumb_layers;
00043 
00044 struct decode {
00045   struct decode *branch[2];
00046   int leaf;
00047 } first_decode[640], *free_decode;
00048 
00049 ushort sget2 (uchar *s)
00050 {
00051   if (order == 0x4949)      /* "II" means little-endian */
00052     return s[0] | s[1] << 8;
00053   else              /* "MM" means big-endian */
00054     return s[0] << 8 | s[1];
00055 }
00056 
00057 ushort get2()
00058 {
00059   uchar str[2] = { 0xff,0xff };
00060   fread (str, 1, 2, ifp);
00061   return sget2(str);
00062 }
00063 
00064 int sget4 (uchar *s)
00065 {
00066   if (order == 0x4949)
00067     return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
00068   else
00069     return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
00070 }
00071 
00072 int get4()
00073 {
00074   uchar str[4] = { 0xff,0xff,0xff,0xff };
00075   fread (str, 1, 4, ifp);
00076   return sget4(str);
00077 }
00078 
00079 float get_float()
00080 {
00081   int i = get4();
00082   return *((float *) &i);
00083 }
00084 
00085 void tiff_dump(int base, int tag, int type, int count, int level)
00086 {
00087   int save, j, num, den;
00088   uchar c;
00089   int size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 };
00090 
00091   if (count * size[type < 13 ? type:0] > 4)
00092     fseek (ifp, get4()+base, SEEK_SET);
00093   save = ftell(ifp);
00094   printf("%*stag=0x%x %d, type=%d, count=%d, offset=%06x, data=",
00095     level*2, "", tag, tag, type, count, save);
00096   if (type==2) putchar('\"');
00097   for (j = 0; j < count && j < DLEN; j++)
00098     switch (type) {
00099       case 1: case 6: case 7:       /* byte values */
00100     printf ("%c%02x",(j & 31) || count < 17 ? ' ':'\n', fgetc(ifp) & 0xff);
00101     break;
00102       case 2:               /* null-terminated ASCII strings */
00103     c = fgetc(ifp);
00104     putchar(isprint(c) ? c:'.');
00105     break;
00106       case 3: case 8:           /* word values */
00107     printf ("%c%04x",(j & 15) || count < 9 ? ' ':'\n', get2());
00108     break;
00109       case 4: case 9:           /* dword values */
00110     printf ("%c%08x",(j & 7) || count < 5 ? ' ':'\n', get4());
00111     break;
00112       case 5: case 10:          /* rationals */
00113     num = get4();
00114     den = get4();
00115     printf (" %d/%d", num, den);
00116     break;
00117     }
00118   if (type==2) putchar('\"');
00119   putchar('\n');
00120   fseek (ifp, save, SEEK_SET);
00121 }
00122 
00123 void nikon_decrypt (uchar ci, uchar cj, int tag, int i, int size, uchar *buf)
00124 {
00125   static const uchar xlat[2][256] = {
00126   { 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
00127     0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
00128     0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
00129     0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
00130     0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
00131     0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
00132     0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
00133     0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
00134     0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
00135     0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
00136     0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
00137     0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
00138     0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
00139     0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
00140     0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
00141     0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 },
00142   { 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
00143     0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
00144     0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
00145     0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
00146     0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
00147     0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
00148     0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
00149     0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
00150     0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
00151     0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
00152     0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
00153     0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
00154     0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
00155     0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
00156     0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
00157     0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } };
00158   uchar ck=0x60;
00159 
00160   if (strncmp (buf, "02", 2)) return;
00161   ci = xlat[0][ci];
00162   cj = xlat[1][cj];
00163   printf("Decrypted tag 0x%x:\n%*s", tag, (i & 31)*3, "");
00164   for (; i < size; i++)
00165     printf("%02x%c", buf[i] ^ (cj += ci * ck++), (i & 31) == 31 ? '\n':' ');
00166   if (size & 31) puts("");
00167 }
00168 
00169 int parse_tiff_ifd (int base, int level);
00170 
00171 void nef_parse_makernote (base)
00172 {
00173   int offset=0, entries, tag, type, count, val, save;
00174   unsigned serial=0, key=0;
00175   uchar buf91[630]="", buf97[608]="", buf98[31]="";
00176   short sorder;
00177   char buf[10];
00178 
00179   puts("  Nikon MakerNote:");
00180 /*
00181    The MakerNote might have its own TIFF header (possibly with
00182    its own byte-order!), or it might just be a table.
00183  */
00184   sorder = order;
00185   fread (buf, 1, 10, ifp);
00186   if (!strcmp (buf,"Nikon")) {  /* starts with "Nikon\0\2\0\0\0" ? */
00187     base = ftell(ifp);
00188     order = get2();     /* might differ from file-wide byteorder */
00189     val = get2();       /* should be 42 decimal */
00190     offset = get4();
00191     fseek (ifp, offset-8, SEEK_CUR);
00192   } else if (!strncmp (buf,"FUJIFILM",8) ||
00193          !strcmp  (buf,"Panasonic")) {
00194     order = 0x4949;
00195     fseek (ifp,  2, SEEK_CUR);
00196   } else if (!strcmp (buf,"OLYMP") ||
00197          !strcmp (buf,"LEICA") ||
00198          !strcmp (buf,"EPSON"))
00199     fseek (ifp, -2, SEEK_CUR);
00200   else if (!strcmp (buf,"AOC"))
00201     fseek (ifp, -4, SEEK_CUR);
00202   else
00203     fseek (ifp, -10, SEEK_CUR);
00204 
00205   entries = get2();
00206   if (entries > 100) return;
00207   while (entries--) {
00208     save = ftell(ifp);
00209     tag  = get2();
00210     type = get2();
00211     count= get4();
00212     tiff_dump (base, tag, type, count, 2);
00213     if (tag == 0x1d)
00214       fscanf (ifp, "%d", &serial);
00215     if (tag == 0x91)
00216       fread (buf91, sizeof buf91, 1, ifp);
00217     if (tag == 0x97)
00218       fread (buf97, sizeof buf97, 1, ifp);
00219     if (tag == 0x98)
00220       fread (buf98, sizeof buf98, 1, ifp);
00221     if (tag == 0xa7)
00222       key = fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp);
00223 
00224     if (tag == 0x100 && type == 7 && !strncmp(make,"OLYMPUS",7)) {
00225       thumb_offset = ftell(ifp);
00226       thumb_length = count;
00227     }
00228     if (tag == 0x280 && type == 1) {    /* EPSON */
00229       strcpy (thumb_head, "\xff");
00230       thumb_offset = ftell(ifp)+1;
00231       thumb_length = count-1;
00232     }
00233     if (strstr(make,"Minolta") || strstr(make,"MINOLTA")) {
00234       switch (tag) {
00235     case 0x81:
00236       thumb_offset = ftell(ifp);
00237       thumb_length = count;
00238       break;
00239     case 0x88:
00240       thumb_offset = get4() + base;
00241       break;
00242     case 0x89:
00243       thumb_length = get4();
00244       }
00245     }
00246     if (!strcmp (buf,"OLYMP") && tag >> 8 == 0x20)
00247       parse_tiff_ifd (base, 3);
00248     fseek (ifp, save+12, SEEK_SET);
00249   }
00250   nikon_decrypt (serial, key, 0x91,   4, sizeof buf91, buf91);
00251   nikon_decrypt (serial, key, 0x97, 284, sizeof buf97, buf97);
00252   nikon_decrypt (serial, key, 0x98,   4, sizeof buf98, buf98);
00253   order = sorder;
00254 }
00255 
00256 void nef_parse_exif(int base)
00257 {
00258   int entries, tag, type, count, save;
00259 
00260   puts("Nikon EXIF tag:");
00261   entries = get2();
00262   while (entries--) {
00263     save = ftell(ifp);
00264     tag  = get2();
00265     type = get2();
00266     count= get4();
00267     tiff_dump (base, tag, type, count, 1);
00268     if (tag == 0x927c)
00269       nef_parse_makernote (base);
00270     fseek (ifp, save+12, SEEK_SET);
00271   }
00272 }
00273 
00274 int parse_tiff_ifd (int base, int level)
00275 {
00276   int entries, tag, type, count, slen, save, save2, val, i;
00277   int comp=0;
00278 
00279   entries = get2();
00280   if (entries > 255) return 1;
00281   while (entries--) {
00282     save = ftell(ifp);
00283     tag  = get2();
00284     type = get2();
00285     count= get4();
00286     slen = count;
00287     if (slen > 128) slen = 128;
00288 
00289     tiff_dump (base, tag, type, count, level);
00290 
00291     save2 = ftell(ifp);
00292     if (type == 3)          /* short int */
00293       val = get2();
00294     else
00295       val = get4();
00296     fseek (ifp, save2, SEEK_SET);
00297 
00298     if (tag > 50700 && tag < 50800)
00299       is_dng = 1;
00300 
00301     if (level == 3) {           /* Olympus E-1 and E-300 */
00302       if (type == 4) {
00303     if (tag == 0x101)
00304       thumb_offset = val;
00305     else if (tag == 0x102)
00306       thumb_length = val;
00307       }
00308       goto cont;
00309     }
00310     switch (tag) {
00311       case 0x100:           /* ImageWidth */
00312     if (!width)  width = val;
00313     break;
00314       case 0x101:           /* ImageHeight */
00315     if (!height) height = val;
00316     break;
00317       case 0x102:           /* Bits per sample */
00318     if (bps) break;
00319     bps = val;
00320     if (count == 1)
00321       thumb_layers = 1;
00322     break;
00323       case 0x103:           /* Compression */
00324     comp = val;
00325     break;
00326       case 0x10f:           /* Make tag */
00327     fgets (make, slen, ifp);
00328     break;
00329       case 0x110:           /* Model tag */
00330     fgets (model, slen, ifp);
00331     break;
00332       case 33405:           /* Model2 tag */
00333     fgets (model2, slen, ifp);
00334     break;
00335       case 0x111:           /* StripOffset */
00336     if (!offset || is_dng) offset = val;
00337     break;
00338       case 0x117:           /* StripByteCounts */
00339     if (!length || is_dng) length = val;
00340     if (offset > val && !strncmp(make,"KODAK",5) && !is_dng)
00341       offset -= val;
00342     break;
00343       case 0x14a:           /* SubIFD tag */
00344     save2 = ftell(ifp);
00345     for (i=0; i < count; i++) {
00346       printf ("SubIFD #%d:\n", i+1);
00347       fseek (ifp, save2 + i*4, SEEK_SET);
00348       fseek (ifp, get4()+base, SEEK_SET);
00349       parse_tiff_ifd (base, level+1);
00350     }
00351     break;
00352       case 0x201:
00353     if (strncmp(make,"OLYMPUS",7) || !thumb_offset)
00354       thumb_offset = val;
00355     break;
00356       case 0x202:
00357     if (strncmp(make,"OLYMPUS",7) || !thumb_length)
00358       thumb_length = val;
00359     break;
00360       case 34665:
00361     fseek (ifp, get4()+base, SEEK_SET);
00362     nef_parse_exif (base);
00363     break;
00364       case 50706:
00365     is_dng = 1;
00366     }
00367 cont:
00368     fseek (ifp, save+12, SEEK_SET);
00369   }
00370   if ((comp == 6 && !strcmp(make,"Canon")) ||
00371       (comp == 7 && is_dng)) {
00372     thumb_offset = offset;
00373     thumb_length = length;
00374   }
00375   return 0;
00376 }
00377 
00378 /*
00379    Parse a TIFF file looking for camera model and decompress offsets.
00380  */
00381 void parse_tiff (int base)
00382 {
00383   int doff, spp=3, ifd=0;
00384 
00385   width = height = offset = length = bps = is_dng = 0;
00386   fseek (ifp, base, SEEK_SET);
00387   order = get2();
00388   if (order != 0x4949 && order != 0x4d4d) return;
00389   get2();
00390   while ((doff = get4())) {
00391     fseek (ifp, doff+base, SEEK_SET);
00392     printf ("IFD #%d:\n", ifd++);
00393     if (parse_tiff_ifd (base, 0)) break;
00394   }
00395   if (is_dng) return;
00396 
00397   if (strncmp(make,"KODAK",5))
00398     thumb_layers = 0;
00399   if (!strncmp(make,"Kodak",5)) {
00400     fseek (ifp, 12+base, SEEK_SET);
00401     puts ("\nSpecial Kodak image directory:");
00402     parse_tiff_ifd (base, 0);
00403   }
00404   if (!strncmp(model,"DCS460A",7)) {
00405     spp = 1;
00406     thumb_layers = 0;
00407   }
00408   if (!thumb_length && offset) {
00409     thumb_offset = offset;
00410     sprintf (thumb_head, "P%d %d %d %d\n",
00411     spp > 1 ? 6:5, width, height, (1 << bps) - 1);
00412     thumb_length = width * height * spp * ((bps+7)/8);
00413   }
00414 }
00415 
00416 void parse_minolta()
00417 {
00418   int data_offset, save, tag, len;
00419 
00420   fseek (ifp, 4, SEEK_SET);
00421   data_offset = get4() + 8;
00422   while ((save=ftell(ifp)) < data_offset) {
00423     tag = get4();
00424     len = get4();
00425     printf ("Tag %c%c%c offset %06x length %06x\n",
00426     tag>>16, tag>>8, tag, save, len);
00427     switch (tag) {
00428       case 0x545457:                /* TTW */
00429     parse_tiff (ftell(ifp));
00430     }
00431     fseek (ifp, save+len+8, SEEK_SET);
00432   }
00433   strcpy (thumb_head, "\xff");
00434   thumb_offset++;
00435   thumb_length--;
00436 }
00437 
00438 /*
00439    Parse the CIFF structure.
00440  */
00441 void parse_ciff (int offset, int length, int level)
00442 {
00443   int tboff, nrecs, i, j, type, len, dlen, roff, aoff=0, save;
00444   char c, name[256];
00445 
00446   fseek (ifp, offset+length-4, SEEK_SET);
00447   tboff = get4() + offset;
00448   fseek (ifp, tboff, SEEK_SET);
00449   nrecs = get2();
00450   if (nrecs > 100) return;
00451   printf ("%*s%d records:\n", level*2, "", nrecs);
00452   for (i = 0; i < nrecs; i++) {
00453     save = ftell(ifp);
00454     type = get2();
00455     printf ("%*stype=0x%04x", level*2, "", type);
00456     if (type & 0x4000) {
00457       len = 8;
00458       type &= 0x3fff;
00459     } else {
00460       len  = get4();
00461       roff = get4();
00462       aoff = offset + roff;
00463       printf (", length=%d, reloff=%d, absoff=%d",
00464         len, roff, aoff);
00465       fseek (ifp, aoff, SEEK_SET);
00466     }
00467     if ((type & 0xe700) == 0)
00468       printf (", data=");
00469     if (type == 0x0032)         /* display as words */
00470     type |= 0x1000;
00471     dlen = len < DLEN ? len:DLEN;
00472     switch (type >> 8) {
00473       case 0x28:
00474       case 0x30:
00475     putchar('\n');
00476     parse_ciff (aoff, len, level+1);
00477     fseek (ifp, save+10, SEEK_SET);
00478     continue;
00479       case 0x00:            /* byte values */
00480     for (j = 0; j < dlen; j++)
00481       printf ("%c%02x",(j & 31) || dlen < 16 ? ' ':'\n', fgetc(ifp) & 0xff);
00482     break;
00483       case 0x08:            /* null-terminated ASCII strings */
00484     putchar('\"');
00485     for (j = 0; j < dlen; j++) {
00486       c = fgetc(ifp);
00487       putchar( isprint(c) ? c:'.');
00488     }
00489     putchar('\"');
00490     break;
00491       case 0x10:            /* word values */
00492     for (j = 0; j < dlen; j+=2)
00493       printf ("%c%5u",(j & 31) || dlen < 16 ? ' ':'\n', get2());
00494     break;
00495       case 0x18:            /* dword values */
00496     for (j = 0; j < dlen; j+=4)
00497       printf ("%c%08x",(j & 31) || dlen < 16 ? ' ':'\n', get4());
00498     }
00499     putchar('\n');
00500     fseek (ifp, save+10, SEEK_SET);
00501     if (type == 0x080a) {       /* Get the camera name */
00502       fseek (ifp, aoff, SEEK_SET);
00503       fread (name, 256, 1, ifp);
00504       strcpy (make, name);
00505       strcpy (model, name + strlen(make)+1);
00506     }
00507     if (type == 0x2007) {       /* Found the JPEG thumbnail */
00508       thumb_offset = aoff;
00509       thumb_length = len;
00510     }
00511   }
00512 }
00513 
00514 int parse_jpeg (int offset)
00515 {
00516   int len, save, hlen;
00517 
00518   fseek (ifp, offset, SEEK_SET);
00519   if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return 0;
00520 
00521   while (fgetc(ifp) == 0xff && fgetc(ifp) >> 4 != 0xd) {
00522     order = 0x4d4d;
00523     len   = get2() - 2;
00524     save  = ftell(ifp);
00525     order = get2();
00526     hlen  = get4();
00527     if (get4() == 0x48454150)       /* "HEAP" */
00528       parse_ciff (save+hlen, len-hlen, 0);
00529     parse_tiff (save+6);
00530     fseek (ifp, save+len, SEEK_SET);
00531   }
00532   thumb_length = 0;
00533   return 1;
00534 }
00535 
00536 void parse_mos(int level)
00537 {
00538   uchar data[256];
00539   int i, skip, save;
00540   char *cp;
00541 
00542   save = ftell(ifp);
00543   while (1) {
00544     fread (data, 1, 8, ifp);
00545     if (strcmp(data,"PKTS")) break;
00546     strcpy (model, "Valeo");
00547     printf ("%*s%s ", level, "", data);
00548     fread (data, 1, 40, ifp);
00549     skip = get4();
00550     printf ("%s %d bytes: ", data, skip);
00551     if (!strcmp(data,"icc_camera_to_tone_matrix")) {
00552       for (i=0; i < skip/4; i++)
00553     printf ("%f ", get_float());
00554       putchar('\n');
00555       continue;
00556     }
00557     if (!strcmp(data,"JPEG_preview_data")) {
00558       thumb_head[0] = 0;
00559       thumb_offset = ftell(ifp);
00560       thumb_length = skip;
00561     }
00562     fread (data, 1, sizeof data, ifp);
00563     fseek (ifp, -sizeof data, SEEK_CUR);
00564     data[sizeof data - 1] = 0;
00565     while ((cp=strchr(data,'\n')))
00566       *cp = ' ';
00567     printf ("%s\n",data);
00568     parse_mos(level+2);
00569     fseek (ifp, skip, SEEK_CUR);
00570   }
00571   fseek (ifp, save, SEEK_SET);
00572 }
00573 
00574 void parse_rollei()
00575 {
00576   char line[128], *val;
00577 
00578   fseek (ifp, 0, SEEK_SET);
00579   do {
00580     fgets (line, 128, ifp);
00581     fputs (line, stdout);
00582     if ((val = strchr(line,'=')))
00583       *val++ = 0;
00584     else
00585       val = line + strlen(line);
00586     if (!strcmp(line,"HDR"))
00587       thumb_offset = atoi(val);
00588     if (!strcmp(line,"TX "))
00589       width = atoi(val);
00590     if (!strcmp(line,"TY "))
00591       height = atoi(val);
00592   } while (strncmp(line,"EOHD",4));
00593   strcpy (make, "Rollei");
00594   strcpy (model, "d530flex");
00595   thumb_length = width*height*2;
00596 }
00597 
00598 void rollei_decode (FILE *tfp)
00599 {
00600   ushort data;
00601   int row, col;
00602 
00603   fseek (ifp, thumb_offset, SEEK_SET);
00604   fprintf (tfp, "P6\n%d %d\n255\n", width, height);
00605   for (row=0; row < height; row++)
00606     for (col=0; col < width; col++) {
00607       fread (&data, 2, 1, ifp);
00608       data = ntohs(data);
00609       putc (data << 3, tfp);
00610       putc (data >> 5  << 2, tfp);
00611       putc (data >> 11 << 3, tfp);
00612     }
00613 }
00614 
00615 void get_utf8 (int offset, char *buf, int len)
00616 {
00617   ushort c;
00618   char *cp;
00619 
00620   fseek (ifp, offset, SEEK_SET);
00621   for (cp=buf; (c = get2()) && cp+3 < buf+len; ) {
00622     if (c < 0x80)
00623       *cp++ = c;
00624     else if (c < 0x800) {
00625       *cp++ = 0xc0 + (c >> 6);
00626       *cp++ = 0x80 + (c & 0x3f);
00627     } else {
00628       *cp++ = 0xe0 + (c >> 12);
00629       *cp++ = 0x80 + (c >> 6 & 0x3f);
00630       *cp++ = 0x80 + (c & 0x3f);
00631     }
00632   }
00633   *cp = 0;
00634 }
00635 
00636 void parse_foveon()
00637 {
00638   int entries, img=0, off, len, tag, save, i, j, k, pent, poff[256][2];
00639   char name[128], value[128], camf[0x20000], *pos, *cp, *dp;
00640   unsigned val, key, type, num, ndim, dim[3];
00641 
00642   order = 0x4949;           /* Little-endian */
00643   fseek (ifp, -4, SEEK_END);
00644   fseek (ifp, get4(), SEEK_SET);
00645   if (get4() != 0x64434553) {   /* SECd */
00646     printf ("Bad Section identifier at %6x\n", (int)ftell(ifp)-4);
00647     return;
00648   }
00649   get4();
00650   entries = get4();
00651   while (entries--) {
00652     off = get4();
00653     len = get4();
00654     tag = get4();
00655     save = ftell(ifp);
00656     fseek (ifp, off, SEEK_SET);
00657     printf ("%c%c%c%c at offset %06x, length %06x, ",
00658     tag, tag >> 8, tag >> 16, tag >> 24, off, len);
00659     if (get4() != (0x20434553 | (tag << 24))) {
00660       printf ("Bad Section identifier at %6x\n", off);
00661       goto next;
00662     }
00663     val = get4();
00664     printf ("version %d.%d, ",val >> 16, val & 0xffff);
00665     switch (tag) {
00666       case 0x32414d49:          /* IMA2 */
00667       case 0x47414d49:          /* IMAG */
00668     printf ("type %d, " , get4());
00669     printf ("format %2d, "  , get4());
00670     printf ("columns %4d, " , get4());
00671     printf ("rows %4d, "    , get4());
00672     printf ("rowsize %d\n"  , get4());
00673     if (parse_jpeg (off+28)) {
00674       thumb_offset = off+28;
00675       thumb_length = len-28;
00676     }
00677     order = 0x4949;
00678     if (++img == 2 && !thumb_length) {
00679       thumb_offset = off;
00680       thumb_length = 1;
00681     }
00682     break;
00683       case 0x464d4143:          /* CAMF */
00684     printf ("type %d, ", get4());
00685     get4();
00686     for (i=0; i < 4; i++)
00687       putchar(fgetc(ifp));
00688     val = get4();
00689     printf (" version %d.%d:\n",val >> 16, val & 0xffff);
00690     key = get4();
00691     if ((len -= 28) > 0x20000)
00692       len = 0x20000;
00693     fread (camf, 1, len, ifp);
00694     for (i=0; i < len; i++) {
00695       key = (key * 1597 + 51749) % 244944;
00696       val = key * (INT64) 301593171 >> 24;
00697       camf[i] ^= ((((key << 8) - val) >> 1) + val) >> 17;
00698     }
00699     for (pos=camf; (unsigned) (pos-camf) < len; pos += sget4(pos+8)) {
00700       if (strncmp (pos, "CMb", 3)) {
00701         printf("Bad CAMF tag \"%.4s\"\n", pos);
00702         break;
00703       }
00704       val = sget4(pos+4);
00705       printf ("  %4.4s version %d.%d: ", pos, val >> 16, val & 0xffff);
00706       switch (pos[3]) {
00707         case 'M':
00708           cp = pos + sget4(pos+16);
00709           type = sget4(cp);
00710           ndim = sget4(cp+4);
00711           dim[0] = dim[1] = dim[2] = 1;
00712           printf ("%d-dimensonal array %s of type %d:\n    Key: (",
00713         ndim, pos+sget4(pos+12), sget4(cp));
00714           dp = pos + sget4(cp+8);
00715           for (i=ndim; i--; ) {
00716         cp += 12;
00717         dim[i] = sget4(cp);
00718         printf ("%s %d%s", pos+sget4(cp+4), dim[i], i ? ", ":")\n");
00719           }
00720           for (i=0; i < dim[2]; i++) {
00721         for (j=0; j < dim[1]; j++) {
00722           printf ("    ");
00723           for (k=0; k < dim[0]; k++)
00724             switch (type) {
00725               case 5:
00726             printf ("%7d", *(uchar *)dp++);
00727             break;
00728               case 0:
00729               case 6:
00730             printf ("%7d", (short) sget2(dp));
00731             dp += 2;
00732             break;
00733               case 1:
00734               case 2:
00735             printf (" %d", sget4(dp));
00736             dp += 4;
00737             break;
00738               case 3:
00739             val = sget4(dp);
00740             printf (" %9f", *(float *)(&val));
00741             dp += 4;
00742             }
00743           printf ("\n");
00744         }
00745         printf ("\n");
00746           }
00747           break;
00748         case 'P':
00749           val = sget4(pos+16);
00750           num = sget4(pos+val);
00751           printf ("%s, %d parameters:\n", pos+sget4(pos+12), num);
00752           cp = pos+val+8 + num*8;
00753           for (i=0; i < num; i++) {
00754         val += 8;
00755         printf ("    %s = %s\n", cp+sget4(pos+val), cp+sget4(pos+val+4));
00756           }
00757           break;
00758         case 'T':
00759           cp = pos + sget4(pos+16);
00760           printf ("%s = %.*s\n", pos+sget4(pos+12), sget4(cp), cp+4);
00761           break;
00762         default:
00763           printf ("\n");
00764       }
00765     }
00766     break;
00767       case 0x504f5250:          /* PROP */
00768     printf ("entries %d, ", pent=get4());
00769     printf ("charset %d, ", get4());
00770     get4();
00771     printf ("nchars %d\n", get4());
00772     off += pent*8 + 24;
00773     if (pent > 256) pent=256;
00774     for (i=0; i < pent*2; i++)
00775       poff[0][i] = off + get4()*2;
00776     for (i=0; i < pent; i++) {
00777       get_utf8 (poff[i][0], name, 128);
00778       get_utf8 (poff[i][1], value, 128);
00779       printf ("  %s = %s\n", name, value);
00780       if (!strcmp (name,"CAMMANUF"))
00781         strcpy (make, value);
00782       if (!strcmp (name,"CAMMODEL"))
00783         strcpy (model, value);
00784     }
00785     }
00786 next:
00787     fseek (ifp, save, SEEK_SET);
00788   }
00789 }
00790 
00791 void foveon_tree (unsigned huff[1024], unsigned code)
00792 {
00793   struct decode *cur;
00794   int i, len;
00795 
00796   cur = free_decode++;
00797   if (code) {
00798     for (i=0; i < 1024; i++)
00799       if (huff[i] == code) {
00800     cur->leaf = i;
00801     return;
00802       }
00803   }
00804   if ((len = code >> 27) > 26) return;
00805   code = (len+1) << 27 | (code & 0x3ffffff) << 1;
00806 
00807   cur->branch[0] = free_decode;
00808   foveon_tree (huff, code);
00809   cur->branch[1] = free_decode;
00810   foveon_tree (huff, code+1);
00811 }
00812 
00813 void foveon_decode (FILE *tfp)
00814 {
00815   int bwide, row, col, bit=-1, c, i;
00816   char *buf;
00817   struct decode *dindex;
00818   short pred[3];
00819   unsigned huff[1024], bitbuf=0;
00820 
00821   fseek (ifp, thumb_offset+16, SEEK_SET);
00822   width  = get4();
00823   height = get4();
00824   bwide  = get4();
00825   fprintf (tfp, "P6\n%d %d\n255\n", width, height);
00826   if (bwide > 0) {
00827     buf = malloc(bwide);
00828     for (row=0; row < height; row++) {
00829       fread  (buf, 1, bwide, ifp);
00830       fwrite (buf, 3, width, tfp);
00831     }
00832     free (buf);
00833     return;
00834   }
00835   for (i=0; i < 256; i++)
00836     huff[i] = get4();
00837   memset (first_decode, 0, sizeof first_decode);
00838   free_decode = first_decode;
00839   foveon_tree (huff, 0);
00840 
00841   for (row=0; row < height; row++) {
00842     memset (pred, 0, sizeof pred);
00843     if (!bit) get4();
00844     for (col=bit=0; col < width; col++) {
00845       for (c=0; c < 3; c++) {
00846     for (dindex=first_decode; dindex->branch[0]; ) {
00847       if ((bit = (bit-1) & 31) == 31)
00848         for (i=0; i < 4; i++)
00849           bitbuf = (bitbuf << 8) + fgetc(ifp);
00850       dindex = dindex->branch[bitbuf >> bit & 1];
00851     }
00852     pred[c] += dindex->leaf;
00853     fputc (pred[c], tfp);
00854       }
00855     }
00856   }
00857 }
00858 
00859 void kodak_yuv_decode (FILE *tfp)
00860 {
00861   uchar c, blen[384];
00862   unsigned row, col, len, bits=0;
00863   INT64 bitbuf=0;
00864   int i, li=0, si, diff, six[6], y[4], cb=0, cr=0, rgb[3];
00865   ushort *out, *op;
00866 
00867   fseek (ifp, thumb_offset, SEEK_SET);
00868   width = (width+1) & -2;
00869   height = (height+1) & -2;
00870   fprintf (tfp, "P6\n%d %d\n65535\n", width, height);
00871   out = malloc (width * 12);
00872   if (!out) {
00873     fprintf (stderr, "kodak_yuv_decode() malloc failed!\n");
00874     exit(1);
00875   }
00876 
00877   for (row=0; row < height; row+=2) {
00878     for (col=0; col < width; col+=2) {
00879       if ((col & 127) == 0) {
00880     len = (width - col + 1) * 3 & -4;
00881     if (len > 384) len = 384;
00882     for (i=0; i < len; ) {
00883       c = fgetc(ifp);
00884       blen[i++] = c & 15;
00885       blen[i++] = c >> 4;
00886     }
00887     li = bitbuf = bits = y[1] = y[3] = cb = cr = 0;
00888     if (len % 8 == 4) {
00889       bitbuf  = fgetc(ifp) << 8;
00890       bitbuf += fgetc(ifp);
00891       bits = 16;
00892     }
00893       }
00894       for (si=0; si < 6; si++) {
00895     len = blen[li++];
00896     if (bits < len) {
00897       for (i=0; i < 32; i+=8)
00898         bitbuf += (INT64) fgetc(ifp) << (bits+(i^8));
00899       bits += 32;
00900     }
00901     diff = bitbuf & (0xffff >> (16-len));
00902     bitbuf >>= len;
00903     bits -= len;
00904     if ((diff & (1 << (len-1))) == 0)
00905       diff -= (1 << len) - 1;
00906     six[si] = diff;
00907       }
00908       y[0] = six[0] + y[1];
00909       y[1] = six[1] + y[0];
00910       y[2] = six[2] + y[3];
00911       y[3] = six[3] + y[2];
00912       cb  += six[4];
00913       cr  += six[5];
00914       for (i=0; i < 4; i++) {
00915     op = out + ((i >> 1)*width + col+(i & 1)) * 3;
00916     rgb[0] = y[i] + 1.40200/2 * cr;
00917     rgb[1] = y[i] - 0.34414/2 * cb - 0.71414/2 * cr;
00918     rgb[2] = y[i] + 1.77200/2 * cb;
00919     for (c=0; c < 3; c++)
00920       if (rgb[c] > 0) op[c] = htons(rgb[c]);
00921       }
00922     }
00923     fwrite (out, sizeof *out, width*6, tfp);
00924   }
00925   free(out);
00926 }
00927 
00928 void parse_fuji (int offset)
00929 {
00930   int entries, tag, len;
00931 
00932   fseek (ifp, offset, SEEK_SET);
00933   fseek (ifp, get4(), SEEK_SET);
00934   entries = get4();
00935   if (entries > 60) return;
00936   while (entries--) {
00937     tag = get2();
00938     len = get2();
00939     printf ("Fuji tag=0x%x, len=%d, data =",tag,len);
00940     while (len--)
00941       printf (" %02x",fgetc(ifp));
00942     putchar ('\n');
00943   }
00944 }
00945 
00946 void parse_phase_one (int base)
00947 {
00948   unsigned entries, tag, type, len, data, save;
00949   char str[256];
00950 
00951   fseek (ifp, base, SEEK_SET);
00952   order = get4() & 0xffff;
00953   if (get4() >> 8 != 0x526177) return;
00954   fseek (ifp, base+get4(), SEEK_SET);
00955   entries = get4();
00956   get4();
00957   while (entries--) {
00958     tag  = get4();
00959     type = get4();
00960     len  = get4();
00961     data = get4();
00962     save = ftell(ifp);
00963     printf ("Phase One tag=0x%x, type=%d, len=%2d, data = 0x%x\n",
00964         tag, type, len, data);
00965     if (len > 4)
00966       fseek (ifp, base+data, SEEK_SET);
00967     if (type == 1 && len < 256) {
00968       fread (str, 256, 1, ifp);
00969       puts (str);
00970     }
00971     if (tag != 0x21c && type == 4 && len > 4) {
00972       for ( ; len > 0; len -= 4)
00973     printf ("%f ", get_float());
00974       puts ("");
00975     }
00976     if (tag == 0x110) {
00977       thumb_offset = data + base;
00978       thumb_length = len;
00979     }
00980     fseek (ifp, save, SEEK_SET);
00981   }
00982   strcpy (make, "Phase One");
00983   strcpy (model, "unknown");
00984 }
00985 
00986 char *memmem (char *haystack, size_t haystacklen,
00987               char *needle, size_t needlelen)
00988 {
00989   char *c;
00990   for (c = haystack; c <= haystack + haystacklen - needlelen; c++)
00991     if (!memcmp (c, needle, needlelen))
00992       return c;
00993   return NULL;
00994 }
00995 
00996 /*
00997    Identify which camera created this file, and set global variables
00998    accordingly.  Return nonzero if the file cannot be decoded.
00999  */
01000 int identify()
01001 {
01002   char head[32], thumb_name[256], *thumb, *rgb, *cp;
01003   unsigned hlen, fsize, toff, tlen, lsize, i;
01004   FILE *tfp;
01005 
01006   make[0] = model[0] = model2[0] = is_dng = 0;
01007   thumb_head[0] = thumb_offset = thumb_length = thumb_layers = 0;
01008   order = get2();
01009   hlen = get4();
01010   fseek (ifp, 0, SEEK_SET);
01011   fread (head, 1, 32, ifp);
01012   fseek (ifp, 0, SEEK_END);
01013   fsize = ftell(ifp);
01014   if ((cp = memmem (head, 32, "MMMM", 4)) ||
01015       (cp = memmem (head, 32, "IIII", 4))) {
01016     parse_phase_one (cp-head);
01017     if (cp-head) parse_tiff (0);
01018   } else if (order == 0x4949 || order == 0x4d4d) {
01019     if (!memcmp(head+6,"HEAPCCDR",8)) {
01020       parse_ciff (hlen, fsize - hlen, 0);
01021       fseek (ifp, hlen, SEEK_SET);
01022     } else
01023       parse_tiff (0);
01024   } else if (!memcmp (head, "\0MRM", 4)) {
01025     parse_minolta();
01026   } else if (!memcmp (head, "FUJIFILM", 8)) {
01027     fseek (ifp, 84, SEEK_SET);
01028     toff = get4();
01029     tlen = get4();
01030     parse_fuji (92);
01031     if (toff > 120) parse_fuji (120);
01032     parse_tiff (toff+12);
01033     thumb_offset = toff;
01034     thumb_length = tlen;
01035   } else if (!memcmp (head, "DSC-Image", 9))
01036     parse_rollei();
01037   else if (!memcmp (head, "FOVb", 4))
01038     parse_foveon();
01039   fseek (ifp, 8, SEEK_SET);
01040   parse_mos(0);
01041   fseek (ifp, 3472, SEEK_SET);
01042   parse_mos(0);
01043   parse_jpeg(0);
01044   if (model[0] == 0) {
01045     fprintf (stderr, "%s: unsupported file format.\n", fname);
01046     return 1;
01047   }
01048   fprintf (stderr, "Findings for %s:\n", fname);
01049   fprintf (stderr, "Make   is \"%s\"\n", make);
01050   fprintf (stderr, "Model  is \"%s\"\n", model);
01051   if (model2[0])
01052     fprintf (stderr, "Model2 is \"%s\"\n", model2);
01053 
01054   if (!thumb_length) {
01055     fprintf (stderr, "Thumbnail image not found\n");
01056     return 0;
01057   }
01058   strcpy (thumb_name, fname);
01059   strcat (thumb_name, ".thumb");
01060   tfp = fopen (thumb_name, "wb");
01061   if (!tfp) {
01062     perror(thumb_name);
01063     return 0;
01064   }
01065   if (is_dng) goto dng_skip;
01066   if (!strncmp(model,"DCS Pro",7)) {
01067     kodak_yuv_decode (tfp);
01068     goto done;
01069   }
01070   if (!strcmp(make,"Rollei")) {
01071     rollei_decode (tfp);
01072     goto done;
01073   }
01074   if (!strcmp(make,"SIGMA")) {
01075     foveon_decode (tfp);
01076     goto done;
01077   }
01078 dng_skip:
01079   thumb = (char *) malloc(thumb_length);
01080   if (!thumb) {
01081     fprintf (stderr, "Cannot allocate %d bytes!!\n", thumb_length);
01082     exit(1);
01083   }
01084   fseek (ifp, thumb_offset, SEEK_SET);
01085   fread (thumb, 1, thumb_length, ifp);
01086   if (thumb_layers && !is_dng) {
01087     rgb = (char *) malloc(thumb_length);
01088     if (!rgb) {
01089       fprintf (stderr, "Cannot allocate %d bytes!!\n", thumb_length);
01090       exit(1);
01091     }
01092     lsize = thumb_length/3;
01093     for (i=0; i < thumb_length; i++)
01094       rgb[(i%lsize)*3 + i/lsize] = thumb[i];
01095     free(thumb);
01096     thumb = rgb;
01097   }
01098   fputs (thumb_head, tfp);
01099   fwrite(thumb, 1, thumb_length, tfp);
01100   free (thumb);
01101 done:
01102   fclose (tfp);
01103   fprintf (stderr, "Thumbnail image written to %s.\n", thumb_name);
01104   return 0;
01105 }
01106 
01107 int main(int argc, char **argv)
01108 {
01109   int arg;
01110 
01111   if (argc == 1)
01112   {
01113     fprintf (stderr,
01114     "\nRaw Photo Parser and Thumbnail Extracter"
01115     "\nby Dave Coffin, dcoffin a cybercom o net"
01116     "\n\nUsage:  %s [options] file1.crw file2.crw ...\n", argv[0]);
01117     return 1;
01118   }
01119 
01120   for (arg=1; arg < argc; arg++)
01121   {
01122     fname = argv[arg];
01123     ifp = fopen (fname,"rb");
01124     if (!ifp) {
01125       perror (fname);
01126       continue;
01127     }
01128     printf ("\nParsing %s:\n", fname);
01129     identify();
01130     fclose (ifp);
01131   }
01132   return 0;
01133 }

Generated on Sat Jan 27 11:36:13 2007 for libopenraw by  doxygen 1.4.7