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