fixdates.c

00001 /*
00002    Fixes dates on Canon PowerShot G2 CRW files to match the
00003    internal time stamps (assumed to be Universal Time).  This
00004    doesn't work with JPEG files; use "TZ= jhead -ft" for them.
00005 
00006    Dave Coffin  9/4/2003
00007 */
00008 
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <string.h>
00012 #include <utime.h>
00013 
00014 typedef unsigned char uchar;
00015 
00016 FILE *ifp;
00017 short order;
00018 int timestamp;
00019 
00020 /*
00021    Get a 2-byte integer, making no assumptions about CPU byte order.
00022    Nor should we assume that the compiler evaluates left-to-right.
00023  */
00024 ushort fget2 (FILE *f)
00025 {
00026   uchar a, b;
00027 
00028   a = fgetc(f);
00029   b = fgetc(f);
00030   if (order == 0x4949)          /* "II" means little-endian */
00031     return a + (b << 8);
00032   else                          /* "MM" means big-endian */
00033     return (a << 8) + b;
00034 }
00035 
00036 /*
00037    Same for a 4-byte integer.
00038  */
00039 int fget4 (FILE *f)
00040 {
00041   uchar a, b, c, d;
00042 
00043   a = fgetc(f);
00044   b = fgetc(f);
00045   c = fgetc(f);
00046   d = fgetc(f);
00047   if (order == 0x4949)
00048     return a + (b << 8) + (c << 16) + (d << 24);
00049   else
00050     return (a << 24) + (b << 16) + (c << 8) + d;
00051 }
00052 
00053 /*
00054    Parse the CIFF structure looking for two pieces of information:
00055    The camera model, and the decode table number.
00056  */
00057 void parse_ciff(int offset, int length)
00058 {
00059   int tboff, nrecs, i, type, len, roff, aoff, save;
00060 
00061   fseek (ifp, offset+length-4, SEEK_SET);
00062   tboff = fget4(ifp) + offset;
00063   fseek (ifp, tboff, SEEK_SET);
00064   nrecs = fget2(ifp);
00065   for (i = 0; i < nrecs; i++) {
00066     type = fget2(ifp);
00067     len  = fget4(ifp);
00068     roff = fget4(ifp);
00069     aoff = offset + roff;
00070     save = ftell(ifp);
00071     if (type == 0x180e) {       /* Get the timestamp */
00072       fseek (ifp, aoff, SEEK_SET);
00073       timestamp = fget4(ifp);
00074     }
00075     if (type >> 8 == 0x28 || type >> 8 == 0x30) /* Get sub-tables */
00076       parse_ciff(aoff, len);
00077     fseek (ifp, save, SEEK_SET);
00078   }
00079 }
00080 
00081 int main(int argc, char **argv)
00082 {
00083   struct utimbuf ut;
00084   char head[26];
00085   int arg, hlen, fsize, magic;
00086 
00087   if (argc < 2)
00088   { fprintf(stderr,"Usage: %s file1 file2 ...\n",argv[0]);
00089     exit(1);
00090   }
00091   for (arg=1; arg < argc; arg++)
00092   {
00093     ifp = fopen(argv[arg],"r");
00094     if (!ifp)
00095     { perror(argv[arg]);
00096       continue;
00097     }
00098 
00099     timestamp = 0;
00100     order = fget2(ifp);
00101     hlen = fget4(ifp);
00102     fread (head, 1, 26, ifp);
00103     fseek (ifp, 0, SEEK_END);
00104     fsize = ftell(ifp);
00105     fseek (ifp, 0, SEEK_SET);
00106     magic = fget4(ifp);
00107     if (order == 0x4949 || order == 0x4d4d)
00108       if (!memcmp(head,"HEAPCCDR",8))
00109         parse_ciff (hlen, fsize - hlen);
00110     fclose(ifp);
00111 
00112     if (timestamp) {
00113       ut.actime = ut.modtime = timestamp;
00114       utime (argv[arg], &ut);
00115     } else
00116       fprintf(stderr,"%s:  Internal date stamp not found.\n", argv[arg]);
00117   }
00118   return 0;
00119 }

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