- Timestamp:
- 2011-06-01T12:33:42+12:00 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone2/perllib/cpan/Image/ExifTool/Exif.pm
r16842 r24107 2 2 # File: Exif.pm 3 3 # 4 # Description: Read EXIF meta information4 # Description: Read EXIF/TIFF meta information 5 5 # 6 6 # Revisions: 11/25/2003 - P. Harvey Created … … 12 12 # References: 0) http://www.exif.org/Exif2-2.PDF 13 13 # 1) http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf 14 # 2) http://www.adobe.com/products/dng/pdfs/dng_spec .pdf14 # 2) http://www.adobe.com/products/dng/pdfs/dng_spec_1_3_0_0.pdf 15 15 # 3) http://www.awaresystems.be/imaging/tiff/tifftags.html 16 16 # 4) http://www.remotesensing.org/libtiff/TIFFTechNote2.html 17 # 5) http://www. asmail.be/msg0054681802.html17 # 5) http://www.exif.org/dcf.PDF 18 18 # 6) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html 19 19 # 7) http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf … … 24 24 # 12) http://www.broomscloset.com/closet/photo/exif/TAG2000-22_DIS12234-2.PDF 25 25 # 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 26 41 #------------------------------------------------------------------------------ 27 42 … … 29 44 30 45 use strict; 31 use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber 32 %lightSource %compression %photometricInterpretation %orientation); 46 use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat 47 %lightSource %flash %compression %photometricInterpretation %orientation 48 %subfileType); 33 49 use Image::ExifTool qw(:DataAccess :Utils); 34 50 use Image::ExifTool::MakerNotes; 35 51 36 $VERSION = ' 2.42';52 $VERSION = '3.21'; 37 53 38 54 sub ProcessExif($$$); … … 42 58 sub EncodeExifText($$); 43 59 sub ValidateIFD($;$); 60 sub ProcessTiffIFD($$$); 61 sub PrintParameter($$$); 62 sub GetOffList($$$$$); 63 sub PrintLensInfo($); 64 sub ConvertLensInfo($); 65 66 # size limit for loading binary data block into memory 67 sub BINARY_DATA_LIMIT { return 10 * 1024 * 1024; } 44 68 45 69 # 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); 47 71 48 72 @formatName = ( … … 50 74 'int32u', 'rational64u', 'int8s', 'undef', 51 75 'int16s', 'int32s', 'rational64s', 'float', 52 'double', 'ifd', undef, undef, # (14 is unicode, 15 is complex? http://remotesensing.org/libtiff/bigtiffdesign.html)53 'int64u', 'int64s', 'ifd 8', # (new BigTIFF formats)76 'double', 'ifd', 'unicode', 'complex', 77 'int64u', 'int64s', 'ifd64', # (new BigTIFF formats) 54 78 ); 55 79 … … 57 81 # (format types are all lower case) 58 82 %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, 76 121 ); 77 122 78 123 # EXIF LightSource PrintConv values 79 124 %lightSource = ( 125 0 => 'Unknown', 80 126 1 => 'Daylight', 81 127 2 => 'Fluorescent', 82 3 => 'Tungsten ',128 3 => 'Tungsten (Incandescent)', 83 129 4 => 'Flash', 84 130 9 => 'Fine Weather', 85 131 10 => 'Cloudy', 86 132 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) 91 138 17 => 'Standard Light A', 92 139 18 => 'Standard Light B', … … 100 147 ); 101 148 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) 102 188 %compression = ( 103 189 1 => 'Uncompressed', … … 111 197 9 => 'JBIG B&W', #3 112 198 10 => 'JBIG Color', #3 199 99 => 'JPEG', #16 200 262 => 'Kodak 262', #16 113 201 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 115 205 32771 => 'CCIRLEW', #3 116 206 32773 => 'PackBits', 117 207 32809 => 'Thunderscan', #3 208 32867 => 'Kodak KDC Compressed', #PH 118 209 32895 => 'IT8CTPAD', #3 119 210 32896 => 'IT8LW', #3 … … 129 220 34712 => 'JPEG 2000', #3 130 221 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 131 226 65000 => 'Kodak DCR Compressed', #PH 132 227 65535 => 'Pentax PEF Compressed', #Jens 133 134 228 ); 135 229 … … 162 256 ); 163 257 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 164 285 # ValueConv that makes long values binary type 165 286 my %longBin = ( … … 168 289 ); 169 290 291 # PrintConv for SampleFormat (0x153) 292 my %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 170 301 # main EXIF tag table 171 302 %Image::ExifTool::Exif::Main = ( … … 173 304 WRITE_PROC => \&WriteExif, 174 305 WRITE_GROUP => 'ExifIFD', # default write group 306 SET_GROUP1 => 1, # set group1 name to directory name for all tags in table 175 307 0x1 => { 176 308 Name => 'InteropIndex', … … 182 314 }, 183 315 }, 184 0x2 => { 316 0x2 => { #5 185 317 Name => 'InteropVersion', 186 318 Description => 'Interoperability Version', 319 RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators) 187 320 }, 188 321 0x0b => { #PH … … 193 326 Name => 'SubfileType', 194 327 # 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, 206 331 }, 207 332 0xff => { 208 333 Name => 'OldSubfileType', 209 334 # 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', 211 336 PrintConv => { 212 337 1 => 'Full-resolution image', … … 220 345 # so it will show up in the group lists 221 346 Groups => { 1 => 'IFD1' }, 222 # set Priority to zero so the value found in the first IFD (IFD0) doesn't223 # 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") 224 349 Priority => 0, 225 350 }, 226 351 0x101 => { 227 352 Name => 'ImageHeight', 353 Notes => 'called ImageLength by the EXIF spec.', 228 354 Priority => 0, 229 355 }, … … 234 360 0x103 => { 235 361 Name => 'Compression', 362 DataMember => 'Compression', 363 SeparateTable => 'Compression', 364 RawConv => q{ 365 Image::ExifTool::Exif::IdentifyRawFile($self, $val); 366 return $$self{Compression} = $val; 367 }, 236 368 PrintConv => \%compression, 237 369 Priority => 0, … … 267 399 Name => 'Make', 268 400 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 272 408 }, 273 409 0x110 => { … … 275 411 Description => 'Camera Model Name', 276 412 Groups => { 2 => 'Camera' }, 277 DataMember => ' CameraModel',278 # save this value as an ExifTool member variable279 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', 280 416 }, 281 417 0x111 => [ 282 418 { 283 419 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]$/) 286 434 ], 287 435 Name => 'StripOffsets', … … 291 439 }, 292 440 { 293 Condition => '$ self->{DIR_NAME} eq "IFD0"',441 Condition => '$$self{DIR_NAME} eq "IFD0"', 294 442 Name => 'PreviewImageStart', 295 443 IsOffset => 1, … … 302 450 Writable => 'int32u', 303 451 WriteGroup => 'IFD0', 304 WriteCondition => '$ self->{TIFF_TYPE} eq "CR2"',452 WriteCondition => '$$self{TIFF_TYPE} eq "CR2"', 305 453 Protected => 2, 306 454 }, 307 455 { 308 Condition => '$ self->{DIR_NAME} eq "SubIFD1"',456 Condition => '$$self{DIR_NAME} eq "SubIFD1"', 309 457 Name => 'PreviewImageStart', 310 458 IsOffset => 1, … … 313 461 Writable => 'int32u', 314 462 WriteGroup => 'SubIFD1', 315 WriteCondition => '$ self->{TIFF_TYPE} eq "DNG"',463 WriteCondition => '$$self{TIFF_TYPE} eq "DNG"', 316 464 Protected => 2, 317 465 }, … … 323 471 Writable => 'int32u', 324 472 WriteGroup => 'SubIFD2', 325 WriteCondition => '$ self->{TIFF_TYPE} eq "DNG"',473 WriteCondition => '$$self{TIFF_TYPE} eq "DNG"', 326 474 Protected => 2, 327 475 }, … … 330 478 Name => 'Orientation', 331 479 PrintConv => \%orientation, 332 Priority => 0, # so IFD1 doesn't takeprecedence480 Priority => 0, # so PRIORITY_DIR takes precedence 333 481 }, 334 482 0x115 => { … … 343 491 { 344 492 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]$/) 347 506 ], 348 507 Name => 'StripByteCounts', … … 351 510 }, 352 511 { 353 Condition => '$ self->{DIR_NAME} eq "IFD0"',512 Condition => '$$self{DIR_NAME} eq "IFD0"', 354 513 Name => 'PreviewImageLength', 355 514 OffsetPair => 0x111, … … 361 520 Writable => 'int32u', 362 521 WriteGroup => 'IFD0', 363 WriteCondition => '$ self->{TIFF_TYPE} eq "CR2"',522 WriteCondition => '$$self{TIFF_TYPE} eq "CR2"', 364 523 Protected => 2, 365 524 }, 366 525 { 367 Condition => '$ self->{DIR_NAME} eq "SubIFD1"',526 Condition => '$$self{DIR_NAME} eq "SubIFD1"', 368 527 Name => 'PreviewImageLength', 369 528 OffsetPair => 0x111, … … 371 530 Writable => 'int32u', 372 531 WriteGroup => 'SubIFD1', 373 WriteCondition => '$ self->{TIFF_TYPE} eq "DNG"',532 WriteCondition => '$$self{TIFF_TYPE} eq "DNG"', 374 533 Protected => 2, 375 534 }, … … 380 539 Writable => 'int32u', 381 540 WriteGroup => 'SubIFD2', 382 WriteCondition => '$ self->{TIFF_TYPE} eq "DNG"',541 WriteCondition => '$$self{TIFF_TYPE} eq "DNG"', 383 542 Protected => 2, 384 543 }, … … 388 547 0x11a => { 389 548 Name => 'XResolution', 390 Priority => 0, # so IFD0 takes priority over IFD1549 Priority => 0, # so PRIORITY_DIR takes precedence 391 550 }, 392 551 0x11b => { … … 446 605 0x128 => { 447 606 Name => 'ResolutionUnit', 607 Notes => 'the value 1 is not standard EXIF', 448 608 PrintConv => { 449 609 1 => 'None', … … 461 621 0x131 => { 462 622 Name => 'Software', 623 RawConv => '$val =~ s/\s+$//; $val', # trim trailing blanks 463 624 }, 464 625 0x132 => { 465 626 Name => 'ModifyDate', 466 627 Groups => { 2 => 'Time' }, 628 Notes => 'called DateTime by the EXIF spec.', 467 629 PrintConv => '$self->ConvertDateTime($val)', 468 630 }, … … 470 632 Name => 'Artist', 471 633 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 472 636 }, 473 637 0x13c => 'HostComputer', … … 516 680 }, 517 681 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 ], 527 712 0x14c => { 528 713 Name => 'InkSet', … … 536 721 0x150 => 'DotRange', 537 722 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 }, 539 731 0x153 => { 540 732 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 ], 549 736 }, 550 737 0x154 => 'SMinSampleValue', … … 569 756 }, 570 757 }, 758 # 0x181 => 'Decode', #20 (typo! - should be 0x1b1, ref 21) 759 # 0x182 => 'DefaultImageColor', #20 (typo! - should be 0x1b2, ref 21) 571 760 0x190 => { #3 572 761 Name => 'GlobalParametersIFD', … … 592 781 5 => 'Lossless color and grayscale, L', 593 782 6 => 'Mixed raster content, M', 783 7 => 'Profile T', #20 784 255 => 'Multi Profiles', #20 594 785 }, 595 786 }, … … 609 800 0x195 => 'ModeNumber', #3 610 801 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 }, 612 808 0x200 => { 613 809 Name => 'JPEGProc', … … 620 816 { 621 817 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 }, 622 825 # thumbnail is found in IFD1 of JPEG and TIFF images, and 623 826 # IFD0 of EXIF information in FujiFilm AVI (RIFF) videos 624 827 Condition => q{ 625 $ self->{DIR_NAME} eq 'IFD1' or626 ($ 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') 627 830 }, 628 831 IsOffset => 1, … … 631 834 Writable => 'int32u', 632 835 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"', 634 874 Protected => 2, 635 875 }, 636 876 { 637 877 Name => 'PreviewImageStart', 638 Condition => '$ self->{DIR_NAME} eq "MakerNotes"',878 Condition => '$$self{DIR_NAME} eq "MakerNotes"', 639 879 IsOffset => 1, 640 880 OffsetPair => 0x202, … … 642 882 Writable => 'int32u', 643 883 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)$/', 644 897 Protected => 2, 645 898 }, 646 899 { 647 900 Name => 'JpgFromRawStart', 648 Condition => '$ self->{DIR_NAME} eq "SubIFD"',901 Condition => '$$self{DIR_NAME} eq "SubIFD"', 649 902 IsOffset => 1, 650 903 OffsetPair => 0x202, … … 652 905 Writable => 'int32u', 653 906 WriteGroup => 'SubIFD', 654 # JpgFromRaw is in SubIFD of NEF files655 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)$/', 656 909 Protected => 2, 657 910 }, 658 911 { 659 912 Name => 'JpgFromRawStart', 660 Condition => '$ self->{DIR_NAME} eq "IFD2"',913 Condition => '$$self{DIR_NAME} eq "IFD2"', 661 914 IsOffset => 1, 662 915 OffsetPair => 0x202, … … 665 918 WriteGroup => 'IFD2', 666 919 # JpgFromRaw is in IFD2 of PEF files 667 WriteCondition => '$ self->{TIFF_TYPE} eq "PEF"',920 WriteCondition => '$$self{TIFF_TYPE} eq "PEF"', 668 921 Protected => 2, 669 922 }, … … 677 930 { 678 931 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 }, 679 939 Condition => q{ 680 $ self->{DIR_NAME} eq 'IFD1' or681 ($ 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') 682 942 }, 683 943 OffsetPair => 0x201, … … 685 945 Writable => 'int32u', 686 946 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"', 688 976 Protected => 2, 689 977 }, 690 978 { 691 979 Name => 'PreviewImageLength', 692 Condition => '$ self->{DIR_NAME} eq "MakerNotes"',980 Condition => '$$self{DIR_NAME} eq "MakerNotes"', 693 981 OffsetPair => 0x201, 694 982 DataTag => 'PreviewImage', 695 983 Writable => 'int32u', 696 984 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)$/', 697 997 Protected => 2, 698 998 }, 699 999 { 700 1000 Name => 'JpgFromRawLength', 701 Condition => '$ self->{DIR_NAME} eq "SubIFD"',1001 Condition => '$$self{DIR_NAME} eq "SubIFD"', 702 1002 OffsetPair => 0x201, 703 1003 DataTag => 'JpgFromRaw', 704 1004 Writable => 'int32u', 705 1005 WriteGroup => 'SubIFD', 706 WriteCondition => '$ self->{TIFF_TYPE} eq "NEF"',1006 WriteCondition => '$$self{TIFF_TYPE} =~ /^(NEF|NRW|SRW)$/', 707 1007 Protected => 2, 708 1008 }, 709 1009 { 710 1010 Name => 'JpgFromRawLength', 711 Condition => '$ self->{DIR_NAME} eq "IFD2"',1011 Condition => '$$self{DIR_NAME} eq "IFD2"', 712 1012 OffsetPair => 0x201, 713 1013 DataTag => 'JpgFromRaw', 714 1014 Writable => 'int32u', 715 1015 WriteGroup => 'IFD2', 716 WriteCondition => '$ self->{TIFF_TYPE} eq "PEF"',1016 WriteCondition => '$$self{TIFF_TYPE} eq "PEF"', 717 1017 Protected => 2, 718 1018 }, … … 725 1025 0x205 => 'JPEGLosslessPredictors', 726 1026 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 }, 730 1045 0x211 => { 731 1046 Name => 'YCbCrCoefficients', … … 734 1049 0x212 => { 735 1050 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, 744 1053 Priority => 0, 745 1054 }, … … 758 1067 0x22f => 'StripRowCounts', 759 1068 0x2bc => { 760 Name => 'ApplicationNotes', 1069 Name => 'ApplicationNotes', # (writable directory!) 1070 Writable => 'int8u', 1071 Format => 'undef', 1072 Flags => [ 'Binary', 'Protected' ], 761 1073 # this could be an XMP block 762 1074 SubDirectory => { … … 765 1077 }, 766 1078 }, 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 }, 770 1086 # (0x474x tags written by MicrosoftPhoto) 771 1087 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 }, 772 1102 0x4749 => 'RatingPercent', #PH 773 1103 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 }, 775 1111 0x80e3 => 'Matteing', #9 776 1112 0x80e4 => 'DataType', #9 … … 778 1114 0x80e6 => 'TileDepth', #9 779 1115 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 783 1122 Name => 'BatteryLevel', 784 1123 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 }, 785 1135 }, 786 1136 0x8298 => { 787 1137 Name => 'Copyright', 788 1138 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$//; $_', 789 1153 }, 790 1154 0x829a => { … … 808 1172 0x82ac => 'MDFileUnits', #3 809 1173 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' ], 812 1190 SubDirectory => { 813 1191 DirName => 'IPTC', … … 818 1196 0x847f => 'IntergraphFlagRegisters', #3 819 1197 0x8480 => 'IntergraphMatrix', 1198 0x8481 => 'INGRReserved', #20 820 1199 0x8482 => { 821 1200 Name => 'ModelTiePoint', … … 825 1204 0x84e1 => 'ColorSequence', #9 826 1205 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 }, 828 1216 0x84e4 => 'BitsPerRunLength', #9 829 1217 0x84e5 => 'BitsPerExtendedRunLength', #9 830 1218 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 }, 833 1233 0x84e9 => 'ImageColorValue', #9 834 1234 0x84ea => 'BackgroundColorValue', #9 … … 836 1236 0x84ec => 'TransparencyIndicator', #9 837 1237 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 839 1248 0x8546 => { #11 840 1249 Name => 'SEMInfo', … … 844 1253 Name => 'AFCP_IPTC', 845 1254 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', 847 1257 TagTable => 'Image::ExifTool::IPTC::Main', 848 1258 }, 849 1259 }, 1260 0x85b8 => 'PixelMagicJBIGOptions', #20 850 1261 0x85d8 => { 851 1262 Name => 'ModelTransform', 852 1263 Groups => { 2 => 'Location' }, 853 1264 }, 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) 854 1270 0x8606 => { 855 1271 Name => 'LeafData', … … 860 1276 }, 861 1277 }, 862 0x8649 => { 1278 0x8649 => { #19 863 1279 Name => 'PhotoshopSettings', 864 1280 Format => 'binary', … … 871 1287 Name => 'ExifOffset', 872 1288 Groups => { 1 => 'ExifIFD' }, 873 Flags => 'SubIFD',1289 SubIFD => 2, 874 1290 SubDirectory => { 875 1291 DirName => 'ExifIFD', … … 883 1299 }, 884 1300 }, 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 885 1336 0x87ac => 'ImageLayer', 886 1337 0x87af => { … … 901 1352 Name => 'ExposureProgram', 902 1353 Groups => { 2 => 'Camera' }, 1354 Notes => 'the value of 9 is not standard EXIF, but is used by the Canon EOS 7D', 903 1355 PrintConv => { 1356 0 => 'Not Defined', 904 1357 1 => 'Manual', 905 1358 2 => 'Program AE', … … 910 1363 7 => 'Portrait', 911 1364 8 => 'Landscape', 1365 9 => 'Bulb', #25 912 1366 }, 913 1367 }, … … 926 1380 }, 927 1381 }, 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 }, 929 1390 0x8828 => { 930 1391 Name => 'Opto-ElectricConvFactor', 1392 Notes => 'called OECF by the EXIF spec.', 931 1393 Binary => 1, 932 1394 }, 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 }, 936 1423 0x885c => 'FaxRecvParams', #9 937 1424 0x885d => 'FaxSubAddress', #9 … … 947 1434 }, 948 1435 }, 949 0x9000 => 'ExifVersion', 1436 0x9000 => { 1437 Name => 'ExifVersion', 1438 RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators) 1439 }, 950 1440 0x9003 => { 951 1441 Name => 'DateTimeOriginal', 952 1442 Description => 'Date/Time Original', 953 1443 Groups => { 2 => 'Time' }, 1444 Notes => 'date/time when original image was taken', 954 1445 PrintConv => '$self->ConvertDateTime($val)', 955 1446 }, … … 957 1448 Name => 'CreateDate', 958 1449 Groups => { 2 => 'Time' }, 1450 Notes => 'called DateTimeDigitized by the EXIF spec.', 959 1451 PrintConv => '$self->ConvertDateTime($val)', 960 1452 }, 961 1453 0x9101 => { 962 1454 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 }, 964 1486 }, 965 1487 0x9102 => 'CompressedBitsPerPixel', 966 1488 0x9201 => { 967 1489 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', 969 1492 PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', 970 1493 }, … … 977 1500 0x9204 => { 978 1501 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)', 980 1505 }, 981 1506 0x9205 => { … … 988 1513 Name => 'SubjectDistance', 989 1514 Groups => { 2 => 'Camera' }, 990 PrintConv => '$val eq "inf"? $val : "${val} m"',1515 PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "${val} m"', 991 1516 }, 992 1517 0x9207 => { … … 994 1519 Groups => { 2 => 'Camera' }, 995 1520 PrintConv => { 1521 0 => 'Unknown', 996 1522 1 => 'Average', 997 1523 2 => 'Center-weighted average', … … 1006 1532 Name => 'LightSource', 1007 1533 Groups => { 2 => 'Camera' }, 1534 SeparateTable => 'LightSource', 1008 1535 PrintConv => \%lightSource, 1009 1536 }, … … 1012 1539 Groups => { 2 => 'Camera' }, 1013 1540 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, 1043 1543 }, 1044 1544 0x920a => { 1045 1545 Name => 'FocalLength', 1046 1546 Groups => { 2 => 'Camera' }, 1047 PrintConv => 'sprintf("%.1f mm",$val)',1547 PrintConv => 'sprintf("%.1f mm",$val)', 1048 1548 }, 1049 1549 # Note: tags 0x920b-0x9217 are duplicates of 0xa20b-0xa217 1050 1550 # (The TIFF standard uses 0xa2xx, but you'll find both in images) 1051 0x920b => { 1551 0x920b => { #12 1052 1552 Name => 'FlashEnergy', 1053 1553 Groups => { 2 => 'Camera' }, 1054 1554 }, 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 1060 1560 Name => 'FocalPlaneResolutionUnit', 1061 1561 Groups => { 2 => 'Camera' }, … … 1068 1568 }, 1069 1569 }, 1070 0x9211 => 'ImageNumber', 1570 0x9211 => 'ImageNumber', #12 1071 1571 0x9212 => { #12 1072 1572 Name => 'SecurityClassification', … … 1079 1579 }, 1080 1580 }, 1081 0x9213 => 'ImageHistory', 1581 0x9213 => 'ImageHistory', #12 1082 1582 0x9214 => { 1083 Name => 'Subject Location',1583 Name => 'SubjectArea', 1084 1584 Groups => { 2 => 'Camera' }, 1085 1585 }, 1086 0x9215 => 'ExposureIndex', 1087 0x9216 => 'TIFF-EPStandardID', 1088 0x9217 => { 1586 0x9215 => 'ExposureIndex', #12 1587 0x9216 => 'TIFF-EPStandardID', #12 1588 0x9217 => { #12 1089 1589 Name => 'SensingMethod', 1090 1590 Groups => { 2 => 'Camera' }, 1591 Notes => 'values 1 and 6 are not standard EXIF', 1091 1592 PrintConv => { 1092 1 => 'Monochrome area', #12 1593 1 => 'Monochrome area', #12 (not standard EXIF) 1093 1594 2 => 'One-chip color area', 1094 1595 3 => 'Two-chip color area', 1095 1596 4 => 'Three-chip color area', 1096 1597 5 => 'Color sequential area', 1097 6 => 'Monochrome linear', #12 1598 6 => 'Monochrome linear', #12 (not standard EXIF) 1098 1599 7 => 'Trilinear', 1099 1600 8 => 'Color sequential linear', … … 1101 1602 }, 1102 1603 0x9213 => 'ImageHistory', 1604 0x923a => 'CIP3DataFile', #20 1605 0x923b => 'CIP3Sheet', #20 1606 0x923c => 'CIP3Side', #20 1103 1607 0x923f => 'StoNits', #9 1104 1608 # handle maker notes as a conditional list … … 1106 1610 0x9286 => { 1107 1611 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)', 1109 1615 }, 1110 1616 0x9290 => { 1111 1617 Name => 'SubSecTime', 1112 1618 Groups => { 2 => 'Time' }, 1619 ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks 1113 1620 }, 1114 1621 0x9291 => { 1115 1622 Name => 'SubSecTimeOriginal', 1116 1623 Groups => { 2 => 'Time' }, 1624 ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks 1117 1625 }, 1118 1626 0x9292 => { 1119 1627 Name => 'SubSecTimeDigitized', 1120 1628 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 1123 1646 Name => 'ImageSourceData', 1124 1647 Binary => 1, … … 1127 1650 Name => 'XPTitle', 1128 1651 Format => 'undef', 1129 ValueConv => '$self-> Unicode2Charset($val,"II")',1652 ValueConv => '$self->Decode($val,"UCS2","II")', 1130 1653 }, 1131 1654 0x9c9c => { 1132 1655 Name => 'XPComment', 1133 1656 Format => 'undef', 1134 ValueConv => '$self-> Unicode2Charset($val,"II")',1657 ValueConv => '$self->Decode($val,"UCS2","II")', 1135 1658 }, 1136 1659 0x9c9d => { … … 1138 1661 Groups => { 2 => 'Author' }, 1139 1662 Format => 'undef', 1140 ValueConv => '$self-> Unicode2Charset($val,"II")',1663 ValueConv => '$self->Decode($val,"UCS2","II")', 1141 1664 }, 1142 1665 0x9c9e => { 1143 1666 Name => 'XPKeywords', 1144 1667 Format => 'undef', 1145 ValueConv => '$self-> Unicode2Charset($val,"II")',1668 ValueConv => '$self->Decode($val,"UCS2","II")', 1146 1669 }, 1147 1670 0x9c9f => { 1148 1671 Name => 'XPSubject', 1149 1672 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 }, 1153 1679 0xa001 => { 1154 1680 Name => 'ColorSpace', 1155 1681 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, 1159 1687 PrintConv => { 1160 1688 1 => 'sRGB', 1161 1689 2 => 'Adobe RGB', 1162 1690 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 }, 1167 1705 0xa004 => 'RelatedSoundFile', 1168 1706 0xa005 => { … … 1190 1728 Name => 'FocalPlaneResolutionUnit', 1191 1729 Groups => { 2 => 'Camera' }, 1730 Notes => 'values 1, 4 and 5 are not standard EXIF', 1192 1731 PrintConv => { 1193 1732 1 => 'None', # (not standard EXIF) … … 1254 1793 1 => 'Manual', 1255 1794 2 => 'Auto bracket', 1795 # have seen 3 for Samsung EX1 images - PH 1256 1796 }, 1257 1797 }, … … 1274 1814 0xa405 => { 1275 1815 Name => 'FocalLengthIn35mmFormat', 1816 Notes => 'called FocalLengthIn35mmFilm by the EXIF spec.', 1276 1817 Groups => { 2 => 'Camera' }, 1277 PrintConv => '"$ {val}mm"',1818 PrintConv => '"$val mm"', 1278 1819 }, 1279 1820 0xa406 => { … … 1328 1869 Name => 'DeviceSettingDescription', 1329 1870 Groups => { 2 => 'Camera' }, 1871 Binary => 1, 1330 1872 }, 1331 1873 0xa40c => { … … 1333 1875 Groups => { 2 => 'Camera' }, 1334 1876 PrintConv => { 1877 0 => 'Unknown', 1335 1878 1 => 'Macro', 1336 1879 2 => 'Close', … … 1338 1881 }, 1339 1882 }, 1883 # 0xa40d - int16u: 0 (GE E1486 TW) 1884 # 0xa40e - int16u: 1 (GE E1486 TW) 1340 1885 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 1341 1906 0xa480 => 'GDALMetadata', #3 1342 1907 0xa481 => 'GDALNoData', #3 1343 1908 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) 1344 1915 # 1345 # Windows Media Photo WDPtags1916 # Windows Media Photo / HD Photo (WDP/HDP) tags 1346 1917 # 1347 1918 0xbc01 => { #13 … … 1350 1921 Format => 'undef', 1351 1922 Notes => q{ 1352 tags 0xbc** are used in Windows Media Photo WDPimages. The actual1923 tags 0xbc** are used in Windows HD Photo (HDP and WDP) images. The actual 1353 1924 PixelFormat values are 16-byte GUID's but the leading 15 bytes, 1354 1925 '6fddc324-4e03-4bfe-b1853-d77768dc9', have been removed below to avoid … … 1421 1992 }, 1422 1993 }, 1423 0xbc04 => { #131424 Name => 'ImageType',1425 PrintConv => { BITMASK => {1426 0 => 'Preview',1427 1 => 'Page',1428 } },1429 },1430 1994 0xbc02 => { #13 1431 Name => 'Transfo mation',1995 Name => 'Transformation', 1432 1996 PrintConv => { 1433 1997 0 => 'Horizontal (normal)', … … 1445 2009 PrintConv => { 0 => 'No', 1 => 'Yes' }, 1446 2010 }, 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 1447 2022 0xbcc0 => { #13 1448 2023 Name => 'ImageOffset', … … 1481 2056 }, 1482 2057 }, 1483 0xbc80 => 'ImageWidth', #131484 0xbc81 => 'ImageHeight', #131485 0xbc82 => 'WidthResolution', #131486 0xbc83 => 'HeightResolution', #131487 2058 # 1488 2059 0xc427 => 'OceScanjobDesc', #3 … … 1490 2061 0xc429 => 'OceIDNumber', #3 1491 2062 0xc42a => 'OceImageLogic', #3 1492 0xc44f => 'Annotations', #72063 0xc44f => { Name => 'Annotations', Binary => 1 }, #7/19 1493 2064 0xc4a5 => { 1494 Name => 'PrintIM', 2065 Name => 'PrintIM', # (writable directory!) 1495 2066 # must set Writable here so this tag will be saved with MakerNotes option 1496 2067 Writable => 'undef', 2068 WriteGroup => 'IFD0', 1497 2069 Description => 'Print Image Matching', 1498 2070 SubDirectory => { … … 1500 2072 }, 1501 2073 }, 2074 0xc580 => { #20 2075 Name => 'USPTOOriginalContentType', 2076 PrintConv => { 2077 0 => 'Text or Drawing', 2078 1 => 'Grayscale', 2079 2 => 'Color', 2080 }, 2081 }, 1502 2082 # 1503 # DNG tags 0xc6XX (ref 2 unless otherwise stated)2083 # DNG tags 0xc6XX and 0xc7XX (ref 2 unless otherwise stated) 1504 2084 # 1505 2085 0xc612 => { 1506 2086 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', 1508 2091 }, 1509 2092 0xc613 => 'DNGBackwardVersion', … … 1512 2095 Name => 'LocalizedCameraModel', 1513 2096 Format => 'string', 1514 PrintConv => '$self->Printable($val )',2097 PrintConv => '$self->Printable($val, 0)', 1515 2098 }, 1516 2099 0xc616 => { … … 1530 2113 4 => 'Even rows offset right 1/2 column', 1531 2114 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 }, 1538 2123 0xc619 => 'BlackLevelRepeatDim', 1539 2124 0xc61a => 'BlackLevel', … … 1565 2150 Name => 'DNGLensInfo', 1566 2151 Groups => { 2 => 'Camera' }, 1567 PrintConv => '$_=$val;s/(\S+) (\S+) (\S+) (\S+)/$1-$2mm f\/$3-$4/;$_',2152 PrintConv =>\&PrintLensInfo, 1568 2153 }, 1569 2154 0xc631 => 'ChromaBlurRadius', … … 1572 2157 0xc634 => [ 1573 2158 { 1574 Condition => '$ self->{TIFF_TYPE} eq "SR2"',2159 Condition => '$$self{TIFF_TYPE} =~ /^(ARW|SR2)$/', 1575 2160 Name => 'SR2Private', 1576 2161 Groups => { 1 => 'SR2' }, 1577 2162 Flags => 'SubIFD', 1578 2163 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) 1579 2168 SubDirectory => { 1580 2169 DirName => 'SR2Private', … … 1586 2175 Condition => '$$valPt =~ /^Adobe\0/', 1587 2176 Name => 'DNGAdobeData', 1588 DNGMakerNotes=> 1,2177 NestedHtmlDump => 1, 1589 2178 SubDirectory => { TagTable => 'Image::ExifTool::DNG::AdobeData' }, 1590 2179 Format => 'undef', # written incorrectly as int8u (change to undef for speed) 1591 2180 }, 1592 2181 { 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 1596 2190 SubDirectory => { 1597 2191 TagTable => 'Image::ExifTool::Pentax::Main', … … 1615 2209 }, 1616 2210 }, 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 }, 1617 2219 0xc65a => { 1618 2220 Name => 'CalibrationIlluminant1', 2221 SeparateTable => 'LightSource', 1619 2222 PrintConv => \%lightSource, 1620 2223 }, 1621 2224 0xc65b => { 1622 2225 Name => 'CalibrationIlluminant2', 2226 SeparateTable => 'LightSource', 1623 2227 PrintConv => \%lightSource, 1624 2228 }, … … 1631 2235 0xc660 => { #3 1632 2236 Name => 'AliasLayerMetadata', 1633 Notes => 'used by Alias Sketchbook Pro , not a DNG tag',2237 Notes => 'used by Alias Sketchbook Pro', 1634 2238 }, 1635 2239 0xc68b => { … … 1638 2242 }, 1639 2243 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' ], 1641 2248 SubDirectory => { 1642 2249 TagTable => 'Image::ExifTool::DNG::OriginalRaw', … … 1665 2272 }, 1666 2273 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 }, 1670 2402 0xea1d => { 1671 2403 Name => 'OffsetSchema', 1672 2404 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. 1673 2429 }, 1674 2430 … … 1678 2434 # of tags, all tags with values above 0xf000 are handled specially 1679 2435 # 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 }, 1680 2448 ); 1681 2449 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) 1685 2451 %Image::ExifTool::Exif::Composite = ( 1686 2452 GROUPS => { 2 => 'Image' }, … … 1690 2456 1 => 'ImageHeight', 1691 2457 }, 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 }, 1693 2468 }, 1694 2469 # pick the best shutter speed value … … 1721 2496 PrintConv => 'sprintf("%.1f",$val)', 1722 2497 }, 1723 FocalLength35efl => { 2498 FocalLength35efl => { #26/PH 1724 2499 Description => 'Focal Length', 1725 2500 Notes => 'this value may be incorrect if the image has been resized', … … 1731 2506 1 => 'ScaleFactor35efl', 1732 2507 }, 1733 ValueConv => ' $val[0] * ($val[1] ? $val[1] :1)',1734 PrintConv => '$val[1] ? sprintf("%.1f mm (35mm equivalent: %.1fmm)", $val[0], $val) : sprintf("%.1fmm", $val)',1735 }, 1736 ScaleFactor35efl => { 1737 Description => 'Scale Factor To 35 mm 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', 1738 2513 Notes => 'this value and any derived values may be incorrect if image has been resized', 1739 2514 Groups => { 2 => 'Camera' }, … … 1748 2523 7 => 'FocalPlaneXResolution', 1749 2524 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', 1754 2529 13 => 'ImageWidth', 1755 2530 14 => 'ImageHeight', … … 1777 2552 }, 1778 2553 ValueConv => q{ 1779 return undef unless $val[1] and $val[2]; 2554 ToFloat(@val); 2555 return 'inf' unless $val[1] and $val[2]; 1780 2556 return $val[0] * $val[0] / ($val[1] * $val[2] * 1000); 1781 2557 }, … … 1783 2559 }, 1784 2560 DOF => { 1785 Description => 'Depth of Field',2561 Description => 'Depth Of Field', 1786 2562 Notes => 'this value may be incorrect if the image has been resized', 1787 2563 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', 1792 2572 }, 1793 2573 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)); 1799 2585 $v[1] < 0 and $v[1] = 0; # 0 means 'inf' 1800 2586 return join(' ',@v); … … 1807 2593 }, 1808 2594 }, 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 }, 1812 2601 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 1820 2633 DateTimeOriginal => { 1821 Condition => 'not defined ($oldVal)',2634 Condition => 'not defined $$self{VALUE}{DateTimeOriginal}', 1822 2635 Description => 'Date/Time Original', 1823 2636 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)', 1827 2648 }, 1828 2649 ThumbnailImage => { … … 1844 2665 Writable => 1, 1845 2666 WriteCheck => '$self->CheckImage(\$val)', 2667 DelCheck => '$val = ""; return undef', # can't delete, so set to empty string 1846 2668 WriteAlso => { 1847 2669 PreviewImageStart => 'defined $val ? 0xfeedfeed : undef', … … 1855 2677 Desire => { 1856 2678 2 => 'PreviewImageValid', 1857 # (DNG may be have 2 preview images)2679 # (DNG and A100 ARW may be have 2 preview images) 1858 2680 3 => 'PreviewImageStart (1)', 1859 2681 4 => 'PreviewImageLength (1)', 1860 2682 }, 2683 # note: extract 2nd preview, but ignore double-referenced preview 2684 # (in A100 ARW images, the 2nd PreviewImageLength from IFD0 may be wrong anyway) 1861 2685 RawConv => q{ 1862 if ($val[3] and $val[4] ) {2686 if ($val[3] and $val[4] and $val[0] ne $val[3]) { 1863 2687 my %val = ( 1864 2688 0 => 'PreviewImageStart (1)', … … 1902 2726 SubSecDateTimeOriginal => { 1903 2727 Description => 'Date/Time Original', 2728 Groups => { 2 => 'Time' }, 1904 2729 Require => { 1905 0 => ' DateTimeOriginal',2730 0 => 'EXIF:DateTimeOriginal', 1906 2731 1 => 'SubSecTimeOriginal', 1907 2732 }, 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 }, 1910 2764 PrintConv => '$self->ConvertDateTime($val)', 1911 2765 }, … … 1919 2773 my @a = split / /, $val[0]; 1920 2774 my @b = split / /, $val[1]; 1921 return undefunless @a==2 and @b==$a[0]*$a[1];2775 return '?' unless @a==2 and @b==$a[0]*$a[1]; 1922 2776 return Set16u($a[0]) . Set16u($a[1]) . pack('C*', @b); 1923 2777 }, … … 1932 2786 3 => 'WB_GRBGLevels', 1933 2787 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', 1937 2793 }, 1938 2794 ValueConv => 'Image::ExifTool::Exif::RedBlueBalance(0,@val)', … … 1947 2803 3 => 'WB_GRBGLevels', 1948 2804 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', 1952 2810 }, 1953 2811 ValueConv => 'Image::ExifTool::Exif::RedBlueBalance(1,@val)', … … 1955 2813 }, 1956 2814 GPSPosition => { 2815 Groups => { 2 => 'Location' }, 1957 2816 Require => { 1958 2817 0 => 'GPSLatitude', … … 1961 2820 ValueConv => '"$val[0] $val[1]"', 1962 2821 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)', 1963 2849 }, 1964 2850 ); … … 1983 2869 1984 2870 #------------------------------------------------------------------------------ 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 2874 sub 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 #------------------------------------------------------------------------------ 1985 2886 # Calculate LV (Light Value) 1986 2887 # Inputs: 0) Aperture, 1) ShutterSpeed, 2) ISO 1987 # Returns: LV value 2888 # Returns: LV value (and converts input values to floating point if necessary) 1988 2889 sub CalculateLV($$$) 1989 2890 { … … 1992 2893 return undef unless @_ >= 3; 1993 2894 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 1995 2897 } 1996 2898 # (A light value of 0 is defined as f/1.0 at 1 second with ISO 100) … … 1999 2901 2000 2902 #------------------------------------------------------------------------------ 2001 # Calculate scale factor for 35mm effective focal length 2903 # Calculate scale factor for 35mm effective focal length (ref 26/PH) 2002 2904 # Inputs: 0) Focal length 2003 2905 # 1) Focal length in 35mm format … … 2011 2913 sub CalcScaleFactor35efl 2012 2914 { 2915 my $res = $_[6]; # save resolution units (in case they have been converted to string) 2916 Image::ExifTool::ToFloat(@_); 2013 2917 my $focal = shift; 2014 2918 my $foc35 = shift; … … 2019 2923 my $diag = shift; 2020 2924 unless ($diag and Image::ExifTool::IsFloat($diag)) { 2925 undef $diag; 2021 2926 my $xsize = shift; 2022 2927 my $ysize = shift; 2023 2928 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) { 2026 2936 # 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; 2028 2939 my $x_res = shift || return undef; 2029 2940 my $y_res = shift || return undef; … … 2051 2962 2052 2963 #------------------------------------------------------------------------------ 2053 # Convert exposure compensation fraction2054 sub ConvertFraction($)2964 # Print exposure compensation fraction 2965 sub PrintFraction($) 2055 2966 { 2056 2967 my $val = shift; … … 2067 2978 $str = sprintf("%+d/3", int($val * 3)); 2068 2979 } else { 2069 $str = sprintf("% .3g", $val);2980 $str = sprintf("%+.3g", $val); 2070 2981 } 2071 2982 } … … 2074 2985 2075 2986 #------------------------------------------------------------------------------ 2987 # Convert fraction or number to floating point value (or 'undef' or 'inf') 2988 sub 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 #------------------------------------------------------------------------------ 2076 2998 # Convert EXIF text to something readable 2077 2999 # Inputs: 0) ExifTool object reference, 1) EXIF text 2078 # Returns: UTF8 or Latin text3000 # Returns: text encoded according to Charset option (with trailing spaces removed) 2079 3001 sub ConvertExifText($$) 2080 3002 { … … 2083 3005 my $id = substr($val, 0, 8); 2084 3006 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 ]$/) { 2090 3018 # MicrosoftPhoto writes as little-endian even in big-endian EXIF, 2091 3019 # 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'); 2101 3023 } else { 2102 # assume everything else is ASCII (Don't convert JIS... yet)2103 $str = ~ s/\0.*//s; # truncate at null terminator3024 $exifTool->Warn("Invalid EXIF text encoding"); 3025 $str = $id . $str; 2104 3026 } 3027 $str =~ s/ +$//; # trim trailing blanks 2105 3028 return $str; 2106 3029 } … … 2130 3053 #------------------------------------------------------------------------------ 2131 3054 # 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 3056 sub PrintParameter($$$) 2133 3057 { 2134 my $val = shift; 3058 my ($val, $inv, $conv) = @_; 3059 return $val if $inv; 2135 3060 if ($val > 0) { 2136 3061 if ($val > 0xfff0) { # a negative value in disguise? … … 2139 3064 $val = "+$val"; 2140 3065 } 2141 } elsif ($val == 0) {2142 $val = 'Normal';2143 3066 } 2144 3067 return $val; … … 2147 3070 #------------------------------------------------------------------------------ 2148 3071 # Convert parameter back to standard EXIF value 2149 # 0 or "Normal" => 03072 # 0,0.00,etc or "Normal" => 0 2150 3073 # -1,-2,etc or "Soft" or "Low" => 1 2151 3074 # +1,+2,1,2,etc or "Hard" or "High" => 2 … … 2153 3076 { 2154 3077 my $val = shift; 3078 my $isFloat = Image::ExifTool::IsFloat($val); 2155 3079 # 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); 2157 3081 # "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 va ilof 22160 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; 2161 3085 return undef; 2162 3086 } … … 2164 3088 #------------------------------------------------------------------------------ 2165 3089 # 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 level3090 # 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 2168 3092 my @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) 2175 3102 ); 2176 3103 sub RedBlueBalance($@) … … 2185 3112 my $g = $$lookup[1]; # get green level or index 2186 3113 if ($g < 4) { 2187 next if @levels < 4;3114 next if @levels < 3; 2188 3115 $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) 2189 3118 } 2190 3119 $val = $levels[$$lookup[$blue * 3]] / $g; … … 2237 3166 2238 3167 #------------------------------------------------------------------------------ 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" 3171 sub 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 3194 sub 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 3217 sub 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 #------------------------------------------------------------------------------ 2239 3301 # translate date into standard EXIF format 2240 3302 # Inputs: 0) date … … 2282 3344 my $image; 2283 3345 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'; 2285 3348 2286 3349 # take data from EXIF block if possible … … 2290 3353 $image = $exifTool->ExtractBinary($offset, $len, $tag); 2291 3354 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 } 2292 3367 } 2293 3368 return $exifTool->ValidateImage(\$image, $tag); … … 2315 3390 my $htmlDump = $exifTool->{HTML_DUMP}; 2316 3391 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 } 2319 3406 $verbose = -1 if $htmlDump; # mix htmlDump into verbose so we can test for both at once 2320 3407 $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/; 2323 3412 2324 3413 my ($numEntries, $dirEnd); … … 2356 3445 $dataLen = $$dirInfo{DataLen} = length $buff; 2357 3446 $dirStart = $$dirInfo{DirStart} = 0; 3447 $dirLen = $$dirInfo{DirLen} = length $buff; 2358 3448 $success = 1; 2359 3449 } … … 2361 3451 } 2362 3452 unless ($success) { 2363 $exifTool->Warn("Bad $ dirName directory");3453 $exifTool->Warn("Bad $name directory"); 2364 3454 return 0; 2365 3455 } … … 2372 3462 if ($bytesFromEnd < 4) { 2373 3463 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); 2375 3465 return 0; 2376 3466 } … … 2386 3476 } 2387 3477 if ($htmlDump) { 3478 my $longName = $name eq 'MakerNotes' ? ($$dirInfo{Name} || $name) : $name; 2388 3479 if (defined $makerAddr) { 2389 3480 my $hdrLen = $dirStart + $dataPos + $base - $makerAddr; 2390 $exifTool->H tmlDump($makerAddr, $hdrLen, "MakerNotes header", $name) if $hdrLen > 0;3481 $exifTool->HDump($makerAddr, $hdrLen, "MakerNotes header", $longName) if $hdrLen > 0; 2391 3482 } 2392 $exifTool->H tmlDump($dirStart + $dataPos + $base, 2, "$name entries",3483 $exifTool->HDump($dirStart + $dataPos + $base, 2, "$longName entries", 2393 3484 "Entry count: $numEntries"); 2394 3485 my $tip; 2395 3486 if ($bytesFromEnd >= 4) { 2396 my $nxt = ($name =~ /^ IFD(\d+)/) ? "IFD" . ($1+ 1) : 'Next IFD';3487 my $nxt = ($name =~ /^(.*?)(\d+)$/) ? $1 . ($2 + 1) : 'Next IFD'; 2397 3488 $tip = sprintf("$nxt offset: 0x%.4x", Get32u($dataPt, $dirEnd)); 2398 3489 } 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); 2401 3491 } 2402 3492 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 2403 3507 # loop through all entries in an EXIF directory (IFD) 2404 my ($index, $valEnd); 3508 my ($index, $valEnd, $offList, $offHash); 3509 my $warnCount = 0; 2405 3510 for ($index=0; $index<$numEntries; ++$index) { 3511 if ($warnCount > 10) { 3512 $exifTool->Warn("Too many warnings -- $name parsing aborted", 1) and return 0; 3513 } 2406 3514 my $entry = $dirStart + 2 + 12 * $index; 2407 3515 my $tagID = Get16u($dataPt, $entry); … … 2409 3517 my $count = Get32u($dataPt, $entry+4); 2410 3518 if ($format < 1 or $format > 13) { 2411 $exifTool->H tmlDump($entry+$dataPos+$base,12,"[invalid IFD entry]",3519 $exifTool->HDump($entry+$dataPos+$base,12,"[invalid IFD entry]", 2412 3520 "Bad format type: $format", 1); 2413 3521 # 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 } 2416 3526 return 0 unless $index; # assume corrupted IFD if this is our first entry 2417 3527 next; 2418 3528 } 2419 3529 my $formatStr = $formatName[$format]; # get name of this format 2420 my $size = $count * $formatSize[$format];2421 3530 my $valueDataPt = $dataPt; 2422 3531 my $valueDataPos = $dataPos; … … 2424 3533 my $valuePtr = $entry + 8; # pointer to value within $$dataPt 2425 3534 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; 2426 3549 if ($size > 4) { 2427 3550 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; 2429 3553 next; 2430 3554 } … … 2434 3558 my $wFlag; 2435 3559 $valEnd or $valEnd = $dataPos + $dirEnd + 4; 2436 #### eval FixOffsets ($valuePtr, $valEnd, $size, $tagID, $wFlag)3560 #### eval FixOffsets ($valuePtr, $valEnd, $size, $tagID, $wFlag) 2437 3561 eval $$dirInfo{FixOffsets}; 2438 3562 } 3563 my $suspect; 3564 # offset shouldn't point into TIFF header 3565 $valuePtr < 8 and $suspect = $warnCount; 2439 3566 # convert offset to pointer in $$dataPt 2440 3567 if ($$dirInfo{EntryBased} or (ref $$tagTablePtr{$tagID} eq 'HASH' and 2441 $tagTablePtr->{$tagID} ->{EntryBased}))3568 $tagTablePtr->{$tagID}{EntryBased})) 2442 3569 { 2443 3570 $valuePtr += $entry; … … 2445 3572 $valuePtr -= $dataPos; 2446 3573 } 3574 # value shouldn't overlap our directory 3575 $suspect = $warnCount if $valuePtr < $dirEnd and $valuePtr+$size > $dirStart; 3576 # load value from file if necessary 2447 3577 if ($valuePtr < 0 or $valuePtr+$size > $dataLen) { 2448 3578 # get value by seeking in file if we are allowed 2449 3579 my $buff; 2450 3580 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)) 2453 3610 { 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; 2461 3616 } 3617 $valueDataPt = \$buff; 3618 $valueDataPos = $valuePtr + $dataPos; 3619 $valueDataLen = length $buff; 3620 $valuePtr = 0; 2462 3621 } else { 2463 my $tagStr;3622 my ($tagStr, $tmpInfo); 2464 3623 if ($tagInfo) { 2465 3624 $tagStr = $$tagInfo{Name}; 2466 3625 } elsif (defined $tagInfo) { 2467 my$tmpInfo = $exifTool->GetTagInfo($tagTablePtr, $tagID, \ '', $formatStr, $count);3626 $tmpInfo = $exifTool->GetTagInfo($tagTablePtr, $tagID, \ '', $formatStr, $count); 2468 3627 $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; 2469 3634 } 2470 3635 $tagStr or $tagStr = sprintf("tag 0x%x",$tagID); … … 2478 3643 $valueDataLen = $size; 2479 3644 $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 } 2480 3658 } else { 2481 $exifTool->Warn("Bad $dirName directory pointer for $tagStr"); 3659 $exifTool->Warn("Bad $name offset for $tagStr"); 3660 ++$warnCount; 2482 3661 } 2483 3662 unless (defined $buff) { … … 2490 3669 } 2491 3670 } 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 } 2492 3679 } 2493 3680 # treat single unknown byte as int8u 2494 3681 $formatStr = 'int8u' if $format == 7 and $count == 1; 2495 3682 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 } 2514 3704 } 2515 3705 } … … 2517 3707 if (defined $tagInfo and not $tagInfo) { 2518 3708 # 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); 2521 3713 } 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 } 2524 3719 if (defined $tagInfo) { 3720 $subdir = $$tagInfo{SubDirectory}; 3721 # override EXIF format if specified 2525 3722 if ($$tagInfo{Format}) { 2526 3723 $formatStr = $$tagInfo{Format}; 2527 # must adjust number of items for new format size2528 3724 my $newNum = $formatNumber{$formatStr}; 2529 if ($newNum ) {3725 if ($newNum and $newNum != $format) { 2530 3726 $origFormStr = $formatName[$format] . '[' . $count . ']'; 2531 3727 $format = $newNum; 2532 $count = $size / $formatSize[$format]; 3728 # adjust number of items for new format size 3729 $count = int($size / $formatSize[$format]); 2533 3730 } 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; 2534 3737 } 2535 3738 } else { … … 2537 3740 } 2538 3741 # convert according to specified format 2539 $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$ size);3742 $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize); 2540 3743 2541 3744 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 } 2542 3752 if ($htmlDump) { 2543 3753 my ($tagName, $colName); … … 2552 3762 # build our tool tip 2553 3763 $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"; 2556 3769 if ($size > 4) { 2557 3770 my $offPt = Get32u($dataPt,$entry+8); 2558 $tip .= sprintf("Value offset: 0x%.4x\\n", $offPt);2559 3771 my $actPt = $valuePtr + $valueDataPos + $base - ($$exifTool{EXIF_POS} || 0); 3772 $tip .= sprintf("Value offset: 0x%.4x\n", $offPt); 2560 3773 # 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'; 2562 3775 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)); 2564 3779 $style = 'F' if $style eq 'H'; # purple for different offsets 2565 3780 } 2566 3781 $colName = "<span class=$style>$tagName</span>"; 3782 $colName .= ' <span class=V>(odd)</span>' if $offPt & 0x01; 2567 3783 } else { 2568 3784 $colName = $tagName; 2569 3785 } 2570 my $tval;2571 if ($valueDataLen < 0 ) {3786 $colName .= ' <span class=V>(err)</span>' if $wrongFormat; 3787 if ($valueDataLen < 0 or not defined $tval) { 2572 3788 $tval = '<bad offset>'; 2573 3789 } else { 2574 $tval = (length $val < 32) ? $val : substr($val,0,28) . '[...]';3790 $tval = substr($tval,0,28) . '[...]' if length($tval) > 32; 2575 3791 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/./; 2580 3794 } elsif ($tagInfo and Image::ExifTool::IsInt($tval)) { 2581 if ($$tagInfo{IsOffset} ) {3795 if ($$tagInfo{IsOffset} or $$tagInfo{SubIFD}) { 2582 3796 $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 } 2583 3803 } elsif ($$tagInfo{PrintHex}) { 2584 3804 $tval = sprintf('0x%x', $tval); … … 2587 3807 } 2588 3808 $tip .= "Value: $tval"; 2589 $exifTool->H tmlDump($entry+$dataPos+$base, 12, "$dname $colName", $tip, 1);3809 $exifTool->HDump($entry+$dataPos+$base, 12, "$dname $colName", $tip, 1); 2590 3810 next if $valueDataLen < 0; # don't process bad pointer entry 2591 3811 if ($size > 4) { 2592 3812 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 } 2593 3821 # 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); 2597 3823 } 2598 3824 } else { 2599 3825 my $fstr = $formatName[$format]; 2600 $ origFormStr and $fstr = "$origFormStr read as $fstr";3826 $fstr = "$origFormStr read as $fstr" if $origFormStr; 2601 3827 $exifTool->VerboseInfo($tagID, $tagInfo, 2602 3828 Table => $tagTablePtr, 2603 3829 Index => $index, 2604 Value => $ val,3830 Value => $tval, 2605 3831 DataPt => $valueDataPt, 2606 3832 DataPos => $valueDataPos + $base, … … 2611 3837 ); 2612 3838 } 2613 next unless $tagInfo;3839 next if not $tagInfo or $wrongFormat; 2614 3840 } 3841 next unless defined $val; 2615 3842 #.............................................................................. 2616 3843 # Handle SubDirectory tag types 2617 3844 # 2618 my $subdir = $$tagInfo{SubDirectory};2619 3845 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 } 2620 3853 my (@values, $newTagTable, $dirNum, $newByteOrder, $invalid); 2621 3854 my $tagStr = $$tagInfo{Name}; … … 2691 3924 # calculate subdirectory start relative to $base for eval 2692 3925 my $start = $subdirStart + $subdirDataPos; 2693 #### eval Base ($start )3926 #### eval Base ($start,$base) 2694 3927 $subdirBase = eval($$subdir{Base}) + $base; 2695 3928 } … … 2701 3934 $exifTool->Warn("Bad $tagStr OffsetPt"); 2702 3935 last; 2703 } 3936 } 2704 3937 SetByteOrder($newByteOrder); 2705 3938 $subdirStart += Get32u($subdirDataPt, $pos); … … 2708 3941 if ($subdirStart < 0 or $subdirStart + 2 > $subdirDataLen) { 2709 3942 # convert $subdirStart back to a file offset 2710 $subdirStart += $subdirDataPos;2711 my $dirOK;2712 3943 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 { 2734 3949 my $msg = "Bad $tagStr SubDirectory start"; 2735 3950 if ($verbose > 0) { … … 2760 3975 RAF => $raf, 2761 3976 Parent => $dirName, 3977 DirName => $$subdir{DirName}, 2762 3978 FixBase => $$subdir{FixBase}, 2763 3979 FixOffsets => $$subdir{FixOffsets}, … … 2765 3981 TagInfo => $tagInfo, 2766 3982 SubIFD => $$tagInfo{SubIFD}, 3983 Subdir => $subdir, 2767 3984 ); 3985 # (remember: some cameras incorrectly write maker notes in IFD0) 2768 3986 if ($$tagInfo{MakerNotes}) { 3987 # don't parse makernotes if FastScan > 1 3988 my $fast = $exifTool->Options('FastScan'); 3989 last if $fast and $fast > 1; 2769 3990 $subdirInfo{MakerNoteAddr} = $valuePtr + $valueDataPos + $base; 2770 $subdirInfo{NoFixBase} = 1 if $$subdir{Base};3991 $subdirInfo{NoFixBase} = 1 if defined $$subdir{Base}; 2771 3992 } 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}; 2776 3998 # number multiple subdirectories 2777 $ dirNum and $subdirInfo{DirName} .=$dirNum;3999 $subdirInfo{DirName} =~ s/\d*$/$dirNum/ if $dirNum; 2778 4000 } 2779 4001 SetByteOrder($newByteOrder); # set byte order for this subdir … … 2800 4022 } 2801 4023 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}; 2803 4026 # extract as a block if specified 2804 4027 if ($$tagInfo{MakerNotes}) { 2805 4028 # save maker note byte order (if it was significant and valid) 2806 4029 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}) ? 2809 4032 $exifTool->{UnknownByteOrder} : $newByteOrder; 2810 4033 } … … 2845 4068 #.............................................................................. 2846 4069 # 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}) { 2848 4072 my $offsetBase = $$tagInfo{IsOffset} eq '2' ? $firstBase : $base; 2849 4073 $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 } 2850 4080 my @vals = split(' ',$val); 2851 4081 foreach $val (@vals) { … … 2856 4086 # save the value of this tag 2857 4087 $tagKey = $exifTool->FoundTag($tagInfo, $val); 2858 # set the group 1 name for tags in main table2859 if (defined $tagKey and $ tagTablePtr eq \%Image::ExifTool::Exif::Main) {2860 $exifTool->SetGroup 1($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); 2861 4091 } 2862 4092 } … … 2873 4103 $newDirInfo{DirStart} = $subdirStart; 2874 4104 # 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; 2877 4107 # must validate SubIFD1 because the nextIFD pointer is invalid for some RAW formats 2878 4108 if ($newDirInfo{DirName} ne 'SubIFD1' or ValidateIFD(\%newDirInfo)) { 2879 4109 $exifTool->{INDENT} =~ s/..$//; # keep indent the same 4110 my $cur = pop @{$$exifTool{PATH}}; 2880 4111 $exifTool->ProcessDirectory(\%newDirInfo, $tagTablePtr) or $success = 0; 4112 push @{$$exifTool{PATH}}, $cur; 2881 4113 } elsif ($verbose or $exifTool->{TIFF_TYPE} eq 'TIFF') { 2882 4114 $exifTool->Warn('Ignored bad IFD linked from SubIFD'); … … 2893 4125 =head1 NAME 2894 4126 2895 Image::ExifTool::Exif - Read EXIF meta information4127 Image::ExifTool::Exif - Read EXIF/TIFF meta information 2896 4128 2897 4129 =head1 SYNOPSIS … … 2902 4134 2903 4135 This module contains routines required by Image::ExifTool for processing 2904 EXIF meta information.4136 EXIF and TIFF meta information. 2905 4137 2906 4138 =head1 AUTHOR 2907 4139 2908 Copyright 2003-20 07, Phil Harvey (phil at owl.phy.queensu.ca)4140 Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca) 2909 4141 2910 4142 This library is free software; you can redistribute it and/or modify it … … 2917 4149 =item L<http://www.exif.org/Exif2-2.PDF> 2918 4150 4151 =item L<http://www.cipa.jp/english/hyoujunka/kikaku/pdf/DC-008-2010_E.pdf> 4152 2919 4153 =item L<http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf> 2920 4154 … … 2927 4161 =item L<http://www.remotesensing.org/libtiff/TIFFTechNote2.html> 2928 4162 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 2929 4175 =item L<http://www.asmail.be/msg0054681802.html> 2930 4176 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> 2940 4186 2941 4187 =back … … 2943 4189 =head1 ACKNOWLEDGEMENTS 2944 4190 2945 Thanks to Matt Madrid for his help with the XP character code conversions. 4191 Thanks to Jeremy Brown for the 35efl tags, and Matt Madrid for his help with 4192 the XP character code conversions. 2946 4193 2947 4194 =head1 SEE ALSO
Note:
See TracChangeset
for help on using the changeset viewer.