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//--------------------------------------------------------------------------
10void 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));
142printf("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//--------------------------------------------------------------------------
156void 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//--------------------------------------------------------------------------
174void 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