Home | History | Annotate | Download | only in jhead
      1 //--------------------------------------------------------------------------
      2 // Parse some maker specific onformation.
      3 // (Very limited right now - add maker specific stuff to this module)
      4 //--------------------------------------------------------------------------
      5 #include "jhead.h"
      6 
      7 //--------------------------------------------------------------------------
      8 // Process exif format directory, as used by Cannon maker note
      9 //--------------------------------------------------------------------------
     10 void ProcessCanonMakerNoteDir(unsigned char * DirStart, unsigned char * OffsetBase,
     11         unsigned ExifLength)
     12 {
     13     int de;
     14     int a;
     15     int NumDirEntries;
     16 
     17     NumDirEntries = Get16u(DirStart);
     18     #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
     19 
     20     {
     21         unsigned char * DirEnd;
     22         DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries);
     23         if (DirEnd > (OffsetBase+ExifLength)){
     24             ErrNonfatal("Illegally sized directory",0,0);
     25             return;
     26         }
     27 
     28         if (DumpExifMap){
     29             printf("Map: %05d-%05d: Directory (makernote)\n",DirStart-OffsetBase, DirEnd-OffsetBase);
     30         }
     31     }
     32 
     33     if (ShowTags){
     34         printf("(dir has %d entries)\n",NumDirEntries);
     35     }
     36 
     37     for (de=0;de<NumDirEntries;de++){
     38         int Tag, Format, Components;
     39         unsigned char * ValuePtr;
     40         int ByteCount;
     41         unsigned char * DirEntry;
     42         DirEntry = DIR_ENTRY_ADDR(DirStart, de);
     43 
     44         Tag = Get16u(DirEntry);
     45         Format = Get16u(DirEntry+2);
     46         Components = Get32u(DirEntry+4);
     47 
     48         if ((Format-1) >= NUM_FORMATS) {
     49             // (-1) catches illegal zero case as unsigned underflows to positive large.
     50             ErrNonfatal("Illegal number format %d for tag %04x", Format, Tag);
     51             continue;
     52         }
     53 
     54         if ((unsigned)Components > 0x10000){
     55             ErrNonfatal("Illegal number of components %d for tag %04x", Components, Tag);
     56             continue;
     57         }
     58 
     59         ByteCount = Components * BytesPerFormat[Format];
     60 
     61         if (ByteCount > 4){
     62             unsigned OffsetVal;
     63             OffsetVal = Get32u(DirEntry+8);
     64             // If its bigger than 4 bytes, the dir entry contains an offset.
     65             if (OffsetVal+ByteCount > ExifLength){
     66                 // Bogus pointer offset and / or bytecount value
     67                 ErrNonfatal("Illegal value pointer for tag %04x", Tag,0);
     68                 continue;
     69             }
     70             ValuePtr = OffsetBase+OffsetVal;
     71 
     72             if (DumpExifMap){
     73                 printf("Map: %05d-%05d:   Data for makernote tag %04x\n",OffsetVal, OffsetVal+ByteCount, Tag);
     74             }
     75         }else{
     76             // 4 bytes or less and value is in the dir entry itself
     77             ValuePtr = DirEntry+8;
     78         }
     79 
     80         if (ShowTags){
     81             // Show tag name
     82             printf("            Canon maker tag %04x Value = ", Tag);
     83         }
     84 
     85         // Show tag value.
     86         switch(Format){
     87 
     88             case FMT_UNDEFINED:
     89                 // Undefined is typically an ascii string.
     90 
     91             case FMT_STRING:
     92                 // String arrays printed without function call (different from int arrays)
     93                 if (ShowTags){
     94                     printf("\"");
     95                     for (a=0;a<ByteCount;a++){
     96                         int ZeroSkipped = 0;
     97                         if (ValuePtr[a] >= 32){
     98                             if (ZeroSkipped){
     99                                 printf("?");
    100                                 ZeroSkipped = 0;
    101                             }
    102                             putchar(ValuePtr[a]);
    103                         }else{
    104                             if (ValuePtr[a] == 0){
    105                                 ZeroSkipped = 1;
    106                             }
    107                         }
    108                     }
    109                     printf("\"\n");
    110                 }
    111                 break;
    112 
    113             default:
    114                 if (ShowTags){
    115                     PrintFormatNumber(ValuePtr, Format, ByteCount);
    116                     printf("\n");
    117                 }
    118         }
    119         if (Tag == 1 && Components > 16){
    120             int IsoCode = Get16u(ValuePtr + 16*sizeof(unsigned short));
    121             if (IsoCode >= 16 && IsoCode <= 24){
    122                 ImageInfo.ISOequivalent = 50 << (IsoCode-16);
    123             }
    124         }
    125 
    126         if (Tag == 4 && Format == FMT_USHORT){
    127             if (Components > 7){
    128                 int WhiteBalance = Get16u(ValuePtr + 7*sizeof(unsigned short));
    129                 switch(WhiteBalance){
    130                     // 0=Auto, 6=Custom
    131                     case 1: ImageInfo.LightSource = 1; break; // Sunny
    132                     case 2: ImageInfo.LightSource = 1; break; // Cloudy
    133                     case 3: ImageInfo.LightSource = 3; break; // Thungsten
    134                     case 4: ImageInfo.LightSource = 2; break; // Fourescent
    135                     case 5: ImageInfo.LightSource = 4; break; // Flash
    136                 }
    137             }
    138             if (Components > 19 && ImageInfo.Distance <= 0) {
    139                 // Inidcates the distance the autofocus camera is focused to.
    140                 // Tends to be less accurate as distance increases.
    141                 int temp_dist = Get16u(ValuePtr + 19*sizeof(unsigned short));
    142 printf("temp dist=%d\n",temp_dist);
    143                 if (temp_dist != 65535){
    144                     ImageInfo.Distance = (float)temp_dist/100;
    145                 }else{
    146                     ImageInfo.Distance = -1 /* infinity */;
    147                 }
    148             }
    149         }
    150     }
    151 }
    152 
    153 //--------------------------------------------------------------------------
    154 // Show generic maker note - just hex bytes.
    155 //--------------------------------------------------------------------------
    156 void ShowMakerNoteGeneric(unsigned char * ValuePtr, int ByteCount)
    157 {
    158     int a;
    159     for (a=0;a<ByteCount;a++){
    160         if (a > 10){
    161             printf("...");
    162             break;
    163         }
    164         printf(" %02x",ValuePtr[a]);
    165     }
    166     printf(" (%d bytes)", ByteCount);
    167     printf("\n");
    168 
    169 }
    170 
    171 //--------------------------------------------------------------------------
    172 // Process maker note - to the limited extent that its supported.
    173 //--------------------------------------------------------------------------
    174 void ProcessMakerNote(unsigned char * ValuePtr, int ByteCount,
    175         unsigned char * OffsetBase, unsigned ExifLength)
    176 {
    177     if (strstr(ImageInfo.CameraMake, "Canon")){
    178         ProcessCanonMakerNoteDir(ValuePtr, OffsetBase, ExifLength);
    179     }else{
    180         if (ShowTags){
    181             ShowMakerNoteGeneric(ValuePtr, ByteCount);
    182         }
    183     }
    184 }
    185 
    186