1#------------------------------------------------------------------------------ 2# File: MakerNotes.pm 3# 4# Description: Read and write EXIF maker notes 5# 6# Revisions: 11/11/2004 - P. Harvey Created 7#------------------------------------------------------------------------------ 8 9package Image::ExifTool::MakerNotes; 10 11use strict; 12use vars qw($VERSION); 13use Image::ExifTool qw(:DataAccess); 14use Image::ExifTool::Exif; 15 16sub ProcessUnknown($$$); 17sub ProcessUnknownOrPreview($$$); 18sub ProcessCanon($$$); 19sub ProcessGE2($$$); 20sub ProcessKodakPatch($$$); 21sub WriteUnknownOrPreview($$$); 22sub FixLeicaBase($$;$); 23 24$VERSION = '2.10'; 25 26my $debug; # set to 1 to enable debugging code 27 28# conditional list of maker notes 29# Notes: 30# - This is NOT a normal tag table! 31# - All byte orders are now specified because we can now 32# write maker notes into a file with different byte ordering! 33# - Put these in alphabetical order to make TagNames documentation nicer. 34@Image::ExifTool::MakerNotes::Main = ( 35 # decide which MakerNotes to use (based on makernote header and camera make/model) 36 { 37 Name => 'MakerNoteApple', 38 Condition => '$$valPt =~ /^Apple iOS\0/', 39 SubDirectory => { 40 TagTable => 'Image::ExifTool::Apple::Main', 41 Start => '$valuePtr + 14', 42 Base => '$start - 14', 43 ByteOrder => 'Unknown', 44 }, 45 }, 46 { 47 # this maker notes starts with a standard TIFF header at offset 0x0a 48 # (must check Nikon signature first because Nikon Capture NX can generate 49 # NEF images containing Nikon maker notes from JPEG images of any camera model) 50 Name => 'MakerNoteNikon', 51 Condition => '$$valPt=~/^Nikon\x00\x02/', 52 SubDirectory => { 53 TagTable => 'Image::ExifTool::Nikon::Main', 54 Start => '$valuePtr + 18', 55 Base => '$start - 8', 56 ByteOrder => 'Unknown', 57 }, 58 }, 59 { 60 Name => 'MakerNoteCanon', 61 # (starts with an IFD) 62 Condition => '$$self{Make} =~ /^Canon/', 63 SubDirectory => { 64 TagTable => 'Image::ExifTool::Canon::Main', 65 ProcessProc => \&ProcessCanon, 66 ByteOrder => 'Unknown', 67 }, 68 }, 69 { 70 Name => 'MakerNoteCasio', 71 # do negative lookahead assertion just to get tags 72 # in a nice order for documentation 73 # (starts with an IFD) 74 Condition => '$$self{Make}=~/^CASIO/ and $$valPt!~/^(QVC|DCI)\0/', 75 SubDirectory => { 76 TagTable => 'Image::ExifTool::Casio::Main', 77 ByteOrder => 'Unknown', 78 }, 79 }, 80 { 81 Name => 'MakerNoteCasio2', 82 # (starts with "QVC\0" [Casio] or "DCI\0" [Concord]) 83 # (also found in AVI and MOV videos) 84 Condition => '$$valPt =~ /^(QVC|DCI)\0/', 85 SubDirectory => { 86 TagTable => 'Image::ExifTool::Casio::Type2', 87 Start => '$valuePtr + 6', 88 ByteOrder => 'Unknown', 89 FixBase => 1, # necessary for AVI and MOV videos 90 }, 91 }, 92 { 93 Name => 'MakerNoteDJI', 94 Condition => '$$self{Make} eq "DJI" and $$valPt !~ /^...\@AMBA/s', 95 SubDirectory => { 96 TagTable => 'Image::ExifTool::DJI::Main', 97 Start => '$valuePtr', 98 ByteOrder => 'Unknown', 99 }, 100 }, 101 { 102 Name => 'MakerNoteFLIR', 103 # (starts with IFD, Make is 'FLIR Systems AB' or 'FLIR Systems') 104 Condition => '$$self{Make} =~ /^FLIR Systems/', 105 SubDirectory => { 106 TagTable => 'Image::ExifTool::FLIR::Main', 107 Start => '$valuePtr', 108 ByteOrder => 'Unknown', 109 }, 110 }, 111 { 112 # The Fuji maker notes use a structure similar to a self-contained 113 # TIFF file, but with "FUJIFILM" instead of the standard TIFF header 114 Name => 'MakerNoteFujiFilm', 115 # (starts with "FUJIFILM" -- also used by some Leica, Minolta and Sharp models) 116 # (GE FujiFilm models start with "GENERALE") 117 Condition => '$$valPt =~ /^(FUJIFILM|GENERALE)/', 118 SubDirectory => { 119 TagTable => 'Image::ExifTool::FujiFilm::Main', 120 # there is an 8-byte maker tag (FUJIFILM) we must skip over 121 OffsetPt => '$valuePtr+8', 122 # the pointers are relative to the subdirectory start 123 # (before adding the offsetPt) - PH 124 Base => '$start', 125 ByteOrder => 'LittleEndian', 126 }, 127 }, 128 { 129 Name => 'MakerNoteGE', 130 Condition => '$$valPt =~ /^GE(\0\0|NIC\0)/', 131 SubDirectory => { 132 TagTable => 'Image::ExifTool::GE::Main', 133 Start => '$valuePtr + 18', 134 FixBase => 1, 135 AutoFix => 1, 136 ByteOrder => 'Unknown', 137 }, 138 }, 139 { 140 Name => 'MakerNoteGE2', 141 Condition => '$$valPt =~ /^GE\x0c\0\0\0\x16\0\0\0/', 142 # Note: we will get a "Maker notes could not be parsed" warning when writing 143 # these maker notes because they aren't currently supported for writing 144 SubDirectory => { 145 TagTable => 'Image::ExifTool::FujiFilm::Main', 146 ProcessProc => \&ProcessGE2, 147 Start => '$valuePtr + 12', 148 Base => '$start - 6', 149 ByteOrder => 'LittleEndian', 150 # hard patch for crazy offsets 151 FixOffsets => '$valuePtr -= 210 if $tagID >= 0x1303', 152 }, 153 }, 154 { 155 Name => 'MakerNoteHasselblad', 156 Condition => '$$self{Make} eq "Hasselblad"', 157 SubDirectory => { 158 TagTable => 'Image::ExifTool::Unknown::Main', 159 ByteOrder => 'Unknown', 160 Start => '$valuePtr', 161 Base => 0, # (avoids warnings since maker notes are not self-contained) 162 }, 163 # 0x0011 - sensor code (ref IB) 164 # 0x0012 - camera model id? 165 # 0x0015 - camera model name 166 # 0x0016 - coating code (ref IB) 167 }, 168 # (the GE X5 has really messed up EXIF-like maker notes starting with 169 # "GENIC\x0c\0" --> currently not decoded) 170 { 171 Name => 'MakerNoteHP', # PhotoSmart 720 (also Vivitar 3705, 3705B and 3715) 172 Condition => '$$valPt =~ /^(Hewlett-Packard|Vivitar)/', 173 SubDirectory => { 174 TagTable => 'Image::ExifTool::HP::Main', 175 ProcessProc => \&ProcessUnknown, 176 ByteOrder => 'Unknown', 177 }, 178 }, 179 { 180 Name => 'MakerNoteHP2', # PhotoSmart E427 181 # (this type of maker note also used by BenQ, Mustek, Sanyo, Traveler and Vivitar) 182 Condition => '$$valPt =~ /^610[\0-\4]/', 183 NotIFD => 1, 184 SubDirectory => { 185 TagTable => 'Image::ExifTool::HP::Type2', 186 Start => '$valuePtr', 187 ByteOrder => 'LittleEndian', 188 }, 189 }, 190 { 191 Name => 'MakerNoteHP4', # PhotoSmart M627 192 Condition => '$$valPt =~ /^IIII\x04\0/', 193 NotIFD => 1, 194 SubDirectory => { 195 TagTable => 'Image::ExifTool::HP::Type4', 196 Start => '$valuePtr', 197 ByteOrder => 'LittleEndian', 198 }, 199 }, 200 { 201 Name => 'MakerNoteHP6', # PhotoSmart M425, M525 and M527 202 Condition => '$$valPt =~ /^IIII\x06\0/', 203 NotIFD => 1, 204 SubDirectory => { 205 TagTable => 'Image::ExifTool::HP::Type6', 206 Start => '$valuePtr', 207 ByteOrder => 'LittleEndian', 208 }, 209 }, 210 { 211 Name => 'MakerNoteISL', # (used in Samsung GX20 samples) 212 Condition => '$$valPt =~ /^ISLMAKERNOTE000\0/', 213 # this maker notes starts with a TIFF-like header at offset 0x10 214 SubDirectory => { 215 TagTable => 'Image::ExifTool::Unknown::Main', 216 Start => '$valuePtr + 24', 217 Base => '$start - 8', 218 ByteOrder => 'Unknown', 219 }, 220 }, 221 { 222 Name => 'MakerNoteJVC', 223 Condition => '$$valPt=~/^JVC /', 224 SubDirectory => { 225 TagTable => 'Image::ExifTool::JVC::Main', 226 Start => '$valuePtr + 4', 227 ByteOrder => 'Unknown', 228 }, 229 }, 230 { 231 Name => 'MakerNoteJVCText', 232 Condition => '$$self{Make}=~/^(JVC|Victor)/ and $$valPt=~/^VER:/', 233 NotIFD => 1, 234 SubDirectory => { 235 TagTable => 'Image::ExifTool::JVC::Text', 236 }, 237 }, 238 { 239 Name => 'MakerNoteKodak1a', 240 Condition => '$$self{Make}=~/^EASTMAN KODAK/ and $$valPt=~/^KDK INFO/', 241 NotIFD => 1, 242 SubDirectory => { 243 TagTable => 'Image::ExifTool::Kodak::Main', 244 Start => '$valuePtr + 8', 245 ByteOrder => 'BigEndian', 246 }, 247 }, 248 { 249 Name => 'MakerNoteKodak1b', 250 Condition => '$$self{Make}=~/^EASTMAN KODAK/ and $$valPt=~/^KDK/', 251 NotIFD => 1, 252 SubDirectory => { 253 TagTable => 'Image::ExifTool::Kodak::Main', 254 Start => '$valuePtr + 8', 255 ByteOrder => 'LittleEndian', 256 }, 257 }, 258 { 259 # used by various Kodak, HP, Pentax and Minolta models 260 Name => 'MakerNoteKodak2', 261 Condition => q{ 262 $$valPt =~ /^.{8}Eastman Kodak/s or 263 $$valPt =~ /^\x01\0[\0\x01]\0\0\0\x04\0[a-zA-Z]{4}/ 264 }, 265 NotIFD => 1, 266 SubDirectory => { 267 TagTable => 'Image::ExifTool::Kodak::Type2', 268 ByteOrder => 'BigEndian', 269 }, 270 }, 271 { 272 # not much to key on here, but we know the 273 # upper byte of the year should be 0x07: 274 Name => 'MakerNoteKodak3', 275 Condition => q{ 276 $$self{Make} =~ /^EASTMAN KODAK/ and 277 $$valPt =~ /^(?!MM|II).{12}\x07/s and 278 $$valPt !~ /^(MM|II|AOC)/ 279 }, 280 NotIFD => 1, 281 SubDirectory => { 282 TagTable => 'Image::ExifTool::Kodak::Type3', 283 ByteOrder => 'BigEndian', 284 }, 285 }, 286 { 287 Name => 'MakerNoteKodak4', 288 Condition => q{ 289 $$self{Make} =~ /^Eastman Kodak/ and 290 $$valPt =~ /^.{41}JPG/s and 291 $$valPt !~ /^(MM|II|AOC)/ 292 }, 293 NotIFD => 1, 294 SubDirectory => { 295 TagTable => 'Image::ExifTool::Kodak::Type4', 296 ByteOrder => 'BigEndian', 297 }, 298 }, 299 { 300 Name => 'MakerNoteKodak5', 301 Condition => q{ 302 $$self{Make}=~/^EASTMAN KODAK/ and 303 ($$self{Model}=~/CX(4200|4230|4300|4310|6200|6230)/ or 304 # try to pick up similar models we haven't tested yet 305 $$valPt=~/^\0(\x1a\x18|\x3a\x08|\x59\xf8|\x14\x80)\0/) 306 }, 307 NotIFD => 1, 308 SubDirectory => { 309 TagTable => 'Image::ExifTool::Kodak::Type5', 310 ByteOrder => 'BigEndian', 311 }, 312 }, 313 { 314 Name => 'MakerNoteKodak6a', 315 Condition => q{ 316 $$self{Make}=~/^EASTMAN KODAK/ and 317 $$self{Model}=~/DX3215/ 318 }, 319 NotIFD => 1, 320 SubDirectory => { 321 TagTable => 'Image::ExifTool::Kodak::Type6', 322 ByteOrder => 'BigEndian', 323 }, 324 }, 325 { 326 Name => 'MakerNoteKodak6b', 327 Condition => q{ 328 $$self{Make}=~/^EASTMAN KODAK/ and 329 $$self{Model}=~/DX3700/ 330 }, 331 NotIFD => 1, 332 SubDirectory => { 333 TagTable => 'Image::ExifTool::Kodak::Type6', 334 ByteOrder => 'LittleEndian', 335 }, 336 }, 337 { 338 Name => 'MakerNoteKodak7', 339 # look for something that looks like a serial number 340 # (confirmed serial numbers have the format KXXXX########, but we also 341 # accept other strings from sample images that may be serial numbers) 342 Condition => q{ 343 $$self{Make}=~/Kodak/i and 344 $$valPt =~ /^[CK][A-Z\d]{3} ?[A-Z\d]{1,2}\d{2}[A-Z\d]\d{4}[ \0]/ 345 }, 346 NotIFD => 1, 347 SubDirectory => { 348 TagTable => 'Image::ExifTool::Kodak::Type7', 349 ByteOrder => 'LittleEndian', 350 }, 351 }, 352 { 353 Name => 'MakerNoteKodak8a', 354 # IFD-format maker notes: look for reasonable number of 355 # entries and check format and count of first IFD entry 356 Condition => q{ 357 $$self{Make}=~/Kodak/i and 358 ($$valPt =~ /^\0[\x02-\x7f]..\0[\x01-\x0c]\0\0/s or 359 $$valPt =~ /^[\x02-\x7f]\0..[\x01-\x0c]\0..\0\0/s) 360 }, 361 SubDirectory => { 362 TagTable => 'Image::ExifTool::Kodak::Type8', 363 ProcessProc => \&ProcessUnknown, 364 ByteOrder => 'Unknown', 365 }, 366 }, 367 { 368 Name => 'MakerNoteKodak8b', 369 # these maker notes have an extra 2 bytes after the entry count 370 # (this is handled by the patch). Also, the IFD uses a Format 13, 371 # which is some 2-byte format (not Float, as decoded by ExifTool) 372 # - written by the PixPro AZ251, AZ361, AZ262, AZ521 373 Condition => q{ 374 $$self{Make}=~/Kodak/i and 375 $$valPt =~ /^MM\0\x2a\0\0\0\x08\0.\0\0/ 376 }, 377 SubDirectory => { 378 TagTable => 'Image::ExifTool::Kodak::Type8', 379 ProcessProc => \&ProcessKodakPatch, 380 ByteOrder => 'BigEndian', 381 Start => '$valuePtr + 8', 382 Base => '$start - 8', 383 }, 384 }, 385 { 386 Name => 'MakerNoteKodak8c', 387 # TIFF-format maker notes 388 Condition => q{ 389 $$self{Make}=~/Kodak/i and 390 $$valPt =~ /^(MM\0\x2a\0\0\0\x08|II\x2a\0\x08\0\0\0)/ 391 }, 392 SubDirectory => { 393 TagTable => 'Image::ExifTool::Kodak::Type8', 394 ProcessProc => \&ProcessUnknown, 395 ByteOrder => 'Unknown', 396 Start => '$valuePtr + 8', 397 Base => '$start - 8', 398 }, 399 }, 400 { 401 Name => 'MakerNoteKodak9', 402 # test header and Kodak:DateTimeOriginal 403 Condition => '$$valPt =~ m{^IIII[\x02\x03]\0.{14}\d{4}/\d{2}/\d{2} }s', 404 NotIFD => 1, 405 SubDirectory => { 406 TagTable => 'Image::ExifTool::Kodak::Type9', 407 ByteOrder => 'LittleEndian', 408 }, 409 }, 410 { 411 Name => 'MakerNoteKodak10', 412 # yet another type of Kodak IFD-format maker notes: 413 # this type begins with a byte order indicator, 414 # followed immediately by the IFD 415 Condition => q{ 416 $$self{Make}=~/Kodak/i and 417 $$valPt =~ /^(MM\0[\x02-\x7f]|II[\x02-\x7f]\0)/ 418 }, 419 SubDirectory => { 420 TagTable => 'Image::ExifTool::Kodak::Type10', 421 ProcessProc => \&ProcessUnknown, 422 ByteOrder => 'Unknown', 423 Start => '$valuePtr + 2', 424 }, 425 }, 426 { 427 Name => 'MakerNoteKodak11', 428 # these maker notes have a 4-byte entry count 429 # - written by the PixPro S-1 (Note: Make is "JK Imaging, Ltd.", so check Model for "Kodak") 430 Condition => q{ 431 $$self{Model}=~/(Kodak|PixPro)/i and 432 $$valPt =~ /^II\x2a\0\x08\0\0\0.\0\0\0/s 433 }, 434 SubDirectory => { 435 TagTable => 'Image::ExifTool::Kodak::Type11', 436 ProcessProc => \&ProcessKodakPatch, 437 ByteOrder => 'LittleEndian', 438 Start => '$valuePtr + 8', 439 Base => '$start - 8', 440 }, 441 }, 442 { 443 Name => 'MakerNoteKodak12', 444 # these maker notes have a 4-byte entry count 445 # - written by the PixPro AZ901 (Note: Make is "JK Imaging, Ltd.", so check Model for "Kodak") 446 Condition => q{ 447 $$self{Model}=~/(Kodak|PixPro)/i and 448 $$valPt =~ /^MM\0\x2a\0\0\0\x08\0\0\0./s 449 }, 450 SubDirectory => { 451 TagTable => 'Image::ExifTool::Kodak::Type11', 452 ProcessProc => \&ProcessKodakPatch, 453 ByteOrder => 'BigEndian', 454 Start => '$valuePtr + 8', 455 Base => '$start - 8', 456 }, 457 }, 458 { 459 Name => 'MakerNoteKodakUnknown', 460 Condition => '$$self{Make}=~/Kodak/i and $$valPt!~/^AOC\0/', 461 NotIFD => 1, 462 SubDirectory => { 463 TagTable => 'Image::ExifTool::Kodak::Unknown', 464 ByteOrder => 'BigEndian', 465 }, 466 }, 467 { 468 Name => 'MakerNoteKyocera', 469 # (starts with "KYOCERA") 470 Condition => '$$valPt =~ /^KYOCERA/', 471 SubDirectory => { 472 TagTable => 'Image::ExifTool::Unknown::Main', 473 Start => '$valuePtr + 22', 474 Base => '$start + 2', 475 EntryBased => 1, 476 ByteOrder => 'Unknown', 477 }, 478 }, 479 { 480 Name => 'MakerNoteMinolta', 481 Condition => q{ 482 $$self{Make}=~/^(Konica Minolta|Minolta)/i and 483 $$valPt !~ /^(MINOL|CAMER|MLY0|KC|\+M\+M|\xd7)/ 484 }, 485 SubDirectory => { 486 TagTable => 'Image::ExifTool::Minolta::Main', 487 ByteOrder => 'Unknown', 488 }, 489 }, 490 { 491 # the DiMAGE E323 (MINOL) and E500 (CAMER), and some models 492 # of Mustek, Pentax, Ricoh and Vivitar (CAMER). 493 Name => 'MakerNoteMinolta2', 494 Condition => '$$valPt =~ /^(MINOL|CAMER)\0/ and $$self{OlympusCAMER} = 1', 495 SubDirectory => { 496 # these models use Olympus tags in the range 0x200-0x221 plus 0xf00 497 TagTable => 'Image::ExifTool::Olympus::Main', 498 Start => '$valuePtr + 8', 499 ByteOrder => 'Unknown', 500 }, 501 }, 502 { 503 # /^MLY0/ - DiMAGE G400, G500, G530, G600 504 # /^KC/ - Revio KD-420Z, DiMAGE E203 505 # /^+M+M/ - DiMAGE E201 506 # /^\xd7/ - DiMAGE RD3000 507 Name => 'MakerNoteMinolta3', 508 Condition => '$$self{Make} =~ /^(Konica Minolta|Minolta)/i', 509 Binary => 1, 510 Notes => 'not EXIF-based', 511 }, 512 { 513 Name => 'MakerNoteMotorola', 514 Condition => '$$valPt=~/^MOT\0/', 515 SubDirectory => { 516 TagTable => 'Image::ExifTool::Motorola::Main', 517 Start => '$valuePtr + 8', 518 Base => '$start - 8', 519 ByteOrder => 'Unknown', 520 }, 521 }, 522 { 523 # older Nikon maker notes 524 Name => 'MakerNoteNikon2', 525 Condition => '$$valPt=~/^Nikon\x00\x01/', 526 SubDirectory => { 527 TagTable => 'Image::ExifTool::Nikon::Type2', 528 Start => '$valuePtr + 8', 529 ByteOrder => 'LittleEndian', 530 }, 531 }, 532 { 533 # headerless Nikon maker notes 534 Name => 'MakerNoteNikon3', 535 Condition => '$$self{Make}=~/^NIKON/i', 536 SubDirectory => { 537 TagTable => 'Image::ExifTool::Nikon::Main', 538 ByteOrder => 'Unknown', # most are little-endian, but D1 is big 539 }, 540 }, 541 { 542 Name => 'MakerNoteNintendo', 543 # (starts with an IFD) 544 Condition => '$$self{Make} eq "Nintendo"', 545 SubDirectory => { 546 TagTable => 'Image::ExifTool::Nintendo::Main', 547 ByteOrder => 'Unknown', 548 }, 549 }, 550 { 551 Name => 'MakerNoteOlympus', 552 # (if Make is 'SEIKO EPSON CORP.', starts with "EPSON\0") 553 # (if Make is 'OLYMPUS OPTICAL CO.,LTD' or 'OLYMPUS CORPORATION', 554 # starts with "OLYMP\0") 555 Condition => '$$valPt =~ /^(OLYMP|EPSON)\0/', 556 SubDirectory => { 557 TagTable => 'Image::ExifTool::Olympus::Main', 558 Start => '$valuePtr + 8', 559 ByteOrder => 'Unknown', 560 }, 561 }, 562 { 563 Name => 'MakerNoteOlympus2', 564 # new Olympus maker notes start with "OLYMPUS\0" 565 Condition => '$$valPt =~ /^OLYMPUS\0/', 566 SubDirectory => { 567 TagTable => 'Image::ExifTool::Olympus::Main', 568 Start => '$valuePtr + 12', 569 Base => '$start - 12', 570 ByteOrder => 'Unknown', 571 }, 572 }, 573 { 574 Name => 'MakerNoteLeica', 575 # (starts with "LEICA\0\0\0") 576 Condition => '$$self{Make} eq "LEICA"', 577 SubDirectory => { 578 # many Leica models use the same format as Panasonic 579 TagTable => 'Image::ExifTool::Panasonic::Main', 580 Start => '$valuePtr + 8', 581 ByteOrder => 'Unknown', 582 }, 583 }, 584 { 585 Name => 'MakerNoteLeica2', # used by the M8 586 # (starts with "LEICA\0\0\0") 587 Condition => '$$self{Make} =~ /^Leica Camera AG/ and $$valPt =~ /^LEICA\0\0\0/', 588 SubDirectory => { 589 TagTable => 'Image::ExifTool::Panasonic::Leica2', 590 # (the offset base is different in JPEG and DNG images, but we 591 # can copy makernotes from one to the other, so we need special 592 # logic to decide which base to apply) 593 ProcessProc => \&FixLeicaBase, 594 Start => '$valuePtr + 8', 595 Base => '$start', # (- 8 for DNG images!) 596 ByteOrder => 'Unknown', 597 }, 598 }, 599 { 600 Name => 'MakerNoteLeica3', # used by the R8 and R9 601 # (starts with IFD) 602 Condition => q{ 603 $$self{Make} =~ /^Leica Camera AG/ and $$valPt !~ /^LEICA/ and 604 $$self{Model} ne "S2" and $$self{Model} ne "LEICA M (Typ 240)" 605 }, 606 SubDirectory => { 607 TagTable => 'Image::ExifTool::Panasonic::Leica3', 608 Start => '$valuePtr', 609 ByteOrder => 'Unknown', 610 }, 611 }, 612 { 613 Name => 'MakerNoteLeica4', # used by the M9/M-Monochrom 614 # (M9 and M Monochrom start with "LEICA0\x03\0") 615 Condition => '$$self{Make} =~ /^Leica Camera AG/ and $$valPt =~ /^LEICA0/', 616 SubDirectory => { 617 TagTable => 'Image::ExifTool::Panasonic::Leica4', 618 Start => '$valuePtr + 8', 619 Base => '$start - 8', # (yay! Leica fixed the M8 problem) 620 ByteOrder => 'Unknown', 621 }, 622 }, 623 { 624 Name => 'MakerNoteLeica5', # used by the X1/X2/X VARIO/T/X-U 625 # (X1 starts with "LEICA\0\x01\0", Make is "LEICA CAMERA AG") 626 # (X2 starts with "LEICA\0\x05\0", Make is "LEICA CAMERA AG") 627 # (X VARIO starts with "LEICA\0\x04\0", Make is "LEICA CAMERA AG") 628 # (T (Typ 701) starts with "LEICA\0\0x6", Make is "LEICA CAMERA AG") 629 # (X (Typ 113) starts with "LEICA\0\0x7", Make is "LEICA CAMERA AG") 630 # (X-U (Typ 113) starts with "LEICA\0\x10\0", Make is "LEICA CAMERA AG") 631 Condition => '$$valPt =~ /^LEICA\0[\x01\x04\x05\x06\x07\x10\x1a]\0/', 632 SubDirectory => { 633 TagTable => 'Image::ExifTool::Panasonic::Leica5', 634 Start => '$valuePtr + 8', 635 Base => '$start - 8', 636 ByteOrder => 'Unknown', 637 }, 638 }, 639 { 640 Name => 'MakerNoteLeica6', # used by the S2, M (Typ 240) and S (Typ 006) 641 # (starts with "LEICA\0\x02\xff", Make is "Leica Camera AG", but test the 642 # model names separately because the maker notes data may not be loaded 643 # at the time this is tested if they are in a JPEG trailer. Also, this 644 # header is used by the M Monochrom (Type 246), with different offsets.) 645 Condition => q{ 646 ($$self{Make} eq 'Leica Camera AG' and ($$self{Model} eq 'S2' or 647 $$self{Model} eq 'LEICA M (Typ 240)' or $$self{Model} eq 'LEICA S (Typ 006)')) 648 }, 649 DataTag => 'LeicaTrailer', # (generates fixup name for this tag) 650 LeicaTrailer => 1, # flag to special-case this tag in the Exif code 651 SubDirectory => { 652 TagTable => 'Image::ExifTool::Panasonic::Leica6', 653 Start => '$valuePtr + 8', 654 ByteOrder => 'Unknown', 655 # NOTE: Leica uses absolute file offsets when this maker note is stored 656 # as a JPEG trailer -- this case is handled by ProcessLeicaTrailer in 657 # Panasonic.pm, and any "Base" defined here is ignored for this case. 658 # ExifTool may also create S2/M maker notes inside the APP1 segment when 659 # copying from other files, and for this the normal EXIF offsets are used, 660 # Base should not be defined! 661 }, 662 }, 663 { 664 Name => 'MakerNoteLeica7', # used by the M Monochrom (Typ 246) 665 # (starts with "LEICA\0\x02\xff", Make is "Leica Camera AG") 666 Condition => '$$valPt =~ /^LEICA\0\x02\xff/', 667 DataTag => 'LeicaTrailer', # (generates fixup name for this tag) 668 LeicaTrailer => 1, # flag to special-case this tag in the Exif code 669 SubDirectory => { 670 TagTable => 'Image::ExifTool::Panasonic::Leica6', 671 Start => '$valuePtr + 8', 672 ByteOrder => 'Unknown', 673 Base => '-$base', # uses absolute file offsets (not based on TIFF header offset) 674 }, 675 }, 676 { 677 Name => 'MakerNoteLeica8', # used by the Q (Type 116) 678 # (Q (Typ 116) starts with "LEICA\0\x08\0", Make is "LEICA CAMERA AG") 679 # (SL (Typ 601) and CL start with "LEICA\0\x09\0", Make is "LEICA CAMERA AG") 680 Condition => '$$valPt =~ /^LEICA\0[\x08\x09]\0/', 681 SubDirectory => { 682 TagTable => 'Image::ExifTool::Panasonic::Leica5', 683 Start => '$valuePtr + 8', 684 ByteOrder => 'Unknown', 685 }, 686 }, 687 { 688 Name => 'MakerNoteLeica9', # used by the M10/S 689 # (M10 and S start with "LEICA0\x02\0") 690 Condition => '$$self{Make} =~ /^Leica Camera AG/ and $$valPt =~ /^LEICA\0\x02\0/', 691 SubDirectory => { 692 TagTable => 'Image::ExifTool::Panasonic::Leica9', 693 Start => '$valuePtr + 8', 694 ByteOrder => 'Unknown', 695 }, 696 }, 697 { 698 Name => 'MakerNoteLeica10', # used by the D-Lux7 699 Condition => '$$valPt =~ /^LEICA CAMERA AG\0/', 700 SubDirectory => { 701 TagTable => 'Image::ExifTool::Panasonic::Main', 702 Start => '$valuePtr + 18', 703 ByteOrder => 'Unknown', 704 }, 705 }, 706 { 707 Name => 'MakerNotePanasonic', 708 # (starts with "Panasonic\0") 709 Condition => '$$valPt=~/^Panasonic/ and $$self{Model} ne "DC-FT7"', 710 SubDirectory => { 711 TagTable => 'Image::ExifTool::Panasonic::Main', 712 Start => '$valuePtr + 12', 713 ByteOrder => 'Unknown', 714 }, 715 }, 716 { 717 Name => 'MakerNotePanasonic2', 718 # (starts with "Panasonic\0") 719 Condition => '$$self{Make}=~/^Panasonic/ and $$valPt=~/^MKE/', 720 SubDirectory => { 721 TagTable => 'Image::ExifTool::Panasonic::Type2', 722 ByteOrder => 'LittleEndian', 723 }, 724 }, 725 { 726 Name => 'MakerNotePanasonic3', # (DC-FT7) 727 # (starts with "Panasonic\0") 728 Condition => '$$valPt=~/^Panasonic/', 729 SubDirectory => { 730 TagTable => 'Image::ExifTool::Panasonic::Main', 731 Start => '$valuePtr + 12', 732 Base => 12, # crazy! 733 ByteOrder => 'Unknown', 734 }, 735 }, 736 { 737 Name => 'MakerNotePentax', 738 # (starts with "AOC\0", but so does MakerNotePentax3) 739 # (also used by some Samsung models) 740 Condition => q{ 741 $$valPt=~/^AOC\0/ and 742 $$self{Model} !~ /^PENTAX Optio ?[34]30RS\s*$/ 743 }, 744 SubDirectory => { 745 TagTable => 'Image::ExifTool::Pentax::Main', 746 # process as Unknown maker notes because the start offset and 747 # byte ordering are so variable 748 ProcessProc => \&ProcessUnknown, 749 # offsets can be totally whacky for Pentax maker notes, 750 # so attempt to fix the offset base if possible 751 FixBase => 1, 752 ByteOrder => 'Unknown', 753 }, 754 }, 755 { 756 Name => 'MakerNotePentax2', 757 # (starts with an IFD) 758 # Casio-like maker notes used only by the Optio 330 and 430 759 Condition => '$$self{Make}=~/^Asahi/ and $$valPt!~/^AOC\0/', 760 SubDirectory => { 761 TagTable => 'Image::ExifTool::Pentax::Type2', 762 ProcessProc => \&ProcessUnknown, 763 FixBase => 1, 764 ByteOrder => 'Unknown', 765 }, 766 }, 767 { 768 Name => 'MakerNotePentax3', 769 # (starts with "AOC\0", like the more common Pentax maker notes) 770 # Casio maker notes used only by the Optio 330RS and 430RS 771 Condition => '$$self{Make}=~/^Asahi/', 772 SubDirectory => { 773 TagTable => 'Image::ExifTool::Casio::Type2', 774 ProcessProc => \&ProcessUnknown, 775 FixBase => 1, 776 ByteOrder => 'Unknown', 777 }, 778 }, 779 { 780 Name => 'MakerNotePentax4', 781 # (starts with 3 or 4 digits) 782 # HP2-like text-based maker notes used by Optio E20 783 Condition => '$$self{Make}=~/^PENTAX/ and $$valPt=~/^\d{3}/', 784 NotIFD => 1, 785 SubDirectory => { 786 TagTable => 'Image::ExifTool::Pentax::Type4', 787 Start => '$valuePtr', 788 ByteOrder => 'LittleEndian', 789 }, 790 }, 791 { 792 Name => 'MakerNotePentax5', 793 # (starts with "PENTAX \0") 794 # used by cameras such as the Q, Optio S1, RS1500 and WG-1 795 Condition => '$$valPt=~/^PENTAX \0/', 796 SubDirectory => { 797 TagTable => 'Image::ExifTool::Pentax::Main', 798 Start => '$valuePtr + 10', 799 Base => '$start - 10', 800 ByteOrder => 'Unknown', 801 }, 802 }, 803 { 804 Name => 'MakerNotePentax6', 805 # (starts with "S1\0\0\0\0\0\0\x0c\0\0\0") 806 Condition => '$$valPt=~/^S1\0{6}\x0c\0{3}/', 807 SubDirectory => { 808 TagTable => 'Image::ExifTool::Pentax::S1', 809 Start => '$valuePtr + 12', 810 Base => '$start - 12', 811 ByteOrder => 'Unknown', 812 }, 813 }, 814 { 815 Name => 'MakerNotePhaseOne', 816 # Starts with: 'IIIITwaR' or 'IIIICwaR' (have seen both written by P25) 817 # (have also seen code which expects 'MMMMRawT') 818 Condition => q{ 819 return undef unless $$valPt =~ /^(IIII.waR|MMMMRaw.)/s; 820 $self->OverrideFileType($$self{TIFF_TYPE} = 'IIQ') if $count > 1000000; 821 return 1; 822 }, 823 NotIFD => 1, 824 IsPhaseOne => 1, # flag to rebuild these differently 825 SubDirectory => { TagTable => 'Image::ExifTool::PhaseOne::Main' }, 826 PutFirst => 1, # place immediately after TIFF header 827 }, 828 { 829 Name => 'MakerNoteReconyx', 830 Condition => q{ 831 $$valPt =~ /^\x01\xf1([\x02\x03]\x00)?/ and 832 ($1 or $$self{Make} eq "RECONYX") 833 }, 834 SubDirectory => { 835 TagTable => 'Image::ExifTool::Reconyx::Main', 836 ByteOrder => 'Little-endian', 837 }, 838 }, 839 { 840 Name => 'MakerNoteReconyx2', 841 Condition => '$$valPt =~ /^RECONYXUF\0/', 842 SubDirectory => { 843 TagTable => 'Image::ExifTool::Reconyx::Type2', 844 ByteOrder => 'Little-endian', 845 }, 846 }, 847 { 848 Name => 'MakerNoteReconyx3', 849 Condition => '$$valPt =~ /^RECONYXH2\0/', 850 SubDirectory => { 851 TagTable => 'Image::ExifTool::Reconyx::Type3', 852 ByteOrder => 'Little-endian', 853 }, 854 }, 855 { 856 Name => 'MakerNoteRicohPentax', 857 # used by cameras such as the Ricoh GR III 858 Condition => '$$valPt=~/^RICOH\0(II|MM)/', 859 SubDirectory => { 860 TagTable => 'Image::ExifTool::Pentax::Main', 861 Start => '$valuePtr + 8', 862 Base => '$start - 8', 863 ByteOrder => 'Unknown', 864 }, 865 }, 866 { 867 Name => 'MakerNoteRicoh', 868 # (my test R50 image starts with " \x02\x01" - PH) 869 Condition => q{ 870 $$self{Make} =~ /^(PENTAX )?RICOH/ and 871 $$valPt =~ /^(Ricoh| |MM\0\x2a|II\x2a\0)/i and 872 $$valPt !~ /^(MM\0\x2a\0\0\0\x08\0.\0\0|II\x2a\0\x08\0\0\0.\0\0\0)/s and 873 $$self{Model} ne 'RICOH WG-M1' 874 }, 875 SubDirectory => { 876 TagTable => 'Image::ExifTool::Ricoh::Main', 877 Start => '$valuePtr + 8', 878 ByteOrder => 'Unknown', 879 }, 880 }, 881 { 882 Name => 'MakerNoteRicoh2', 883 # (the Ricoh HZ15 starts with "MM\0\x2a" and the Pentax XG-1 starts with "II\x2a\0", 884 # but an extra 2 bytes of padding after the IFD entry count prevents these from 885 # being processed as a standard IFD. Note that the offsets for the HZ15 are all 886 # zeros, but they seem to be mostly OK for the XG-1) 887 Condition => q{ 888 $$self{Make} =~ /^(PENTAX )?RICOH/ and ($$self{Model} eq 'RICOH WG-M1' or 889 $$valPt =~ /^(MM\0\x2a\0\0\0\x08\0.\0\0|II\x2a\0\x08\0\0\0.\0\0\0)/s) 890 }, 891 SubDirectory => { 892 TagTable => 'Image::ExifTool::Ricoh::Type2', 893 Start => '$valuePtr + 8', 894 Base => '$start - 8', 895 ByteOrder => 'Unknown', 896 ProcessProc => \&ProcessKodakPatch, 897 }, 898 }, 899 { 900 Name => 'MakerNoteRicohText', 901 Condition => '$$self{Make}=~/^RICOH/', 902 NotIFD => 1, 903 SubDirectory => { 904 TagTable => 'Image::ExifTool::Ricoh::Text', 905 ByteOrder => 'Unknown', 906 }, 907 }, 908 { 909 Name => 'MakerNoteSamsung1a', 910 # Samsung STMN maker notes WITHOUT PreviewImage 911 Condition => '$$valPt =~ /^STMN\d{3}.\0{4}/s', 912 Binary => 1, 913 Notes => 'Samsung "STMN" maker notes without PreviewImage', 914 }, 915 { 916 Name => 'MakerNoteSamsung1b', 917 # Samsung STMN maker notes WITH PreviewImage 918 Condition => '$$valPt =~ /^STMN\d{3}/', 919 SubDirectory => { 920 TagTable => 'Image::ExifTool::Samsung::Main', 921 }, 922 }, 923 { 924 Name => 'MakerNoteSamsung2', 925 # Samsung EXIF-format maker notes ( 926 Condition => q{ 927 uc $$self{Make} eq 'SAMSUNG' and ($$self{TIFF_TYPE} eq 'SRW' or 928 $$valPt=~/^(\0.\0\x01\0\x07\0{3}\x04|.\0\x01\0\x07\0\x04\0{3})0100/s) 929 }, 930 SubDirectory => { 931 TagTable => 'Image::ExifTool::Samsung::Type2', 932 # Samsung is very inconsistent here, and uses absolute offsets for some 933 # models and relative offsets for others, so process as Unknown 934 ProcessProc => \&ProcessUnknown, 935 FixBase => 1, 936 ByteOrder => 'Unknown', 937 }, 938 }, 939 { 940 Name => 'MakerNoteSanyo', 941 # (starts with "SANYO\0") 942 Condition => '$$self{Make}=~/^SANYO/ and $$self{Model}!~/^(C4|J\d|S\d)\b/', 943 SubDirectory => { 944 TagTable => 'Image::ExifTool::Sanyo::Main', 945 Validate => '$val =~ /^SANYO/', 946 Start => '$valuePtr + 8', 947 ByteOrder => 'Unknown', 948 }, 949 }, 950 { 951 Name => 'MakerNoteSanyoC4', 952 # The C4 offsets are wrong by 12, so they must be fixed 953 Condition => '$$self{Make}=~/^SANYO/ and $$self{Model}=~/^C4\b/', 954 SubDirectory => { 955 TagTable => 'Image::ExifTool::Sanyo::Main', 956 Validate => '$val =~ /^SANYO/', 957 Start => '$valuePtr + 8', 958 FixBase => 1, 959 ByteOrder => 'Unknown', 960 }, 961 }, 962 { 963 Name => 'MakerNoteSanyoPatch', 964 # The J1, J2, J4, S1, S3 and S4 offsets are completely screwy 965 Condition => '$$self{Make}=~/^SANYO/', 966 SubDirectory => { 967 TagTable => 'Image::ExifTool::Sanyo::Main', 968 Validate => '$val =~ /^SANYO/', 969 Start => '$valuePtr + 8', 970 ByteOrder => 'Unknown', 971 FixOffsets => 'Image::ExifTool::Sanyo::FixOffsets($valuePtr, $valEnd, $size, $tagID, $wFlag)', 972 }, 973 }, 974 { 975 Name => 'MakerNoteSigma', 976 Condition => q{ 977 return undef unless $$self{Make}=~/^(SIGMA|FOVEON)/; 978 # save version number in "MakerNoteSigmaVer" member variable 979 $$self{MakerNoteSigmaVer} = $$valPt=~/^SIGMA\0\0\0\0(.)/ ? ord($1) : -1; 980 return 1; 981 }, 982 SubDirectory => { 983 TagTable => 'Image::ExifTool::Sigma::Main', 984 Validate => '$val =~ /^(SIGMA|FOVEON)/', 985 Start => '$valuePtr + 10', 986 ByteOrder => 'Unknown', 987 }, 988 }, 989 { 990 Name => 'MakerNoteSony', 991 # (starts with "SONY DSC \0" or "SONY CAM \0") 992 # (TF1 starts with "\0\0SONY PIC\0") 993 # (Hasselblad models start with "VHAB \0") 994 Condition => '$$valPt=~/^(SONY (DSC|CAM|MOBILE)|\0\0SONY PIC\0|VHAB \0)/', 995 SubDirectory => { 996 TagTable => 'Image::ExifTool::Sony::Main', 997 Start => '$valuePtr + 12', 998 ByteOrder => 'Unknown', 999 }, 1000 }, 1001 { 1002 Name => 'MakerNoteSony2', 1003 # (starts with "SONY PI\0" -- DSC-S650/S700/S750) 1004 Condition => '$$valPt=~/^SONY PI\0/ and $$self{OlympusCAMER}=1', 1005 SubDirectory => { 1006 TagTable => 'Image::ExifTool::Olympus::Main', 1007 Start => '$valuePtr + 12', 1008 ByteOrder => 'Unknown', 1009 }, 1010 }, 1011 { 1012 Name => 'MakerNoteSony3', 1013 # (starts with "PREMI\0" -- DSC-S45/S500) 1014 Condition => '$$valPt=~/^(PREMI)\0/ and $$self{OlympusCAMER}=1', 1015 SubDirectory => { 1016 TagTable => 'Image::ExifTool::Olympus::Main', 1017 Start => '$valuePtr + 8', 1018 ByteOrder => 'Unknown', 1019 }, 1020 }, 1021 { 1022 Name => 'MakerNoteSony4', 1023 # (starts with "SONY PIC\0" -- DSC-H200/J20/W370/W510, MHS-TS20) 1024 Condition => '$$valPt=~/^SONY PIC\0/', 1025 SubDirectory => { TagTable => 'Image::ExifTool::Sony::PIC' }, 1026 }, 1027 { 1028 Name => 'MakerNoteSony5', # used in SR2 and ARW images 1029 Condition => '$$self{Make}=~/^SONY/ and $$valPt!~/^\x01\x00/', 1030 Condition => q{ 1031 ($$self{Make}=~/^SONY/ or ($$self{Make}=~/^HASSELBLAD/ and 1032 $$self{Model}=~/^(HV|Stellar|Lusso|Lunar)/)) and $$valPt!~/^\x01\x00/ 1033 }, 1034 SubDirectory => { 1035 TagTable => 'Image::ExifTool::Sony::Main', 1036 Start => '$valuePtr', 1037 ByteOrder => 'Unknown', 1038 }, 1039 }, 1040 { 1041 Name => 'MakerNoteSonyEricsson', 1042 Condition => '$$valPt =~ /^SEMC MS\0/', 1043 SubDirectory => { 1044 TagTable => 'Image::ExifTool::Sony::Ericsson', 1045 Start => '$valuePtr + 20', 1046 Base => '$start - 8', 1047 ByteOrder => 'Unknown', 1048 }, 1049 }, 1050 { 1051 Name => 'MakerNoteSonySRF', 1052 Condition => '$$self{Make}=~/^SONY/', 1053 SubDirectory => { 1054 TagTable => 'Image::ExifTool::Sony::SRF', 1055 Start => '$valuePtr', 1056 ByteOrder => 'Unknown', 1057 }, 1058 }, 1059 { 1060 Name => 'MakerNoteUnknownText', 1061 Condition => '$$valPt =~ /^[\x09\x0d\x0a\x20-\x7e]+\0*$/', 1062 Notes => 'unknown text-based maker notes', 1063 # show as binary if it is too long 1064 ValueConv => 'length($val) > 64 ? \$val : $val', 1065 ValueConvInv => '$val', 1066 }, 1067 { 1068 Name => 'MakerNoteUnknownBinary', 1069 # "LSI1\0" - SilverFast 1070 Condition => '$$valPt =~ /^LSI1\0/', 1071 Notes => 'unknown binary maker notes', 1072 Binary => 1, 1073 }, 1074 { 1075 Name => 'MakerNoteUnknown', 1076 PossiblePreview => 1, 1077 SubDirectory => { 1078 TagTable => 'Image::ExifTool::Unknown::Main', 1079 ProcessProc => \&ProcessUnknownOrPreview, 1080 WriteProc => \&WriteUnknownOrPreview, 1081 ByteOrder => 'Unknown', 1082 FixBase => 2, 1083 }, 1084 }, 1085); 1086 1087# insert writable properties so we can write our maker notes 1088my $tagInfo; 1089foreach $tagInfo (@Image::ExifTool::MakerNotes::Main) { 1090 $$tagInfo{Writable} = 'undef'; 1091 $$tagInfo{Format} = 'undef', # (make sure we don't convert this when reading) 1092 $$tagInfo{WriteGroup} = 'ExifIFD'; 1093 $$tagInfo{Groups} = { 1 => 'MakerNotes' }; 1094 next unless $$tagInfo{SubDirectory}; 1095 # make all SubDirectory tags block-writable 1096 $$tagInfo{Binary} = 1, 1097 $$tagInfo{MakerNotes} = 1; 1098} 1099 1100#------------------------------------------------------------------------------ 1101# Get normal offset of value data from end of maker note IFD 1102# Inputs: 0) ExifTool object reference 1103# Returns: Array: 0) relative flag (undef for no change) 1104# 1) normal offset from end of IFD to first value (empty if unknown) 1105# 2-N) other possible offsets used by some models 1106# Notes: Directory size should be validated before calling this routine 1107sub GetMakerNoteOffset($) 1108{ 1109 my $et = shift; 1110 # figure out where we expect the value data based on camera type 1111 my $make = $$et{Make}; 1112 my $model = $$et{Model}; 1113 my ($relative, @offsets); 1114 1115 # normally value data starts 4 bytes after end of directory, so this is the default. 1116 # offsets of 0 and 4 are always allowed even if not specified, 1117 # but the first offset specified is the one used when writing 1118 if ($make =~ /^Canon/) { 1119 push @offsets, ($model =~ /\b(20D|350D|REBEL XT|Kiss Digital N)\b/) ? 6 : 4; 1120 # some Canon models (FV-M30, Optura50, Optura60) leave 24 unused bytes 1121 # at the end of the IFD (2 spare IFD entries?) 1122 push @offsets, 28 if $model =~ /\b(FV\b|OPTURA)/; 1123 # some Canon PowerShot models leave 12 unused bytes 1124 push @offsets, 16 if $model =~ /(PowerShot|IXUS|IXY)/; 1125 } elsif ($make =~ /^CASIO/) { 1126 # Casio AVI and MOV images use no padding, and their JPEG's use 4, 1127 # except some models like the EX-S770,Z65,Z70,Z75 and Z700 which use 16, 1128 # and the EX-Z35 which uses 2 (grrrr...) 1129 push @offsets, $$et{FILE_TYPE} =~ /^(RIFF|MOV)$/ ? 0 : (4, 16, 2); 1130 } elsif ($make =~ /^(General Imaging Co.|GEDSC IMAGING CORP.)/i) { 1131 push @offsets, 0; 1132 } elsif ($make =~ /^KYOCERA/) { 1133 push @offsets, 12; 1134 } elsif ($make =~ /^Leica Camera AG/) { 1135 if ($model eq 'S2') { 1136 # lots of empty space before first value in S2 images 1137 push @offsets, 4, ($$et{FILE_TYPE} eq 'JPEG' ? 286 : 274); 1138 } elsif ($model eq 'LEICA M MONOCHROM (Typ 246)') { 1139 push @offsets, 4, 130; 1140 } elsif ($model eq 'LEICA M (Typ 240)') { 1141 push @offsets, 4, 118; 1142 } elsif ($model =~ /^(R8|R9|M8)\b/) { 1143 push @offsets, 6; 1144 } else { 1145 push @offsets, 4; 1146 } 1147 } elsif ($make =~ /^OLYMPUS/ and $model =~ /^E-(1|300|330)\b/) { 1148 push @offsets, 16; 1149 } elsif ($make =~ /^OLYMPUS/ and 1150 # these Olympus models are just weird 1151 $model =~ /^(C2500L|C-1Z?|C-5000Z|X-2|C720UZ|C725UZ|C150|C2Z|E-10|E-20|FerrariMODEL2003|u20D|u10D)\b/) 1152 { 1153 # no expected offset --> determine offset empirically via FixBase() 1154 } elsif ($make =~ /^(Panasonic|JVC)\b/) { 1155 push @offsets, 0; 1156 } elsif ($make =~ /^SONY/) { 1157 # earlier DSLR and "PREMI" models use an offset of 4 1158 if ($model =~ /^(DSLR-.*|SLT-A(33|35|55V)|NEX-(3|5|C3|VG10E))$/ or 1159 $$et{OlympusCAMER}) 1160 { 1161 push @offsets, 4; 1162 } else { 1163 push @offsets, 0; 1164 } 1165 } elsif ($$et{TIFF_TYPE} eq 'SRW' and $make eq 'SAMSUNG' and $model eq 'EK-GN120') { 1166 push @offsets, 40; # patch to read most of the maker notes, but breaks PreviewIFD 1167 } elsif ($make eq 'FUJIFILM') { 1168 # some models have offset of 6, so allow that too (A345,A350,A360,A370) 1169 push @offsets, 4, 6; 1170 } elsif ($make =~ /^TOSHIBA/) { 1171 # similar to Canon, can also have 24 bytes of padding 1172 push @offsets, 0, 24; 1173 } elsif ($make =~ /^PENTAX/) { 1174 push @offsets, 4; 1175 # the Pentax addressing mode is determined automatically, but 1176 # sometimes the algorithm gets it wrong, but Pentax always uses 1177 # absolute addressing, so force it to be absolute 1178 $relative = 0; 1179 } elsif ($make =~ /^Konica Minolta/i) { 1180 # patch for DiMAGE X50, Xg, Z2 and Z10 1181 push @offsets, 4, -16; 1182 } elsif ($make =~ /^Minolta/) { 1183 # patch for DiMAGE 7, X20 and Z1 1184 push @offsets, 4, -8, -12; 1185 } else { 1186 push @offsets, 4; # the normal offset 1187 } 1188 return ($relative, @offsets); 1189} 1190 1191#------------------------------------------------------------------------------ 1192# Get hash of value offsets / block sizes 1193# Inputs: 0) Data pointer, 1) offset to start of directory, 1194# 2) hash ref to return value pointers based on tag ID 1195# Returns: 0) hash reference: keys are offsets, values are block sizes 1196# 1) same thing, but with keys adjusted for value-based offsets 1197# Notes: Directory size should be validated before calling this routine 1198# - calculates MIN and MAX offsets in entry-based hash 1199sub GetValueBlocks($$;$) 1200{ 1201 my ($dataPt, $dirStart, $tagPtr) = @_; 1202 my $numEntries = Get16u($dataPt, $dirStart); 1203 my ($index, $valPtr, %valBlock, %valBlkAdj, $end); 1204 for ($index=0; $index<$numEntries; ++$index) { 1205 my $entry = $dirStart + 2 + 12 * $index; 1206 my $format = Get16u($dataPt, $entry+2); 1207 last if $format < 1 or $format > 13; 1208 my $count = Get32u($dataPt, $entry+4); 1209 my $size = $count * $Image::ExifTool::Exif::formatSize[$format]; 1210 next if $size <= 4; 1211 $valPtr = Get32u($dataPt, $entry+8); 1212 $tagPtr and $$tagPtr{Get16u($dataPt, $entry)} = $valPtr; 1213 # save location and size of longest block at this offset 1214 unless (defined $valBlock{$valPtr} and $valBlock{$valPtr} > $size) { 1215 $valBlock{$valPtr} = $size; 1216 } 1217 # adjust for case of value-based offsets 1218 $valPtr += 12 * $index; 1219 unless (defined $valBlkAdj{$valPtr} and $valBlkAdj{$valPtr} > $size) { 1220 $valBlkAdj{$valPtr} = $size; 1221 my $end = $valPtr + $size; 1222 if (defined $valBlkAdj{MIN}) { 1223 # save minimum only if it has a value of 12 or greater 1224 $valBlkAdj{MIN} = $valPtr if $valBlkAdj{MIN} < 12 or $valBlkAdj{MIN} > $valPtr; 1225 $valBlkAdj{MAX} = $end if $valBlkAdj{MAX} > $end; 1226 } else { 1227 $valBlkAdj{MIN} = $valPtr; 1228 $valBlkAdj{MAX} = $end; 1229 } 1230 } 1231 } 1232 return(\%valBlock, \%valBlkAdj); 1233} 1234 1235#------------------------------------------------------------------------------ 1236# Fix base for value offsets in maker notes IFD (if necessary) 1237# Inputs: 0) ExifTool object ref, 1) DirInfo hash ref 1238# Return: amount of base shift (and $dirInfo Base and DataPos are updated, 1239# FixedBy is set if offsets fixed, and Relative or EntryBased may be set) 1240sub FixBase($$) 1241{ 1242 local $_; 1243 my ($et, $dirInfo) = @_; 1244 # don't fix base if fixing offsets individually or if we don't want to fix them 1245 return 0 if $$dirInfo{FixOffsets} or $$dirInfo{NoFixBase}; 1246 1247 my $dataPt = $$dirInfo{DataPt}; 1248 my $dataPos = $$dirInfo{DataPos}; 1249 my $dirStart = $$dirInfo{DirStart} || 0; 1250 my $entryBased = $$dirInfo{EntryBased}; 1251 my $dirName = $$dirInfo{DirName}; 1252 my $fixBase = $et->Options('FixBase'); 1253 my $setBase = (defined $fixBase and $fixBase ne '') ? 1 : 0; 1254 my ($fix, $fixedBy, %tagPtr); 1255 1256 # get hash of value block positions 1257 my ($valBlock, $valBlkAdj) = GetValueBlocks($dataPt, $dirStart, \%tagPtr); 1258 return 0 unless %$valBlock; 1259 # get sorted list of value offsets 1260 my @valPtrs = sort { $a <=> $b } keys %$valBlock; 1261# 1262# handle special case of Canon maker notes with TIFF footer containing original offset 1263# 1264 if ($$et{Make} =~ /^Canon/ and $$dirInfo{DirLen} > 8) { 1265 my $footerPos = $dirStart + $$dirInfo{DirLen} - 8; 1266 my $footer = substr($$dataPt, $footerPos, 8); 1267 if ($footer =~ /^(II\x2a\0|MM\0\x2a)/ and # check for TIFF footer 1268 substr($footer,0,2) eq GetByteOrder()) # validate byte ordering 1269 { 1270 my $oldOffset = Get32u(\$footer, 4); 1271 my $newOffset = $dirStart + $dataPos; 1272 if ($setBase) { 1273 $fix = $fixBase; 1274 } else { 1275 $fix = $newOffset - $oldOffset; 1276 return 0 unless $fix; 1277 # Picasa and ACDSee have a bug where they update other offsets without 1278 # updating the TIFF footer (PH - 2009/02/25), so test for this case: 1279 # validate Canon maker note footer fix by checking offset of last value 1280 my $maxPt = $valPtrs[-1] + $$valBlock{$valPtrs[-1]}; 1281 # compare to end of maker notes, taking 8-byte footer into account 1282 my $endDiff = $dirStart + $$dirInfo{DirLen} - ($maxPt - $dataPos) - 8; 1283 # ignore footer offset only if end difference is exactly correct 1284 # (allow for possible padding byte, although I have never seen this) 1285 if (not $endDiff or $endDiff == 1) { 1286 $et->Warn('Canon maker note footer may be invalid (ignored)',1); 1287 return 0; 1288 } 1289 } 1290 $et->Warn("Adjusted $dirName base by $fix",1); 1291 $$dirInfo{FixedBy} = $fix; 1292 $$dirInfo{Base} += $fix; 1293 $$dirInfo{DataPos} -= $fix; 1294 return $fix; 1295 } 1296 } 1297# 1298# analyze value offsets to see if they need fixing. The first task is to determine 1299# the minimum valid offset used (this is tricky, because we have to weed out bad 1300# offsets written by some cameras) 1301# 1302 my $minPt = $$dirInfo{MinOffset} = $valPtrs[0]; # if life were simple, this would be it 1303 my $ifdLen = 2 + 12 * Get16u($$dirInfo{DataPt}, $dirStart); 1304 my $ifdEnd = $dirStart + $ifdLen; 1305 my ($relative, @offsets) = GetMakerNoteOffset($et); 1306 my $makeDiff = $offsets[0]; 1307 my $verbose = $et->Options('Verbose'); 1308 my ($diff, $shift); 1309 1310 # calculate expected minimum value offset 1311 my $expected = $dataPos + $ifdEnd + (defined $makeDiff ? $makeDiff : 4); 1312 $debug and print "$expected expected\n"; 1313 1314 # zero our counters 1315 my ($countNeg12, $countZero, $countOverlap) = (0, 0, 0); 1316 my ($valPtr, $last); 1317 foreach $valPtr (@valPtrs) { 1318 printf("%d - %d (%d)\n", $valPtr, $valPtr + $$valBlock{$valPtr}, 1319 $valPtr - ($last || 0)) if $debug; 1320 if (defined $last) { 1321 my $gap = $valPtr - $last; 1322 if ($gap == 0 or $gap == 1) { 1323 ++$countZero; 1324 } elsif ($gap == -12 and not $entryBased) { 1325 # you get this when value offsets are relative to the IFD entry 1326 ++$countNeg12; 1327 } elsif ($gap < 0) { 1328 # any other negative difference indicates overlapping values 1329 ++$countOverlap if $valPtr; # (but ignore zero value pointers) 1330 } elsif ($gap >= $ifdLen) { 1331 # ignore previous minimum if we took a jump to near the expected value 1332 # (some values can be stored before the IFD) 1333 $minPt = $valPtr if abs($valPtr - $expected) <= 4; 1334 } 1335 # an offset less than 12 is surely garbage, so ignore it 1336 $minPt = $valPtr if $minPt < 12; 1337 } 1338 $last = $valPtr + $$valBlock{$valPtr}; 1339 } 1340 # could this IFD be using entry-based offsets? 1341 if ((($countNeg12 > $countZero and $$valBlkAdj{MIN} >= $ifdLen - 2) or 1342 ($$valBlkAdj{MIN} == $ifdLen - 2 or $$valBlkAdj{MIN} == $ifdLen + 2) 1343 ) and $$valBlkAdj{MAX} <= $$dirInfo{DirLen}-2) 1344 { 1345 # looks like these offsets are entry-based, so use the offsets 1346 # which have been correcting for individual entry position 1347 $entryBased = 1; 1348 $verbose and $et->Warn("$dirName offsets are entry-based",1); 1349 } else { 1350 # calculate offset difference from end of IFD to first value 1351 $diff = ($minPt - $dataPos) - $ifdEnd; 1352 $shift = 0; 1353 $countOverlap and $et->Warn("Overlapping $dirName values",1); 1354 if ($entryBased) { 1355 $et->Warn("$dirName offsets do NOT look entry-based",1); 1356 undef $entryBased; 1357 undef $relative; 1358 } 1359 # use PrintIM tag to do special check for correct absolute offsets 1360 if ($tagPtr{0xe00}) { 1361 my $ptr = $tagPtr{0xe00} - $dataPos; 1362 return 0 if $ptr > 0 and $ptr <= length($$dataPt) - 8 and 1363 substr($$dataPt, $ptr, 8) eq "PrintIM\0"; 1364 } 1365 # allow a range of reasonable differences for Unknown maker notes 1366 if ($$dirInfo{FixBase} and $$dirInfo{FixBase} == 2) { 1367 return 0 if $diff >=0 and $diff <= 24; 1368 } 1369 # ******** (used for testing to extract differences) ******** 1370 # $et->FoundTag('Diff', $diff); 1371 # $et->FoundTag('MakeDiff',$makeDiff); 1372 } 1373# 1374# handle entry-based offsets 1375# 1376 if ($entryBased) { 1377 $debug and print "--> entry-based!\n"; 1378 # most of my entry-based samples have first value immediately 1379 # after last IFD entry (ie. no padding or next IFD pointer) 1380 $makeDiff = 0; 1381 push @offsets, 4; # but some do have a next IFD pointer 1382 # corrected entry-based offsets are relative to start of first entry 1383 my $expected = 12 * Get16u($$dirInfo{DataPt}, $dirStart); 1384 $diff = $$valBlkAdj{MIN} - $expected; 1385 # set up directory to read values with entry-based offsets 1386 # (ignore everything and set base to start of first entry) 1387 $shift = $dataPos + $dirStart + 2; 1388 $$dirInfo{Base} += $shift; 1389 $$dirInfo{DataPos} -= $shift; 1390 $$dirInfo{EntryBased} = 1; 1391 $$dirInfo{Relative} = 1; # entry-based offsets are relative 1392 delete $$dirInfo{FixBase}; # no automatic base fix 1393 undef $fixBase unless $setBase; 1394 } 1395# 1396# return without doing shift if offsets look OK 1397# 1398 unless ($setBase) { 1399 # don't try to fix offsets for whacky cameras 1400 return $shift unless defined $makeDiff; 1401 # normal value data starts 4 bytes after IFD, but allow 0 or 4... 1402 return $shift if $diff == 0 or $diff == 4; 1403 # also check for allowed make-specific differences 1404 foreach (@offsets) { 1405 return $shift if $diff == $_; 1406 } 1407 } 1408# 1409# apply the fix, or issue a warning 1410# 1411 # use default padding of 4 bytes unless already specified 1412 $makeDiff = 4 unless defined $makeDiff; 1413 $fix = $makeDiff - $diff; # assume standard diff for this make 1414 1415 if ($$dirInfo{FixBase}) { 1416 # set flag if offsets are relative (base is at or above directory start) 1417 if ($dataPos - $fix + $dirStart <= 0) { 1418 $$dirInfo{Relative} = (defined $relative) ? $relative : 1; 1419 } 1420 if ($setBase) { 1421 $fixedBy = $fixBase; 1422 $fix += $fixBase; 1423 } 1424 } elsif (defined $fixBase) { 1425 $fix = $fixBase if $fixBase ne ''; 1426 $fixedBy = $fix; 1427 } else { 1428 # print warning unless difference looks reasonable 1429 if ($diff < 0 or $diff > 16 or ($diff & 0x01)) { 1430 $et->Warn("Possibly incorrect maker notes offsets (fix by $fix?)",1); 1431 } 1432 # don't do the fix (but we already adjusted base if entry-based) 1433 return $shift; 1434 } 1435 if (defined $fixedBy) { 1436 $et->Warn("Adjusted $dirName base by $fixedBy",1); 1437 $$dirInfo{FixedBy} = $fixedBy; 1438 } 1439 $$dirInfo{Base} += $fix; 1440 $$dirInfo{DataPos} -= $fix; 1441 return $fix + $shift; 1442} 1443 1444#------------------------------------------------------------------------------ 1445# Find start of IFD in unknown maker notes 1446# Inputs: 0) reference to directory information 1447# Returns: offset to IFD on success, undefined otherwise 1448# - dirInfo may contain TagInfo reference for tag associated with directory 1449# - on success, updates DirStart, DirLen, Base and DataPos in dirInfo 1450# - also sets Relative flag in dirInfo if offsets are relative to IFD 1451# Note: Changes byte ordering! 1452sub LocateIFD($$) 1453{ 1454 my ($et, $dirInfo) = @_; 1455 my $dataPt = $$dirInfo{DataPt}; 1456 my $dirStart = $$dirInfo{DirStart} || 0; 1457 # (ignore MakerNotes DirLen since sometimes this is incorrect) 1458 my $size = $$dirInfo{DataLen} - $dirStart; 1459 my $dirLen = defined $$dirInfo{DirLen} ? $$dirInfo{DirLen} : $size; 1460 my $tagInfo = $$dirInfo{TagInfo}; 1461 my $ifdOffsetPos; 1462 # the IFD should be within the first 32 bytes 1463 # (Kyocera sets the current record at 22 bytes) 1464 my ($firstTry, $lastTry) = (0, 32); 1465 1466 # make sure Base and DataPos are defined 1467 $$dirInfo{Base} or $$dirInfo{Base} = 0; 1468 $$dirInfo{DataPos} or $$dirInfo{DataPos} = 0; 1469# 1470# use tag information (if provided) to determine directory location 1471# 1472 if ($tagInfo and $$tagInfo{SubDirectory}) { 1473 my $subdir = $$tagInfo{SubDirectory}; 1474 unless ($$subdir{ProcessProc} and 1475 ($$subdir{ProcessProc} eq \&ProcessUnknown or 1476 $$subdir{ProcessProc} eq \&ProcessUnknownOrPreview)) 1477 { 1478 # look for the IFD at the "Start" specified in our SubDirectory information 1479 my $valuePtr = $dirStart; 1480 my $newStart = $dirStart; 1481 if (defined $$subdir{Start}) { 1482 #### eval Start ($valuePtr) 1483 $newStart = eval($$subdir{Start}); 1484 } 1485 if ($$subdir{Base}) { 1486 # calculate subdirectory start relative to $base for eval 1487 my $start = $newStart + $$dirInfo{DataPos}; 1488 my $base = $$dirInfo{Base} || 0; 1489 #### eval Base ($start,$base) 1490 my $baseShift = eval($$subdir{Base}); 1491 # shift directory base (note: we may do this again below 1492 # if an OffsetPt is defined, but that doesn't matter since 1493 # the base shift is relative to DataPos, which we set too) 1494 $$dirInfo{Base} += $baseShift; 1495 $$dirInfo{DataPos} -= $baseShift; 1496 # this is a relative directory if Base depends on $start 1497 if ($$subdir{Base} =~ /\$start\b/) { 1498 $$dirInfo{Relative} = 1; 1499 # hack to fix Leica quirk 1500 if ($$subdir{ProcessProc} and $$subdir{ProcessProc} eq \&FixLeicaBase) { 1501 my $oldStart = $$dirInfo{DirStart}; 1502 $$dirInfo{DirStart} = $newStart; 1503 FixLeicaBase($et, $dirInfo); 1504 $$dirInfo{DirStart} = $oldStart; 1505 } 1506 } 1507 } 1508 # add offset to the start of the directory if necessary 1509 if ($$subdir{OffsetPt}) { 1510 if ($$subdir{ByteOrder} =~ /^Little/i) { 1511 SetByteOrder('II'); 1512 } elsif ($$subdir{ByteOrder} =~ /^Big/i) { 1513 SetByteOrder('MM'); 1514 } else { 1515 warn "Can't have variable byte ordering for SubDirectories using OffsetPt\n"; 1516 return undef; 1517 } 1518 #### eval OffsetPt ($valuePtr) 1519 $ifdOffsetPos = eval($$subdir{OffsetPt}) - $dirStart; 1520 } 1521 # pinpoint position to look for this IFD 1522 $firstTry = $lastTry = $newStart - $dirStart; 1523 } 1524 } 1525# 1526# scan for something that looks like an IFD 1527# 1528 if ($dirLen >= 14 + $firstTry) { # minimum size for an IFD 1529 my $offset; 1530IFD_TRY: for ($offset=$firstTry; $offset<=$lastTry; $offset+=2) { 1531 last if $offset + 14 > $dirLen; # 14 bytes is minimum size for an IFD 1532 my $pos = $dirStart + $offset; 1533# 1534# look for a standard TIFF header (Nikon uses it, others may as well), 1535# 1536 if (SetByteOrder(substr($$dataPt, $pos, 2)) and 1537 Get16u($dataPt, $pos + 2) == 0x2a) 1538 { 1539 $ifdOffsetPos = 4; 1540 } 1541 if (defined $ifdOffsetPos) { 1542 # get pointer to IFD 1543 my $ptr = Get32u($dataPt, $pos + $ifdOffsetPos); 1544 if ($ptr >= $ifdOffsetPos + 4 and $ptr + $offset + 14 <= $dirLen) { 1545 # shift directory start and shorten dirLen accordingly 1546 $$dirInfo{DirStart} += $ptr + $offset; 1547 $$dirInfo{DirLen} -= $ptr + $offset; 1548 # shift pointer base to the start of the TIFF header 1549 my $shift = $$dirInfo{DataPos} + $dirStart + $offset; 1550 $$dirInfo{Base} += $shift; 1551 $$dirInfo{DataPos} -= $shift; 1552 $$dirInfo{Relative} = 1; # set "relative offsets" flag 1553 return $ptr + $offset; 1554 } 1555 undef $ifdOffsetPos; 1556 } 1557# 1558# look for a standard IFD (starts with 2-byte entry count) 1559# 1560 my $num = Get16u($dataPt, $pos); 1561 next unless $num; 1562 # number of entries in an IFD should be between 1 and 255 1563 if (!($num & 0xff)) { 1564 # lower byte is zero -- byte order could be wrong 1565 ToggleByteOrder(); 1566 $num >>= 8; 1567 } elsif ($num & 0xff00) { 1568 # upper byte isn't zero -- not an IFD 1569 next; 1570 } 1571 my $bytesFromEnd = $size - ($offset + 2 + 12 * $num); 1572 if ($bytesFromEnd < 4) { 1573 next unless $bytesFromEnd == 2 or $bytesFromEnd == 0; 1574 } 1575 # do a quick validation of all format types 1576 my $index; 1577 for ($index=0; $index<$num; ++$index) { 1578 my $entry = $pos + 2 + 12 * $index; 1579 my $format = Get16u($dataPt, $entry+2); 1580 my $count = Get32u($dataPt, $entry+4); 1581 unless ($format) { 1582 # patch for buggy Samsung NX200 JPEG MakerNotes entry count 1583 if ($num == 23 and $index == 21 and $$et{Make} eq 'SAMSUNG') { 1584 Set16u(21, $dataPt, $pos); # really 21 IFD entries! 1585 $et->Warn('Fixed incorrect Makernote entry count', 1); 1586 last; 1587 } 1588 # allow everything to be zero if not first entry 1589 # because some manufacturers pad with null entries 1590 next unless $count or $index == 0; 1591 # patch for Canon EOS 40D firmware 1.0.4 bug: allow zero format for last entry 1592 next if $index==$num-1 and $$et{Model}=~/EOS 40D/; 1593 } 1594 # patch for Sony cameras like the DSC-P10 that have invalid MakerNote entries 1595 next if $num == 12 and $$et{Make} eq 'SONY' and $index >= 8; 1596 # (would like to verify tag ID, but some manufactures don't 1597 # sort entries in order of tag ID so we don't have much of 1598 # a handle to verify this field) 1599 # verify format 1600 next IFD_TRY if $format < 1 or $format > 13; 1601 # count must be reasonable (can't test for zero count because 1602 # cameras like the 1DmkIII use this value) 1603 next IFD_TRY if $count & 0xff000000; 1604 # extra tests to avoid mis-identifying Samsung makernotes (GT-I9000, etc) 1605 next unless $num == 1; 1606 my $valueSize = $count * $Image::ExifTool::Exif::formatSize[$format]; 1607 if ($valueSize > 4) { 1608 next IFD_TRY if $valueSize > $size; 1609 my $valuePtr = Get32u($dataPt, $entry+8); 1610 next IFD_TRY if $valuePtr > 0x10000; 1611 } 1612 } 1613 $$dirInfo{DirStart} += $offset; # update directory start 1614 $$dirInfo{DirLen} -= $offset; 1615 return $offset; # success!! 1616 } 1617 } 1618 return undef; 1619} 1620 1621#------------------------------------------------------------------------------ 1622# Fix base offset for Leica maker notes 1623# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref 1624# Returns: 1 on success, and updates $dirInfo if necessary for new directory 1625sub FixLeicaBase($$;$) 1626{ 1627 my ($et, $dirInfo, $tagTablePtr) = @_; 1628 my $dataPt = $$dirInfo{DataPt}; 1629 my $dirStart = $$dirInfo{DirStart} || 0; 1630 # get hash of value block positions 1631 my ($valBlock, $valBlkAdj) = GetValueBlocks($dataPt, $dirStart); 1632 if (%$valBlock) { 1633 # get sorted list of value offsets 1634 my @valPtrs = sort { $a <=> $b } keys %$valBlock; 1635 my $numEntries = Get16u($dataPt, $dirStart); 1636 my $diff = $valPtrs[0] - ($numEntries * 12 + 4); 1637 if ($diff > 8) { 1638 $$dirInfo{Base} -= 8; 1639 $$dirInfo{DataPos} += 8; 1640 } 1641 } 1642 my $success = 1; 1643 if ($tagTablePtr) { 1644 $success = Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); 1645 } 1646 return $success; 1647} 1648 1649#------------------------------------------------------------------------------ 1650# Process Canon maker notes 1651# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref 1652# Returns: 1 on success 1653sub ProcessCanon($$$) 1654{ 1655 my ($et, $dirInfo, $tagTablePtr) = @_; 1656 # identify Canon MakerNote footer in HtmlDump 1657 # (this code moved from FixBase so it also works for Adobe MakN in DNG images) 1658 if ($$et{HTML_DUMP} and $$dirInfo{DirLen} > 8) { 1659 my $dataPos = $$dirInfo{DataPos}; 1660 my $dirStart = $$dirInfo{DirStart} || 0; 1661 my $footerPos = $dirStart + $$dirInfo{DirLen} - 8; 1662 my $footer = substr(${$$dirInfo{DataPt}}, $footerPos, 8); 1663 if ($footer =~ /^(II\x2a\0|MM\0\x2a)/ and substr($footer,0,2) eq GetByteOrder()) { 1664 my $oldOffset = Get32u(\$footer, 4); 1665 my $newOffset = $dirStart + $dataPos; 1666 my $str = sprintf('Original maker note offset: 0x%.4x', $oldOffset); 1667 if ($oldOffset != $newOffset) { 1668 $str .= sprintf("\nCurrent maker note offset: 0x%.4x", $newOffset); 1669 } 1670 my $filePos = ($$dirInfo{Base} || 0) + $dataPos + $footerPos; 1671 $et->HDump($filePos, 8, '[Canon MakerNotes footer]', $str); 1672 } 1673 } 1674 # process as normal 1675 return Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); 1676} 1677 1678#------------------------------------------------------------------------------ 1679# Process GE type 2 maker notes 1680# Inputs: 0) ExifTool object ref, 1) DirInfo ref, 2) tag table ref 1681# Returns: 1 on success 1682sub ProcessGE2($$$) 1683{ 1684 my ($et, $dirInfo, $tagTablePtr) = @_; 1685 my $dataPt = $$dirInfo{DataPt} or return 0; 1686 my $dirStart = $$dirInfo{DirStart} || 0; 1687 1688 # these maker notes are missing the IFD entry count, but they 1689 # always have 25 entries, so write the entry count manually 1690 Set16u(25, $dataPt, $dirStart); 1691 return Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); 1692} 1693 1694#------------------------------------------------------------------------------ 1695# Process broken Kodak type 8b maker notes 1696# Inputs: 0) ExifTool object ref, 1) DirInfo ref, 2) tag table ref 1697# Returns: 1 on success 1698sub ProcessKodakPatch($$$) 1699{ 1700 my ($et, $dirInfo, $tagTablePtr) = @_; 1701 my $dataPt = $$dirInfo{DataPt} or return 0; 1702 my $dirStart = $$dirInfo{DirStart} || 0; 1703 1704 # these maker notes have an 2 extra null bytes either before or after the entry count, 1705 # so fix this by making a 2-byte entry count just before the first IFD entry 1706 return 0 unless $$dirInfo{DirLen} >= 4; 1707 my $t1 = Get16u($dataPt,$dirStart); 1708 my $t2 = Get16u($dataPt,$dirStart+2); 1709 Set16u($t1 || $t2, $dataPt, $dirStart+2); 1710 $$dirInfo{DirStart} += 2; 1711 return Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); 1712} 1713 1714#------------------------------------------------------------------------------ 1715# Process unknown maker notes or PreviewImage 1716# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref 1717# Returns: 1 on success, and updates $dirInfo if necessary for new directory 1718sub ProcessUnknownOrPreview($$$) 1719{ 1720 my ($et, $dirInfo, $tagTablePtr) = @_; 1721 my $dataPt = $$dirInfo{DataPt}; 1722 my $dirStart = $$dirInfo{DirStart}; 1723 my $dirLen = $$dirInfo{DirLen}; 1724 # check to see if this is a preview image 1725 if ($dirLen > 6 and substr($$dataPt, $dirStart, 3) eq "\xff\xd8\xff") { 1726 $et->VerboseDir('PreviewImage'); 1727 if ($$et{HTML_DUMP}) { 1728 my $pos = $$dirInfo{DataPos} + $$dirInfo{Base} + $dirStart; 1729 $et->HDump($pos, $dirLen, '(MakerNotes:PreviewImage data)', "Size: $dirLen bytes") 1730 } 1731 $et->FoundTag('PreviewImage', substr($$dataPt, $dirStart, $dirLen)); 1732 return 1; 1733 } 1734 return ProcessUnknown($et, $dirInfo, $tagTablePtr); 1735} 1736 1737#------------------------------------------------------------------------------ 1738# Write unknown maker notes or PreviewImage 1739# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref 1740# Returns: directory data, '' to delete, or undef on error 1741sub WriteUnknownOrPreview($$$) 1742{ 1743 my ($et, $dirInfo, $tagTablePtr) = @_; 1744 my $dataPt = $$dirInfo{DataPt}; 1745 my $dirStart = $$dirInfo{DirStart}; 1746 my $dirLen = $$dirInfo{DirLen}; 1747 my $newVal; 1748 # check to see if this is a preview image 1749 if ($dirLen > 6 and substr($$dataPt, $dirStart, 3) eq "\xff\xd8\xff") { 1750 if ($$et{NEW_VALUE}{$Image::ExifTool::Extra{PreviewImage}}) { 1751 # write or delete new preview (if deleted, it can't currently be added back again) 1752 $newVal = $et->GetNewValue('PreviewImage') || ''; 1753 if ($et->Options('Verbose') > 1) { 1754 $et->VerboseValue("- MakerNotes:PreviewImage", substr($$dataPt, $dirStart, $dirLen)); 1755 $et->VerboseValue("+ MakerNotes:PreviewImage", $newVal) if $newVal; 1756 } 1757 ++$$et{CHANGED}; 1758 } else { 1759 $newVal = substr($$dataPt, $dirStart, $dirLen); 1760 } 1761 } else { 1762 # rewrite MakerNote IFD 1763 $newVal = Image::ExifTool::Exif::WriteExif($et, $dirInfo, $tagTablePtr); 1764 } 1765 return $newVal; 1766} 1767 1768#------------------------------------------------------------------------------ 1769# Process unknown maker notes assuming it is in EXIF IFD format 1770# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref 1771# Returns: 1 on success, and updates $dirInfo if necessary for new directory 1772sub ProcessUnknown($$$) 1773{ 1774 my ($et, $dirInfo, $tagTablePtr) = @_; 1775 my $success = 0; 1776 1777 my $loc = LocateIFD($et, $dirInfo); 1778 if (defined $loc) { 1779 $$et{UnknownByteOrder} = GetByteOrder(); 1780 if ($et->Options('Verbose') > 1) { 1781 my $out = $et->Options('TextOut'); 1782 my $indent = $$et{INDENT}; 1783 $indent =~ s/\| $/ /; 1784 printf $out "${indent}Found IFD at offset 0x%.4x in maker notes:\n", 1785 $$dirInfo{DirStart} + $$dirInfo{DataPos} + $$dirInfo{Base}; 1786 } 1787 $success = Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr); 1788 } else { 1789 $$et{UnknownByteOrder} = ''; # indicates we tried but didn't set byte order 1790 $et->Warn("Unrecognized $$dirInfo{DirName}", 1); 1791 } 1792 return $success; 1793} 1794 1795 17961; # end 1797 1798__END__ 1799 1800=head1 NAME 1801 1802Image::ExifTool::MakerNotes - Read and write EXIF maker notes 1803 1804=head1 SYNOPSIS 1805 1806This module is required by Image::ExifTool. 1807 1808=head1 DESCRIPTION 1809 1810This module contains definitions required by Image::ExifTool to interpret 1811maker notes in EXIF information. 1812 1813=head1 AUTHOR 1814 1815Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com) 1816 1817This library is free software; you can redistribute it and/or modify it 1818under the same terms as Perl itself. 1819 1820=head1 SEE ALSO 1821 1822L<Image::ExifTool::TagNames(3pm)|Image::ExifTool::TagNames>, 1823L<Image::ExifTool(3pm)|Image::ExifTool> 1824 1825=cut 1826