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 //--------------------------------------------------------------------------
ProcessCanonMakerNoteDir(unsigned char * DirStart,unsigned char * OffsetBase,unsigned ExifLength)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: %05td-%05td: 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 //--------------------------------------------------------------------------
ShowMakerNoteGeneric(unsigned char * ValuePtr,int ByteCount)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 //--------------------------------------------------------------------------
ProcessMakerNote(unsigned char * ValuePtr,int ByteCount,unsigned char * OffsetBase,unsigned ExifLength)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