134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//--------------------------------------------------------------------------
234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Parse some maker specific onformation.
334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// (Very limited right now - add maker specific stuff to this module)
434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//--------------------------------------------------------------------------
534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include "jhead.h"
634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//--------------------------------------------------------------------------
834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Process exif format directory, as used by Cannon maker note
934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//--------------------------------------------------------------------------
1034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid ProcessCanonMakerNoteDir(unsigned char * DirStart, unsigned char * OffsetBase,
1134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        unsigned ExifLength)
1234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{
1334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int de;
1434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int a;
1534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int NumDirEntries;
1634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
1734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    NumDirEntries = Get16u(DirStart);
1834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
1934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
2034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    {
2134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        unsigned char * DirEnd;
2234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries);
2334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (DirEnd > (OffsetBase+ExifLength)){
2434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            ErrNonfatal("Illegally sized directory",0,0);
2534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            return;
2634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
2734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
2834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (DumpExifMap){
2934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            printf("Map: %05d-%05d: Directory (makernote)\n",DirStart-OffsetBase, DirEnd-OffsetBase);
3034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
3134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
3234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
3334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ShowTags){
3434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        printf("(dir has %d entries)\n",NumDirEntries);
3534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
3634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
3734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    for (de=0;de<NumDirEntries;de++){
3834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        int Tag, Format, Components;
3934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        unsigned char * ValuePtr;
4034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        int ByteCount;
4134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        unsigned char * DirEntry;
4234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        DirEntry = DIR_ENTRY_ADDR(DirStart, de);
4334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
4434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        Tag = Get16u(DirEntry);
4534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        Format = Get16u(DirEntry+2);
4634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        Components = Get32u(DirEntry+4);
4734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
4834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if ((Format-1) >= NUM_FORMATS) {
4934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            // (-1) catches illegal zero case as unsigned underflows to positive large.
5034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            ErrNonfatal("Illegal number format %d for tag %04x", Format, Tag);
5134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            continue;
5234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
5334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
5434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if ((unsigned)Components > 0x10000){
5534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            ErrNonfatal("Illegal number of components %d for tag %04x", Components, Tag);
5634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            continue;
5734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
5834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
5934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        ByteCount = Components * BytesPerFormat[Format];
6034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
6134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (ByteCount > 4){
6234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            unsigned OffsetVal;
6334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            OffsetVal = Get32u(DirEntry+8);
6434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            // If its bigger than 4 bytes, the dir entry contains an offset.
6534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            if (OffsetVal+ByteCount > ExifLength){
6634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                // Bogus pointer offset and / or bytecount value
6734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                ErrNonfatal("Illegal value pointer for tag %04x", Tag,0);
6834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                continue;
6934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            }
7034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            ValuePtr = OffsetBase+OffsetVal;
7134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
7234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            if (DumpExifMap){
7334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                printf("Map: %05d-%05d:   Data for makernote tag %04x\n",OffsetVal, OffsetVal+ByteCount, Tag);
7434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            }
7534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }else{
7634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            // 4 bytes or less and value is in the dir entry itself
7734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            ValuePtr = DirEntry+8;
7834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
7934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
8034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (ShowTags){
8134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            // Show tag name
8234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            printf("            Canon maker tag %04x Value = ", Tag);
8334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
8434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
8534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        // Show tag value.
8634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        switch(Format){
8734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
8834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            case FMT_UNDEFINED:
8934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                // Undefined is typically an ascii string.
9034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
9134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            case FMT_STRING:
9234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                // String arrays printed without function call (different from int arrays)
9334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                if (ShowTags){
9434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    printf("\"");
9534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    for (a=0;a<ByteCount;a++){
9634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                        int ZeroSkipped = 0;
9734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                        if (ValuePtr[a] >= 32){
9834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                            if (ZeroSkipped){
9934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                                printf("?");
10034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                                ZeroSkipped = 0;
10134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                            }
10234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                            putchar(ValuePtr[a]);
10334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                        }else{
10434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                            if (ValuePtr[a] == 0){
10534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                                ZeroSkipped = 1;
10634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                            }
10734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                        }
10834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    }
10934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    printf("\"\n");
11034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                }
11134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                break;
11234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
11334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            default:
11434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                if (ShowTags){
11534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    PrintFormatNumber(ValuePtr, Format, ByteCount);
11634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    printf("\n");
11734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                }
11834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
11934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (Tag == 1 && Components > 16){
12034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            int IsoCode = Get16u(ValuePtr + 16*sizeof(unsigned short));
12134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            if (IsoCode >= 16 && IsoCode <= 24){
12234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                ImageInfo.ISOequivalent = 50 << (IsoCode-16);
12334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            }
12434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
12534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
12634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (Tag == 4 && Format == FMT_USHORT){
12734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            if (Components > 7){
12834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                int WhiteBalance = Get16u(ValuePtr + 7*sizeof(unsigned short));
12934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                switch(WhiteBalance){
13034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    // 0=Auto, 6=Custom
13134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    case 1: ImageInfo.LightSource = 1; break; // Sunny
13234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    case 2: ImageInfo.LightSource = 1; break; // Cloudy
13334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    case 3: ImageInfo.LightSource = 3; break; // Thungsten
13434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    case 4: ImageInfo.LightSource = 2; break; // Fourescent
13534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    case 5: ImageInfo.LightSource = 4; break; // Flash
13634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                }
13734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            }
13834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            if (Components > 19 && ImageInfo.Distance <= 0) {
13934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                // Inidcates the distance the autofocus camera is focused to.
14034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                // Tends to be less accurate as distance increases.
14134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                int temp_dist = Get16u(ValuePtr + 19*sizeof(unsigned short));
14234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectprintf("temp dist=%d\n",temp_dist);
14334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                if (temp_dist != 65535){
14434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    ImageInfo.Distance = (float)temp_dist/100;
14534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                }else{
14634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                    ImageInfo.Distance = -1 /* infinity */;
14734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                }
14834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            }
14934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
15034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
15134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
15234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
15334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//--------------------------------------------------------------------------
15434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Show generic maker note - just hex bytes.
15534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//--------------------------------------------------------------------------
15634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid ShowMakerNoteGeneric(unsigned char * ValuePtr, int ByteCount)
15734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{
15834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int a;
15934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    for (a=0;a<ByteCount;a++){
16034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (a > 10){
16134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            printf("...");
16234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            break;
16334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
16434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        printf(" %02x",ValuePtr[a]);
16534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
16634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    printf(" (%d bytes)", ByteCount);
16734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    printf("\n");
16834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
16934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
17034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
17134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//--------------------------------------------------------------------------
17234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Process maker note - to the limited extent that its supported.
17334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//--------------------------------------------------------------------------
17434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid ProcessMakerNote(unsigned char * ValuePtr, int ByteCount,
17534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        unsigned char * OffsetBase, unsigned ExifLength)
17634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{
17734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (strstr(ImageInfo.CameraMake, "Canon")){
17834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        ProcessCanonMakerNoteDir(ValuePtr, OffsetBase, ExifLength);
17934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }else{
18034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (ShowTags){
18134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            ShowMakerNoteGeneric(ValuePtr, ByteCount);
18234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
18334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
18434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
18534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
186