Changeset 190

Show
Ignore:
Timestamp:
Thu Nov 8 14:28:11 2007
Author:
manatlan
Message:

- new version of lib exif.py (version 1.0.4)

Files:

Legend:

Unmodified
Added
Removed
Modified
  • trunk/libs/exif.py

    r122 r190  
    1   # Library to extract EXIF information in digital camera image files  
    2   #  
    3   # To use this library call with:  
    4   #    f=open(path_name, 'rb')  
    5   #    tags=EXIF.process_file(f)  
    6   # tags will now be a dictionary mapping names of EXIF tags to their  
    7   # values in the file named by path_name.  You can process the tags  
    8   # as you wish.  In particular, you can iterate through all the tags with:  
    9   #     for tag in tags.keys():  
    10   #         if tag not in ('JPEGThumbnail', 'TIFFThumbnail', 'Filename',  
    11   #                        'EXIF MakerNote'):  
    12   #             print "Key: %s, value %s" % (tag, tags[tag])  
    13   # (This code uses the if statement to avoid printing out a few of the  
    14   # tags that tend to be long or boring.)  
    15   #  
    16   # The tags dictionary will include keys for all of the usual EXIF  
    17   # tags, and will also include keys for Makernotes used by some  
    18   # cameras, for which we have a good specification.  
    19   #  
    20   # Contains code from "exifdump.py" originally written by Thierry Bousch  
    21   # <bousch@topo.math.u-psud.fr> and released into the public domain.  
    22   #  
    23   # Updated and turned into general-purpose library by Gene Cash  
    24   # <email gcash at cfl.rr.com>  
    25   #  
    26   # This copyright license is intended to be similar to the FreeBSD license.  
    27   #  
    28   # Copyright 2002 Gene Cash All rights reserved.  
    29   #  
    30   # Redistribution and use in source and binary forms, with or without  
    31   # modification, are permitted provided that the following conditions are  
    32   # met:  
    33   #  
    34   #    1. Redistributions of source code must retain the above copyright  
    35   #       notice, this list of conditions and the following disclaimer.  
    36   #    2. Redistributions in binary form must reproduce the above copyright  
    37   #       notice, this list of conditions and the following disclaimer in the  
    38   #       documentation and/or other materials provided with the  
    39   #       distribution.  
    40   #  
    41   # THIS SOFTWARE IS PROVIDED BY GENE CASH ``AS IS'' AND ANY EXPRESS OR  
    42   # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  
    43   # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  
    44   # DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR  
    45   # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  
    46   # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  
    47   # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  
    48   # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,  
    49   # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN  
    50   # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  
    51   # POSSIBILITY OF SUCH DAMAGE.  
    52   #  
    53   # This means you may do anything you want with this code, except claim you  
    54   # wrote it. Also, if it breaks you get to keep both pieces.  
    55   #  
    56   # Patch Contributors:  
    57   # * Simon J. Gerraty <sjg@crufty.net>  
    58   #   s2n fix & orientation decode  
    59   # * John T. Riedl <riedl@cs.umn.edu>  
    60   #   Added support for newer Nikon type 3 Makernote format for D70 and some  
    61   #   other Nikon cameras.  
    62   # * Joerg Schaefer <schaeferj@gmx.net>  
    63   #   Fixed subtle bug when faking an EXIF header, which affected maker notes  
    64   #   using relative offsets, and a fix for Nikon D100.  
    65   #  
    66   # 21-AUG-99 TB  Last update by Thierry Bousch to his code.  
    67   # 17-JAN-02 CEC Discovered code on web.  
    68   #               Commented everything.  
    69   #               Made small code improvements.  
    70   #               Reformatted for readability.  
    71   # 19-JAN-02 CEC Added ability to read TIFFs and JFIF-format JPEGs.  
    72   #               Added ability to extract JPEG formatted thumbnail.  
    73   #               Added ability to read GPS IFD (not tested).  
    74   #               Converted IFD data structure to dictionaries indexed by  
    75   #               tag name.  
    76   #               Factored into library returning dictionary of IFDs plus  
    77   #               thumbnail, if any.  
    78   # 20-JAN-02 CEC Added MakerNote processing logic.  
    79   #               Added Olympus MakerNote.  
    80   #               Converted data structure to single-level dictionary, avoiding  
    81   #               tag name collisions by prefixing with IFD name.  This makes  
    82   #               it much easier to use.  
    83   # 23-JAN-02 CEC Trimmed nulls from end of string values.  
    84   # 25-JAN-02 CEC Discovered JPEG thumbnail in Olympus TIFF MakerNote.  
    85   # 26-JAN-02 CEC Added ability to extract TIFF thumbnails.  
    86   #               Added Nikon, Fujifilm, Casio MakerNotes.  
    87   # 30-NOV-03 CEC Fixed problem with canon_decode_tag() not creating an  
    88   #               IFD_Tag() object.  
    89   # 15-FEB-04 CEC Finally fixed bit shift warning by converting Y to 0L.  
    90   #  
    91    
    92   # field type descriptions as (length, abbreviation, full name) tuples  
    93   FIELD_TYPES=(  
    94       (0, 'X',  'Proprietary'), # no such type  
    95       (1, 'B',  'Byte'),  
    96       (1, 'A',  'ASCII'),  
    97       (2, 'S',  'Short'),  
    98       (4, 'L',  'Long'),  
    99       (8, 'R',  'Ratio'),  
    100       (1, 'SB', 'Signed Byte'),  
    101       (1, 'U',  'Undefined'),  
    102       (2, 'SS', 'Signed Short'),  
    103       (4, 'SL', 'Signed Long'),  
    104       (8, 'SR', 'Signed Ratio')  
    105       )  
    106    
    107   # dictionary of main EXIF tag names  
    108   # first element of tuple is tag name, optional second element is  
    109   # another dictionary giving names to values  
    110   EXIF_TAGS={  
    111       0x0100: ('ImageWidth', ),  
    112       0x0101: ('ImageLength', ),  
    113       0x0102: ('BitsPerSample', ),  
    114       0x0103: ('Compression',  
    115                {1: 'Uncompressed TIFF',  
    116                 6: 'JPEG Compressed'}),  
    117       0x0106: ('PhotometricInterpretation', ),  
    118       0x010A: ('FillOrder', ),  
    119       0x010D: ('DocumentName', ),  
    120       0x010E: ('ImageDescription', ),  
    121       0x010F: ('Make', ),  
    122       0x0110: ('Model', ),  
    123       0x0111: ('StripOffsets', ),  
    124       0x0112: ('Orientation',  
    125                {1: 'Horizontal (normal)',  
    126                 2: 'Mirrored horizontal',  
    127                 3: 'Rotated 180',  
    128                 4: 'Mirrored vertical',  
    129                 5: 'Mirrored horizontal then rotated 90 CCW',  
    130                 6: 'Rotated 90 CW',  
    131                 7: 'Mirrored horizontal then rotated 90 CW',  
    132                 8: 'Rotated 90 CCW'}),  
    133       0x0115: ('SamplesPerPixel', ),  
    134       0x0116: ('RowsPerStrip', ),  
    135       0x0117: ('StripByteCounts', ),  
    136       0x011A: ('XResolution', ),  
    137       0x011B: ('YResolution', ),  
    138       0x011C: ('PlanarConfiguration', ),  
    139       0x0128: ('ResolutionUnit',  
    140                {1: 'Not Absolute',  
    141                 2: 'Pixels/Inch',  
    142                 3: 'Pixels/Centimeter'}),  
    143       0x012D: ('TransferFunction', ),  
    144       0x0131: ('Software', ),  
    145       0x0132: ('DateTime', ),  
    146       0x013B: ('Artist', ),  
    147       0x013E: ('WhitePoint', ),  
    148       0x013F: ('PrimaryChromaticities', ),  
    149       0x0156: ('TransferRange', ),  
    150       0x0200: ('JPEGProc', ),  
    151       0x0201: ('JPEGInterchangeFormat', ),  
    152       0x0202: ('JPEGInterchangeFormatLength', ),  
    153       0x0211: ('YCbCrCoefficients', ),  
    154       0x0212: ('YCbCrSubSampling', ),  
    155       0x0213: ('YCbCrPositioning', ),  
    156       0x0214: ('ReferenceBlackWhite', ),  
    157       0x828D: ('CFARepeatPatternDim', ),  
    158       0x828E: ('CFAPattern', ),  
    159       0x828F: ('BatteryLevel', ),  
    160       0x8298: ('Copyright', ),  
    161       0x829A: ('ExposureTime', ),  
    162       0x829D: ('FNumber', ),  
    163       0x83BB: ('IPTC/NAA', ),  
    164       0x8769: ('ExifOffset', ),  
    165       0x8773: ('InterColorProfile', ),  
    166       0x8822: ('ExposureProgram',  
    167                {0: 'Unidentified',  
    168                 1: 'Manual',  
    169                 2: 'Program Normal',  
    170                 3: 'Aperture Priority',  
    171                 4: 'Shutter Priority',  
    172                 5: 'Program Creative',  
    173                 6: 'Program Action',  
    174                 7: 'Portrait Mode',  
    175                 8: 'Landscape Mode'}),  
    176       0x8824: ('SpectralSensitivity', ),  
    177       0x8825: ('GPSInfo', ),  
    178       0x8827: ('ISOSpeedRatings', ),  
    179       0x8828: ('OECF', ),  
    180       # print as string  
    181       0x9000: ('ExifVersion', lambda x: ''.join(map(chr, x))),  
    182       0x9003: ('DateTimeOriginal', ),  
    183       0x9004: ('DateTimeDigitized', ),  
    184       0x9101: ('ComponentsConfiguration',  
    185                {0: '',  
    186                 1: 'Y',  
    187                 2: 'Cb',  
    188                 3: 'Cr',  
    189                 4: 'Red',  
    190                 5: 'Green',  
    191                 6: 'Blue'}),  
    192       0x9102: ('CompressedBitsPerPixel', ),  
    193       0x9201: ('ShutterSpeedValue', ),  
    194       0x9202: ('ApertureValue', ),  
    195       0x9203: ('BrightnessValue', ),  
    196       0x9204: ('ExposureBiasValue', ),  
    197       0x9205: ('MaxApertureValue', ),  
    198       0x9206: ('SubjectDistance', ),  
    199       0x9207: ('MeteringMode',  
    200                {0: 'Unidentified',  
    201                 1: 'Average',  
    202                 2: 'CenterWeightedAverage',  
    203                 3: 'Spot',  
    204                 4: 'MultiSpot'}),  
    205       0x9208: ('LightSource',  
    206                {0:   'Unknown',  
    207                 1:   'Daylight',  
    208                 2:   'Fluorescent',  
    209                 3:   'Tungsten',  
    210                 10:  'Flash',  
    211                 17:  'Standard Light A',  
    212                 18:  'Standard Light B',  
    213                 19:  'Standard Light C',  
    214                 20:  'D55',  
    215                 21:  'D65',  
    216                 22:  'D75',  
    217                 255: 'Other'}),  
    218       0x9209: ('Flash', {0:  'No',  
    219                          1:  'Fired',  
    220                          5:  'Fired (?)', # no return sensed  
    221                          7:  'Fired (!)', # return sensed  
    222                          9:  'Fill Fired',  
    223                          13: 'Fill Fired (?)',  
    224                          15: 'Fill Fired (!)',  
    225                          16: 'Off',  
    226                          24: 'Auto Off',  
    227                          25: 'Auto Fired',  
    228                          29: 'Auto Fired (?)',  
    229                          31: 'Auto Fired (!)',  
    230                          32: 'Not Available'}),  
    231       0x920A: ('FocalLength', ),  
    232       0x927C: ('MakerNote', ),  
    233       # print as string  
    234       0x9286: ('UserComment', lambda x: ''.join(map(chr, x))),  
    235       0x9290: ('SubSecTime', ),  
    236       0x9291: ('SubSecTimeOriginal', ),  
    237       0x9292: ('SubSecTimeDigitized', ),  
    238       # print as string  
    239       0xA000: ('FlashPixVersion', lambda x: ''.join(map(chr, x))),  
    240       0xA001: ('ColorSpace', ),  
    241       0xA002: ('ExifImageWidth', ),  
    242       0xA003: ('ExifImageLength', ),  
    243       0xA005: ('InteroperabilityOffset', ),  
    244       0xA20B: ('FlashEnergy', ),               # 0x920B in TIFF/EP  
    245       0xA20C: ('SpatialFrequencyResponse', ),  # 0x920C    -  -  
    246       0xA20E: ('FocalPlaneXResolution', ),     # 0x920E    -  -  
    247       0xA20F: ('FocalPlaneYResolution', ),     # 0x920F    -  -  
    248       0xA210: ('FocalPlaneResolutionUnit', ),  # 0x9210    -  -  
    249       0xA214: ('SubjectLocation', ),           # 0x9214    -  -  
    250       0xA215: ('ExposureIndex', ),             # 0x9215    -  -  
    251       0xA217: ('SensingMethod', ),             # 0x9217    -  -  
    252       0xA300: ('FileSource',  
    253                {3: 'Digital Camera'}),  
    254       0xA301: ('SceneType',  
    255                {1: 'Directly Photographed'}),  
    256       0xA302: ('CVAPattern',),  
    257       }  
    258    
    259   # interoperability tags  
    260   INTR_TAGS={  
    261       0x0001: ('InteroperabilityIndex', ),  
    262       0x0002: ('InteroperabilityVersion', ),  
    263       0x1000: ('RelatedImageFileFormat', ),  
    264       0x1001: ('RelatedImageWidth', ),  
    265       0x1002: ('RelatedImageLength', ),  
    266       }  
    267    
    268   # GPS tags (not used yet, haven't seen camera with GPS)  
    269   GPS_TAGS={  
    270       0x0000: ('GPSVersionID', ),  
    271       0x0001: ('GPSLatitudeRef', ),  
    272       0x0002: ('GPSLatitude', ),  
    273       0x0003: ('GPSLongitudeRef', ),  
    274       0x0004: ('GPSLongitude', ),  
    275       0x0005: ('GPSAltitudeRef', ),  
    276       0x0006: ('GPSAltitude', ),  
    277       0x0007: ('GPSTimeStamp', ),  
    278       0x0008: ('GPSSatellites', ),  
    279       0x0009: ('GPSStatus', ),  
    280       0x000A: ('GPSMeasureMode', ),  
    281       0x000B: ('GPSDOP', ),  
    282       0x000C: ('GPSSpeedRef', ),  
    283       0x000D: ('GPSSpeed', ),  
    284       0x000E: ('GPSTrackRef', ),  
    285       0x000F: ('GPSTrack', ),  
    286       0x0010: ('GPSImgDirectionRef', ),  
    287       0x0011: ('GPSImgDirection', ),  
    288       0x0012: ('GPSMapDatum', ),  
    289       0x0013: ('GPSDestLatitudeRef', ),  
    290       0x0014: ('GPSDestLatitude', ),  
    291       0x0015: ('GPSDestLongitudeRef', ),  
    292       0x0016: ('GPSDestLongitude', ),  
    293       0x0017: ('GPSDestBearingRef', ),  
    294       0x0018: ('GPSDestBearing', ),  
    295       0x0019: ('GPSDestDistanceRef', ),  
    296       0x001A: ('GPSDestDistance', )  
    297       }  
    298    
    299   # Nikon E99x MakerNote Tags  
    300   # http://members.tripod.com/~tawba/990exif.htm  
    301   MAKERNOTE_NIKON_NEWER_TAGS={  
    302       0x0002: ('ISOSetting', ),  
    303       0x0003: ('ColorMode', ),  
    304       0x0004: ('Quality', ),  
    305       0x0005: ('Whitebalance', ),  
    306       0x0006: ('ImageSharpening', ),  
    307       0x0007: ('FocusMode', ),  
    308       0x0008: ('FlashSetting', ),  
    309       0x0009: ('AutoFlashMode', ),  
    310       0x000B: ('WhiteBalanceBias', ),  
    311       0x000C: ('WhiteBalanceRBCoeff', ),  
    312       0x000F: ('ISOSelection', ),  
    313       0x0012: ('FlashCompensation', ),  
    314       0x0013: ('ISOSpeedRequested', ),  
    315       0x0016: ('PhotoCornerCoordinates', ),  
    316       0x0018: ('FlashBracketCompensationApplied', ),  
    317       0x0019: ('AEBracketCompensationApplied', ),  
    318       0x0080: ('ImageAdjustment', ),  
    319       0x0081: ('ToneCompensation', ),  
    320       0x0082: ('AuxiliaryLens', ),  
    321       0x0083: ('LensType', ),  
    322       0x0084: ('LensMinMaxFocalMaxAperture', ),  
    323       0x0085: ('ManualFocusDistance', ),  
    324       0x0086: ('DigitalZoomFactor', ),  
    325       0x0088: ('AFFocusPosition',  
    326                {0x0000: 'Center',  
    327                 0x0100: 'Top',  
    328                 0x0200: 'Bottom',  
    329                 0x0300: 'Left',  
    330                 0x0400: 'Right'}),  
    331       0x0089: ('BracketingMode',  
    332                {0x00: 'Single frame, no bracketing',  
    333                 0x01: 'Continuous, no bracketing',  
    334                 0x02: 'Timer, no bracketing',  
    335                 0x10: 'Single frame, exposure bracketing',  
    336                 0x11: 'Continuous, exposure bracketing',  
    337                 0x12: 'Timer, exposure bracketing',  
    338                 0x40: 'Single frame, white balance bracketing',  
    339                 0x41: 'Continuous, white balance bracketing',  
    340                 0x42: 'Timer, white balance bracketing'}),  
    341       0x008D: ('ColorMode', ),  
    342       0x008F: ('SceneMode?', ),  
    343       0x0090: ('LightingType', ),  
    344       0x0092: ('HueAdjustment', ),  
    345       0x0094: ('Saturation',  
    346                {-3: 'B&W',  
    347                 -2: '-2',  
    348                 -1: '-1',  
    349                 0:  '0',  
    350                 1:  '1',  
    351                 2:  '2'}),  
    352       0x0095: ('NoiseReduction', ),  
    353       0x00A7: ('TotalShutterReleases', ),  
    354       0x00A9: ('ImageOptimization', ),  
    355       0x00AA: ('Saturation', ),  
    356       0x00AB: ('DigitalVariProgram', ),  
    357       0x0010: ('DataDump', )  
    358       }  
    359    
    360   MAKERNOTE_NIKON_OLDER_TAGS={  
    361       0x0003: ('Quality',  
    362                {1: 'VGA Basic',  
    363                 2: 'VGA Normal',  
    364                 3: 'VGA Fine',  
    365                 4: 'SXGA Basic',  
    366                 5: 'SXGA Normal',  
    367                 6: 'SXGA Fine'}),  
    368       0x0004: ('ColorMode',  
    369                {1: 'Color',  
    370                 2: 'Monochrome'}),  
    371       0x0005: ('ImageAdjustment',  
    372                {0: 'Normal',  
    373                 1: 'Bright+',  
    374                 2: 'Bright-',  
    375                 3: 'Contrast+',  
    376                 4: 'Contrast-'}),  
    377       0x0006: ('CCDSpeed',  
    378                {0: 'ISO 80',  
    379                 2: 'ISO 160',  
    380                 4: 'ISO 320',  
    381                 5: 'ISO 100'}),  
    382       0x0007: ('WhiteBalance',  
    383                {0: 'Auto',  
    384                 1: 'Preset',  
    385                 2: 'Daylight',  
    386                 3: 'Incandescent',  
    387                 4: 'Fluorescent',  
    388                 5: 'Cloudy',  
    389                 6: 'Speed Light'})  
    390       }  
    391    
    392   # decode Olympus SpecialMode tag in MakerNote  
    393   def olympus_special_mode(v):  
    394       a={  
    395           0: 'Normal',  
    396           1: 'Unknown',  
    397           2: 'Fast',  
    398           3: 'Panorama'}  
    399       b={  
    400           0: 'Non-panoramic',  
    401           1: 'Left to right',  
    402           2: 'Right to left',  
    403           3: 'Bottom to top',  
    404           4: 'Top to bottom'}  
    405       return '%s - sequence %d - %s' % (a[v[0]], v[1], b[v[2]])  
    406            
    407   MAKERNOTE_OLYMPUS_TAGS={  
    408       # ah HAH! those sneeeeeaky bastids! this is how they get past the fact  
    409       # that a JPEG thumbnail is not allowed in an uncompressed TIFF file  
    410       0x0100: ('JPEGThumbnail', ),  
    411       0x0200: ('SpecialMode', olympus_special_mode),  
    412       0x0201: ('JPEGQual',  
    413                {1: 'SQ',  
    414                 2: 'HQ',  
    415                 3: 'SHQ'}),  
    416       0x0202: ('Macro',  
    417                {0: 'Normal',  
    418                 1: 'Macro'}),  
    419       0x0204: ('DigitalZoom', ),  
    420       0x0207: ('SoftwareRelease',  ),  
    421       0x0208: ('PictureInfo',  ),  
    422       # print as string  
    423       0x0209: ('CameraID', lambda x: ''.join(map(chr, x))),  
    424       0x0F00: ('DataDump',  )  
    425       }  
    426    
    427   MAKERNOTE_CASIO_TAGS={  
    428       0x0001: ('RecordingMode',  
    429                {1: 'Single Shutter',  
    430                 2: 'Panorama',  
    431                 3: 'Night Scene',  
    432                 4: 'Portrait',  
    433                 5: 'Landscape'}),  
    434       0x0002: ('Quality',  
    435                {1: 'Economy',  
    436                 2: 'Normal',  
    437                 3: 'Fine'}),  
    438       0x0003: ('FocusingMode',  
    439                {2: 'Macro',  
    440                 3: 'Auto Focus',  
    441                 4: 'Manual Focus',  
    442                 5: 'Infinity'}),  
    443       0x0004: ('FlashMode',  
    444                {1: 'Auto',  
    445                 2: 'On',  
    446                 3: 'Off',  
    447                 4: 'Red Eye Reduction'}),  
    448       0x0005: ('FlashIntensity',  
    449                {11: 'Weak',  
    450                 13: 'Normal',  
    451                 15: 'Strong'}),  
    452       0x0006: ('Object Distance', ),  
    453       0x0007: ('WhiteBalance',  
    454                {1:   'Auto',  
    455                 2:   'Tungsten',  
    456                 3:   'Daylight',  
    457                 4:   'Fluorescent',  
    458                 5:   'Shade',  
    459                 129: 'Manual'}),  
    460       0x000B: ('Sharpness',  
    461                {0: 'Normal',  
    462                 1: 'Soft',  
    463                 2: 'Hard'}),  
    464       0x000C: ('Contrast',  
    465                {0: 'Normal',  
    466                 1: 'Low',  
    467                 2: 'High'}),  
    468       0x000D: ('Saturation',  
    469                {0: 'Normal',  
    470                 1: 'Low',  
    471                 2: 'High'}),  
    472       0x0014: ('CCDSpeed',  
    473                {64:  'Normal',  
    474                 80:  'Normal',  
    475                 100: 'High',  
    476                 125: '+1.0',  
    477                 244: '+3.0',  
    478                 250: '+2.0',})  
    479       }  
    480    
    481   MAKERNOTE_FUJIFILM_TAGS={  
    482       0x0000: ('NoteVersion', lambda x: ''.join(map(chr, x))),  
    483       0x1000: ('Quality', ),  
    484       0x1001: ('Sharpness',  
    485                {1: 'Soft',  
    486                 2: 'Soft',  
    487                 3: 'Normal',  
    488                 4: 'Hard',  
    489                 5: 'Hard'}),  
    490       0x1002: ('WhiteBalance',  
    491                {0:    'Auto',  
    492                 256:  'Daylight',  
    493                 512:  'Cloudy',  
    494                 768:  'DaylightColor-Fluorescent',  
    495                 769:  'DaywhiteColor-Fluorescent',  
    496                 770:  'White-Fluorescent',  
    497                 1024: 'Incandescent',  
    498                 3840: 'Custom'}),  
    499       0x1003: ('Color',  
    500                {0:   'Normal',  
    501                 256: 'High',  
    502                 512: 'Low'}),  
    503       0x1004: ('Tone',  
    504                {0:   'Normal',  
    505                 256: 'High',  
    506                 512: 'Low'}),  
    507       0x1010: ('FlashMode',  
    508                {0: 'Auto',  
    509                 1: 'On',  
    510                 2: 'Off',  
    511                 3: 'Red Eye Reduction'}),  
    512       0x1011: ('FlashStrength', ),  
    513       0x1020: ('Macro',  
    514                {0: 'Off',  
    515                 1: 'On'}),  
    516       0x1021: ('FocusMode',  
    517                {0: 'Auto',  
    518                 1: 'Manual'}),  
    519       0x1030: ('SlowSync',  
    520                {0: 'Off',  
    521                 1: 'On'}),  
    522       0x1031: ('PictureMode',  
    523                {0:   'Auto',  
    524                 1:   'Portrait',  
    525                 2:   'Landscape',  
    526                 4:   'Sports',  
    527                 5:   'Night',  
    528                 6:   'Program AE',  
    529                 256: 'Aperture Priority AE',  
    530                 512: 'Shutter Priority AE',  
    531                 768: 'Manual Exposure'}),  
    532       0x1100: ('MotorOrBracket',  
    533                {0: 'Off',  
    534                 1: 'On'}),  
    535       0x1300: ('BlurWarning',  
    536                {0: 'Off',  
    537                 1: 'On'}),  
    538       0x1301: ('FocusWarning',  
    539                {0: 'Off',  
    540                 1: 'On'}),  
    541       0x1302: ('AEWarning',  
    542                {0: 'Off',  
    543                 1: 'On'})  
    544       }  
    545    
    546   MAKERNOTE_CANON_TAGS={  
    547       0x0006: ('ImageType', ),  
    548       0x0007: ('FirmwareVersion', ),  
    549       0x0008: ('ImageNumber', ),  
    550       0x0009: ('OwnerName', )  
    551       }  
    552    
    553   # see http://www.burren.cx/david/canon.html by David Burren  
    554   # this is in element offset, name, optional value dictionary format  
    555   MAKERNOTE_CANON_TAG_0x001={  
    556       1: ('Macromode',  
    557           {1: 'Macro',  
    558            2: 'Normal'}),  
    559       2: ('SelfTimer', ),  
    560       3: ('Quality',  
    561           {2: 'Normal',  
    562            3: 'Fine',  
    563            5: 'Superfine'}),  
    564       4: ('FlashMode',  
    565           {0: 'Flash Not Fired',  
    566            1: 'Auto',  
    567            2: 'On',  
    568            3: 'Red-Eye Reduction',  
    569            4: 'Slow Synchro',  
    570            5: 'Auto + Red-Eye Reduction',  
    571            6: 'On + Red-Eye Reduction',  
    572            16: 'external flash'}),  
    573       5: ('ContinuousDriveMode',  
    574           {0: 'Single Or Timer',  
    575            1: 'Continuous'}),  
    576       7: ('FocusMode',  
    577           {0: 'One-Shot',  
    578            1: 'AI Servo',  
    579            2: 'AI Focus',  
    580            3: 'MF',  
    581            4: 'Single',  
    582            5: 'Continuous',  
    583            6: 'MF'}),  
    584       10: ('ImageSize',  
    585            {0: 'Large',  
    586             1: 'Medium',  
    587             2: 'Small'}),  
    588       11: ('EasyShootingMode',  
    589            {0: 'Full Auto',  
    590             1: 'Manual',  
    591             2: 'Landscape',  
    592             3: 'Fast Shutter',  
    593             4: 'Slow Shutter',  
    594             5: 'Night',  
    595             6: 'B&W',  
    596             7: 'Sepia',  
    597             8: 'Portrait',  
    598             9: 'Sports',  
    599             10: 'Macro/Close-Up',  
    600             11: 'Pan Focus'}),  
    601       12: ('DigitalZoom',  
    602            {0: 'None',  
    603             1: '2x',  
    604             2: '4x'}),  
    605       13: ('Contrast',  
    606            {0xFFFF: 'Low',  
    607             0: 'Normal',  
    608             1: 'High'}),  
    609       14: ('Saturation',  
    610            {0xFFFF: 'Low',  
    611             0: 'Normal',  
    612             1: 'High'}),  
    613       15: ('Sharpness',  
    614            {0xFFFF: 'Low',  
    615             0: 'Normal',  
    616             1: 'High'}),  
    617       16: ('ISO',  
    618            {0: 'See ISOSpeedRatings Tag',  
    619             15: 'Auto',  
    620             16: '50',  
    621             17: '100',  
    622             18: '200',  
    623             19: '400'}),  
    624       17: ('MeteringMode',  
    625            {3: 'Evaluative',  
    626             4: 'Partial',  
    627             5: 'Center-weighted'}),  
    628       18: ('FocusType',  
    629            {0: 'Manual',  
    630             1: 'Auto',  
    631             3: 'Close-Up (Macro)',  
    632             8: 'Locked (Pan Mode)'}),  
    633       19: ('AFPointSelected',  
    634            {0x3000: 'None (MF)',  
    635             0x3001: 'Auto-Selected',  
    636             0x3002: 'Right',  
    637             0x3003: 'Center',  
    638             0x3004: 'Left'}),  
    639       20: ('ExposureMode',  
    640            {0: 'Easy Shooting',  
    641             1: 'Program',  
    642             2: 'Tv-priority',  
    643             3: 'Av-priority',  
    644             4: 'Manual',  
    645             5: 'A-DEP'}),  
    646       23: ('LongFocalLengthOfLensInFocalUnits', ),  
    647       24: ('ShortFocalLengthOfLensInFocalUnits', ),  
    648       25: ('FocalUnitsPerMM', ),  
    649       28: ('FlashActivity',  
    650            {0: 'Did Not Fire',  
    651             1: 'Fired'}),  
    652       29: ('FlashDetails',  
    653            {14: 'External E-TTL',  
    654             13: 'Internal Flash',  
    655             11: 'FP Sync Used',  
    656             7: '2nd("Rear")-Curtain Sync Used',  
    657             4: 'FP Sync Enabled'}),  
    658       32: ('FocusMode',  
    659            {0: 'Single',  
    660             1: 'Continuous'})  
    661       }  
    662    
    663   MAKERNOTE_CANON_TAG_0x004={  
    664       7: ('WhiteBalance',  
    665           {0: 'Auto',  
    666            1: 'Sunny',  
    667            2: 'Cloudy',  
    668            3: 'Tungsten',  
    669            4: 'Fluorescent',  
    670            5: 'Flash',  
    671            6: 'Custom'}),  
    672       9: ('SequenceNumber', ),  
    673       14: ('AFPointUsed', ),  
    674       15: ('FlashBias',  
    675           {0XFFC0: '-2 EV',  
    676            0XFFCC: '-1.67 EV',  
    677            0XFFD0: '-1.50 EV',  
    678            0XFFD4: '-1.33 EV',  
    679            0XFFE0: '-1 EV',  
    680            0XFFEC: '-0.67 EV',  
    681            0XFFF0: '-0.50 EV',  
    682            0XFFF4: '-0.33 EV',  
    683            0X0000: '0 EV',  
    684            0X000C: '0.33 EV',  
    685            0X0010: '0.50 EV',  
    686            0X0014: '0.67 EV',  
    687            0X0020: '1 EV',  
    688            0X002C: '1.33 EV',  
    689            0X0030: '1.50 EV',  
    690            0X0034: '1.67 EV',  
    691            0X0040: '2 EV'}),  
    692       19: ('SubjectDistance', )  
    693       }  
    694    
    695   # extract multibyte integer in Motorola format (little endian)  
    696   def s2n_motorola(str):  
    697       x=0  
    698       for c in str:  
    699           x=(x << 8) | ord(c)  
    700       return x  
    701    
    702   # extract multibyte integer in Intel format (big endian)  
    703   def s2n_intel(str):  
    704       x=0  
    705       y=0L  
    706       for c in str:  
    707           x=x | (ord(c) << y)  
    708           y=y+8  
    709       return x  
    710    
    711   # ratio object that eventually will be able to reduce itself to lowest  
    712   # common denominator for printing  
    713   def gcd(a, b):  
    714      if b == 0:  
    715         return a  
    716      else:  
    717         return gcd(b, a % b)  
    718    
    719   class Ratio:  
    720       def __init__(self, num, den):  
    721           self.num=num  
    722           self.den=den  
    723