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