static void ProcessCanonMakerNoteDir(unsigned char * DirStart, unsigned char * OffsetBase, 
        unsigned ExifLength)
{
    int de;
    int a;
    int NumDirEntries;

    NumDirEntries = Get16u(DirStart);
    #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))

    {
        unsigned char * DirEnd;
        DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries);
        if (DirEnd > (OffsetBase+ExifLength)){
            ErrNonfatal("Illegally sized Exif makernote subdir (%d entries)",NumDirEntries,0);
            return;
        }

        if (DumpExifMap){
            printf("Map: %05u-%05u: Directory (makernote)\n",(int)(DirStart-OffsetBase), (int)(DirEnd-OffsetBase));
        }
    }

    if (ShowTags){
        printf("(dir has %d entries)\n",NumDirEntries);
    }

    for (de=0;de<NumDirEntries;de++){
        int Tag, Format, Components;
        unsigned char * ValuePtr;
        int ByteCount;
        unsigned char * DirEntry;
        DirEntry = DIR_ENTRY_ADDR(DirStart, de);

        Tag = Get16u(DirEntry);
        Format = Get16u(DirEntry+2);
        Components = Get32u(DirEntry+4);
        
        if (Components > 0x10000){
            //Components count too large could cause overflow on subsequent check
            ErrNonfatal("Bad components count %x", Components,0);
            continue;
        }

        if ((Format-1) >= NUM_FORMATS) {
            // (-1) catches illegal zero case as unsigned underflows to positive large.
            ErrNonfatal("Illegal Exif number format %d for maker tag %04x", Format, Tag);
            continue;
        }

        if ((unsigned)Components > 0x10000){
            ErrNonfatal("Too many components (%d) for Exif maker tag %04x", Components, Tag);
            continue;
        }

        ByteCount = Components * BytesPerFormat[Format];

        if (ByteCount > 4){
            unsigned OffsetVal;
            OffsetVal = Get32u(DirEntry+8);
            // If its bigger than 4 bytes, the dir entry contains an offset.
            if (OffsetVal+ByteCount > ExifLength || OffsetVal > 65536){
                // Bogus pointer offset and / or bytecount value
                ErrNonfatal("Illegal value pointer for Exif maker tag %04x", Tag,0);
                continue;
            }
            ValuePtr = OffsetBase+OffsetVal;

            if (DumpExifMap){
                printf("Map: %05d-%05d:   Data for makernote tag %04x\n",OffsetVal, OffsetVal+ByteCount, Tag);
            }
        }else{
            // 4 bytes or less and value is in the dir entry itself
            ValuePtr = DirEntry+8;
        }

        if (ShowTags){
            // Show tag name
            printf("            Canon maker tag %04x Value = ", Tag);
        }

        // Show tag value.
        switch(Format){

            case FMT_UNDEFINED:
                // Undefined is typically an ascii string.

            case FMT_STRING:
                // String arrays printed without function call (different from int arrays)
                if (ShowTags){
                    printf("\"");
                    for (a=0;a<ByteCount;a++){
                        int ZeroSkipped = 0;
                        if (ValuePtr[a] >= 32){
                            if (ZeroSkipped){
                                printf("?");
                                ZeroSkipped = 0;
                            }
                            putchar(ValuePtr[a]);
                        }else{
                            if (ValuePtr[a] == 0){
                                ZeroSkipped = 1;
                            }
                        }
                    }
                    printf("\"\n");
                }
                break;

            default:
                if (ShowTags){
                    PrintFormatNumber(ValuePtr, Format, ByteCount);
                    printf("\n");
                }
        }
        if (Tag == 1 && Components > 16){
            int IsoCode = Get16u(ValuePtr + 16*sizeof(unsigned short));
            if (IsoCode >= 16 && IsoCode <= 24){
                ImageInfo.ISOequivalent = 50 << (IsoCode-16);
            } 
        }

        if (Tag == 4 && Format == FMT_USHORT){
            if (Components > 7){
                int WhiteBalance = Get16u(ValuePtr + 7*sizeof(unsigned short));
                switch(WhiteBalance){
                    // 0=Auto, 6=Custom
                    case 1: ImageInfo.LightSource = 1; break; // Sunny
                    case 2: ImageInfo.LightSource = 1; break; // Cloudy
                    case 3: ImageInfo.LightSource = 3; break; // Thungsten
                    case 4: ImageInfo.LightSource = 2; break; // Fourescent
                    case 5: ImageInfo.LightSource = 4; break; // Flash
                }
            }
            if (Components > 19 && ImageInfo.Distance <= 0) {
                // Indicates the distance the autofocus camera is focused to.
                // Tends to be less accurate as distance increases.
                int temp_dist = Get16u(ValuePtr + 19*sizeof(unsigned short));
                if (temp_dist != 65535){
                    ImageInfo.Distance = (float)temp_dist/100;
                }else{
                    ImageInfo.Distance = -1 /* infinity */;
                }
            }
        }
    }
}
static void ProcessCanonMakerNoteDir(unsigned char * DirStart, unsigned char * OffsetBase, 
        unsigned ExifLength)
{
    int de;
    int a;
    int NumDirEntries;

    NumDirEntries = Get16u(DirStart);
    #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))

    {
        unsigned char * DirEnd;
        DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries);
        if (DirEnd > (OffsetBase+ExifLength)){
            ErrNonfatal("Illegally sized Exif makernote subdir (%d entries)",NumDirEntries,0);
            return;
        }

        if (DumpExifMap){
            printf("Map: %05u-%05u: Directory (makernote)\n",(int)(DirStart-OffsetBase), (int)(DirEnd-OffsetBase));
        }
    }

    if (ShowTags){
        printf("(dir has %d entries)\n",NumDirEntries);
    }

    for (de=0;de<NumDirEntries;de++){
        int Tag, Format, Components;
        unsigned char * ValuePtr;
        int ByteCount;
        unsigned char * DirEntry;
        DirEntry = DIR_ENTRY_ADDR(DirStart, de);

        Tag = Get16u(DirEntry);
        Format = Get16u(DirEntry+2);
        Components = Get32u(DirEntry+4);
        
        if (Components > 0x10000){
             
            ErrNonfatal("Bad components count %x", Components,0);
            continue;
        }

        if ((Format-1) >= NUM_FORMATS) {
             
            ErrNonfatal("Illegal Exif number format %d for maker tag %04x", Format, Tag);
            continue;
        }

        if ((unsigned)Components > 0x10000){
            ErrNonfatal("Too many components (%d) for Exif maker tag %04x", Components, Tag);
            continue;
        }

        ByteCount = Components * BytesPerFormat[Format];

        if (ByteCount > 4){
            unsigned OffsetVal;
            OffsetVal = Get32u(DirEntry+8);
             
            if (OffsetVal+ByteCount > ExifLength || OffsetVal > 65536){
                 
                ErrNonfatal("Illegal value pointer for Exif maker tag %04x", Tag,0);
                continue;
            }
            ValuePtr = OffsetBase+OffsetVal;

            if (DumpExifMap){
                printf("Map: %05d-%05d:   Data for makernote tag %04x\n",OffsetVal, OffsetVal+ByteCount, Tag);
            }
        }else{
             
            ValuePtr = DirEntry+8;
        }

        if (ShowTags){
             
            printf("            Canon maker tag %04x Value = ", Tag);
        }

         
        switch(Format){

            case FMT_UNDEFINED:
                 

            case FMT_STRING:
                 
                if (ShowTags){
                    printf("\"");
                    for (a=0;a<ByteCount;a++){
                        int ZeroSkipped = 0;
                        if (ValuePtr[a] >= 32){
                            if (ZeroSkipped){
                                printf("?");
                                ZeroSkipped = 0;
                            }
                            putchar(ValuePtr[a]);
                        }else{
                            if (ValuePtr[a] == 0){
                                ZeroSkipped = 1;
                            }
                        }
                    }
                    printf("\"\n");
                }
                break;

            default:
                if (ShowTags){
                    PrintFormatNumber(ValuePtr, Format, ByteCount);
                    printf("\n");
                }
        }
        if (Tag == 1 && Components > 16){
            int IsoCode = Get16u(ValuePtr + 16*sizeof(unsigned short));
            if (IsoCode >= 16 && IsoCode <= 24){
                ImageInfo.ISOequivalent = 50 << (IsoCode-16);
            } 
        }

        if (Tag == 4 && Format == FMT_USHORT){
            if (Components > 7){
                int WhiteBalance = Get16u(ValuePtr + 7*sizeof(unsigned short));
                switch(WhiteBalance){
                     
                    case 1: ImageInfo.LightSource = 1; break;  
                    case 2: ImageInfo.LightSource = 1; break;  
                    case 3: ImageInfo.LightSource = 3; break;  
                    case 4: ImageInfo.LightSource = 2; break;  
                    case 5: ImageInfo.LightSource = 4; break;  
                }
            }
            if (Components > 19 && ImageInfo.Distance <= 0) {
                 
                 
                int temp_dist = Get16u(ValuePtr + 19*sizeof(unsigned short));
                if (temp_dist != 65535){
                    ImageInfo.Distance = (float)temp_dist/100;
                }else{
                    ImageInfo.Distance = -1  ;
                }
            }
        }
    }
}