Ignore:
Timestamp:
2011-06-01T12:33:42+12:00 (13 years ago)
Author:
sjm84
Message:

Updating the ExifTool perl modules

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone2/perllib/cpan/Image/ExifTool/Exif.pm

    r16842 r24107  
    22# File:         Exif.pm
    33#
    4 # Description:  Read EXIF meta information
     4# Description:  Read EXIF/TIFF meta information
    55#
    66# Revisions:    11/25/2003 - P. Harvey Created
     
    1212# References:   0) http://www.exif.org/Exif2-2.PDF
    1313#               1) http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf
    14 #               2) http://www.adobe.com/products/dng/pdfs/dng_spec.pdf
     14#               2) http://www.adobe.com/products/dng/pdfs/dng_spec_1_3_0_0.pdf
    1515#               3) http://www.awaresystems.be/imaging/tiff/tifftags.html
    1616#               4) http://www.remotesensing.org/libtiff/TIFFTechNote2.html
    17 #               5) http://www.asmail.be/msg0054681802.html
     17#               5) http://www.exif.org/dcf.PDF
    1818#               6) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html
    1919#               7) http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf
     
    2424#              12) http://www.broomscloset.com/closet/photo/exif/TAG2000-22_DIS12234-2.PDF
    2525#              13) http://www.microsoft.com/whdc/xps/wmphoto.mspx
     26#              14) http://www.asmail.be/msg0054681802.html
     27#              15) http://crousseau.free.fr/imgfmt_raw.htm
     28#              16) http://www.cybercom.net/~dcoffin/dcraw/
     29#              17) http://www.digitalpreservation.gov/formats/content/tiff_tags.shtml
     30#              18) http://www.asmail.be/msg0055568584.html
     31#              19) http://libpsd.graphest.com/files/Photoshop%20File%20Formats.pdf
     32#              20) http://tiki-lounge.com/~raf/tiff/fields.html
     33#              21) http://community.roxen.com/developers/idocs/rfc/rfc3949.html
     34#              22) http://tools.ietf.org/html/draft-ietf-fax-tiff-fx-extension1-01
     35#              23) MetaMorph Stack (STK) Image File Format:
     36#                  --> ftp://ftp.meta.moleculardevices.com/support/stack/STK.doc
     37#              24) http://www.cipa.jp/english/hyoujunka/kikaku/pdf/DC-008-2010_E.pdf (Exif 2.3)
     38#              25) Vesa Kivisto private communication (7D)
     39#              26) Jeremy Brown private communication
     40#              JD) Jens Duttke private communication
    2641#------------------------------------------------------------------------------
    2742
     
    2944
    3045use strict;
    31 use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber
    32             %lightSource %compression %photometricInterpretation %orientation);
     46use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat
     47            %lightSource %flash %compression %photometricInterpretation %orientation
     48            %subfileType);
    3349use Image::ExifTool qw(:DataAccess :Utils);
    3450use Image::ExifTool::MakerNotes;
    3551
    36 $VERSION = '2.42';
     52$VERSION = '3.21';
    3753
    3854sub ProcessExif($$$);
     
    4258sub EncodeExifText($$);
    4359sub ValidateIFD($;$);
     60sub ProcessTiffIFD($$$);
     61sub PrintParameter($$$);
     62sub GetOffList($$$$$);
     63sub PrintLensInfo($);
     64sub ConvertLensInfo($);
     65
     66# size limit for loading binary data block into memory
     67sub BINARY_DATA_LIMIT { return 10 * 1024 * 1024; }
    4468
    4569# byte sizes for the various EXIF format types below
    46 @formatSize = (undef,1,1,2,4,8,1,1,2,4,8,4,8,4,undef,undef,8,8,8);
     70@formatSize = (undef,1,1,2,4,8,1,1,2,4,8,4,8,4,2,8,8,8,8);
    4771
    4872@formatName = (
     
    5074    'int32u', 'rational64u', 'int8s', 'undef',
    5175    'int16s', 'int32s', 'rational64s', 'float',
    52     'double', 'ifd', undef, undef, # (14 is unicode, 15 is complex? http://remotesensing.org/libtiff/bigtiffdesign.html)
    53     'int64u', 'int64s', 'ifd8', # (new BigTIFF formats)
     76    'double', 'ifd', 'unicode', 'complex',
     77    'int64u', 'int64s', 'ifd64', # (new BigTIFF formats)
    5478);
    5579
     
    5781# (format types are all lower case)
    5882%formatNumber = (
    59     'int8u'         => 1,   # BYTE
    60     'string'        => 2,   # ASCII
    61     'int16u'        => 3,   # SHORT
    62     'int32u'        => 4,   # LONG
    63     'rational64u'   => 5,   # RATIONAL
    64     'int8s'         => 6,   # SBYTE
    65     'undef'         => 7,   # UNDEFINED
    66     'binary'        => 7,   # (treat binary data as undef)
    67     'int16s'        => 8,   # SSHORT
    68     'int32s'        => 9,   # SLONG
    69     'rational64s'   => 10,  # SRATIONAL
    70     'float'         => 11,  # FLOAT
    71     'double'        => 12,  # DOUBLE
    72     'ifd'           => 13,  # IFD (with int32u format)
    73     'int64u'        => 16,  # LONG8 [BigTIFF]
    74     'int64s'        => 17,  # SLONG8 [BigTIFF]
    75     'ifd8'          => 18,  # IFD8 (with int64u format) [BigTIFF]
     83    'int8u'       => 1,  # BYTE
     84    'string'      => 2,  # ASCII
     85    'int16u'      => 3,  # SHORT
     86    'int32u'      => 4,  # LONG
     87    'rational64u' => 5,  # RATIONAL
     88    'int8s'       => 6,  # SBYTE
     89    'undef'       => 7,  # UNDEFINED
     90    'binary'      => 7,  # (treat binary data as undef)
     91    'int16s'      => 8,  # SSHORT
     92    'int32s'      => 9,  # SLONG
     93    'rational64s' => 10, # SRATIONAL
     94    'float'       => 11, # FLOAT
     95    'double'      => 12, # DOUBLE
     96    'ifd'         => 13, # IFD (with int32u format)
     97    'unicode'     => 14, # UNICODE [see Note below]
     98    'complex'     => 15, # COMPLEX [see Note below]
     99    'int64u'      => 16, # LONG8 [BigTIFF]
     100    'int64s'      => 17, # SLONG8 [BigTIFF]
     101    'ifd64'       => 18, # IFD8 (with int64u format) [BigTIFF]
     102    # Note: unicode and complex types are not yet properly supported by ExifTool.
     103    # These are types which have been observed in the Adobe DNG SDK code, but
     104    # aren't fully supported there either.  We know the sizes, but that's about it.
     105    # We don't know if the unicode is null terminated, or the format for complex
     106    # (although I suspect it would be two 4-byte floats, real and imaginary).
     107);
     108
     109# lookup for integer format strings
     110%intFormat = (
     111    'int8u'  => 1,
     112    'int16u' => 3,
     113    'int32u' => 4,
     114    'int8s'  => 6,
     115    'int16s' => 8,
     116    'int32s' => 9,
     117    'ifd'    => 13,
     118    'int64u' => 16,
     119    'int64s' => 17,
     120    'ifd64'  => 18,
    76121);
    77122
    78123# EXIF LightSource PrintConv values
    79124%lightSource = (
     125    0 => 'Unknown',
    80126    1 => 'Daylight',
    81127    2 => 'Fluorescent',
    82     3 => 'Tungsten',
     128    3 => 'Tungsten (Incandescent)',
    83129    4 => 'Flash',
    84130    9 => 'Fine Weather',
    85131    10 => 'Cloudy',
    86132    11 => 'Shade',
    87     12 => 'Daylight Fluorescent',
    88     13 => 'Day White Fluorescent',
    89     14 => 'Cool White Fluorescent',
    90     15 => 'White Fluorescent',
     133    12 => 'Daylight Fluorescent',   # (D 5700 - 7100K)
     134    13 => 'Day White Fluorescent',  # (N 4600 - 5500K)
     135    14 => 'Cool White Fluorescent', # (W 3800 - 4500K)
     136    15 => 'White Fluorescent',      # (WW 3250 - 3800K)
     137    16 => 'Warm White Fluorescent', # (L 2600 - 3250K)
    91138    17 => 'Standard Light A',
    92139    18 => 'Standard Light B',
     
    100147);
    101148
     149# EXIF Flash values
     150%flash = (
     151    OTHER => sub {
     152        # translate "Off" and "On" when writing
     153        my ($val, $inv) = @_;
     154        return undef unless $inv and $val =~ /^(off|on)$/i;
     155        return lc $val eq 'off' ? 0x00 : 0x01;
     156    },
     157    0x00 => 'No Flash',
     158    0x01 => 'Fired',
     159    0x05 => 'Fired, Return not detected',
     160    0x07 => 'Fired, Return detected',
     161    0x08 => 'On, Did not fire', # not charged up?
     162    0x09 => 'On, Fired',
     163    0x0d => 'On, Return not detected',
     164    0x0f => 'On, Return detected',
     165    0x10 => 'Off, Did not fire',
     166    0x14 => 'Off, Did not fire, Return not detected',
     167    0x18 => 'Auto, Did not fire',
     168    0x19 => 'Auto, Fired',
     169    0x1d => 'Auto, Fired, Return not detected',
     170    0x1f => 'Auto, Fired, Return detected',
     171    0x20 => 'No flash function',
     172    0x30 => 'Off, No flash function',
     173    0x41 => 'Fired, Red-eye reduction',
     174    0x45 => 'Fired, Red-eye reduction, Return not detected',
     175    0x47 => 'Fired, Red-eye reduction, Return detected',
     176    0x49 => 'On, Red-eye reduction',
     177    0x4d => 'On, Red-eye reduction, Return not detected',
     178    0x4f => 'On, Red-eye reduction, Return detected',
     179    0x50 => 'Off, Red-eye reduction',
     180    0x58 => 'Auto, Did not fire, Red-eye reduction',
     181    0x59 => 'Auto, Fired, Red-eye reduction',
     182    0x5d => 'Auto, Fired, Red-eye reduction, Return not detected',
     183    0x5f => 'Auto, Fired, Red-eye reduction, Return detected',
     184);
     185
     186# TIFF Compression values
     187# (values with format "Xxxxx XXX Compressed" are used to identify RAW file types)
    102188%compression = (
    103189    1 => 'Uncompressed',
     
    111197    9 => 'JBIG B&W', #3
    112198    10 => 'JBIG Color', #3
     199    99 => 'JPEG', #16
     200    262 => 'Kodak 262', #16
    113201    32766 => 'Next', #3
    114     32769 => 'Epson ERF Compressed', #PH
     202    32767 => 'Sony ARW Compressed', #16
     203    32769 => 'Packed RAW', #PH (used by Epson, Nikon, Samsung)
     204    32770 => 'Samsung SRW Compressed', #PH
    115205    32771 => 'CCIRLEW', #3
    116206    32773 => 'PackBits',
    117207    32809 => 'Thunderscan', #3
     208    32867 => 'Kodak KDC Compressed', #PH
    118209    32895 => 'IT8CTPAD', #3
    119210    32896 => 'IT8LW', #3
     
    129220    34712 => 'JPEG 2000', #3
    130221    34713 => 'Nikon NEF Compressed', #PH
     222    34715 => 'JBIG2 TIFF FX', #20
     223    34718 => 'Microsoft Document Imaging (MDI) Binary Level Codec', #18
     224    34719 => 'Microsoft Document Imaging (MDI) Progressive Transform Codec', #18
     225    34720 => 'Microsoft Document Imaging (MDI) Vector', #18
    131226    65000 => 'Kodak DCR Compressed', #PH
    132227    65535 => 'Pentax PEF Compressed', #Jens
    133    
    134228);
    135229
     
    162256);
    163257
     258%subfileType = (
     259    0 => 'Full-resolution Image',
     260    1 => 'Reduced-resolution image',
     261    2 => 'Single page of multi-page image',
     262    3 => 'Single page of multi-page reduced-resolution image',
     263    4 => 'Transparency mask',
     264    5 => 'Transparency mask of reduced-resolution image',
     265    6 => 'Transparency mask of multi-page image',
     266    7 => 'Transparency mask of reduced-resolution multi-page image',
     267    0xffffffff => 'invalid', #(found in E5700 NEF's)
     268    BITMASK => {
     269        0 => 'Reduced resolution',
     270        1 => 'Single page',
     271        2 => 'Transparency mask',
     272        3 => 'TIFF/IT final page', #20
     273        4 => 'TIFF-FX mixed raster content', #20
     274    },
     275);
     276
     277# PrintConv for parameter tags
     278%Image::ExifTool::Exif::printParameter = (
     279    PrintConv => {
     280        0 => 'Normal',
     281        OTHER => \&Image::ExifTool::Exif::PrintParameter,
     282    },
     283);
     284
    164285# ValueConv that makes long values binary type
    165286my %longBin = (
     
    168289);
    169290
     291# PrintConv for SampleFormat (0x153)
     292my %sampleFormat = (
     293    1 => 'Unsigned',        # unsigned integer
     294    2 => 'Signed',          # two's complement signed integer
     295    3 => 'Float',           # IEEE floating point
     296    4 => 'Undefined',
     297    5 => 'Complex int',     # complex integer (ref 3)
     298    6 => 'Complex float',   # complex IEEE floating point (ref 3)
     299);
     300
    170301# main EXIF tag table
    171302%Image::ExifTool::Exif::Main = (
     
    173304    WRITE_PROC => \&WriteExif,
    174305    WRITE_GROUP => 'ExifIFD',   # default write group
     306    SET_GROUP1 => 1, # set group1 name to directory name for all tags in table
    175307    0x1 => {
    176308        Name => 'InteropIndex',
     
    182314        },
    183315    },
    184     0x2 => {
     316    0x2 => { #5
    185317        Name => 'InteropVersion',
    186318        Description => 'Interoperability Version',
     319        RawConv => '$val=~s/\0+$//; $val',  # (some idiots add null terminators)
    187320    },
    188321    0x0b => { #PH
     
    193326        Name => 'SubfileType',
    194327        # set priority directory if this is the full resolution image
    195         RawConv => '$self->SetPriorityDir() if $val == 0; $val',
    196         PrintConv => {
    197             0 => 'Full-resolution Image',
    198             1 => 'Reduced-resolution image',
    199             2 => 'Single page of multi-page image',
    200             3 => 'Single page of multi-page reduced-resolution image',
    201             4 => 'Transparency mask',
    202             5 => 'Transparency mask of reduced-resolution image',
    203             6 => 'Transparency mask of multi-page image',
    204             7 => 'Transparency mask of reduced-resolution multi-page image',
    205         },
     328        DataMember => 'SubfileType',
     329        RawConv => '$self->SetPriorityDir() if $val eq "0"; $$self{SubfileType} = $val',
     330        PrintConv => \%subfileType,
    206331    },
    207332    0xff => {
    208333        Name => 'OldSubfileType',
    209334        # set priority directory if this is the full resolution image
    210         RawConv => '$self->SetPriorityDir() if $val == 1; $val',
     335        RawConv => '$self->SetPriorityDir() if $val eq "1"; $val',
    211336        PrintConv => {
    212337            1 => 'Full-resolution image',
     
    220345        # so it will show up in the group lists
    221346        Groups => { 1 => 'IFD1' },
    222         # set Priority to zero so the value found in the first IFD (IFD0) doesn't
    223         # get overwritten by subsequent IFD's (same for ImageHeight below)
     347        # Note: priority 0 tags automatically have their priority increased for the
     348        # priority direcory (the directory with a SubfileType of "Full-resolution image")
    224349        Priority => 0,
    225350    },
    226351    0x101 => {
    227352        Name => 'ImageHeight',
     353        Notes => 'called ImageLength by the EXIF spec.',
    228354        Priority => 0,
    229355    },
     
    234360    0x103 => {
    235361        Name => 'Compression',
     362        DataMember => 'Compression',
     363        SeparateTable => 'Compression',
     364        RawConv => q{
     365            Image::ExifTool::Exif::IdentifyRawFile($self, $val);
     366            return $$self{Compression} = $val;
     367        },
    236368        PrintConv => \%compression,
    237369        Priority => 0,
     
    267399        Name => 'Make',
    268400        Groups => { 2 => 'Camera' },
    269         DataMember => 'CameraMake',
    270         # save this value as an ExifTool member variable
    271         RawConv => '$self->{CameraMake} = $val',
     401        DataMember => 'Make',
     402        # remove trailing blanks and save as an ExifTool member variable
     403        RawConv => '$val =~ s/\s+$//; $$self{Make} = $val',
     404        # NOTE: trailing "blanks" (spaces) are removed from all EXIF tags which
     405        # may be "unknown" (filled with spaces) according to the EXIF spec.
     406        # This allows conditional replacement with "exiftool -TAG-= -TAG=VALUE".
     407        # - also removed are any other trailing whitespace characters
    272408    },
    273409    0x110 => {
     
    275411        Description => 'Camera Model Name',
    276412        Groups => { 2 => 'Camera' },
    277         DataMember => 'CameraModel',
    278         # save this value as an ExifTool member variable
    279         RawConv => '$self->{CameraModel} = $val',
     413        DataMember => 'Model',
     414        # remove trailing blanks and save as an ExifTool member variable
     415        RawConv => '$val =~ s/\s+$//; $$self{Model} = $val',
    280416    },
    281417    0x111 => [
    282418        {
    283419            Condition => q[
    284                 ($self->{TIFF_TYPE} ne "CR2" or $self->{DIR_NAME} ne "IFD0") and
    285                 ($self->{TIFF_TYPE} ne "DNG" or $self->{DIR_NAME} !~ /^SubIFD[12]$/)
     420                $$self{TIFF_TYPE} eq 'MRW' and $$self{DIR_NAME} eq 'IFD0' and
     421                $$self{Model} =~ /^DiMAGE A200/
     422            ],
     423            Name => 'StripOffsets',
     424            IsOffset => 1,
     425            OffsetPair => 0x117,  # point to associated byte counts
     426            # A200 stores this information in the wrong byte order!!
     427            ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val',
     428            ByteOrder => 'LittleEndian',
     429        },
     430        {
     431            Condition => q[
     432                ($$self{TIFF_TYPE} ne 'CR2' or $$self{DIR_NAME} ne 'IFD0') and
     433                ($$self{TIFF_TYPE} ne 'DNG' or $$self{DIR_NAME} !~ /^SubIFD[12]$/)
    286434            ],
    287435            Name => 'StripOffsets',
     
    291439        },
    292440        {
    293             Condition => '$self->{DIR_NAME} eq "IFD0"',
     441            Condition => '$$self{DIR_NAME} eq "IFD0"',
    294442            Name => 'PreviewImageStart',
    295443            IsOffset => 1,
     
    302450            Writable => 'int32u',
    303451            WriteGroup => 'IFD0',
    304             WriteCondition => '$self->{TIFF_TYPE} eq "CR2"',
     452            WriteCondition => '$$self{TIFF_TYPE} eq "CR2"',
    305453            Protected => 2,
    306454        },
    307455        {
    308             Condition => '$self->{DIR_NAME} eq "SubIFD1"',
     456            Condition => '$$self{DIR_NAME} eq "SubIFD1"',
    309457            Name => 'PreviewImageStart',
    310458            IsOffset => 1,
     
    313461            Writable => 'int32u',
    314462            WriteGroup => 'SubIFD1',
    315             WriteCondition => '$self->{TIFF_TYPE} eq "DNG"',
     463            WriteCondition => '$$self{TIFF_TYPE} eq "DNG"',
    316464            Protected => 2,
    317465        },
     
    323471            Writable => 'int32u',
    324472            WriteGroup => 'SubIFD2',
    325             WriteCondition => '$self->{TIFF_TYPE} eq "DNG"',
     473            WriteCondition => '$$self{TIFF_TYPE} eq "DNG"',
    326474            Protected => 2,
    327475        },
     
    330478        Name => 'Orientation',
    331479        PrintConv => \%orientation,
    332         Priority => 0,  # so IFD1 doesn't take precedence
     480        Priority => 0,  # so PRIORITY_DIR takes precedence
    333481    },
    334482    0x115 => {
     
    343491        {
    344492            Condition => q[
    345                 ($self->{TIFF_TYPE} ne "CR2" or $self->{DIR_NAME} ne "IFD0") and
    346                 ($self->{TIFF_TYPE} ne "DNG" or $self->{DIR_NAME} !~ /^SubIFD[12]$/)
     493                $$self{TIFF_TYPE} eq 'MRW' and $$self{DIR_NAME} eq 'IFD0' and
     494                $$self{Model} =~ /^DiMAGE A200/
     495            ],
     496            Name => 'StripByteCounts',
     497            OffsetPair => 0x111,   # point to associated offset
     498            # A200 stores this information in the wrong byte order!!
     499            ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val',
     500            ByteOrder => 'LittleEndian',
     501        },
     502        {
     503            Condition => q[
     504                ($$self{TIFF_TYPE} ne 'CR2' or $$self{DIR_NAME} ne 'IFD0') and
     505                ($$self{TIFF_TYPE} ne 'DNG' or $$self{DIR_NAME} !~ /^SubIFD[12]$/)
    347506            ],
    348507            Name => 'StripByteCounts',
     
    351510        },
    352511        {
    353             Condition => '$self->{DIR_NAME} eq "IFD0"',
     512            Condition => '$$self{DIR_NAME} eq "IFD0"',
    354513            Name => 'PreviewImageLength',
    355514            OffsetPair => 0x111,
     
    361520            Writable => 'int32u',
    362521            WriteGroup => 'IFD0',
    363             WriteCondition => '$self->{TIFF_TYPE} eq "CR2"',
     522            WriteCondition => '$$self{TIFF_TYPE} eq "CR2"',
    364523            Protected => 2,
    365524        },
    366525        {
    367             Condition => '$self->{DIR_NAME} eq "SubIFD1"',
     526            Condition => '$$self{DIR_NAME} eq "SubIFD1"',
    368527            Name => 'PreviewImageLength',
    369528            OffsetPair => 0x111,
     
    371530            Writable => 'int32u',
    372531            WriteGroup => 'SubIFD1',
    373             WriteCondition => '$self->{TIFF_TYPE} eq "DNG"',
     532            WriteCondition => '$$self{TIFF_TYPE} eq "DNG"',
    374533            Protected => 2,
    375534        },
     
    380539            Writable => 'int32u',
    381540            WriteGroup => 'SubIFD2',
    382             WriteCondition => '$self->{TIFF_TYPE} eq "DNG"',
     541            WriteCondition => '$$self{TIFF_TYPE} eq "DNG"',
    383542            Protected => 2,
    384543        },
     
    388547    0x11a => {
    389548        Name => 'XResolution',
    390         Priority => 0,  # so IFD0 takes priority over IFD1
     549        Priority => 0,  # so PRIORITY_DIR takes precedence
    391550    },
    392551    0x11b => {
     
    446605    0x128 => {
    447606        Name => 'ResolutionUnit',
     607        Notes => 'the value 1 is not standard EXIF',
    448608        PrintConv => {
    449609            1 => 'None',
     
    461621    0x131 => {
    462622        Name => 'Software',
     623        RawConv => '$val =~ s/\s+$//; $val', # trim trailing blanks
    463624    },
    464625    0x132 => {
    465626        Name => 'ModifyDate',
    466627        Groups => { 2 => 'Time' },
     628        Notes => 'called DateTime by the EXIF spec.',
    467629        PrintConv => '$self->ConvertDateTime($val)',
    468630    },
     
    470632        Name => 'Artist',
    471633        Groups => { 2 => 'Author' },
     634        Notes => 'becomes a list-type tag when the MWG module is loaded',
     635        RawConv => '$val =~ s/\s+$//; $val', # trim trailing blanks
    472636    },
    473637    0x13c => 'HostComputer',
     
    516680    },
    517681    0x148 => 'ConsecutiveBadFaxLines', #3
    518     0x14a => {
    519         Name => 'SubIFD',
    520         Groups => { 1 => 'SubIFD' },
    521         Flags => 'SubIFD',
    522         SubDirectory => {
    523             Start => '$val',
    524             MaxSubdirs => 3,
    525         },
    526     },
     682    0x14a => [
     683        {
     684            Name => 'SubIFD',
     685            # use this opportunity to identify an ARW image, and if so we
     686            # must decide if this is a SubIFD or the A100 raw data
     687            # (use SubfileType, Compression and FILE_TYPE to identify ARW/SR2,
     688            # then call SetARW to finish the job)
     689            Condition => q{
     690                $$self{DIR_NAME} ne 'IFD0' or $$self{FILE_TYPE} ne 'TIFF' or
     691                $$self{Make} !~ /^SONY/ or
     692                not $$self{SubfileType} or $$self{SubfileType} != 1 or
     693                not $$self{Compression} or $$self{Compression} != 6 or
     694                not require Image::ExifTool::Sony or
     695                Image::ExifTool::Sony::SetARW($self, $valPt)
     696            },
     697            Groups => { 1 => 'SubIFD' },
     698            Flags => 'SubIFD',
     699            SubDirectory => {
     700                Start => '$val',
     701                MaxSubdirs => 3,
     702            },
     703        },
     704        { #16
     705            Name => 'A100DataOffset',
     706            Notes => 'the data offset in original Sony DSLR-A100 ARW images',
     707            DataMember => 'A100DataOffset',
     708            RawConv => '$$self{A100DataOffset} = $val',
     709            IsOffset => 1,
     710        },
     711    ],
    527712    0x14c => {
    528713        Name => 'InkSet',
     
    536721    0x150 => 'DotRange',
    537722    0x151 => 'TargetPrinter',
    538     0x152 => 'ExtraSamples',
     723    0x152 => {
     724        Name => 'ExtraSamples',
     725        PrintConv => { #20
     726            0 => 'Unspecified',
     727            1 => 'Associated Alpha',
     728            2 => 'Unassociated Alpha',
     729        },
     730    },
    539731    0x153 => {
    540732        Name => 'SampleFormat',
    541         PrintConv => {
    542             1 => 'Unsigned integer',
    543             2 => "Two's complement signed integer",
    544             3 => 'IEEE floating point',
    545             4 => 'Undefined',
    546             5 => 'Complex integer', #3
    547             6 => 'IEEE floating point', #3
    548         },
     733        Notes => 'SamplesPerPixel values',
     734        PrintConvColumns => 2,
     735        PrintConv => [ \%sampleFormat, \%sampleFormat, \%sampleFormat, \%sampleFormat ],
    549736    },
    550737    0x154 => 'SMinSampleValue',
     
    569756        },
    570757    },
     758    # 0x181 => 'Decode', #20 (typo! - should be 0x1b1, ref 21)
     759    # 0x182 => 'DefaultImageColor', #20 (typo! - should be 0x1b2, ref 21)
    571760    0x190 => { #3
    572761        Name => 'GlobalParametersIFD',
     
    592781            5 => 'Lossless color and grayscale, L',
    593782            6 => 'Mixed raster content, M',
     783            7 => 'Profile T', #20
     784            255 => 'Multi Profiles', #20
    594785        },
    595786    },
     
    609800    0x195 => 'ModeNumber', #3
    610801    0x1b1 => 'Decode', #3
    611     0x1b2 => 'DefaultImageColor', #3
     802    0x1b2 => 'DefaultImageColor', #3 (changed to ImageBaseColor, ref 21)
     803    0x1b3 => 'T82Options', #20
     804    0x1b5 => { #19
     805        Name => 'JPEGTables',
     806        Binary => 1,
     807    },
    612808    0x200 => {
    613809        Name => 'JPEGProc',
     
    620816        {
    621817            Name => 'ThumbnailOffset',
     818            Notes => q{
     819                ThumbnailOffset in IFD1 of JPEG and some TIFF-based images, IFD0 of MRW
     820                images and AVI videos, and the SubIFD in IFD1 of SRW images;
     821                PreviewImageStart in MakerNotes and IFD0 of ARW and SR2 images;
     822                JpgFromRawStart in SubIFD of NEF images and IFD2 of PEF images; and
     823                OtherImageStart in everything else
     824            },
    622825            # thumbnail is found in IFD1 of JPEG and TIFF images, and
    623826            # IFD0 of EXIF information in FujiFilm AVI (RIFF) videos
    624827            Condition => q{
    625                 $self->{DIR_NAME} eq 'IFD1' or
    626                 ($self->{FILE_TYPE} eq 'RIFF' and $self->{DIR_NAME} eq 'IFD0')
     828                $$self{DIR_NAME} eq 'IFD1' or
     829                ($$self{FILE_TYPE} eq 'RIFF' and $$self{DIR_NAME} eq 'IFD0')
    627830            },
    628831            IsOffset => 1,
     
    631834            Writable => 'int32u',
    632835            WriteGroup => 'IFD1',
    633             WriteCondition => '$$self{FILE_TYPE} ne "TIFF"',
     836            # according to the EXIF spec. a JPEG-compressed thumbnail image may not
     837            # be stored in a TIFF file, but these TIFF-based RAW image formats
     838            # use IFD1 for a JPEG-compressed thumbnail:  CR2, ARW, SR2 and PEF.
     839            # (SRF also stores a JPEG image in IFD1, but it is actually a preview
     840            # and we don't yet write SRF anyway)
     841            WriteCondition => q{
     842                $$self{FILE_TYPE} ne "TIFF" or
     843                $$self{TIFF_TYPE} =~ /^(CR2|ARW|SR2|PEF)$/
     844            },
     845            Protected => 2,
     846        },
     847        {
     848            Name => 'ThumbnailOffset',
     849            # thumbnail in IFD0 of MRW images (Minolta A200)
     850            Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} eq "MRW"',
     851            IsOffset => 1,
     852            OffsetPair => 0x202,
     853            # A200 uses the wrong base offset for this pointer!!
     854            WrongBase => '$$self{Model} =~ /^DiMAGE A200/ ? $$self{MRW_WrongBase} : undef',
     855            DataTag => 'ThumbnailImage',
     856            Writable => 'int32u',
     857            WriteGroup => 'IFD0',
     858            WriteCondition => '$$self{FILE_TYPE} eq "MRW"',
     859            Protected => 2,
     860        },
     861        {
     862            Name => 'ThumbnailOffset',
     863            # in SubIFD of IFD1 in Samsung SRW images
     864            Condition => q{
     865                $$self{TIFF_TYPE} eq 'SRW' and $$self{DIR_NAME} eq 'SubIFD' and
     866                $$self{PATH}[-2] eq 'IFD1'
     867            },
     868            IsOffset => 1,
     869            OffsetPair => 0x202,
     870            DataTag => 'ThumbnailImage',
     871            Writable => 'int32u',
     872            WriteGroup => 'SubIFD',
     873            WriteCondition => '$$self{TIFF_TYPE} eq "SRW"',
    634874            Protected => 2,
    635875        },
    636876        {
    637877            Name => 'PreviewImageStart',
    638             Condition => '$self->{DIR_NAME} eq "MakerNotes"',
     878            Condition => '$$self{DIR_NAME} eq "MakerNotes"',
    639879            IsOffset => 1,
    640880            OffsetPair => 0x202,
     
    642882            Writable => 'int32u',
    643883            WriteGroup => 'MakerNotes',
     884            # (no WriteCondition necessary because MakerNotes won't be created)
     885            Protected => 2,
     886        },
     887        {
     888            Name => 'PreviewImageStart',
     889            # PreviewImage in IFD0 of ARW and SR2 files for all models
     890            Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
     891            IsOffset => 1,
     892            OffsetPair => 0x202,
     893            DataTag => 'PreviewImage',
     894            Writable => 'int32u',
     895            WriteGroup => 'IFD0',
     896            WriteCondition => '$$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
    644897            Protected => 2,
    645898        },
    646899        {
    647900            Name => 'JpgFromRawStart',
    648             Condition => '$self->{DIR_NAME} eq "SubIFD"',
     901            Condition => '$$self{DIR_NAME} eq "SubIFD"',
    649902            IsOffset => 1,
    650903            OffsetPair => 0x202,
     
    652905            Writable => 'int32u',
    653906            WriteGroup => 'SubIFD',
    654             # JpgFromRaw is in SubIFD of NEF files
    655             WriteCondition => '$self->{TIFF_TYPE} eq "NEF"',
     907            # JpgFromRaw is in SubIFD of NEF, NRW and SRW files
     908            WriteCondition => '$$self{TIFF_TYPE} =~ /^(NEF|NRW|SRW)$/',
    656909            Protected => 2,
    657910        },
    658911        {
    659912            Name => 'JpgFromRawStart',
    660             Condition => '$self->{DIR_NAME} eq "IFD2"',
     913            Condition => '$$self{DIR_NAME} eq "IFD2"',
    661914            IsOffset => 1,
    662915            OffsetPair => 0x202,
     
    665918            WriteGroup => 'IFD2',
    666919            # JpgFromRaw is in IFD2 of PEF files
    667             WriteCondition => '$self->{TIFF_TYPE} eq "PEF"',
     920            WriteCondition => '$$self{TIFF_TYPE} eq "PEF"',
    668921            Protected => 2,
    669922        },
     
    677930        {
    678931            Name => 'ThumbnailLength',
     932            Notes => q{
     933                ThumbnailLength in IFD1 of JPEG and some TIFF-based images, IFD0 of MRW
     934                images and AVI videos, and the SubIFD in IFD1 of SRW images;
     935                PreviewImageLength in MakerNotes and IFD0 of ARW and SR2 images;
     936                JpgFromRawLength in SubIFD of NEF images, and IFD2 of PEF images; and
     937                OtherImageLength in everything else
     938            },
    679939            Condition => q{
    680                 $self->{DIR_NAME} eq 'IFD1' or
    681                 ($self->{FILE_TYPE} eq 'RIFF' and $self->{DIR_NAME} eq 'IFD0')
     940                $$self{DIR_NAME} eq 'IFD1' or
     941                ($$self{FILE_TYPE} eq 'RIFF' and $$self{DIR_NAME} eq 'IFD0')
    682942            },
    683943            OffsetPair => 0x201,
     
    685945            Writable => 'int32u',
    686946            WriteGroup => 'IFD1',
    687             WriteCondition => '$$self{FILE_TYPE} ne "TIFF"',
     947            WriteCondition => q{
     948                $$self{FILE_TYPE} ne "TIFF" or
     949                $$self{TIFF_TYPE} =~ /^(CR2|ARW|SR2|PEF)$/
     950            },
     951            Protected => 2,
     952        },
     953        {
     954            Name => 'ThumbnailLength',
     955            # thumbnail in IFD0 of MRW images (Minolta A200)
     956            Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} eq "MRW"',
     957            OffsetPair => 0x201,
     958            DataTag => 'ThumbnailImage',
     959            Writable => 'int32u',
     960            WriteGroup => 'IFD0',
     961            WriteCondition => '$$self{FILE_TYPE} eq "MRW"',
     962            Protected => 2,
     963        },
     964        {
     965            Name => 'ThumbnailLength',
     966            # in SubIFD of IFD1 in Samsung SRW images
     967            Condition => q{
     968                $$self{TIFF_TYPE} eq 'SRW' and $$self{DIR_NAME} eq 'SubIFD' and
     969                $$self{PATH}[-2] eq 'IFD1'
     970            },
     971            OffsetPair => 0x201,
     972            DataTag => 'ThumbnailImage',
     973            Writable => 'int32u',
     974            WriteGroup => 'SubIFD',
     975            WriteCondition => '$$self{TIFF_TYPE} eq "SRW"',
    688976            Protected => 2,
    689977        },
    690978        {
    691979            Name => 'PreviewImageLength',
    692             Condition => '$self->{DIR_NAME} eq "MakerNotes"',
     980            Condition => '$$self{DIR_NAME} eq "MakerNotes"',
    693981            OffsetPair => 0x201,
    694982            DataTag => 'PreviewImage',
    695983            Writable => 'int32u',
    696984            WriteGroup => 'MakerNotes',
     985            # (no WriteCondition necessary because MakerNotes won't be created)
     986            Protected => 2,
     987        },
     988        {
     989            Name => 'PreviewImageLength',
     990            # PreviewImage in IFD0 of ARW and SR2 files for all models
     991            Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
     992            OffsetPair => 0x201,
     993            DataTag => 'PreviewImage',
     994            Writable => 'int32u',
     995            WriteGroup => 'IFD0',
     996            WriteCondition => '$$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
    697997            Protected => 2,
    698998        },
    699999        {
    7001000            Name => 'JpgFromRawLength',
    701             Condition => '$self->{DIR_NAME} eq "SubIFD"',
     1001            Condition => '$$self{DIR_NAME} eq "SubIFD"',
    7021002            OffsetPair => 0x201,
    7031003            DataTag => 'JpgFromRaw',
    7041004            Writable => 'int32u',
    7051005            WriteGroup => 'SubIFD',
    706             WriteCondition => '$self->{TIFF_TYPE} eq "NEF"',
     1006            WriteCondition => '$$self{TIFF_TYPE} =~ /^(NEF|NRW|SRW)$/',
    7071007            Protected => 2,
    7081008        },
    7091009        {
    7101010            Name => 'JpgFromRawLength',
    711             Condition => '$self->{DIR_NAME} eq "IFD2"',
     1011            Condition => '$$self{DIR_NAME} eq "IFD2"',
    7121012            OffsetPair => 0x201,
    7131013            DataTag => 'JpgFromRaw',
    7141014            Writable => 'int32u',
    7151015            WriteGroup => 'IFD2',
    716             WriteCondition => '$self->{TIFF_TYPE} eq "PEF"',
     1016            WriteCondition => '$$self{TIFF_TYPE} eq "PEF"',
    7171017            Protected => 2,
    7181018        },
     
    7251025    0x205 => 'JPEGLosslessPredictors',
    7261026    0x206 => 'JPEGPointTransforms',
    727     0x207 => 'JPEGQTables',
    728     0x208 => 'JPEGDCTables',
    729     0x209 => 'JPEGACTables',
     1027    0x207 => {
     1028        Name => 'JPEGQTables',
     1029        IsOffset => 1,
     1030        # this tag is not supported for writing, so define an
     1031        # invalid offset pair to cause a "No size tag" error to be
     1032        # generated if we try to write a file containing this tag
     1033        OffsetPair => -1,
     1034    },
     1035    0x208 => {
     1036        Name => 'JPEGDCTables',
     1037        IsOffset => 1,
     1038        OffsetPair => -1, # (see comment for JPEGQTables)
     1039    },
     1040    0x209 => {
     1041        Name => 'JPEGACTables',
     1042        IsOffset => 1,
     1043        OffsetPair => -1, # (see comment for JPEGQTables)
     1044    },
    7301045    0x211 => {
    7311046        Name => 'YCbCrCoefficients',
     
    7341049    0x212 => {
    7351050        Name => 'YCbCrSubSampling',
    736         PrintConv => {
    737             '1 1' => 'YCbCr4:4:4 (1 1)', #PH
    738             '2 1' => 'YCbCr4:2:2 (2 1)', #6
    739             '2 2' => 'YCbCr4:2:0 (2 2)', #6
    740             '4 1' => 'YCbCr4:1:1 (4 1)', #6
    741             '4 2' => 'YCbCr4:1:0 (4 2)', #PH
    742             '1 2' => 'YCbCr4:4:0 (1 2)', #PH
    743         },
     1051        PrintConvColumns => 2,
     1052        PrintConv => \%Image::ExifTool::JPEG::yCbCrSubSampling,
    7441053        Priority => 0,
    7451054    },
     
    7581067    0x22f => 'StripRowCounts',
    7591068    0x2bc => {
    760         Name => 'ApplicationNotes',
     1069        Name => 'ApplicationNotes', # (writable directory!)
     1070        Writable => 'int8u',
     1071        Format => 'undef',
     1072        Flags => [ 'Binary', 'Protected' ],
    7611073        # this could be an XMP block
    7621074        SubDirectory => {
     
    7651077        },
    7661078    },
    767     0x1000 => 'RelatedImageFileFormat',
    768     0x1001 => 'RelatedImageWidth',
    769     0x1002 => 'RelatedImageLength',
     1079    0x3e7 => 'USPTOMiscellaneous', #20
     1080    0x1000 => 'RelatedImageFileFormat', #5
     1081    0x1001 => 'RelatedImageWidth', #5
     1082    0x1002 => { #5
     1083        Name => 'RelatedImageHeight',
     1084        Notes => 'called RelatedImageLength by the DCF spec.',
     1085    },
    7701086    # (0x474x tags written by MicrosoftPhoto)
    7711087    0x4746 => 'Rating', #PH
     1088    0x4747 => { # (written by Digital Image Pro)
     1089        Name => 'XP_DIP_XML',
     1090        Format => 'undef',
     1091        # the following reference indicates this is Unicode:
     1092        # http://social.msdn.microsoft.com/Forums/en-US/isvvba/thread/ce6edcbb-8fc2-40c6-ad98-85f5d835ddfb
     1093        ValueConv => '$self->Decode($val,"UCS2","II")',
     1094    },
     1095    0x4748 => {
     1096        Name => 'StitchInfo',
     1097        SubDirectory => {
     1098            TagTable => 'Image::ExifTool::Microsoft::Stitch',
     1099            ByteOrder => 'LittleEndian', #PH (NC)
     1100        },
     1101    },
    7721102    0x4749 => 'RatingPercent', #PH
    7731103    0x800d => 'ImageID', #10
    774     0x80a4 => 'WangAnnotation',
     1104    0x80a3 => { Name => 'WangTag1', Binary => 1 }, #20
     1105    0x80a4 => { Name => 'WangAnnotation', Binary => 1 },
     1106    0x80a5 => { Name => 'WangTag3', Binary => 1 }, #20
     1107    0x80a6 => { #20
     1108        Name => 'WangTag4',
     1109        PrintConv => 'length($val) <= 64 ? $val : \$val',
     1110    },
    7751111    0x80e3 => 'Matteing', #9
    7761112    0x80e4 => 'DataType', #9
     
    7781114    0x80e6 => 'TileDepth', #9
    7791115    0x827d => 'Model2',
    780     0x828d => 'CFARepeatPatternDim',
    781     0x828e => 'CFAPattern2',
    782     0x828f => {
     1116    0x828d => 'CFARepeatPatternDim', #12
     1117    0x828e => {
     1118        Name => 'CFAPattern2', #12
     1119        Format => 'int8u',  # (written incorrectly as 'undef' in Nikon NRW images)
     1120    },
     1121    0x828f => { #12
    7831122        Name => 'BatteryLevel',
    7841123        Groups => { 2 => 'Camera' },
     1124    },
     1125    0x8290 => {
     1126        Name => 'KodakIFD',
     1127        Groups => { 1 => 'KodakIFD' },
     1128        Flags => 'SubIFD',
     1129        Notes => 'used in various types of Kodak images',
     1130        SubDirectory => {
     1131            TagTable => 'Image::ExifTool::Kodak::IFD',
     1132            DirName => 'KodakIFD',
     1133            Start => '$val',
     1134        },
    7851135    },
    7861136    0x8298 => {
    7871137        Name => 'Copyright',
    7881138        Groups => { 2 => 'Author' },
     1139        Format => 'undef',
     1140        Notes => q{
     1141            may contain copyright notices for photographer and editor, separated by a
     1142            newline in ExifTool
     1143        },
     1144        # internally the strings are separated by a null character in this format:
     1145        # Photographer only: photographer + NULL
     1146        # Both:              photographer + NULL + editor + NULL
     1147        # Editor only:       SPACE + NULL + editor + NULL
     1148        # 1) translate first NULL to a newline, removing trailing blanks
     1149        # 2) truncate at second NULL and remove trailing blanks
     1150        # 3) remove trailing newline if it exists
     1151        # (this is done as a RawConv so conditional replaces will work properly)
     1152        RawConv => '$_=$val; s/ *\0/\n/; s/ *\0.*//s; s/\n$//; $_',
    7891153    },
    7901154    0x829a => {
     
    8081172    0x82ac => 'MDFileUnits', #3
    8091173    0x830e => 'PixelScale',
    810     0x83bb => {
    811         Name => 'IPTC-NAA',
     1174    0x8335 => 'AdventScale', #20
     1175    0x8336 => 'AdventRevision', #20
     1176    0x835c => 'UIC1Tag', #23
     1177    0x835d => 'UIC2Tag', #23
     1178    0x835e => 'UIC3Tag', #23
     1179    0x835f => 'UIC4Tag', #23
     1180    0x83bb => { #12
     1181        Name => 'IPTC-NAA', # (writable directory!)
     1182        # this should actually be written as 'undef' (see
     1183        # http://www.awaresystems.be/imaging/tiff/tifftags/iptc.html),
     1184        # but Photoshop writes it as int32u and Nikon Capture won't read
     1185        # anything else, so we do the same thing here...  Doh!
     1186        Format => 'undef',      # convert binary values as undef
     1187        Writable => 'int32u',   # but write int32u format code in IFD
     1188        WriteGroup => 'IFD0',
     1189        Flags => [ 'Binary', 'Protected' ],
    8121190        SubDirectory => {
    8131191            DirName => 'IPTC',
     
    8181196    0x847f => 'IntergraphFlagRegisters', #3
    8191197    0x8480 => 'IntergraphMatrix',
     1198    0x8481 => 'INGRReserved', #20
    8201199    0x8482 => {
    8211200        Name => 'ModelTiePoint',
     
    8251204    0x84e1 => 'ColorSequence', #9
    8261205    0x84e2 => 'IT8Header', #9
    827     0x84e3 => 'RasterPadding', #9
     1206    0x84e3 => { #9
     1207        Name => 'RasterPadding',
     1208        PrintConv => { #20
     1209            0 => 'Byte',
     1210            1 => 'Word',
     1211            2 => 'Long Word',
     1212            9 => 'Sector',
     1213            10 => 'Long Sector',
     1214        },
     1215    },
    8281216    0x84e4 => 'BitsPerRunLength', #9
    8291217    0x84e5 => 'BitsPerExtendedRunLength', #9
    8301218    0x84e6 => 'ColorTable', #9
    831     0x84e7 => 'ImageColorIndicator', #9
    832     0x84e8 => 'BackgroundColorIndicator', #9
     1219    0x84e7 => { #9
     1220        Name => 'ImageColorIndicator',
     1221        PrintConv => { #20
     1222            0 => 'Unspecified Image Color',
     1223            1 => 'Specified Image Color',
     1224        },
     1225    },
     1226    0x84e8 => { #9
     1227        Name => 'BackgroundColorIndicator',
     1228        PrintConv => { #20
     1229            0 => 'Unspecified Background Color',
     1230            1 => 'Specified Background Color',
     1231        },
     1232    },
    8331233    0x84e9 => 'ImageColorValue', #9
    8341234    0x84ea => 'BackgroundColorValue', #9
     
    8361236    0x84ec => 'TransparencyIndicator', #9
    8371237    0x84ed => 'ColorCharacterization', #9
    838     0x84ee => 'HCUsage', #9
     1238    0x84ee => { #9
     1239        Name => 'HCUsage',
     1240        PrintConv => { #20
     1241            0 => 'CT',
     1242            1 => 'Line Art',
     1243            2 => 'Trap',
     1244        },
     1245    },
     1246    0x84ef => 'TrapIndicator', #17
     1247    0x84f0 => 'CMYKEquivalent', #17
    8391248    0x8546 => { #11
    8401249        Name => 'SEMInfo',
     
    8441253        Name => 'AFCP_IPTC',
    8451254        SubDirectory => {
    846             DirName => 'IPTC2', # change name because this isn't the IPTC we want to write
     1255            # must change directory name so we don't create this directory
     1256            DirName => 'AFCP_IPTC',
    8471257            TagTable => 'Image::ExifTool::IPTC::Main',
    8481258        },
    8491259    },
     1260    0x85b8 => 'PixelMagicJBIGOptions', #20
    8501261    0x85d8 => {
    8511262        Name => 'ModelTransform',
    8521263        Groups => { 2 => 'Location' },
    8531264    },
     1265    0x8602 => { #16
     1266        Name => 'WB_GRGBLevels',
     1267        Notes => 'found in IFD0 of Leaf MOS images',
     1268    },
     1269    # 0x8603 - Leaf CatchLight color matrix (ref 16)
    8541270    0x8606 => {
    8551271        Name => 'LeafData',
     
    8601276        },
    8611277    },
    862     0x8649 => {
     1278    0x8649 => { #19
    8631279        Name => 'PhotoshopSettings',
    8641280        Format => 'binary',
     
    8711287        Name => 'ExifOffset',
    8721288        Groups => { 1 => 'ExifIFD' },
    873         Flags => 'SubIFD',
     1289        SubIFD => 2,
    8741290        SubDirectory => {
    8751291            DirName => 'ExifIFD',
     
    8831299        },
    8841300    },
     1301    0x877f => { #20
     1302        Name => 'TIFF_FXExtensions',
     1303        PrintConv => { BITMASK => {
     1304            0 => 'Resolution/Image Width',
     1305            1 => 'N Layer Profile M',
     1306            2 => 'Shared Data',
     1307            3 => 'B&W JBIG2',
     1308            4 => 'JBIG2 Profile M',
     1309        }},
     1310    },
     1311    0x8780 => { #20
     1312        Name => 'MultiProfiles',
     1313        PrintConv => { BITMASK => {
     1314            0 => 'Profile S',
     1315            1 => 'Profile F',
     1316            2 => 'Profile J',
     1317            3 => 'Profile C',
     1318            4 => 'Profile L',
     1319            5 => 'Profile M',
     1320            6 => 'Profile T',
     1321            7 => 'Resolution/Image Width',
     1322            8 => 'N Layer Profile M',
     1323            9 => 'Shared Data',
     1324            10 => 'JBIG2 Profile M',
     1325        }},
     1326    },
     1327    0x8781 => { #22
     1328        Name => 'SharedData',
     1329        IsOffset => 1,
     1330        # this tag is not supported for writing, so define an
     1331        # invalid offset pair to cause a "No size tag" error to be
     1332        # generated if we try to write a file containing this tag
     1333        OffsetPair => -1,
     1334    },
     1335    0x8782 => 'T88Options', #20
    8851336    0x87ac => 'ImageLayer',
    8861337    0x87af => {
     
    9011352        Name => 'ExposureProgram',
    9021353        Groups => { 2 => 'Camera' },
     1354        Notes => 'the value of 9 is not standard EXIF, but is used by the Canon EOS 7D',
    9031355        PrintConv => {
     1356            0 => 'Not Defined',
    9041357            1 => 'Manual',
    9051358            2 => 'Program AE',
     
    9101363            7 => 'Portrait',
    9111364            8 => 'Landscape',
     1365            9 => 'Bulb', #25
    9121366        },
    9131367    },
     
    9261380        },
    9271381    },
    928     0x8827 => 'ISO',
     1382    0x8827 => {
     1383        Name => 'ISO',
     1384        Notes => q{
     1385            called ISOSpeedRatings by EXIF 2.2, then PhotographicSensitivity by the EXIF
     1386            2.3 spec.
     1387        },
     1388        PrintConv => '$val=~s/\s+/, /g; $val',
     1389    },
    9291390    0x8828 => {
    9301391        Name => 'Opto-ElectricConvFactor',
     1392        Notes => 'called OECF by the EXIF spec.',
    9311393        Binary => 1,
    9321394    },
    933     0x8829 => 'Interlace',
    934     0x882a => 'TimeZoneOffset',
    935     0x882b => 'SelfTimerMode',
     1395    0x8829 => 'Interlace', #12
     1396    0x882a => 'TimeZoneOffset', #12
     1397    0x882b => 'SelfTimerMode', #12
     1398    0x8830 => { #24
     1399        Name => 'SensitivityType',
     1400        Notes => 'applies to EXIF:ISO tag',
     1401        PrintConv => {
     1402            0 => 'Unknown',
     1403            1 => 'Standard Output Sensitivity',
     1404            2 => 'Recommended Exposure Index',
     1405            3 => 'ISO Speed',
     1406            4 => 'Standard Output Sensitivity and Recommended Exposure Index',
     1407            5 => 'Standard Output Sensitivity and ISO Speed',
     1408            6 => 'Recommended Exposure Index and ISO Speed',
     1409            7 => 'Standard Output Sensitivity, Recommended Exposure Index and ISO Speed',
     1410        },
     1411    },
     1412    0x8831 => 'StandardOutputSensitivity', #24
     1413    0x8832 => 'RecommendedExposureIndex', #24
     1414    0x8833 => 'ISOSpeed', #24
     1415    0x8834 => { #24
     1416        Name => 'ISOSpeedLatitudeyyy',
     1417        Description => 'ISO Speed Latitude yyy',
     1418    },
     1419    0x8835 => { #24
     1420        Name => 'ISOSpeedLatitudezzz',
     1421        Description => 'ISO Speed Latitude zzz',
     1422    },
    9361423    0x885c => 'FaxRecvParams', #9
    9371424    0x885d => 'FaxSubAddress', #9
     
    9471434        },
    9481435    },
    949     0x9000 => 'ExifVersion',
     1436    0x9000 => {
     1437        Name => 'ExifVersion',
     1438        RawConv => '$val=~s/\0+$//; $val',  # (some idiots add null terminators)
     1439    },
    9501440    0x9003 => {
    9511441        Name => 'DateTimeOriginal',
    9521442        Description => 'Date/Time Original',
    9531443        Groups => { 2 => 'Time' },
     1444        Notes => 'date/time when original image was taken',
    9541445        PrintConv => '$self->ConvertDateTime($val)',
    9551446    },
     
    9571448        Name => 'CreateDate',
    9581449        Groups => { 2 => 'Time' },
     1450        Notes => 'called DateTimeDigitized by the EXIF spec.',
    9591451        PrintConv => '$self->ConvertDateTime($val)',
    9601452    },
    9611453    0x9101 => {
    9621454        Name => 'ComponentsConfiguration',
    963         PrintConv => '$_=$val;s/\0.*//s;tr/\x01-\x06/YbrRGB/;s/b/Cb/g;s/r/Cr/g;$_',
     1455        Format => 'int8u',
     1456        PrintConvColumns => 2,
     1457        PrintConv => {
     1458            0 => '-',
     1459            1 => 'Y',
     1460            2 => 'Cb',
     1461            3 => 'Cr',
     1462            4 => 'R',
     1463            5 => 'G',
     1464            6 => 'B',
     1465            OTHER => sub {
     1466                my ($val, $inv, $conv) = @_;
     1467                my @a = split /,?\s+/, $val;
     1468                if ($inv) {
     1469                    my %invConv;
     1470                    $invConv{lc $$conv{$_}} = $_ foreach keys %$conv;
     1471                    # strings like "YCbCr" and "RGB" still work for writing
     1472                    @a = $a[0] =~ /(Y|Cb|Cr|R|G|B)/g if @a == 1;
     1473                    foreach (@a) {
     1474                        $_ = $invConv{lc $_};
     1475                        return undef unless defined $_;
     1476                    }
     1477                    push @a, 0 while @a < 4;
     1478                } else {
     1479                    foreach (@a) {
     1480                        $_ = $$conv{$_} || "Err ($_)";
     1481                    }
     1482                }
     1483                return join ', ', @a;
     1484            },
     1485        },
    9641486    },
    9651487    0x9102 => 'CompressedBitsPerPixel',
    9661488    0x9201 => {
    9671489        Name => 'ShutterSpeedValue',
    968         ValueConv => 'abs($val)<100 ? 1/(2**$val) : 0',
     1490        Format => 'rational64s', # Leica M8 patch (incorrectly written as rational64u)
     1491        ValueConv => 'abs($val)<100 ? 2**(-$val) : 0',
    9691492        PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
    9701493    },
     
    9771500    0x9204 => {
    9781501        Name => 'ExposureCompensation',
    979         PrintConv => 'Image::ExifTool::Exif::ConvertFraction($val)',
     1502        Format => 'rational64s', # Leica M8 patch (incorrectly written as rational64u)
     1503        Notes => 'called ExposureBiasValue by the EXIF spec.',
     1504        PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)',
    9801505    },
    9811506    0x9205 => {
     
    9881513        Name => 'SubjectDistance',
    9891514        Groups => { 2 => 'Camera' },
    990         PrintConv => '$val eq "inf" ? $val : "${val} m"',
     1515        PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "${val} m"',
    9911516    },
    9921517    0x9207 => {
     
    9941519        Groups => { 2 => 'Camera' },
    9951520        PrintConv => {
     1521            0 => 'Unknown',
    9961522            1 => 'Average',
    9971523            2 => 'Center-weighted average',
     
    10061532        Name => 'LightSource',
    10071533        Groups => { 2 => 'Camera' },
     1534        SeparateTable => 'LightSource',
    10081535        PrintConv => \%lightSource,
    10091536    },
     
    10121539        Groups => { 2 => 'Camera' },
    10131540        Flags => 'PrintHex',
    1014         PrintConv => {
    1015             0x00 => 'No Flash',
    1016             0x01 => 'Fired',
    1017             0x05 => 'Fired, Return not detected',
    1018             0x07 => 'Fired, Return detected',
    1019             0x08 => 'On, Did not fire', # not charged up?
    1020             0x09 => 'On',
    1021             0x0d => 'On, Return not detected',
    1022             0x0f => 'On, Return detected',
    1023             0x10 => 'Off',
    1024             0x14 => 'Off, Did not fire, Return not detected',
    1025             0x18 => 'Auto, Did not fire',
    1026             0x19 => 'Auto, Fired',
    1027             0x1d => 'Auto, Fired, Return not detected',
    1028             0x1f => 'Auto, Fired, Return detected',
    1029             0x20 => 'No flash function',
    1030             0x30 => 'Off, No flash function',
    1031             0x41 => 'Fired, Red-eye reduction',
    1032             0x45 => 'Fired, Red-eye reduction, Return not detected',
    1033             0x47 => 'Fired, Red-eye reduction, Return detected',
    1034             0x49 => 'On, Red-eye reduction',
    1035             0x4d => 'On, Red-eye reduction, Return not detected',
    1036             0x4f => 'On, Red-eye reduction, Return detected',
    1037             0x50 => 'Off, Red-eye reduction',
    1038             0x58 => 'Auto, Did not fire, Red-eye reduction',
    1039             0x59 => 'Auto, Fired, Red-eye reduction',
    1040             0x5d => 'Auto, Fired, Red-eye reduction, Return not detected',
    1041             0x5f => 'Auto, Fired, Red-eye reduction, Return detected',
    1042         },
     1541        SeparateTable => 'Flash',
     1542        PrintConv => \%flash,
    10431543    },
    10441544    0x920a => {
    10451545        Name => 'FocalLength',
    10461546        Groups => { 2 => 'Camera' },
    1047         PrintConv => 'sprintf("%.1fmm",$val)',
     1547        PrintConv => 'sprintf("%.1f mm",$val)',
    10481548    },
    10491549    # Note: tags 0x920b-0x9217 are duplicates of 0xa20b-0xa217
    10501550    # (The TIFF standard uses 0xa2xx, but you'll find both in images)
    1051     0x920b => {
     1551    0x920b => { #12
    10521552        Name => 'FlashEnergy',
    10531553        Groups => { 2 => 'Camera' },
    10541554    },
    1055     0x920c => 'SpatialFrequencyResponse',   # ?? (not in Fuji images - PH)
    1056     0x920d => 'Noise',
    1057     0x920e => 'FocalPlaneXResolution',
    1058     0x920f => 'FocalPlaneYResolution',
    1059     0x9210 => {
     1555    0x920c => 'SpatialFrequencyResponse', #12 (not in Fuji images - PH)
     1556    0x920d => 'Noise', #12
     1557    0x920e => 'FocalPlaneXResolution', #12
     1558    0x920f => 'FocalPlaneYResolution', #12
     1559    0x9210 => { #12
    10601560        Name => 'FocalPlaneResolutionUnit',
    10611561        Groups => { 2 => 'Camera' },
     
    10681568        },
    10691569    },
    1070     0x9211 => 'ImageNumber',
     1570    0x9211 => 'ImageNumber', #12
    10711571    0x9212 => { #12
    10721572        Name => 'SecurityClassification',
     
    10791579        },
    10801580    },
    1081     0x9213 => 'ImageHistory',
     1581    0x9213 => 'ImageHistory', #12
    10821582    0x9214 => {
    1083         Name => 'SubjectLocation',
     1583        Name => 'SubjectArea',
    10841584        Groups => { 2 => 'Camera' },
    10851585    },
    1086     0x9215 => 'ExposureIndex',
    1087     0x9216 => 'TIFF-EPStandardID',
    1088     0x9217 => {
     1586    0x9215 => 'ExposureIndex', #12
     1587    0x9216 => 'TIFF-EPStandardID', #12
     1588    0x9217 => { #12
    10891589        Name => 'SensingMethod',
    10901590        Groups => { 2 => 'Camera' },
     1591        Notes => 'values 1 and 6 are not standard EXIF',
    10911592        PrintConv => {
    1092             1 => 'Monochrome area', #12
     1593            1 => 'Monochrome area', #12 (not standard EXIF)
    10931594            2 => 'One-chip color area',
    10941595            3 => 'Two-chip color area',
    10951596            4 => 'Three-chip color area',
    10961597            5 => 'Color sequential area',
    1097             6 => 'Monochrome linear', #12
     1598            6 => 'Monochrome linear', #12 (not standard EXIF)
    10981599            7 => 'Trilinear',
    10991600            8 => 'Color sequential linear',
     
    11011602    },
    11021603    0x9213 => 'ImageHistory',
     1604    0x923a => 'CIP3DataFile', #20
     1605    0x923b => 'CIP3Sheet', #20
     1606    0x923c => 'CIP3Side', #20
    11031607    0x923f => 'StoNits', #9
    11041608    # handle maker notes as a conditional list
     
    11061610    0x9286 => {
    11071611        Name => 'UserComment',
    1108         PrintConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val)',
     1612        # may consider forcing a Format of 'undef' for this tag because I have
     1613        # seen other applications write it incorrectly as 'string' or 'int8u'
     1614        RawConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val)',
    11091615    },
    11101616    0x9290 => {
    11111617        Name => 'SubSecTime',
    11121618        Groups => { 2 => 'Time' },
     1619        ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks
    11131620    },
    11141621    0x9291 => {
    11151622        Name => 'SubSecTimeOriginal',
    11161623        Groups => { 2 => 'Time' },
     1624        ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks
    11171625    },
    11181626    0x9292 => {
    11191627        Name => 'SubSecTimeDigitized',
    11201628        Groups => { 2 => 'Time' },
    1121     },
    1122     0x935c => { #3
     1629        ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks
     1630    },
     1631    # The following 3 tags are found in MSOffice TIFF images
     1632    # References:
     1633    # http://social.msdn.microsoft.com/Forums/en-US/os_standocs/thread/03086d55-294a-49d5-967a-5303d34c40f8/
     1634    # http://blogs.msdn.com/openspecification/archive/2009/12/08/details-of-three-tiff-tag-extensions-that-microsoft-office-document-imaging-modi-software-may-write-into-the-tiff-files-it-generates.aspx
     1635    # http://www.microsoft.com/downloads/details.aspx?FamilyID=0dbc435d-3544-4f4b-9092-2f2643d64a39&displaylang=en#filelist
     1636    0x932f => 'MSDocumentText',
     1637    0x9330 => {
     1638        Name => 'MSPropertySetStorage',
     1639        Binary => 1,
     1640    },
     1641    0x9331 => {
     1642        Name => 'MSDocumentTextPosition',
     1643        Binary => 1, # (just in case -- don't know what format this is)
     1644    },
     1645    0x935c => { #3/19
    11231646        Name => 'ImageSourceData',
    11241647        Binary => 1,
     
    11271650        Name => 'XPTitle',
    11281651        Format => 'undef',
    1129         ValueConv => '$self->Unicode2Charset($val,"II")',
     1652        ValueConv => '$self->Decode($val,"UCS2","II")',
    11301653    },
    11311654    0x9c9c => {
    11321655        Name => 'XPComment',
    11331656        Format => 'undef',
    1134         ValueConv => '$self->Unicode2Charset($val,"II")',
     1657        ValueConv => '$self->Decode($val,"UCS2","II")',
    11351658    },
    11361659    0x9c9d => {
     
    11381661        Groups => { 2 => 'Author' },
    11391662        Format => 'undef',
    1140         ValueConv => '$self->Unicode2Charset($val,"II")',
     1663        ValueConv => '$self->Decode($val,"UCS2","II")',
    11411664    },
    11421665    0x9c9e => {
    11431666        Name => 'XPKeywords',
    11441667        Format => 'undef',
    1145         ValueConv => '$self->Unicode2Charset($val,"II")',
     1668        ValueConv => '$self->Decode($val,"UCS2","II")',
    11461669    },
    11471670    0x9c9f => {
    11481671        Name => 'XPSubject',
    11491672        Format => 'undef',
    1150         ValueConv => '$self->Unicode2Charset($val,"II")',
    1151     },
    1152     0xa000 => 'FlashpixVersion',
     1673        ValueConv => '$self->Decode($val,"UCS2","II")',
     1674    },
     1675    0xa000 => {
     1676        Name => 'FlashpixVersion',
     1677        RawConv => '$val=~s/\0+$//; $val',  # (some idiots add null terminators)
     1678    },
    11531679    0xa001 => {
    11541680        Name => 'ColorSpace',
    11551681        Notes => q{
    1156             the value of 2 is not standard EXIF.  Instead, an Adobe RGB image is
    1157             indicated by "Uncalibrated" with an InteropIndex of "R03"'
    1158         },
     1682            the value of 0x2 is not standard EXIF.  Instead, an Adobe RGB image is
     1683            indicated by "Uncalibrated" with an InteropIndex of "R03".  The values
     1684            0xfffd and 0xfffe are also non-standard, and are used by some Sony cameras
     1685        },
     1686        PrintHex => 1,
    11591687        PrintConv => {
    11601688            1 => 'sRGB',
    11611689            2 => 'Adobe RGB',
    11621690            0xffff => 'Uncalibrated',
    1163         },
    1164     },
    1165     0xa002 => 'ExifImageWidth',
    1166     0xa003 => 'ExifImageLength',
     1691            # Sony uses these definitions: (ref JD)
     1692            # 0xffff => 'Adobe RGB', (conflicts with Uncalibrated)
     1693            0xfffe => 'ICC Profile',
     1694            0xfffd => 'Wide Gamut RGB',
     1695        },
     1696    },
     1697    0xa002 => {
     1698        Name => 'ExifImageWidth',
     1699        Notes => 'called PixelXDimension by the EXIF spec.',
     1700    },
     1701    0xa003 => {
     1702        Name => 'ExifImageHeight',
     1703        Notes => 'called PixelYDimension by the EXIF spec.',
     1704    },
    11671705    0xa004 => 'RelatedSoundFile',
    11681706    0xa005 => {
     
    11901728        Name => 'FocalPlaneResolutionUnit',
    11911729        Groups => { 2 => 'Camera' },
     1730        Notes => 'values 1, 4 and 5 are not standard EXIF',
    11921731        PrintConv => {
    11931732            1 => 'None', # (not standard EXIF)
     
    12541793            1 => 'Manual',
    12551794            2 => 'Auto bracket',
     1795            # have seen 3 for Samsung EX1 images - PH
    12561796        },
    12571797    },
     
    12741814    0xa405 => {
    12751815        Name => 'FocalLengthIn35mmFormat',
     1816        Notes => 'called FocalLengthIn35mmFilm by the EXIF spec.',
    12761817        Groups => { 2 => 'Camera' },
    1277         PrintConv => '"${val}mm"',
     1818        PrintConv => '"$val mm"',
    12781819    },
    12791820    0xa406 => {
     
    13281869        Name => 'DeviceSettingDescription',
    13291870        Groups => { 2 => 'Camera' },
     1871        Binary => 1,
    13301872    },
    13311873    0xa40c => {
     
    13331875        Groups => { 2 => 'Camera' },
    13341876        PrintConv => {
     1877            0 => 'Unknown',
    13351878            1 => 'Macro',
    13361879            2 => 'Close',
     
    13381881        },
    13391882    },
     1883    # 0xa40d - int16u: 0 (GE E1486 TW)
     1884    # 0xa40e - int16u: 1 (GE E1486 TW)
    13401885    0xa420 => 'ImageUniqueID',
     1886    0xa430 => { #24
     1887        Name => 'OwnerName',
     1888        Notes => 'called CameraOwnerName by the EXIF spec.',
     1889    },
     1890    0xa431 => { #24
     1891        Name => 'SerialNumber',
     1892        Notes => 'called BodySerialNumber by the EXIF spec.',
     1893    },
     1894    0xa432 => { #24
     1895        Name => 'LensInfo',
     1896        Notes => q{
     1897            4 rational values giving focal and aperture ranges, called LensSpecification
     1898            by the EXIF spec.
     1899        },
     1900        # convert to the form "12-20mm f/3.8-4.5" or "50mm f/1.4"
     1901        PrintConv => \&Image::ExifTool::Exif::PrintLensInfo,
     1902    },
     1903    0xa433 => 'LensMake', #24
     1904    0xa434 => 'LensModel', #24
     1905    0xa435 => 'LensSerialNumber', #24
    13411906    0xa480 => 'GDALMetadata', #3
    13421907    0xa481 => 'GDALNoData', #3
    13431908    0xa500 => 'Gamma',
     1909    0xafc0 => 'ExpandSoftware', #JD (Opanda)
     1910    0xafc1 => 'ExpandLens', #JD (Opanda)
     1911    0xafc2 => 'ExpandFilm', #JD (Opanda)
     1912    0xafc3 => 'ExpandFilterLens', #JD (Opanda)
     1913    0xafc4 => 'ExpandScanner', #JD (Opanda)
     1914    0xafc5 => 'ExpandFlashLamp', #JD (Opanda)
    13441915#
    1345 # Windows Media Photo WDP tags
     1916# Windows Media Photo / HD Photo (WDP/HDP) tags
    13461917#
    13471918    0xbc01 => { #13
     
    13501921        Format => 'undef',
    13511922        Notes => q{
    1352             tags 0xbc** are used in Windows Media Photo WDP images. The actual
     1923            tags 0xbc** are used in Windows HD Photo (HDP and WDP) images. The actual
    13531924            PixelFormat values are 16-byte GUID's but the leading 15 bytes,
    13541925            '6fddc324-4e03-4bfe-b1853-d77768dc9', have been removed below to avoid
     
    14211992        },
    14221993    },
    1423     0xbc04 => { #13
    1424         Name => 'ImageType',
    1425         PrintConv => { BITMASK => {
    1426             0 => 'Preview',
    1427             1 => 'Page',
    1428         } },
    1429     },
    14301994    0xbc02 => { #13
    1431         Name => 'Transfomation',
     1995        Name => 'Transformation',
    14321996        PrintConv => {
    14331997            0 => 'Horizontal (normal)',
     
    14452009        PrintConv => { 0 => 'No', 1 => 'Yes' },
    14462010    },
     2011    0xbc04 => { #13
     2012        Name => 'ImageType',
     2013        PrintConv => { BITMASK => {
     2014            0 => 'Preview',
     2015            1 => 'Page',
     2016        } },
     2017    },
     2018    0xbc80 => 'ImageWidth', #13
     2019    0xbc81 => 'ImageHeight', #13
     2020    0xbc82 => 'WidthResolution', #13
     2021    0xbc83 => 'HeightResolution', #13
    14472022    0xbcc0 => { #13
    14482023        Name => 'ImageOffset',
     
    14812056        },
    14822057    },
    1483     0xbc80 => 'ImageWidth', #13
    1484     0xbc81 => 'ImageHeight', #13
    1485     0xbc82 => 'WidthResolution', #13
    1486     0xbc83 => 'HeightResolution', #13
    14872058#
    14882059    0xc427 => 'OceScanjobDesc', #3
     
    14902061    0xc429 => 'OceIDNumber', #3
    14912062    0xc42a => 'OceImageLogic', #3
    1492     0xc44f => 'Annotations', #7
     2063    0xc44f => { Name => 'Annotations', Binary => 1 }, #7/19
    14932064    0xc4a5 => {
    1494         Name => 'PrintIM',
     2065        Name => 'PrintIM', # (writable directory!)
    14952066        # must set Writable here so this tag will be saved with MakerNotes option
    14962067        Writable => 'undef',
     2068        WriteGroup => 'IFD0',
    14972069        Description => 'Print Image Matching',
    14982070        SubDirectory => {
     
    15002072        },
    15012073    },
     2074    0xc580 => { #20
     2075        Name => 'USPTOOriginalContentType',
     2076        PrintConv => {
     2077            0 => 'Text or Drawing',
     2078            1 => 'Grayscale',
     2079            2 => 'Color',
     2080        },
     2081    },
    15022082#
    1503 # DNG tags 0xc6XX (ref 2 unless otherwise stated)
     2083# DNG tags 0xc6XX and 0xc7XX (ref 2 unless otherwise stated)
    15042084#
    15052085    0xc612 => {
    15062086        Name => 'DNGVersion',
    1507         Notes => 'tags 0xc612-0xc65d are used in DNG images',
     2087        Notes => 'tags 0xc612-0xc761 are used in DNG images unless otherwise noted',
     2088        DataMember => 'DNGVersion',
     2089        RawConv => '$$self{DNGVersion} = $val',
     2090        PrintConv => '$val =~ tr/ /./; $val',
    15082091    },
    15092092    0xc613 => 'DNGBackwardVersion',
     
    15122095        Name => 'LocalizedCameraModel',
    15132096        Format => 'string',
    1514         PrintConv => '$self->Printable($val)',
     2097        PrintConv => '$self->Printable($val, 0)',
    15152098    },
    15162099    0xc616 => {
     
    15302113            4 => 'Even rows offset right 1/2 column',
    15312114            5 => 'Even rows offset left 1/2 column',
    1532         },
    1533     },
    1534     0xc618 => {
    1535         Name => 'LinearizationTable',
    1536         Binary => 1,
    1537     },
     2115            # the following are new for DNG 1.3:
     2116            6 => 'Even rows offset up by 1/2 row, even columns offset left by 1/2 column',
     2117            7 => 'Even rows offset up by 1/2 row, even columns offset right by 1/2 column',
     2118            8 => 'Even rows offset down by 1/2 row, even columns offset left by 1/2 column',
     2119            9 => 'Even rows offset down by 1/2 row, even columns offset right by 1/2 column',
     2120        },
     2121    },
     2122    0xc618 => { Name => 'LinearizationTable', Binary => 1 },
    15382123    0xc619 => 'BlackLevelRepeatDim',
    15392124    0xc61a => 'BlackLevel',
     
    15652150        Name => 'DNGLensInfo',
    15662151        Groups => { 2 => 'Camera' },
    1567         PrintConv => '$_=$val;s/(\S+) (\S+) (\S+) (\S+)/$1-$2mm f\/$3-$4/;$_',
     2152        PrintConv =>\&PrintLensInfo,
    15682153    },
    15692154    0xc631 => 'ChromaBlurRadius',
     
    15722157    0xc634 => [
    15732158        {
    1574             Condition => '$self->{TIFF_TYPE} eq "SR2"',
     2159            Condition => '$$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
    15752160            Name => 'SR2Private',
    15762161            Groups => { 1 => 'SR2' },
    15772162            Flags => 'SubIFD',
    15782163            Format => 'int32u',
     2164            # some utilites have problems unless this is int8u format:
     2165            # - Adobe Camera Raw 5.3 gives an error
     2166            # - Apple Preview 10.5.8 gets the wrong white balance
     2167            FixFormat => 'int8u', # (stupid Sony)
    15792168            SubDirectory => {
    15802169                DirName => 'SR2Private',
     
    15862175            Condition => '$$valPt =~ /^Adobe\0/',
    15872176            Name => 'DNGAdobeData',
    1588             DNGMakerNotes => 1,
     2177            NestedHtmlDump => 1,
    15892178            SubDirectory => { TagTable => 'Image::ExifTool::DNG::AdobeData' },
    15902179            Format => 'undef',  # written incorrectly as int8u (change to undef for speed)
    15912180        },
    15922181        {
    1593             Condition => '$$valPt =~ /^PENTAX \0/',
    1594             Name => 'DNGPentaxData',
    1595             DNGMakerNotes => 1,
     2182            Condition => '$$valPt =~ /^(PENTAX |SAMSUNG)\0/',
     2183            Name => 'MakerNotePentax',
     2184            MakerNotes => 1,    # (causes "MakerNotes header" to be identified in HtmlDump output)
     2185            Binary => 1,
     2186            # Note: Don't make this block-writable for a few reasons:
     2187            # 1) It would be dangerous (possibly confusing Pentax software)
     2188            # 2) It is a different format from the JPEG version of MakerNotePentax
     2189            # 3) It is converted to JPEG format by RebuildMakerNotes() when copying
    15962190            SubDirectory => {
    15972191                TagTable => 'Image::ExifTool::Pentax::Main',
     
    16152209        },
    16162210    },
     2211    0xc640 => { #15
     2212        Name => 'RawImageSegmentation',
     2213        # (int16u[3], not writable)
     2214        Notes => q{
     2215            used in segmented Canon CR2 images.  3 numbers: 1. Number of segments minus
     2216            one; 2. Pixel width of segments except last; 3. Pixel width of last segment
     2217        },
     2218    },
    16172219    0xc65a => {
    16182220        Name => 'CalibrationIlluminant1',
     2221        SeparateTable => 'LightSource',
    16192222        PrintConv => \%lightSource,
    16202223    },
    16212224    0xc65b => {
    16222225        Name => 'CalibrationIlluminant2',
     2226        SeparateTable => 'LightSource',
    16232227        PrintConv => \%lightSource,
    16242228    },
     
    16312235    0xc660 => { #3
    16322236        Name => 'AliasLayerMetadata',
    1633         Notes => 'used by Alias Sketchbook Pro, not a DNG tag',
     2237        Notes => 'used by Alias Sketchbook Pro',
    16342238    },
    16352239    0xc68b => {
     
    16382242    },
    16392243    0xc68c => {
    1640         Name => 'OriginalRawFileData',
     2244        Name => 'OriginalRawFileData', # (writable directory!)
     2245        Writable => 'undef', # must be defined here so tag will be extracted if specified
     2246        WriteGroup => 'IFD0',
     2247        Flags => [ 'Binary', 'Protected' ],
    16412248        SubDirectory => {
    16422249            TagTable => 'Image::ExifTool::DNG::OriginalRaw',
     
    16652272    },
    16662273    0xc692 => 'CurrentPreProfileMatrix',
    1667     # 0xea1c - unknown tag written by MicrosoftPhoto (undef)
    1668     #  observed: 1720 bytes in IFD0 or 1988 bytes in ExifIFD, in both cases
    1669     #  the data starts with "1c ea 00 00 00 08" followed by all 00's
     2274    0xc6bf => 'ColorimetricReference',
     2275    0xc6d2 => { #JD (Panasonic DMC-TZ5)
     2276        # this text is UTF-8 encoded (hooray!) - PH (TZ5)
     2277        Name => 'PanasonicTitle',
     2278        Format => 'string', # written incorrectly as 'undef'
     2279        Notes => 'proprietary Panasonic tag used for baby/pet name, etc',
     2280        # panasonic always records this tag (64 zero bytes),
     2281        # so ignore it unless it contains valid information
     2282        RawConv => 'length($val) ? $val : undef',
     2283        ValueConv => '$self->Decode($val, "UTF8")',
     2284    },
     2285    0xc6d3 => { #PH (Panasonic DMC-FS7)
     2286        Name => 'PanasonicTitle2',
     2287        Format => 'string', # written incorrectly as 'undef'
     2288        Notes => 'proprietary Panasonic tag used for baby/pet name with age',
     2289        # panasonic always records this tag (128 zero bytes),
     2290        # so ignore it unless it contains valid information
     2291        RawConv => 'length($val) ? $val : undef',
     2292        ValueConv => '$self->Decode($val, "UTF8")',
     2293    },
     2294    0xc6f3 => 'CameraCalibrationSig',
     2295    0xc6f4 => 'ProfileCalibrationSig',
     2296    0xc6f5 => {
     2297        Name => 'ProfileIFD', # (ExtraCameraProfiles)
     2298        Groups => { 1 => 'ProfileIFD' },
     2299        Flags => 'SubIFD',
     2300        SubDirectory => {
     2301            ProcessProc => \&ProcessTiffIFD,
     2302            WriteProc => \&ProcessTiffIFD,
     2303            DirName => 'ProfileIFD',
     2304            Start => '$val',
     2305            Base => '$start',   # offsets relative to start of TIFF-like header
     2306            MaxSubdirs => 10,
     2307            Magic => 0x4352,    # magic number for TIFF-like header
     2308        },
     2309    },
     2310    0xc6f6 => 'AsShotProfileName',
     2311    0xc6f7 => 'NoiseReductionApplied',
     2312    0xc6f8 => 'ProfileName',
     2313    0xc6f9 => 'ProfileHueSatMapDims',
     2314    0xc6fa => 'ProfileHueSatMapData1',
     2315    0xc6fb => 'ProfileHueSatMapData2',
     2316    0xc6fc => {
     2317        Name => 'ProfileToneCurve',
     2318        Binary => 1,
     2319    },
     2320    0xc6fd => {
     2321        Name => 'ProfileEmbedPolicy',
     2322        PrintConv => {
     2323            0 => 'Allow Copying',
     2324            1 => 'Embed if Used',
     2325            2 => 'Never Embed',
     2326            3 => 'No Restrictions',
     2327        },
     2328    },
     2329    0xc6fe => 'ProfileCopyright',
     2330    0xc714 => 'ForwardMatrix1',
     2331    0xc715 => 'ForwardMatrix2',
     2332    0xc716 => 'PreviewApplicationName',
     2333    0xc717 => 'PreviewApplicationVersion',
     2334    0xc718 => 'PreviewSettingsName',
     2335    0xc719 => {
     2336        Name => 'PreviewSettingsDigest',
     2337        Format => 'undef',
     2338        ValueConv => 'unpack("H*", $val)',
     2339    },
     2340    0xc71a => 'PreviewColorSpace',
     2341    0xc71b => {
     2342        Name => 'PreviewDateTime',
     2343        Groups => { 2 => 'Time' },
     2344        ValueConv => q{
     2345            require Image::ExifTool::XMP;
     2346            return Image::ExifTool::XMP::ConvertXMPDate($val);
     2347        },
     2348    },
     2349    0xc71c => {
     2350        Name => 'RawImageDigest',
     2351        Format => 'undef',
     2352        ValueConv => 'unpack("H*", $val)',
     2353    },
     2354    0xc71d => {
     2355        Name => 'OriginalRawFileDigest',
     2356        Format => 'undef',
     2357        ValueConv => 'unpack("H*", $val)',
     2358    },
     2359    0xc71e => 'SubTileBlockSize',
     2360    0xc71f => 'RowInterleaveFactor',
     2361    0xc725 => 'ProfileLookTableDims',
     2362    0xc726 => {
     2363        Name => 'ProfileLookTableData',
     2364        Binary => 1,
     2365    },
     2366    0xc740 => { # DNG 1.3
     2367        Name => 'OpcodeList1',
     2368        Binary => 1,
     2369        # opcodes:
     2370        # 1 => 'WarpRectilinear',
     2371        # 2 => 'WarpFisheye',
     2372        # 3 => 'FixVignetteRadial',
     2373        # 4 => 'FixBadPixelsConstant',
     2374        # 5 => 'FixBadPixelsList',
     2375        # 6 => 'TrimBounds',
     2376        # 7 => 'MapTable',
     2377        # 8 => 'MapPolynomial',
     2378        # 9 => 'GainMap',
     2379        # 10 => 'DeltaPerRow',
     2380        # 11 => 'DeltaPerColumn',
     2381        # 12 => 'ScalePerRow',
     2382        # 13 => 'ScalePerColumn',
     2383    },
     2384    0xc741 => { # DNG 1.3
     2385        Name => 'OpcodeList2',
     2386        Binary => 1,
     2387    },
     2388    0xc74e => { # DNG 1.3
     2389        Name => 'OpcodeList3',
     2390        Binary => 1,
     2391    },
     2392    0xc761 => 'NoiseProfile', # DNG 1.3
     2393    0xea1c => { #13
     2394        Name => 'Padding',
     2395        Binary => 1,
     2396        Writable => 'undef',
     2397        # must start with 0x1c 0xea by the WM Photo specification
     2398        # (not sure what should happen if padding is only 1 byte)
     2399        # (why does MicrosoftPhoto write "1c ea 00 00 00 08"?)
     2400        RawConvInv => '$val=~s/^../\x1c\xea/s; $val',
     2401    },
    16702402    0xea1d => {
    16712403        Name => 'OffsetSchema',
    16722404        Notes => "Microsoft's ill-conceived maker note offset difference",
     2405        # From the Microsoft documentation:
     2406        #
     2407        #     Any time the "Maker Note" is relocated by Windows, the Exif MakerNote
     2408        #     tag (37500) is updated automatically to reference the new location. In
     2409        #     addition, Windows records the offset (or difference) between the old and
     2410        #     new locations in the Exif OffsetSchema tag (59933). If the "Maker Note"
     2411        #     contains relative references, the developer can add the value in
     2412        #     OffsetSchema to the original references to find the correct information.
     2413        #
     2414        # My recommendation is for other developers to ignore this tag because the
     2415        # information it contains is unreliable. It will be wrong if the image has
     2416        # been subsequently edited by another application that doesn't recognize the
     2417        # new Microsoft tag.
     2418        #
     2419        # The new tag unfortunately only gives the difference between the new maker
     2420        # note offset and the original offset. Instead, it should have been designed
     2421        # to store the original offset. The new offset may change if the image is
     2422        # edited, which will invalidate the tag as currently written. If instead the
     2423        # original offset had been stored, the new difference could be easily
     2424        # calculated because the new maker note offset is known.
     2425        #
     2426        # I exchanged emails with a Microsoft technical representative, pointing out
     2427        # this problem shortly after they released the update (Feb 2007), but so far
     2428        # they have taken no steps to address this.
    16732429    },
    16742430
     
    16782434    # of tags, all tags with values above 0xf000 are handled specially
    16792435    # by ProcessExif().
     2436
     2437    0xfe00 => {
     2438        Name => 'KDC_IFD',
     2439        Groups => { 1 => 'KDC_IFD' },
     2440        Flags => 'SubIFD',
     2441        Notes => 'used in some Kodak KDC images',
     2442        SubDirectory => {
     2443            TagTable => 'Image::ExifTool::Kodak::KDC_IFD',
     2444            DirName => 'KDC_IFD',
     2445            Start => '$val',
     2446        },
     2447    },
    16802448);
    16812449
    1682 # the Composite tags are evaluated last, and are used
    1683 # to calculate values based on the other tags
    1684 # (the main script looks for the special 'Composite' hash)
     2450# EXIF Composite tags (plus other more general Composite tags)
    16852451%Image::ExifTool::Exif::Composite = (
    16862452    GROUPS => { 2 => 'Image' },
     
    16902456            1 => 'ImageHeight',
    16912457        },
    1692         ValueConv => '"$val[0]x$val[1]"',
     2458        Desire => {
     2459            2 => 'ExifImageWidth',
     2460            3 => 'ExifImageHeight',
     2461        },
     2462        # use ExifImageWidth/Height only for Canon and Phase One TIFF-base RAW images
     2463        ValueConv => q{
     2464            return "$val[2]x$val[3]" if $val[2] and $val[3] and
     2465                    $$self{TIFF_TYPE} =~ /^(CR2|Canon 1D RAW|IIQ|EIP)$/;
     2466            return "$val[0]x$val[1]";
     2467        },
    16932468    },
    16942469    # pick the best shutter speed value
     
    17212496        PrintConv => 'sprintf("%.1f",$val)',
    17222497    },
    1723     FocalLength35efl => {
     2498    FocalLength35efl => { #26/PH
    17242499        Description => 'Focal Length',
    17252500        Notes => 'this value may be incorrect if the image has been resized',
     
    17312506            1 => 'ScaleFactor35efl',
    17322507        },
    1733         ValueConv => '$val[0] * ($val[1] ? $val[1] : 1)',
    1734         PrintConv => '$val[1] ? sprintf("%.1fmm (35mm equivalent: %.1fmm)", $val[0], $val) : sprintf("%.1fmm", $val)',
    1735     },
    1736     ScaleFactor35efl => {
    1737         Description => 'Scale Factor To 35mm Equivalent',
     2508        ValueConv => 'ToFloat(@val); ($val[0] || 0) * ($val[1] || 1)',
     2509        PrintConv => '$val[1] ? sprintf("%.1f mm (35 mm equivalent: %.1f mm)", $val[0], $val) : sprintf("%.1f mm", $val)',
     2510    },
     2511    ScaleFactor35efl => { #26/PH
     2512        Description => 'Scale Factor To 35 mm Equivalent',
    17382513        Notes => 'this value and any derived values may be incorrect if image has been resized',
    17392514        Groups => { 2 => 'Camera' },
     
    17482523            7 => 'FocalPlaneXResolution',
    17492524            8 => 'FocalPlaneYResolution',
    1750             9 => 'CanonImageWidth',
    1751            10 => 'CanonImageHeight',
    1752            11 => 'ExifImageWidth',
    1753            12 => 'ExifImageLength',
     2525            9 => 'ExifImageWidth',
     2526           10 => 'ExifImageHeight',
     2527           11 => 'CanonImageWidth',
     2528           12 => 'CanonImageHeight',
    17542529           13 => 'ImageWidth',
    17552530           14 => 'ImageHeight',
     
    17772552        },
    17782553        ValueConv => q{
    1779             return undef unless $val[1] and $val[2];
     2554            ToFloat(@val);
     2555            return 'inf' unless $val[1] and $val[2];
    17802556            return $val[0] * $val[0] / ($val[1] * $val[2] * 1000);
    17812557        },
     
    17832559    },
    17842560    DOF => {
    1785         Description => 'Depth of Field',
     2561        Description => 'Depth Of Field',
    17862562        Notes => 'this value may be incorrect if the image has been resized',
    17872563        Require => {
    1788             0 => 'FocusDistance', # FocusDistance in meters, 0 means 'inf'
    1789             1 => 'FocalLength',
    1790             2 => 'Aperture',
    1791             3 => 'CircleOfConfusion',
     2564            0 => 'FocalLength',
     2565            1 => 'Aperture',
     2566            2 => 'CircleOfConfusion',
     2567        },
     2568        Desire => {
     2569            3 => 'FocusDistance',   # focus distance in metres (0 is infinity)
     2570            4 => 'SubjectDistance',
     2571            5 => 'ObjectDistance',
    17922572        },
    17932573        ValueConv => q{
    1794             return undef unless $val[1] and $val[3];
    1795             $val[0] or $val[0] = 1e10;  # use a large number for 'inf'
    1796             my ($s, $f) = ($val[0], $val[1]);
    1797             my $t = $val[2] * $val[3] * ($s * 1000 - $f) / ($f * $f);
    1798             my @v = ($s / (1 + $t), $s / (1 - $t));
     2574            ToFloat(@val);
     2575            my ($d, $f) = ($val[3], $val[0]);
     2576            if (defined $d) {
     2577                $d or $d = 1e10;    # (use large number for infinity)
     2578            } else {
     2579                $d = $val[4] || $val[5];
     2580                return undef unless defined $d;
     2581            }
     2582            return 0 unless $f and $val[2];
     2583            my $t = $val[1] * $val[2] * ($d * 1000 - $f) / ($f * $f);
     2584            my @v = ($d / (1 + $t), $d / (1 - $t));
    17992585            $v[1] < 0 and $v[1] = 0; # 0 means 'inf'
    18002586            return join(' ',@v);
     
    18072593        },
    18082594    },
    1809     DateTimeCreated => { # used by IPTC, XMP, WAV, etc
    1810         Description => 'Date/Time Created',
    1811         Groups => { 2 => 'Time' },
     2595    FOV => {
     2596        Description => 'Field Of View',
     2597        Notes => q{
     2598            calculated for the long image dimension, this value may be incorrect for
     2599            fisheye lenses, or if the image has been resized
     2600        },
    18122601        Require => {
    1813             0 => 'DateCreated',
    1814             1 => 'TimeCreated',
    1815         },
    1816         ValueConv => '"$val[0] $val[1]"',
    1817         PrintConv => '$self->ConvertDateTime($val)',
    1818     },
    1819     # create DateTimeOriginal from DateTimeCreated if not set already
     2602            0 => 'FocalLength',
     2603            1 => 'ScaleFactor35efl',
     2604        },
     2605        Desire => {
     2606            2 => 'FocusDistance', # (multiply by 1000 to convert to mm)
     2607        },
     2608        # ref http://www.bobatkins.com/photography/technical/field_of_view.html
     2609        # (calculations below apply to rectilinear lenses only, not fisheye)
     2610        ValueConv => q{
     2611            ToFloat(@val);
     2612            return undef unless $val[0] and $val[1];
     2613            my $corr = 1;
     2614            if ($val[2]) {
     2615                my $d = 1000 * $val[2] - $val[0];
     2616                $corr += $val[0]/$d if $d > 0;
     2617            }
     2618            my $fd2 = atan2(36, 2*$val[0]*$val[1]*$corr);
     2619            my @fov = ( $fd2 * 360 / 3.14159 );
     2620            if ($val[2] and $val[2] > 0 and $val[2] < 10000) {
     2621                push @fov, 2 * $val[2] * sin($fd2) / cos($fd2);
     2622            }
     2623            return join(' ', @fov);
     2624        },
     2625        PrintConv => q{
     2626            my @v = split(' ',$val);
     2627            my $str = sprintf("%.1f deg", $v[0]);
     2628            $str .= sprintf(" (%.2f m)", $v[1]) if $v[1];
     2629            return $str;
     2630        },
     2631    },
     2632    # generate DateTimeOriginal from Date and Time Created if not extracted already
    18202633    DateTimeOriginal => {
    1821         Condition => 'not defined($oldVal)',
     2634        Condition => 'not defined $$self{VALUE}{DateTimeOriginal}',
    18222635        Description => 'Date/Time Original',
    18232636        Groups => { 2 => 'Time' },
    1824         Require => 'DateTimeCreated',
    1825         ValueConv => '$val[0]',
    1826         PrintConv => '$prt[0]',
     2637        Desire => {
     2638            0 => 'DateTimeCreated',
     2639            1 => 'DateCreated',
     2640            2 => 'TimeCreated',
     2641        },
     2642        ValueConv => q{
     2643            return $val[0] if $val[0] and $val[0]=~/ /;
     2644            return undef unless $val[1] and $val[2];
     2645            return "$val[1] $val[2]";
     2646        },
     2647        PrintConv => '$self->ConvertDateTime($val)',
    18272648    },
    18282649    ThumbnailImage => {
     
    18442665        Writable => 1,
    18452666        WriteCheck => '$self->CheckImage(\$val)',
     2667        DelCheck => '$val = ""; return undef', # can't delete, so set to empty string
    18462668        WriteAlso => {
    18472669            PreviewImageStart  => 'defined $val ? 0xfeedfeed : undef',
     
    18552677        Desire => {
    18562678            2 => 'PreviewImageValid',
    1857             # (DNG may be have 2 preview images)
     2679            # (DNG and A100 ARW may be have 2 preview images)
    18582680            3 => 'PreviewImageStart (1)',
    18592681            4 => 'PreviewImageLength (1)',
    18602682        },
     2683        # note: extract 2nd preview, but ignore double-referenced preview
     2684        # (in A100 ARW images, the 2nd PreviewImageLength from IFD0 may be wrong anyway)
    18612685        RawConv => q{
    1862             if ($val[3] and $val[4]) {
     2686            if ($val[3] and $val[4] and $val[0] ne $val[3]) {
    18632687                my %val = (
    18642688                    0 => 'PreviewImageStart (1)',
     
    19022726    SubSecDateTimeOriginal => {
    19032727        Description => 'Date/Time Original',
     2728        Groups => { 2 => 'Time' },
    19042729        Require => {
    1905             0 => 'DateTimeOriginal',
     2730            0 => 'EXIF:DateTimeOriginal',
    19062731            1 => 'SubSecTimeOriginal',
    19072732        },
    1908         # be careful here in case there is a timezone following the seconds
    1909         ValueConv => '$_=$val[0];s/(.*:\d{2})/$1\.$val[1]/;$_',
     2733        # be careful here just in case there is a timezone following the seconds
     2734        ValueConv => q{
     2735            return undef if $val[1] eq '';
     2736            $_ = $val[0]; s/( \d{2}:\d{2}:\d{2})/$1\.$val[1]/; $_;
     2737        },
     2738        PrintConv => '$self->ConvertDateTime($val)',
     2739    },
     2740    SubSecCreateDate => {
     2741        Description => 'Create Date',
     2742        Groups => { 2 => 'Time' },
     2743        Require => {
     2744            0 => 'EXIF:CreateDate',
     2745            1 => 'SubSecTimeDigitized',
     2746        },
     2747        ValueConv => q{
     2748            return undef if $val[1] eq '';
     2749            $_ = $val[0]; s/( \d{2}:\d{2}:\d{2})/$1\.$val[1]/; $_;
     2750        },
     2751        PrintConv => '$self->ConvertDateTime($val)',
     2752    },
     2753    SubSecModifyDate => {
     2754        Description => 'Modify Date',
     2755        Groups => { 2 => 'Time' },
     2756        Require => {
     2757            0 => 'EXIF:ModifyDate',
     2758            1 => 'SubSecTime',
     2759        },
     2760        ValueConv => q{
     2761            return undef if $val[1] eq '';
     2762            $_ = $val[0]; s/( \d{2}:\d{2}:\d{2})/$1\.$val[1]/; $_;
     2763        },
    19102764        PrintConv => '$self->ConvertDateTime($val)',
    19112765    },
     
    19192773            my @a = split / /, $val[0];
    19202774            my @b = split / /, $val[1];
    1921             return undef unless @a==2 and @b==$a[0]*$a[1];
     2775            return '?' unless @a==2 and @b==$a[0]*$a[1];
    19222776            return Set16u($a[0]) . Set16u($a[1]) . pack('C*', @b);
    19232777        },
     
    19322786            3 => 'WB_GRBGLevels',
    19332787            4 => 'WB_GRGBLevels',
    1934             5 => 'WB_RBLevels',
    1935             6 => 'WBRedLevel',
    1936             7 => 'WBGreenLevel',
     2788            5 => 'WB_GBRGLevels',
     2789            6 => 'WB_RGBLevels',
     2790            7 => 'WB_RBLevels',
     2791            8 => 'WBRedLevel', # red
     2792            9 => 'WBGreenLevel',
    19372793        },
    19382794        ValueConv => 'Image::ExifTool::Exif::RedBlueBalance(0,@val)',
     
    19472803            3 => 'WB_GRBGLevels',
    19482804            4 => 'WB_GRGBLevels',
    1949             5 => 'WB_RBLevels',
    1950             6 => 'WBBlueLevel',
    1951             7 => 'WBGreenLevel',
     2805            5 => 'WB_GBRGLevels',
     2806            6 => 'WB_RGBLevels',
     2807            7 => 'WB_RBLevels',
     2808            8 => 'WBBlueLevel', # blue
     2809            9 => 'WBGreenLevel',
    19522810        },
    19532811        ValueConv => 'Image::ExifTool::Exif::RedBlueBalance(1,@val)',
     
    19552813    },
    19562814    GPSPosition => {
     2815        Groups => { 2 => 'Location' },
    19572816        Require => {
    19582817            0 => 'GPSLatitude',
     
    19612820        ValueConv => '"$val[0] $val[1]"',
    19622821        PrintConv => '"$prt[0], $prt[1]"',
     2822    },
     2823    LensID => {
     2824        Groups => { 2 => 'Camera' },
     2825        Require => {
     2826            0 => 'LensType',
     2827        },
     2828        Desire => {
     2829            1 => 'FocalLength',
     2830            2 => 'MaxAperture',
     2831            3 => 'MaxApertureValue',
     2832            4 => 'ShortFocal',
     2833            5 => 'LongFocal',
     2834            6 => 'LensModel',
     2835            7 => 'LensFocalRange',
     2836        },
     2837        Notes => q{
     2838            attempt to identify the actual lens from all lenses with a given LensType.
     2839            Applies only to LensType values with a lookup table.  May be configured
     2840            by adding user-defined lenses
     2841        },
     2842        # this LensID is only valid if the LensType has a PrintConv or is a model name
     2843        ValueConv => q{
     2844            return $val[0] if ref $$self{TAG_INFO}{LensType}{PrintConv} eq "HASH" or
     2845                              $prt[0] =~ /(mm|\d\/F)/;
     2846            return undef;
     2847        },
     2848        PrintConv => 'Image::ExifTool::Exif::PrintLensID($self, $prt[0], @val)',
    19632849    },
    19642850);
     
    19832869
    19842870#------------------------------------------------------------------------------
     2871# Identify RAW file type for some TIFF-based formats using Compression value
     2872# Inputs: 0) ExifTool object reference, 1) Compression value
     2873# - sets TIFF_TYPE and FileType if identified
     2874sub IdentifyRawFile($$)
     2875{
     2876    my ($exifTool, $comp) = @_;
     2877    if ($$exifTool{FILE_TYPE} eq 'TIFF' and not $$exifTool{IdentifiedRawFile}) {
     2878        if ($compression{$comp} and $compression{$comp} =~ /^\w+ ([A-Z]{3}) Compressed$/) {
     2879            $exifTool->OverrideFileType($$exifTool{TIFF_TYPE} = $1);
     2880            $$exifTool{IdentifiedRawFile} = 1;
     2881        }
     2882    }
     2883}
     2884
     2885#------------------------------------------------------------------------------
    19852886# Calculate LV (Light Value)
    19862887# Inputs: 0) Aperture, 1) ShutterSpeed, 2) ISO
    1987 # Returns: LV value
     2888# Returns: LV value (and converts input values to floating point if necessary)
    19882889sub CalculateLV($$$)
    19892890{
     
    19922893    return undef unless @_ >= 3;
    19932894    foreach (@_) {
    1994         return undef unless defined $_ and Image::ExifTool::IsFloat($_) and $_ > 0;
     2895        return undef unless $_ and /([+-]?(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?)/ and $1 > 0;
     2896        $_ = $1;    # extract float from any other garbage
    19952897    }
    19962898    # (A light value of 0 is defined as f/1.0 at 1 second with ISO 100)
     
    19992901
    20002902#------------------------------------------------------------------------------
    2001 # Calculate scale factor for 35mm effective focal length
     2903# Calculate scale factor for 35mm effective focal length (ref 26/PH)
    20022904# Inputs: 0) Focal length
    20032905#         1) Focal length in 35mm format
     
    20112913sub CalcScaleFactor35efl
    20122914{
     2915    my $res = $_[6];    # save resolution units (in case they have been converted to string)
     2916    Image::ExifTool::ToFloat(@_);
    20132917    my $focal = shift;
    20142918    my $foc35 = shift;
     
    20192923    my $diag = shift;
    20202924    unless ($diag and Image::ExifTool::IsFloat($diag)) {
     2925        undef $diag;
    20212926        my $xsize = shift;
    20222927        my $ysize = shift;
    20232928        if ($xsize and $ysize) {
    2024             $diag = sqrt($xsize * $xsize + $ysize * $ysize);
    2025         } else {
     2929            # validate by checking aspect ratio because FocalPlaneX/YSize is not reliable
     2930            my $a = $xsize / $ysize;
     2931            if (abs($a-1.3333) < .1 or abs($a-1.5) < .1) {
     2932                $diag = sqrt($xsize * $xsize + $ysize * $ysize);
     2933            }
     2934        }
     2935        unless ($diag) {
    20262936            # get number of mm in units (assume inches unless otherwise specified)
    2027             my $units = { 3=>10, 4=>1, 5=>0.001 }->{ shift() || '' } || 25.4;
     2937            my %lkup = ( 3=>10, 4=>1, 5=>0.001 , cm=>10, mm=>1, um=>0.001 );
     2938            my $units = $lkup{ shift() || $res || '' } || 25.4;
    20282939            my $x_res = shift || return undef;
    20292940            my $y_res = shift || return undef;
     
    20512962
    20522963#------------------------------------------------------------------------------
    2053 # Convert exposure compensation fraction
    2054 sub ConvertFraction($)
     2964# Print exposure compensation fraction
     2965sub PrintFraction($)
    20552966{
    20562967    my $val = shift;
     
    20672978            $str = sprintf("%+d/3", int($val * 3));
    20682979        } else {
    2069             $str = sprintf("%.3g", $val);
     2980            $str = sprintf("%+.3g", $val);
    20702981        }
    20712982    }
     
    20742985
    20752986#------------------------------------------------------------------------------
     2987# Convert fraction or number to floating point value (or 'undef' or 'inf')
     2988sub ConvertFraction($)
     2989{
     2990    my $val = shift;
     2991    if ($val =~ m{([-+]?\d+)/(\d+)}) {
     2992        $val = $2 ? $1 / $2 : ($1 ? 'inf' : 'undef');
     2993    }
     2994    return $val;
     2995}
     2996
     2997#------------------------------------------------------------------------------
    20762998# Convert EXIF text to something readable
    20772999# Inputs: 0) ExifTool object reference, 1) EXIF text
    2078 # Returns: UTF8 or Latin text
     3000# Returns: text encoded according to Charset option (with trailing spaces removed)
    20793001sub ConvertExifText($$)
    20803002{
     
    20833005    my $id = substr($val, 0, 8);
    20843006    my $str = substr($val, 8);
    2085     # by the EXIF spec, the string should be "UNICODE\0", but apparently Kodak
    2086     # sometimes uses "Unicode\0" in the APP3 "Meta" information.  But unfortunately
    2087     # Ricoh uses "Unicode\0" in the RR30 EXIF UserComment when the text is actually
    2088     # ASCII, so only recognize uppercase "UNICODE\0" here.
    2089     if ($id eq "UNICODE\0") {
     3007    # Note: allow spaces instead of nulls in the ID codes because
     3008    # it is fairly common for camera manufacturers to get this wrong
     3009    if ($id =~ /^(ASCII)?[\0 ]+$/) {
     3010        # truncate at null terminator (shouldn't have a null based on the
     3011        # EXIF spec, but it seems that few people actually read the spec)
     3012        $str =~ s/\0.*//s;
     3013    # by the EXIF spec, the following string should be "UNICODE\0", but
     3014    # apparently Kodak sometimes uses "Unicode\0" in the APP3 "Meta" information.
     3015    # However, unfortunately Ricoh uses "Unicode\0" in the RR30 EXIF UserComment
     3016    # when the text is actually ASCII, so only recognize uppercase "UNICODE\0".
     3017    } elsif ($id =~ /^UNICODE[\0 ]$/) {
    20903018        # MicrosoftPhoto writes as little-endian even in big-endian EXIF,
    20913019        # so we must guess at the true byte ordering
    2092         my ($ii, $mm) = (0, 0);
    2093         foreach (unpack('n*', $str)) {
    2094             ++$mm unless $_ & 0xff00;
    2095             ++$ii unless $_ & 0x00ff;
    2096         }
    2097         my $order;
    2098         $order = ($ii > $mm) ? 'II' : 'MM' if $ii != $mm;
    2099         # convert from unicode
    2100         $str = $exifTool->Unicode2Charset($str, $order);
     3020        $str = $exifTool->Decode($str, 'UCS2', 'Unknown');
     3021    } elsif ($id =~ /^JIS[\0 ]{5}$/) {
     3022        $str = $exifTool->Decode($str, 'JIS', 'Unknown');
    21013023    } else {
    2102         # assume everything else is ASCII (Don't convert JIS... yet)
    2103         $str =~ s/\0.*//s;   # truncate at null terminator
     3024        $exifTool->Warn("Invalid EXIF text encoding");
     3025        $str = $id . $str;
    21043026    }
     3027    $str =~ s/ +$//;    # trim trailing blanks
    21053028    return $str;
    21063029}
     
    21303053#------------------------------------------------------------------------------
    21313054# Print numerical parameter value (with sign, or 'Normal' for zero)
    2132 sub PrintParameter($)
     3055# Inputs: 0) value, 1) flag for inverse conversion, 2) conversion hash reference
     3056sub PrintParameter($$$)
    21333057{
    2134     my $val = shift;
     3058    my ($val, $inv, $conv) = @_;
     3059    return $val if $inv;
    21353060    if ($val > 0) {
    21363061        if ($val > 0xfff0) {    # a negative value in disguise?
     
    21393064            $val = "+$val";
    21403065        }
    2141     } elsif ($val == 0) {
    2142         $val = 'Normal';
    21433066    }
    21443067    return $val;
     
    21473070#------------------------------------------------------------------------------
    21483071# Convert parameter back to standard EXIF value
    2149 #   0 or "Normal" => 0
     3072#   0,0.00,etc or "Normal" => 0
    21503073#   -1,-2,etc or "Soft" or "Low" => 1
    21513074#   +1,+2,1,2,etc or "Hard" or "High" => 2
     
    21533076{
    21543077    my $val = shift;
     3078    my $isFloat = Image::ExifTool::IsFloat($val);
    21553079    # normal is a value of zero
    2156     return 0 if $val =~ /\bn/i or not $val;
     3080    return 0 if $val =~ /\bn/i or ($isFloat and $val == 0);
    21573081    # "soft", "low" or any negative number is a value of 1
    2158     return 1 if $val =~ /\b(s|l|-)/i;
    2159     # "hard", "high" or any positive number is a vail of 2
    2160     return 2 if $val =~ /\b(h|\+|\d)/i;
     3082    return 1 if $val =~ /\b(s|l)/i or ($isFloat and $val < 0);
     3083    # "hard", "high" or any positive number is a value of 2
     3084    return 2 if $val =~ /\bh/i or $isFloat;
    21613085    return undef;
    21623086}
     
    21643088#------------------------------------------------------------------------------
    21653089# Calculate Red/BlueBalance
    2166 # Inputs: 0) 0=red, 1=blue, 1-6) WB_RGGB/RGBG/RBGG/GRBG/GRGB/RBLevels,
    2167 #         7) red or blue level, 8) green level
     3090# Inputs: 0) 0=red, 1=blue, 1-7) WB_RGGB/RGBG/RBGG/GRBG/GRGB/RGB/RBLevels,
     3091#         8) red or blue level, 9) green level
    21683092my @rggbLookup = (
    2169     [ 0, 1, 2, 3 ], # RGGB
    2170     [ 0, 1, 3, 2 ], # RGBG
    2171     [ 0, 2, 3, 1 ], # RBGG
    2172     [ 1, 0, 3, 2 ], # GRBG
    2173     [ 1, 0, 2, 3 ], # GRGB
    2174     [ 0, 256, 256, 1 ], # RB (green level is 256)
     3093    # indices for R, G, G and B components in input value
     3094    [ 0, 1, 2, 3 ], # 0 RGGB
     3095    [ 0, 1, 3, 2 ], # 1 RGBG
     3096    [ 0, 2, 3, 1 ], # 2 RBGG
     3097    [ 1, 0, 3, 2 ], # 3 GRBG
     3098    [ 1, 0, 2, 3 ], # 4 GRGB
     3099    [ 2, 3, 0, 1 ], # 5 GBRG
     3100    [ 0, 1, 1, 2 ], # 6 RGB
     3101    [ 0, 256, 256, 1 ], # 7 RB (green level is 256)
    21753102);
    21763103sub RedBlueBalance($@)
     
    21853112        my $g = $$lookup[1];    # get green level or index
    21863113        if ($g < 4) {
    2187             next if @levels < 4;
     3114            next if @levels < 3;
    21883115            $g = ($levels[$g] + $levels[$$lookup[2]]) / 2 or next;
     3116        } elsif ($levels[$$lookup[$blue * 3]] < 4) {
     3117            $g = 1; # Some Nikon cameras use a scaling factor of 1 (E5700)
    21893118        }
    21903119        $val = $levels[$$lookup[$blue * 3]] / $g;
     
    22373166
    22383167#------------------------------------------------------------------------------
     3168# Print conversion for lens info
     3169# Inputs: 0) string of values (min focal, max focal, min F, max F)
     3170# Returns: string in the form "12-20mm f/3.8-4.5" or "50mm f/1.4"
     3171sub PrintLensInfo($)
     3172{
     3173    my $val = shift;
     3174    my @vals = split ' ', $val;
     3175    return $val unless @vals == 4;
     3176    my $c = 0;
     3177    foreach (@vals) {
     3178        Image::ExifTool::IsFloat($_) and ++$c, next;
     3179        $_ eq 'inf' and $_ = '?', ++$c, next;
     3180        $_ eq 'undef' and $_ = '?', ++$c, next;
     3181    }
     3182    return $val unless $c == 4;
     3183    $val = "$vals[1]mm f/$vals[2]";
     3184    $val = "$vals[0]-$val" if $vals[0] ne $vals[1];
     3185    $val .= "-$vals[3]" if $vals[3] ne $vals[2];
     3186    return $val;
     3187}
     3188
     3189#------------------------------------------------------------------------------
     3190# Get lens info from lens model string
     3191# Inputs: 0) lens string, 1) flag to allow unknown "?" values
     3192# Returns: 0) min focal, 1) max focal, 2) min aperture, 3) max aperture
     3193# Notes: returns empty list if lens string could not be parsed
     3194sub GetLensInfo($;$)
     3195{
     3196    my ($lens, $unk) = @_;
     3197    # extract focal length and aperture ranges for this lens
     3198    my $pat = '\\d+(?:\\.\\d+)?';
     3199    $pat .= '|\\?' if $unk;
     3200    return () unless $lens =~ /($pat)(?:-($pat))?\s*mm.*?(?:[fF]\/?\s*)($pat)(?:-($pat))?/;
     3201    # ($1=short focal, $2=long focal, $3=max aperture wide, $4=max aperture tele)
     3202    my @a = ($1, $2, $3, $4);
     3203    $a[1] or $a[1] = $a[0];
     3204    $a[3] or $a[3] = $a[2];
     3205    if ($unk) {
     3206        local $_;
     3207        $_ eq '?' and $_ = 'undef' foreach @a;
     3208    }
     3209    return @a;
     3210}
     3211
     3212#------------------------------------------------------------------------------
     3213# Attempt to identify the specific lens if multiple lenses have the same LensType
     3214# Inputs: 0) ExifTool object ref, 1) LensType string, 2) LensType value,
     3215#         3) FocalLength, 4) MaxAperture, 5) MaxApertureValue, 6) ShortFocal,
     3216#         7) LongFocal, 8) LensModel, 9) LensFocalRange
     3217sub PrintLensID($$@)
     3218{
     3219    my ($exifTool, $lensTypePrt, $lensType, $focalLength, $maxAperture,
     3220        $maxApertureValue, $shortFocal, $longFocal, $lensModel, $lensFocalRange) = @_;
     3221    # the rest of the logic relies on the LensType lookup:
     3222    return undef unless defined $lensType;
     3223    my $printConv = $exifTool->{TAG_INFO}{LensType}{PrintConv};
     3224    # just copy LensType PrintConv value if it was a lens name
     3225    # (Olympus or Panasonic -- just exclude things like Nikon and Leaf LensType)
     3226    unless (ref $printConv eq 'HASH') {
     3227        return $lensTypePrt if $lensTypePrt =~ /mm/;
     3228        return $lensTypePrt if $lensTypePrt =~ s/(\d)\/F/$1mm F/;
     3229        return undef;
     3230    }
     3231    # use MaxApertureValue if MaxAperture is not available
     3232    $maxAperture = $maxApertureValue unless $maxAperture;
     3233    if ($lensFocalRange and $lensFocalRange =~ /^(\d+)(?: to (\d+))?$/) {
     3234        ($shortFocal, $longFocal) = ($1, $2 || $1);
     3235    }
     3236    if ($shortFocal and $longFocal) {
     3237        # Canon includes makernote information which allows better lens identification
     3238        require Image::ExifTool::Canon;
     3239        return Image::ExifTool::Canon::PrintLensID($printConv, $lensType,
     3240                    $shortFocal, $longFocal, $maxAperture, $lensModel);
     3241    }
     3242    my $lens = $$printConv{$lensType};
     3243    return ($lensModel || $lensTypePrt) unless $lens;
     3244    return $lens unless $$printConv{"$lensType.1"};
     3245    $lens =~ s/ or .*//s;    # remove everything after "or"
     3246    # make list of all possible matching lenses
     3247    my @lenses = ( $lens );
     3248    my $i;
     3249    for ($i=1; $$printConv{"$lensType.$i"}; ++$i) {
     3250        push @lenses, $$printConv{"$lensType.$i"};
     3251    }
     3252    # attempt to determine actual lens
     3253    my (@matches, @best, @user, $diff);
     3254    foreach $lens (@lenses) {
     3255        if ($Image::ExifTool::userLens{$lens}) {
     3256            push @user, $lens;
     3257            next;
     3258        }
     3259        my ($sf, $lf, $sa, $la) = GetLensInfo($lens);
     3260        next unless $sf;
     3261        # see if we can rule out this lens using FocalLength and MaxAperture
     3262        if ($focalLength) {
     3263            next if $focalLength < $sf - 0.5;
     3264            next if $focalLength > $lf + 0.5;
     3265        }
     3266        if ($maxAperture) {
     3267            # it seems that most manufacturers set MaxAperture and MaxApertureValue
     3268            # to the maximum aperture (smallest F number) for the current focal length
     3269            # of the lens, so assume that MaxAperture varies with focal length and find
     3270            # the closest match (this is somewhat contrary to the EXIF specification which
     3271            # states "The smallest F number of the lens", without mention of focal length)
     3272            next if $maxAperture < $sa - 0.15;  # (0.15 is arbitrary)
     3273            next if $maxAperture > $la + 0.15;
     3274            # now determine the best match for this aperture
     3275            my $aa; # approximate maximum aperture at this focal length
     3276            if ($sf == $lf or $sa == $la) {
     3277                $aa = $sa;
     3278            } else {
     3279                # assume a log-log variation of max aperture with focal length
     3280                # (see http://regex.info/blog/2006-10-05/263)
     3281                $aa = exp(log($sa) + (log($la)-log($sa)) / (log($lf)-log($sf)) *
     3282                                     (log($focalLength)-log($sf)));
     3283            }
     3284            my $d = abs($maxAperture - $aa);
     3285            if (defined $diff) {
     3286                $d > $diff + 0.15 and next;     # (0.15 is arbitrary)
     3287                $d < $diff - 0.15 and undef @best;
     3288            }
     3289            $diff = $d;
     3290            push @best, $lens;
     3291        }
     3292        push @matches, $lens;
     3293    }
     3294    return join(' or ', @user) if @user;
     3295    return join(' or ', @best) if @best;
     3296    return join(' or ', @matches) if @matches;
     3297    return $$printConv{$lensType};
     3298}
     3299
     3300#------------------------------------------------------------------------------
    22393301# translate date into standard EXIF format
    22403302# Inputs: 0) date
     
    22823344    my $image;
    22833345
    2284     return undef unless $len;   # no image if length is zero
     3346    # no image if length is zero, and don't try to extract binary from XMP file
     3347    return undef if not $len or $$exifTool{FILE_TYPE} eq 'XMP';
    22853348
    22863349    # take data from EXIF block if possible
     
    22903353        $image = $exifTool->ExtractBinary($offset, $len, $tag);
    22913354        return undef unless defined $image;
     3355        # patch for incorrect ThumbnailOffset in some Sony DSLR-A100 ARW images
     3356        if ($tag and $tag eq 'ThumbnailImage' and $$exifTool{TIFF_TYPE} eq 'ARW' and
     3357            $$exifTool{Model} eq 'DSLR-A100' and $offset < 0x10000 and
     3358            $image !~ /^(Binary data|\xff\xd8\xff)/)
     3359        {
     3360            my $try = $exifTool->ExtractBinary($offset + 0x10000, $len, $tag);
     3361            if (defined $try and $try =~ /^\xff\xd8\xff/) {
     3362                $image = $try;
     3363                $exifTool->{VALUE}->{ThumbnailOffset} += 0x10000;
     3364                $exifTool->Warn('Adjusted incorrect A100 ThumbnailOffset', 1);
     3365            }
     3366        }
    22923367    }
    22933368    return $exifTool->ValidateImage(\$image, $tag);
     
    23153390    my $htmlDump = $exifTool->{HTML_DUMP};
    23163391    my $success = 1;
    2317     my ($tagKey, $name, $dirSize, $makerAddr);
    2318 
     3392    my ($tagKey, $dirSize, $makerAddr);
     3393    my $inMakerNotes = $tagTablePtr->{GROUPS}{0} eq 'MakerNotes';
     3394
     3395    # ignore non-standard EXIF while in strict MWG compatibility mode
     3396    if ($Image::ExifTool::MWG::strict and $dirName eq 'IFD0' and
     3397        $tagTablePtr eq \%Image::ExifTool::Exif::Main and
     3398        $$exifTool{FILE_TYPE} =~ /^(JPEG|TIFF|PSD)$/)
     3399    {
     3400        my $path = $exifTool->MetadataPath();
     3401        unless ($path =~ /^(JPEG-APP1-IFD0|TIFF-IFD0|PSD-EXIFInfo-IFD0)$/) {
     3402            $exifTool->Warn("Ignored non-standard EXIF at $path");
     3403            return 1;
     3404        }
     3405    }
    23193406    $verbose = -1 if $htmlDump; # mix htmlDump into verbose so we can test for both at once
    23203407    $dirName eq 'EXIF' and $dirName = $$dirInfo{DirName} = 'IFD0';
    2321     $$dirInfo{Multi} = 1 if $dirName eq 'IFD0' or $dirName eq 'SubIFD';
    2322     $htmlDump and $name = ($dirName eq 'MakerNotes') ? $$dirInfo{Name} : $dirName;
     3408    $$dirInfo{Multi} = 1 if $dirName =~ /^(IFD0|SubIFD)$/ and not defined $$dirInfo{Multi};
     3409    # get a more descriptive name for MakerNote sub-directories
     3410    my $name = $$dirInfo{Name};
     3411    $name = $dirName unless $name and $inMakerNotes and $name !~ /^MakerNote/;
    23233412
    23243413    my ($numEntries, $dirEnd);
     
    23563445                    $dataLen = $$dirInfo{DataLen} = length $buff;
    23573446                    $dirStart = $$dirInfo{DirStart} = 0;
     3447                    $dirLen = $$dirInfo{DirLen} = length $buff;
    23583448                    $success = 1;
    23593449                }
     
    23613451        }
    23623452        unless ($success) {
    2363             $exifTool->Warn("Bad $dirName directory");
     3453            $exifTool->Warn("Bad $name directory");
    23643454            return 0;
    23653455        }
     
    23723462    if ($bytesFromEnd < 4) {
    23733463        unless ($bytesFromEnd==2 or $bytesFromEnd==0) {
    2374             $exifTool->Warn(sprintf"Illegal $dirName directory size (0x%x entries)",$numEntries);
     3464            $exifTool->Warn(sprintf"Illegal $name directory size (0x%x entries)",$numEntries);
    23753465            return 0;
    23763466        }
     
    23863476    }
    23873477    if ($htmlDump) {
     3478        my $longName = $name eq 'MakerNotes' ? ($$dirInfo{Name} || $name) : $name;
    23883479        if (defined $makerAddr) {
    23893480            my $hdrLen = $dirStart + $dataPos + $base - $makerAddr;
    2390             $exifTool->HtmlDump($makerAddr, $hdrLen, "MakerNotes header", $name) if $hdrLen > 0;
     3481            $exifTool->HDump($makerAddr, $hdrLen, "MakerNotes header", $longName) if $hdrLen > 0;
    23913482        }
    2392         $exifTool->HtmlDump($dirStart + $dataPos + $base, 2, "$name entries",
     3483        $exifTool->HDump($dirStart + $dataPos + $base, 2, "$longName entries",
    23933484                 "Entry count: $numEntries");
    23943485        my $tip;
    23953486        if ($bytesFromEnd >= 4) {
    2396             my $nxt = ($name =~ /^IFD(\d+)/) ? "IFD" . ($1 + 1) : 'Next IFD';
     3487            my $nxt = ($name =~ /^(.*?)(\d+)$/) ? $1 . ($2 + 1) : 'Next IFD';
    23973488            $tip = sprintf("$nxt offset: 0x%.4x", Get32u($dataPt, $dirEnd));
    23983489        }
    2399         $exifTool->HtmlDump($dirEnd + $dataPos + $base, 4, "Next IFD", $tip, 0);
    2400         $name = $dirName if $name =~ /^MakerNote/;
     3490        $exifTool->HDump($dirEnd + $dataPos + $base, 4, "Next IFD", $tip, 0);
    24013491    }
    24023492
     3493    # patch for Canon EOS 40D firmware 1.0.4 bug (incorrect directory counts)
     3494    # (must do this before parsing directory or CameraSettings offset will be suspicious)
     3495    if ($inMakerNotes and $$exifTool{Model} eq 'Canon EOS 40D') {
     3496        my $entry = $dirStart + 2 + 12 * ($numEntries - 1);
     3497        my $fmt = Get16u($dataPt, $entry + 2);
     3498        if ($fmt < 1 or $fmt > 13) {
     3499            $exifTool->HDump($entry+$dataPos+$base,12,"[invalid IFD entry]",
     3500                     "Bad format type: $fmt", 1);
     3501            # adjust the number of directory entries
     3502            --$numEntries;
     3503            $dirEnd -= 12;
     3504        }
     3505    }
     3506
    24033507    # loop through all entries in an EXIF directory (IFD)
    2404     my ($index, $valEnd);
     3508    my ($index, $valEnd, $offList, $offHash);
     3509    my $warnCount = 0;
    24053510    for ($index=0; $index<$numEntries; ++$index) {
     3511        if ($warnCount > 10) {
     3512            $exifTool->Warn("Too many warnings -- $name parsing aborted", 1) and return 0;
     3513        }
    24063514        my $entry = $dirStart + 2 + 12 * $index;
    24073515        my $tagID = Get16u($dataPt, $entry);
     
    24093517        my $count = Get32u($dataPt, $entry+4);
    24103518        if ($format < 1 or $format > 13) {
    2411             $exifTool->HtmlDump($entry+$dataPos+$base,12,"[invalid IFD entry]",
     3519            $exifTool->HDump($entry+$dataPos+$base,12,"[invalid IFD entry]",
    24123520                     "Bad format type: $format", 1);
    24133521            # warn unless the IFD was just padded with zeros
    2414             $format and $exifTool->Warn(
    2415                 sprintf("Unknown format ($format) for $dirName tag 0x%x",$tagID));
     3522            if ($format) {
     3523                $exifTool->Warn(sprintf("Unknown format ($format) for $name tag 0x%x",$tagID));
     3524                ++$warnCount;
     3525            }
    24163526            return 0 unless $index; # assume corrupted IFD if this is our first entry
    24173527            next;
    24183528        }
    24193529        my $formatStr = $formatName[$format];   # get name of this format
    2420         my $size = $count * $formatSize[$format];
    24213530        my $valueDataPt = $dataPt;
    24223531        my $valueDataPos = $dataPos;
     
    24243533        my $valuePtr = $entry + 8;      # pointer to value within $$dataPt
    24253534        my $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tagID);
     3535        my $origFormStr;
     3536        # hack to patch incorrect count in Kodak SubIFD3 tags
     3537        if ($count < 2 and ref $$tagTablePtr{$tagID} eq 'HASH' and $$tagTablePtr{$tagID}{FixCount}) {
     3538            $offList or ($offList, $offHash) = GetOffList($dataPt, $dirStart, $dataPos,
     3539                                                          $numEntries, $tagTablePtr);
     3540            my $i = $$offHash{Get32u($dataPt, $valuePtr)};
     3541            if (defined $i and $i < $#$offList) {
     3542                my $oldCount = $count;
     3543                $count = int(($$offList[$i+1] - $$offList[$i]) / $formatSize[$format]);
     3544                $origFormStr = $formatName[$format] . '[' . $oldCount . ']' if $oldCount != $count;
     3545            }
     3546        }
     3547        my $size = $count * $formatSize[$format];
     3548        my $readSize = $size;
    24263549        if ($size > 4) {
    24273550            if ($size > 0x7fffffff) {
    2428                 $exifTool->Warn(sprintf("Invalid size ($size) for $dirName tag 0x%x",$tagID));
     3551                $exifTool->Warn(sprintf("Invalid size ($size) for $name tag 0x%x",$tagID));
     3552                ++$warnCount;
    24293553                next;
    24303554            }
     
    24343558                my $wFlag;
    24353559                $valEnd or $valEnd = $dataPos + $dirEnd + 4;
    2436                 #### eval FixOffsets($valuePtr, $valEnd, $size, $tagID, $wFlag)
     3560                #### eval FixOffsets ($valuePtr, $valEnd, $size, $tagID, $wFlag)
    24373561                eval $$dirInfo{FixOffsets};
    24383562            }
     3563            my $suspect;
     3564            # offset shouldn't point into TIFF header
     3565            $valuePtr < 8 and $suspect = $warnCount;
    24393566            # convert offset to pointer in $$dataPt
    24403567            if ($$dirInfo{EntryBased} or (ref $$tagTablePtr{$tagID} eq 'HASH' and
    2441                 $tagTablePtr->{$tagID}->{EntryBased}))
     3568                $tagTablePtr->{$tagID}{EntryBased}))
    24423569            {
    24433570                $valuePtr += $entry;
     
    24453572                $valuePtr -= $dataPos;
    24463573            }
     3574            # value shouldn't overlap our directory
     3575            $suspect = $warnCount if $valuePtr < $dirEnd and $valuePtr+$size > $dirStart;
     3576            # load value from file if necessary
    24473577            if ($valuePtr < 0 or $valuePtr+$size > $dataLen) {
    24483578                # get value by seeking in file if we are allowed
    24493579                my $buff;
    24503580                if ($raf) {
    2451                     if ($raf->Seek($base + $valuePtr + $dataPos,0) and
    2452                         $raf->Read($buff,$size) == $size)
     3581                    # avoid loading large binary data unless necessary
     3582                    # (ie. ImageSourceData -- layers in Photoshop TIFF image)
     3583                    while ($size > BINARY_DATA_LIMIT) {
     3584                        if ($tagInfo) {
     3585                            # make large unknown blocks binary data
     3586                            $$tagInfo{Binary} = 1 if $$tagInfo{Unknown};
     3587                            last unless $$tagInfo{Binary};      # must read non-binary data
     3588                            last if $$tagInfo{SubDirectory};    # must read SubDirectory data
     3589                            if ($exifTool->{OPTIONS}{Binary}) {
     3590                                # read binary data if specified unless tagsFromFile won't use it
     3591                                last unless $$exifTool{TAGS_FROM_FILE} and $$tagInfo{Protected};
     3592                            }
     3593                            # must read if tag is specified by name
     3594                            last if $exifTool->{REQ_TAG_LOOKUP}{lc($$tagInfo{Name})};
     3595                        } else {
     3596                            # must read value if needed for a condition
     3597                            last if defined $tagInfo;
     3598                        }
     3599                        # (note: changing the value without changing $size will cause
     3600                        # a warning in the verbose output, but we need to maintain the
     3601                        # proper size for the htmlDump, so we can't change this)
     3602                        $buff = "Binary data $size bytes";
     3603                        $readSize = length $buff;
     3604                        last;
     3605                    }
     3606                    # read from file if necessary
     3607                    unless (defined $buff or
     3608                            ($raf->Seek($base + $valuePtr + $dataPos,0) and
     3609                             $raf->Read($buff,$size) == $size))
    24533610                    {
    2454                         $valueDataPt = \$buff;
    2455                         $valueDataPos = $valuePtr + $dataPos;
    2456                         $valueDataLen = $size;
    2457                         $valuePtr = 0;
    2458                     } else {
    2459                         $exifTool->Warn("Error reading value for $dirName entry $index");
    2460                         return 0;
     3611                        $exifTool->Warn("Error reading value for $name entry $index", $inMakerNotes);
     3612                        return 0 unless $inMakerNotes;
     3613                        ++$warnCount;
     3614                        $buff = '' unless defined $buff;
     3615                        $readSize = length $buff;
    24613616                    }
     3617                    $valueDataPt = \$buff;
     3618                    $valueDataPos = $valuePtr + $dataPos;
     3619                    $valueDataLen = length $buff;
     3620                    $valuePtr = 0;
    24623621                } else {
    2463                     my $tagStr;
     3622                    my ($tagStr, $tmpInfo);
    24643623                    if ($tagInfo) {
    24653624                        $tagStr = $$tagInfo{Name};
    24663625                    } elsif (defined $tagInfo) {
    2467                         my $tmpInfo = $exifTool->GetTagInfo($tagTablePtr, $tagID, \ '', $formatStr, $count);
     3626                        $tmpInfo = $exifTool->GetTagInfo($tagTablePtr, $tagID, \ '', $formatStr, $count);
    24683627                        $tagStr = $$tmpInfo{Name} if $tmpInfo;
     3628                    }
     3629                    if ($tagInfo and $$tagInfo{ChangeBase}) {
     3630                        # adjust base offset for this tag only
     3631                        #### eval ChangeBase ($dirStart,$dataPos)
     3632                        my $newBase = eval $$tagInfo{ChangeBase};
     3633                        $valuePtr += $newBase;
    24693634                    }
    24703635                    $tagStr or $tagStr = sprintf("tag 0x%x",$tagID);
     
    24783643                        $valueDataLen = $size;
    24793644                        $valuePtr = 0;
     3645                    } elsif ($tagStr eq 'MakerNoteLeica6' and $exifTool->{RAF}) {
     3646                        if ($verbose > 0) {
     3647                            $exifTool->VPrint(0, "$$exifTool{INDENT}$index) $tagStr --> (outside APP1 segment)\n");
     3648                        }
     3649                        if ($exifTool->Options('FastScan')) {
     3650                            $exifTool->Warn('Ignored Leica MakerNote trailer');
     3651                        } else {
     3652                            $$exifTool{LeicaTrailer} = {
     3653                                TagInfo => $tagInfo || $tmpInfo,
     3654                                Offset  => $base + $valuePtr + $dataPos,
     3655                                Size    => $size,
     3656                            };
     3657                        }
    24803658                    } else {
    2481                         $exifTool->Warn("Bad $dirName directory pointer for $tagStr");
     3659                        $exifTool->Warn("Bad $name offset for $tagStr");
     3660                        ++$warnCount;
    24823661                    }
    24833662                    unless (defined $buff) {
     
    24903669                }
    24913670            }
     3671            # warn about suspect offsets if they didn't already cause another warning
     3672            if (defined $suspect and $suspect == $warnCount) {
     3673                my $tagStr = $tagInfo ? $$tagInfo{Name} : sprintf('tag 0x%.4x', $tagID);
     3674                if ($exifTool->Warn("Suspicious $name offset for $tagStr", $inMakerNotes)) {
     3675                    ++$warnCount;
     3676                    next unless $verbose;
     3677                }
     3678            }
    24923679        }
    24933680        # treat single unknown byte as int8u
    24943681        $formatStr = 'int8u' if $format == 7 and $count == 1;
    24953682
    2496         my $val;
    2497         if ($tagID > 0xf000 and not $$tagTablePtr{$tagID}
    2498             and $tagTablePtr eq \%Image::ExifTool::Exif::Main)
    2499         {
    2500             # handle special case of Photoshop RAW tags (0xfde8-0xfe58)
    2501             # --> generate tags from the value if possible
    2502             $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$size);
    2503             if (defined $val and $val =~ /(.*): (.*)/) {
    2504                 my $tag = $1;
    2505                 $val = $2;
    2506                 $tag =~ s/'s//; # remove 's (so "Owner's Name" becomes "OwnerName")
    2507                 $tag =~ tr/a-zA-Z0-9_//cd; # remove unknown characters
    2508                 if ($tag) {
    2509                     $tagInfo = {
    2510                         Name => $tag,
    2511                         ValueConv => '$_=$val;s/.*: //;$_', # remove descr
    2512                     };
    2513                     Image::ExifTool::AddTagToTable($tagTablePtr, $tagID, $tagInfo);
     3683        my ($val, $subdir, $wrongFormat);
     3684        if ($tagID > 0xf000 and $tagTablePtr eq \%Image::ExifTool::Exif::Main) {
     3685            my $oldInfo = $$tagTablePtr{$tagID};
     3686            if (not $oldInfo or (ref $oldInfo eq 'HASH' and $$oldInfo{Condition})) {
     3687                # handle special case of Photoshop RAW tags (0xfde8-0xfe58)
     3688                # --> generate tags from the value if possible
     3689                $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize);
     3690                if (defined $val and $val =~ /(.*): (.*)/) {
     3691                    my $tag = $1;
     3692                    $val = $2;
     3693                    $tag =~ s/'s//; # remove 's (so "Owner's Name" becomes "OwnerName")
     3694                    $tag =~ tr/a-zA-Z0-9_//cd; # remove unknown characters
     3695                    if ($tag) {
     3696                        $tagInfo = {
     3697                            Name => $tag,
     3698                            ValueConv => '$_=$val;s/.*: //;$_', # remove descr
     3699                        };
     3700                        Image::ExifTool::AddTagToTable($tagTablePtr, $tagID, $tagInfo);
     3701                        # generate conditional list if a conditional tag already existed
     3702                        $$tagTablePtr{$tagID} = [ $oldInfo, $tagInfo ] if $oldInfo;
     3703                    }
    25143704                }
    25153705            }
     
    25173707        if (defined $tagInfo and not $tagInfo) {
    25183708            # GetTagInfo() required the value for a Condition
    2519             my $tmpVal = substr($$valueDataPt, $valuePtr, $size < 48 ? $size : 48);
    2520             $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tagID, \$tmpVal, $formatStr, $count);
     3709            my $tmpVal = substr($$valueDataPt, $valuePtr, $readSize < 128 ? $readSize : 128);
     3710            # (use original format name in this call -- $formatStr may have been changed to int8u)
     3711            $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tagID, \$tmpVal,
     3712                                             $formatName[$format], $count);
    25213713        }
    2522         # override EXIF format if specified
    2523         my $origFormStr;
     3714        # make sure we are handling the 'ifd' format properly
     3715        if (($format == 13 or $format == 18) and (not $tagInfo or not $$tagInfo{SubIFD})) {
     3716            my $str = sprintf('%s tag 0x%.4x IFD format not handled', $dirName, $tagID);
     3717            $exifTool->Warn($str, $inMakerNotes);
     3718        }
    25243719        if (defined $tagInfo) {
     3720            $subdir = $$tagInfo{SubDirectory};
     3721            # override EXIF format if specified
    25253722            if ($$tagInfo{Format}) {
    25263723                $formatStr = $$tagInfo{Format};
    2527                 # must adjust number of items for new format size
    25283724                my $newNum = $formatNumber{$formatStr};
    2529                 if ($newNum) {
     3725                if ($newNum and $newNum != $format) {
    25303726                    $origFormStr = $formatName[$format] . '[' . $count . ']';
    25313727                    $format = $newNum;
    2532                     $count = $size / $formatSize[$format];
     3728                    # adjust number of items for new format size
     3729                    $count = int($size / $formatSize[$format]);
    25333730                }
     3731            }
     3732            # verify that offset-type values are integral
     3733            if (($$tagInfo{IsOffset} or $$tagInfo{SubIFD}) and not $intFormat{$formatStr}) {
     3734                $exifTool->Warn("Wrong format ($formatStr) for $name $$tagInfo{Name}");
     3735                next unless $verbose;
     3736                $wrongFormat = 1;
    25343737            }
    25353738        } else {
     
    25373740        }
    25383741        # convert according to specified format
    2539         $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$size);
     3742        $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize);
    25403743
    25413744        if ($verbose) {
     3745            my $tval = $val;
     3746            if ($formatStr =~ /^rational64([su])$/ and defined $tval) {
     3747                # show numerator/denominator separately
     3748                my $f = ReadValue($valueDataPt,$valuePtr,"int32$1",$count*2,$readSize);
     3749                $f =~ s/(-?\d+) (-?\d+)/$1\/$2/g;
     3750                $tval .= " ($f)";
     3751            }
    25423752            if ($htmlDump) {
    25433753                my ($tagName, $colName);
     
    25523762                # build our tool tip
    25533763                $size < 0 and $size = $count * $formatSize[$format];
    2554                 my $tip = sprintf("Tag ID: 0x%.4x\\n", $tagID) .
    2555                           "Format: $formatName[$format]\[$count]\\nSize: $size bytes\\n";
     3764                my $fstr = "$formatName[$format]\[$count]";
     3765                $fstr = "$origFormStr read as $fstr" if $origFormStr and $origFormStr ne $fstr;
     3766                $fstr .= ' <-- WRONG' if $wrongFormat;
     3767                my $tip = sprintf("Tag ID: 0x%.4x\n", $tagID) .
     3768                          "Format: $fstr\nSize: $size bytes\n";
    25563769                if ($size > 4) {
    25573770                    my $offPt = Get32u($dataPt,$entry+8);
    2558                     $tip .= sprintf("Value offset: 0x%.4x\\n", $offPt);
    25593771                    my $actPt = $valuePtr + $valueDataPos + $base - ($$exifTool{EXIF_POS} || 0);
     3772                    $tip .= sprintf("Value offset: 0x%.4x\n", $offPt);
    25603773                    # highlight tag name (red for bad size)
    2561                     my $style = ($valueDataLen < 0) ? 'V' : 'H';
     3774                    my $style = ($valueDataLen < 0 or not defined $tval) ? 'V' : 'H';
    25623775                    if ($actPt != $offPt) {
    2563                         $tip .= sprintf("Actual offset: 0x%.4x\\n", $actPt);
     3776                        $tip .= sprintf("Actual offset: 0x%.4x\n", $actPt);
     3777                        my $sign = $actPt < $offPt ? '-' : '';
     3778                        $tip .= sprintf("Offset base: ${sign}0x%.4x\n", abs($actPt - $offPt));
    25643779                        $style = 'F' if $style eq 'H';  # purple for different offsets
    25653780                    }
    25663781                    $colName = "<span class=$style>$tagName</span>";
     3782                    $colName .= ' <span class=V>(odd)</span>' if $offPt & 0x01;
    25673783                } else {
    25683784                    $colName = $tagName;
    25693785                }
    2570                 my $tval;
    2571                 if ($valueDataLen < 0) {
     3786                $colName .= ' <span class=V>(err)</span>' if $wrongFormat;
     3787                if ($valueDataLen < 0 or not defined $tval) {
    25723788                    $tval = '<bad offset>';
    25733789                } else {
    2574                     $tval = (length $val < 32) ? $val : substr($val,0,28) . '[...]';
     3790                    $tval = substr($tval,0,28) . '[...]' if length($tval) > 32;
    25753791                    if ($formatStr =~ /^(string|undef|binary)/) {
    2576                         # translate all characters that could mess up JavaScript
    2577                         $tval =~ tr/\\\x00-\x1f\x7f-\xff/./;
    2578                         $tval =~ tr/"/'/;
    2579                         $tval = "$tval";
     3792                        # translate non-printable characters
     3793                        $tval =~ tr/\x00-\x1f\x7f-\xff/./;
    25803794                    } elsif ($tagInfo and Image::ExifTool::IsInt($tval)) {
    2581                         if ($$tagInfo{IsOffset}) {
     3795                        if ($$tagInfo{IsOffset} or $$tagInfo{SubIFD}) {
    25823796                            $tval = sprintf('0x%.4x', $tval);
     3797                            my $actPt = $val + $base - ($$exifTool{EXIF_POS} || 0);
     3798                            if ($actPt != $val) {
     3799                                $tval .= sprintf("\nActual offset: 0x%.4x", $actPt);
     3800                                my $sign = $actPt < $val ? '-' : '';
     3801                                $tval .= sprintf("\nOffset base: ${sign}0x%.4x", abs($actPt - $val));
     3802                            }
    25833803                        } elsif ($$tagInfo{PrintHex}) {
    25843804                            $tval = sprintf('0x%x', $tval);
     
    25873807                }
    25883808                $tip .= "Value: $tval";
    2589                 $exifTool->HtmlDump($entry+$dataPos+$base, 12, "$dname $colName", $tip, 1);
     3809                $exifTool->HDump($entry+$dataPos+$base, 12, "$dname $colName", $tip, 1);
    25903810                next if $valueDataLen < 0;  # don't process bad pointer entry
    25913811                if ($size > 4) {
    25923812                    my $exifDumpPos = $valuePtr + $valueDataPos + $base;
     3813                    my $flag = 0;
     3814                    if ($subdir) {
     3815                        if ($$tagInfo{MakerNotes}) {
     3816                            $flag = 0x04;
     3817                        } elsif ($$tagInfo{NestedHtmlDump}) {
     3818                            $flag = $$tagInfo{NestedHtmlDump} == 2 ? 0x10 : 0x04;
     3819                        }
     3820                    }
    25933821                    # add value data block (underlining maker notes data)
    2594                     $exifTool->HtmlDump($exifDumpPos,$size,"$tagName value",'SAME',
    2595                         ($tagInfo and $$tagInfo{SubDirectory} and
    2596                         ($$tagInfo{MakerNotes} or $$tagInfo{DNGMakerNotes})) ? 4 : 0);
     3822                    $exifTool->HDump($exifDumpPos,$size,"$tagName value",'SAME', $flag);
    25973823                }
    25983824            } else {
    25993825                my $fstr = $formatName[$format];
    2600                 $origFormStr and $fstr = "$origFormStr read as $fstr";
     3826                $fstr = "$origFormStr read as $fstr" if $origFormStr;
    26013827                $exifTool->VerboseInfo($tagID, $tagInfo,
    26023828                    Table   => $tagTablePtr,
    26033829                    Index   => $index,
    2604                     Value   => $val,
     3830                    Value   => $tval,
    26053831                    DataPt  => $valueDataPt,
    26063832                    DataPos => $valueDataPos + $base,
     
    26113837                );
    26123838            }
    2613             next unless $tagInfo;
     3839            next if not $tagInfo or $wrongFormat;
    26143840        }
     3841        next unless defined $val;
    26153842#..............................................................................
    26163843# Handle SubDirectory tag types
    26173844#
    2618         my $subdir = $$tagInfo{SubDirectory};
    26193845        if ($subdir) {
     3846            # don't process empty subdirectories
     3847            unless ($size) {
     3848                unless ($$tagInfo{MakerNotes} or $inMakerNotes) {
     3849                    $exifTool->Warn("Empty $$tagInfo{Name} data", 1);
     3850                }
     3851                next;
     3852            }
    26203853            my (@values, $newTagTable, $dirNum, $newByteOrder, $invalid);
    26213854            my $tagStr = $$tagInfo{Name};
     
    26913924                    # calculate subdirectory start relative to $base for eval
    26923925                    my $start = $subdirStart + $subdirDataPos;
    2693                     #### eval Base ($start)
     3926                    #### eval Base ($start,$base)
    26943927                    $subdirBase = eval($$subdir{Base}) + $base;
    26953928                }
     
    27013934                        $exifTool->Warn("Bad $tagStr OffsetPt");
    27023935                        last;
    2703                     }                   
     3936                    }
    27043937                    SetByteOrder($newByteOrder);
    27053938                    $subdirStart += Get32u($subdirDataPt, $pos);
     
    27083941                if ($subdirStart < 0 or $subdirStart + 2 > $subdirDataLen) {
    27093942                    # convert $subdirStart back to a file offset
    2710                     $subdirStart += $subdirDataPos;
    2711                     my $dirOK;
    27123943                    if ($raf) {
    2713                         # read the directory from the file
    2714                         if ($raf->Seek($subdirStart + $base,0)) {
    2715                             my ($buff, $buf2);
    2716                             if ($raf->Read($buff,2) == 2) {
    2717                                 # get no. dir entries
    2718                                 $size = 12 * Get16u(\$buff, 0);
    2719                                 # read dir (plus next IFD pointer)
    2720                                 if ($raf->Read($buf2,$size+4) >= $size) {
    2721                                     # set up variables to process new subdir data
    2722                                     $buff .= $buf2;
    2723                                     $size = length $buff;
    2724                                     $subdirDataPt = \$buff;
    2725                                     $subdirDataPos = $subdirStart;
    2726                                     $subdirDataLen = $size;
    2727                                     $subdirStart = 0;
    2728                                     $dirOK = 1;
    2729                                 }
    2730                             }
    2731                         }
    2732                     }
    2733                     unless ($dirOK) {
     3944                        # reset SubDirectory buffer (we will load it later)
     3945                        my $buff = '';
     3946                        $subdirDataPt = \$buff;
     3947                        $subdirDataLen = $size = length $buff;
     3948                    } else {
    27343949                        my $msg = "Bad $tagStr SubDirectory start";
    27353950                        if ($verbose > 0) {
     
    27603975                    RAF        => $raf,
    27613976                    Parent     => $dirName,
     3977                    DirName    => $$subdir{DirName},
    27623978                    FixBase    => $$subdir{FixBase},
    27633979                    FixOffsets => $$subdir{FixOffsets},
     
    27653981                    TagInfo    => $tagInfo,
    27663982                    SubIFD     => $$tagInfo{SubIFD},
     3983                    Subdir     => $subdir,
    27673984                );
     3985                # (remember: some cameras incorrectly write maker notes in IFD0)
    27683986                if ($$tagInfo{MakerNotes}) {
     3987                    # don't parse makernotes if FastScan > 1
     3988                    my $fast = $exifTool->Options('FastScan');
     3989                    last if $fast and $fast > 1;
    27693990                    $subdirInfo{MakerNoteAddr} = $valuePtr + $valueDataPos + $base;
    2770                     $subdirInfo{NoFixBase} = 1 if $$subdir{Base};
     3991                    $subdirInfo{NoFixBase} = 1 if defined $$subdir{Base};
    27713992                }
    2772                 # some Pentax cameras (Optio 330) write maker notes in IFD0
    2773                 # set directory IFD name from group name of family 1 in tag information if it exists
    2774                 if ($$tagInfo{Groups}) {
    2775                     $subdirInfo{DirName} = $tagInfo->{Groups}->{1};
     3993                # set directory IFD name from group name of family 1 if it exists,
     3994                # unless the tag is extracted as a block in which case group 1 may
     3995                # have been set automatically if the block was previously extracted
     3996                if ($$tagInfo{Groups} and not $$tagInfo{BlockExtract}) {
     3997                    $subdirInfo{DirName} = $tagInfo->{Groups}{1};
    27763998                    # number multiple subdirectories
    2777                     $dirNum and $subdirInfo{DirName} .= $dirNum;
     3999                    $subdirInfo{DirName} =~ s/\d*$/$dirNum/ if $dirNum;
    27784000                }
    27794001                SetByteOrder($newByteOrder);    # set byte order for this subdir
     
    28004022            }
    28014023            my $doMaker = $exifTool->Options('MakerNotes');
    2802             next unless $doMaker or $exifTool->{REQ_TAG_LOOKUP}->{lc($tagStr)};
     4024            next unless $doMaker or $exifTool->{REQ_TAG_LOOKUP}{lc($tagStr)} or
     4025                        $$tagInfo{BlockExtract};
    28034026            # extract as a block if specified
    28044027            if ($$tagInfo{MakerNotes}) {
    28054028                # save maker note byte order (if it was significant and valid)
    28064029                if ($$subdir{ByteOrder} and not $invalid) {
    2807                     $exifTool->{MAKER_NOTE_BYTE_ORDER} = 
    2808                         defined ($exifTool->{UnknownByteOrder}) ? 
     4030                    $exifTool->{MAKER_NOTE_BYTE_ORDER} =
     4031                        defined ($exifTool->{UnknownByteOrder}) ?
    28094032                                 $exifTool->{UnknownByteOrder} : $newByteOrder;
    28104033                }
     
    28454068 #..............................................................................
    28464069        # convert to absolute offsets if this tag is an offset
    2847         if ($$tagInfo{IsOffset}) {
     4070        #### eval IsOffset ($val, $exifTool)
     4071        if ($$tagInfo{IsOffset} and eval $$tagInfo{IsOffset}) {
    28484072            my $offsetBase = $$tagInfo{IsOffset} eq '2' ? $firstBase : $base;
    28494073            $offsetBase += $$exifTool{BASE};
     4074            # handle offsets which use a wrong base (Minolta A200)
     4075            if ($$tagInfo{WrongBase}) {
     4076                my $self = $exifTool;
     4077                #### eval WrongBase ($self)
     4078                $offsetBase += eval $$tagInfo{WrongBase} || 0;
     4079            }
    28504080            my @vals = split(' ',$val);
    28514081            foreach $val (@vals) {
     
    28564086        # save the value of this tag
    28574087        $tagKey = $exifTool->FoundTag($tagInfo, $val);
    2858         # set the group 1 name for tags in main table
    2859         if (defined $tagKey and $tagTablePtr eq \%Image::ExifTool::Exif::Main) {
    2860             $exifTool->SetGroup1($tagKey, $dirName);
     4088        # set the group 1 name for tags in specified tables
     4089        if (defined $tagKey and $$tagTablePtr{SET_GROUP1}) {
     4090            $exifTool->SetGroup($tagKey, $dirName);
    28614091        }
    28624092    }
     
    28734103            $newDirInfo{DirStart} = $subdirStart;
    28744104            # increment IFD number
    2875             $newDirInfo{DirName} =~ s/(\d+)$//;
    2876             $newDirInfo{DirName} .= ($1 || 0) + 1;
     4105            my $ifdNum = $newDirInfo{DirName} =~ s/(\d+)$// ? $1 : 0;
     4106            $newDirInfo{DirName} .= $ifdNum + 1;
    28774107            # must validate SubIFD1 because the nextIFD pointer is invalid for some RAW formats
    28784108            if ($newDirInfo{DirName} ne 'SubIFD1' or ValidateIFD(\%newDirInfo)) {
    28794109                $exifTool->{INDENT} =~ s/..$//; # keep indent the same
     4110                my $cur = pop @{$$exifTool{PATH}};
    28804111                $exifTool->ProcessDirectory(\%newDirInfo, $tagTablePtr) or $success = 0;
     4112                push @{$$exifTool{PATH}}, $cur;
    28814113            } elsif ($verbose or $exifTool->{TIFF_TYPE} eq 'TIFF') {
    28824114                $exifTool->Warn('Ignored bad IFD linked from SubIFD');
     
    28934125=head1 NAME
    28944126
    2895 Image::ExifTool::Exif - Read EXIF meta information
     4127Image::ExifTool::Exif - Read EXIF/TIFF meta information
    28964128
    28974129=head1 SYNOPSIS
     
    29024134
    29034135This module contains routines required by Image::ExifTool for processing
    2904 EXIF meta information.
     4136EXIF and TIFF meta information.
    29054137
    29064138=head1 AUTHOR
    29074139
    2908 Copyright 2003-2007, Phil Harvey (phil at owl.phy.queensu.ca)
     4140Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
    29094141
    29104142This library is free software; you can redistribute it and/or modify it
     
    29174149=item L<http://www.exif.org/Exif2-2.PDF>
    29184150
     4151=item L<http://www.cipa.jp/english/hyoujunka/kikaku/pdf/DC-008-2010_E.pdf>
     4152
    29194153=item L<http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf>
    29204154
     
    29274161=item L<http://www.remotesensing.org/libtiff/TIFFTechNote2.html>
    29284162
     4163=item L<http://www.exif.org/dcf.PDF>
     4164
     4165=item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html>
     4166
     4167=item L<http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf>
     4168
     4169=item L<http://www.ozhiker.com/electronics/pjmt/jpeg_info/meta.html>
     4170
     4171=item L<http://hul.harvard.edu/jhove/tiff-tags.html>
     4172
     4173=item L<http://www.microsoft.com/whdc/xps/wmphoto.mspx>
     4174
    29294175=item L<http://www.asmail.be/msg0054681802.html>
    29304176
    2931 =item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html>
    2932 
    2933 =item L<http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf>
    2934 
    2935 =item L<http://www.ozhiker.com/electronics/pjmt/jpeg_info/meta.html>
    2936 
    2937 =item L<http://hul.harvard.edu/jhove/tiff-tags.html>
    2938 
    2939 =item L<http://www.microsoft.com/whdc/xps/wmphoto.mspx>
     4177=item L<http://crousseau.free.fr/imgfmt_raw.htm>
     4178
     4179=item L<http://www.cybercom.net/~dcoffin/dcraw/>
     4180
     4181=item L<http://www.digitalpreservation.gov/formats/content/tiff_tags.shtml>
     4182
     4183=item L<http://community.roxen.com/developers/idocs/rfc/rfc3949.html>
     4184
     4185=item L<http://tools.ietf.org/html/draft-ietf-fax-tiff-fx-extension1-01>
    29404186
    29414187=back
     
    29434189=head1 ACKNOWLEDGEMENTS
    29444190
    2945 Thanks to Matt Madrid for his help with the XP character code conversions.
     4191Thanks to Jeremy Brown for the 35efl tags, and Matt Madrid for his help with
     4192the XP character code conversions.
    29464193
    29474194=head1 SEE ALSO
Note: See TracChangeset for help on using the changeset viewer.