exiftool-vendored.pl 12.55.0 → 12.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/bin/Changes +97 -4
  2. package/bin/MANIFEST +9 -0
  3. package/bin/META.json +1 -1
  4. package/bin/META.yml +1 -1
  5. package/bin/README +19 -19
  6. package/bin/arg_files/xmp2exif.args +4 -1
  7. package/bin/config_files/example.config +1 -0
  8. package/bin/config_files/rotate_regions.config +1 -1
  9. package/bin/exiftool +197 -122
  10. package/bin/fmt_files/kml.fmt +3 -0
  11. package/bin/fmt_files/kml_track.fmt +3 -0
  12. package/bin/lib/Image/ExifTool/AIFF.pm +2 -2
  13. package/bin/lib/Image/ExifTool/APE.pm +2 -2
  14. package/bin/lib/Image/ExifTool/BuildTagLookup.pm +25 -19
  15. package/bin/lib/Image/ExifTool/Canon.pm +33 -7
  16. package/bin/lib/Image/ExifTool/CanonRaw.pm +5 -1
  17. package/bin/lib/Image/ExifTool/DJI.pm +28 -2
  18. package/bin/lib/Image/ExifTool/Exif.pm +107 -20
  19. package/bin/lib/Image/ExifTool/FlashPix.pm +92 -9
  20. package/bin/lib/Image/ExifTool/FujiFilm.pm +9 -4
  21. package/bin/lib/Image/ExifTool/GPS.pm +7 -2
  22. package/bin/lib/Image/ExifTool/Geotag.pm +30 -7
  23. package/bin/lib/Image/ExifTool/InfiRay.pm +227 -0
  24. package/bin/lib/Image/ExifTool/JPEG.pm +53 -7
  25. package/bin/lib/Image/ExifTool/Jpeg2000.pm +5 -5
  26. package/bin/lib/Image/ExifTool/LIF.pm +10 -2
  27. package/bin/lib/Image/ExifTool/LNK.pm +5 -4
  28. package/bin/lib/Image/ExifTool/MIE.pm +3 -3
  29. package/bin/lib/Image/ExifTool/MPEG.pm +2 -2
  30. package/bin/lib/Image/ExifTool/MakerNotes.pm +3 -2
  31. package/bin/lib/Image/ExifTool/Minolta.pm +6 -7
  32. package/bin/lib/Image/ExifTool/MinoltaRaw.pm +2 -1
  33. package/bin/lib/Image/ExifTool/Nikon.pm +1199 -1325
  34. package/bin/lib/Image/ExifTool/NikonCustom.pm +2 -2
  35. package/bin/lib/Image/ExifTool/NikonSettings.pm +1 -1
  36. package/bin/lib/Image/ExifTool/Olympus.pm +88 -6
  37. package/bin/lib/Image/ExifTool/OpenEXR.pm +32 -15
  38. package/bin/lib/Image/ExifTool/PNG.pm +89 -3
  39. package/bin/lib/Image/ExifTool/PanasonicRaw.pm +27 -1
  40. package/bin/lib/Image/ExifTool/Pentax.pm +8 -5
  41. package/bin/lib/Image/ExifTool/PhaseOne.pm +14 -1
  42. package/bin/lib/Image/ExifTool/Photoshop.pm +38 -7
  43. package/bin/lib/Image/ExifTool/QuickTime.pm +44 -13
  44. package/bin/lib/Image/ExifTool/QuickTimeStream.pl +63 -20
  45. package/bin/lib/Image/ExifTool/README +19 -2
  46. package/bin/lib/Image/ExifTool/RIFF.pm +34 -13
  47. package/bin/lib/Image/ExifTool/Rawzor.pm +2 -2
  48. package/bin/lib/Image/ExifTool/Real.pm +2 -2
  49. package/bin/lib/Image/ExifTool/Ricoh.pm +2 -1
  50. package/bin/lib/Image/ExifTool/Sigma.pm +5 -4
  51. package/bin/lib/Image/ExifTool/SigmaRaw.pm +9 -3
  52. package/bin/lib/Image/ExifTool/Sony.pm +28 -1
  53. package/bin/lib/Image/ExifTool/TagLookup.pm +4691 -4624
  54. package/bin/lib/Image/ExifTool/TagNames.pod +511 -117
  55. package/bin/lib/Image/ExifTool/VCard.pm +19 -5
  56. package/bin/lib/Image/ExifTool/Validate.pm +5 -5
  57. package/bin/lib/Image/ExifTool/WriteExif.pl +42 -0
  58. package/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
  59. package/bin/lib/Image/ExifTool/Writer.pl +150 -36
  60. package/bin/lib/Image/ExifTool/XMP.pm +19 -4
  61. package/bin/lib/Image/ExifTool/XMP2.pl +2 -1
  62. package/bin/lib/Image/ExifTool.pm +248 -54
  63. package/bin/lib/Image/ExifTool.pod +94 -58
  64. package/bin/perl-Image-ExifTool.spec +18 -18
  65. package/bin/pp_build_exe.args +7 -6
  66. package/package.json +3 -3
@@ -56,7 +56,7 @@ use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat
56
56
  use Image::ExifTool qw(:DataAccess :Utils);
57
57
  use Image::ExifTool::MakerNotes;
58
58
 
59
- $VERSION = '4.42';
59
+ $VERSION = '4.44';
60
60
 
61
61
  sub ProcessExif($$$);
62
62
  sub WriteExif($$$);
@@ -65,6 +65,7 @@ sub RebuildMakerNotes($$$);
65
65
  sub EncodeExifText($$);
66
66
  sub ValidateIFD($;$);
67
67
  sub ValidateImageData($$$;$);
68
+ sub AddImageDataMD5($$$);
68
69
  sub ProcessTiffIFD($$$);
69
70
  sub PrintParameter($$$);
70
71
  sub GetOffList($$$$$);
@@ -573,11 +574,20 @@ my %opcodeInfo = (
573
574
  ],
574
575
  Name => 'StripOffsets',
575
576
  IsOffset => 1,
577
+ IsImageData => 1,
576
578
  OffsetPair => 0x117, # point to associated byte counts
577
579
  # A200 stores this information in the wrong byte order!!
578
580
  ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val',
579
581
  ByteOrder => 'LittleEndian',
580
582
  },
583
+ {
584
+ Condition => '$$self{Compression} and $$self{Compression} eq "34892"', # DNG Lossy JPEG
585
+ Name => 'OtherImageStart',
586
+ IsOffset => 1,
587
+ IsImageData => 1,
588
+ OffsetPair => 0x117, # point to associated byte counts
589
+ DataTag => 'OtherImage',
590
+ },
581
591
  {
582
592
  # (APP1 IFD2 is for Leica JPEG preview)
583
593
  Condition => q[
@@ -587,6 +597,7 @@ my %opcodeInfo = (
587
597
  ],
588
598
  Name => 'StripOffsets',
589
599
  IsOffset => 1,
600
+ IsImageData => 1,
590
601
  OffsetPair => 0x117, # point to associated byte counts
591
602
  ValueConv => 'length($val) > 32 ? \$val : $val',
592
603
  },
@@ -623,6 +634,7 @@ my %opcodeInfo = (
623
634
  # JpgFromRawStart in various IFD's of DNG images except SubIFD2
624
635
  Name => 'JpgFromRawStart',
625
636
  IsOffset => 1,
637
+ IsImageData => 1,
626
638
  OffsetPair => 0x117,
627
639
  DataTag => 'JpgFromRaw',
628
640
  Writable => 'int32u',
@@ -664,6 +676,12 @@ my %opcodeInfo = (
664
676
  ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val',
665
677
  ByteOrder => 'LittleEndian',
666
678
  },
679
+ {
680
+ Condition => '$$self{Compression} and $$self{Compression} eq "34892"', # DNG Lossy JPEG
681
+ Name => 'OtherImageLength',
682
+ OffsetPair => 0x111, # point to associated offset
683
+ DataTag => 'OtherImage',
684
+ },
667
685
  {
668
686
  # (APP1 IFD2 is for Leica JPEG preview)
669
687
  Condition => q[
@@ -920,6 +938,7 @@ my %opcodeInfo = (
920
938
  0x144 => {
921
939
  Name => 'TileOffsets',
922
940
  IsOffset => 1,
941
+ IsImageData => 1,
923
942
  OffsetPair => 0x145,
924
943
  ValueConv => 'length($val) > 32 ? \$val : $val',
925
944
  },
@@ -1174,6 +1193,7 @@ my %opcodeInfo = (
1174
1193
  Name => 'JpgFromRawStart',
1175
1194
  Condition => '$$self{DIR_NAME} eq "SubIFD"',
1176
1195
  IsOffset => 1,
1196
+ IsImageData => 1,
1177
1197
  OffsetPair => 0x202,
1178
1198
  DataTag => 'JpgFromRaw',
1179
1199
  Writable => 'int32u',
@@ -1186,6 +1206,7 @@ my %opcodeInfo = (
1186
1206
  Name => 'JpgFromRawStart',
1187
1207
  Condition => '$$self{DIR_NAME} eq "IFD2"',
1188
1208
  IsOffset => 1,
1209
+ IsImageData => 1,
1189
1210
  OffsetPair => 0x202,
1190
1211
  DataTag => 'JpgFromRaw',
1191
1212
  Writable => 'int32u',
@@ -1197,6 +1218,7 @@ my %opcodeInfo = (
1197
1218
  {
1198
1219
  Name => 'OtherImageStart',
1199
1220
  Condition => '$$self{DIR_NAME} eq "SubIFD1"',
1221
+ IsImageData => 1,
1200
1222
  IsOffset => 1,
1201
1223
  OffsetPair => 0x202,
1202
1224
  DataTag => 'OtherImage',
@@ -1209,6 +1231,7 @@ my %opcodeInfo = (
1209
1231
  Name => 'OtherImageStart',
1210
1232
  Condition => '$$self{DIR_NAME} eq "SubIFD2"',
1211
1233
  IsOffset => 1,
1234
+ IsImageData => 1,
1212
1235
  OffsetPair => 0x202,
1213
1236
  DataTag => 'OtherImage',
1214
1237
  Writable => 'int32u',
@@ -1219,6 +1242,7 @@ my %opcodeInfo = (
1219
1242
  {
1220
1243
  Name => 'OtherImageStart',
1221
1244
  IsOffset => 1,
1245
+ IsImageData => 1,
1222
1246
  OffsetPair => 0x202,
1223
1247
  },
1224
1248
  ],
@@ -1487,9 +1511,10 @@ my %opcodeInfo = (
1487
1511
  0x7031 => {
1488
1512
  Name => 'VignettingCorrection',
1489
1513
  Notes => 'found in Sony ARW images',
1490
- Protected => 1,
1491
1514
  Writable => 'int16s',
1492
1515
  WriteGroup => 'SubIFD',
1516
+ Permanent => 1,
1517
+ Protected => 1,
1493
1518
  PrintConv => {
1494
1519
  256 => 'Off',
1495
1520
  257 => 'Auto',
@@ -1500,17 +1525,19 @@ my %opcodeInfo = (
1500
1525
  0x7032 => {
1501
1526
  Name => 'VignettingCorrParams', #forum7640
1502
1527
  Notes => 'found in Sony ARW images',
1503
- Protected => 1,
1504
1528
  Writable => 'int16s',
1505
1529
  WriteGroup => 'SubIFD',
1506
1530
  Count => 17,
1531
+ Permanent => 1,
1532
+ Protected => 1,
1507
1533
  },
1508
1534
  0x7034 => {
1509
1535
  Name => 'ChromaticAberrationCorrection',
1510
1536
  Notes => 'found in Sony ARW images',
1511
- Protected => 1,
1512
1537
  Writable => 'int16s',
1513
1538
  WriteGroup => 'SubIFD',
1539
+ Permanent => 1,
1540
+ Protected => 1,
1514
1541
  PrintConv => {
1515
1542
  0 => 'Off',
1516
1543
  1 => 'Auto',
@@ -1520,17 +1547,19 @@ my %opcodeInfo = (
1520
1547
  0x7035 => {
1521
1548
  Name => 'ChromaticAberrationCorrParams', #forum6509
1522
1549
  Notes => 'found in Sony ARW images',
1523
- Protected => 1,
1524
1550
  Writable => 'int16s',
1525
1551
  WriteGroup => 'SubIFD',
1526
1552
  Count => 33,
1553
+ Permanent => 1,
1554
+ Protected => 1,
1527
1555
  },
1528
1556
  0x7036 => {
1529
1557
  Name => 'DistortionCorrection',
1530
1558
  Notes => 'found in Sony ARW images',
1531
- Protected => 1,
1532
1559
  Writable => 'int16s',
1533
1560
  WriteGroup => 'SubIFD',
1561
+ Permanent => 1,
1562
+ Protected => 1,
1534
1563
  PrintConv => {
1535
1564
  0 => 'Off',
1536
1565
  1 => 'Auto',
@@ -1541,10 +1570,38 @@ my %opcodeInfo = (
1541
1570
  0x7037 => {
1542
1571
  Name => 'DistortionCorrParams', #forum6509
1543
1572
  Notes => 'found in Sony ARW images',
1544
- Protected => 1,
1545
1573
  Writable => 'int16s',
1546
1574
  WriteGroup => 'SubIFD',
1547
1575
  Count => 17,
1576
+ Permanent => 1,
1577
+ Protected => 1,
1578
+ },
1579
+ 0x7038 => { #github#195 (Sony ARW)
1580
+ Name => 'SonyRawImageSize',
1581
+ Notes => 'size of actual image in Sony ARW files',
1582
+ Writable => 'int32u',
1583
+ WriteGroup => 'SubIFD',
1584
+ Count => 2,
1585
+ Permanent => 1,
1586
+ Protected => 1,
1587
+ },
1588
+ 0x7310 => { #github#195 (Sony ARW)
1589
+ Name => 'BlackLevel',
1590
+ Notes => 'found in Sony ARW images',
1591
+ Writable => 'int16u',
1592
+ WriteGroup => 'SubIFD',
1593
+ Count => 4,
1594
+ Permanent => 1,
1595
+ Protected => 1,
1596
+ },
1597
+ 0x7313 => { #github#195 (Sony ARW)
1598
+ Name => 'WB_RGGBLevels',
1599
+ Notes => 'found in Sony ARW images',
1600
+ Writable => 'int16s',
1601
+ WriteGroup => 'SubIFD',
1602
+ Count => 4,
1603
+ Permanent => 1,
1604
+ Protected => 1,
1548
1605
  },
1549
1606
  0x74c7 => { #IB (in ARW images from some Sony cameras)
1550
1607
  Name => 'SonyCropTopLeft',
@@ -2955,6 +3012,7 @@ my %opcodeInfo = (
2955
3012
  0xbcc0 => { #13
2956
3013
  Name => 'ImageOffset',
2957
3014
  IsOffset => 1,
3015
+ IsImageData => 1,
2958
3016
  OffsetPair => 0xbcc1, # point to associated byte count
2959
3017
  },
2960
3018
  0xbcc1 => { #13
@@ -2964,6 +3022,7 @@ my %opcodeInfo = (
2964
3022
  0xbcc2 => { #13
2965
3023
  Name => 'AlphaOffset',
2966
3024
  IsOffset => 1,
3025
+ IsImageData => 1,
2967
3026
  OffsetPair => 0xbcc3, # point to associated byte count
2968
3027
  },
2969
3028
  0xbcc3 => { #13
@@ -4706,12 +4765,28 @@ my %subSecConv = (
4706
4765
  0 => 'OtherImageStart',
4707
4766
  1 => 'OtherImageLength',
4708
4767
  },
4768
+ Desire => {
4769
+ 2 => 'OtherImageStart (1)',
4770
+ 3 => 'OtherImageLength (1)',
4771
+ },
4709
4772
  Notes => q{
4710
4773
  this tag is writable, and may be used to update existing embedded images,
4711
4774
  but not create or delete them
4712
4775
  },
4713
- # retrieve the thumbnail from our EXIF data
4776
+ # retrieve all other images
4714
4777
  RawConv => q{
4778
+ if ($val[2] and $val[3]) {
4779
+ my $i = 1;
4780
+ for (;;) {
4781
+ my %val = ( 0 => $$val{2}, 1 => $$val{3} );
4782
+ $self->FoundTag($tagInfo, \%val);
4783
+ ++$i;
4784
+ $$val{2} = "$$val{0} ($i)";
4785
+ last unless defined $$self{VALUE}{$$val{2}};
4786
+ $$val{3} = "$$val{1} ($i)";
4787
+ last unless defined $$self{VALUE}{$$val{3}};
4788
+ }
4789
+ }
4715
4790
  @grps = $self->GetGroup($$val{0});
4716
4791
  Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"OtherImage");
4717
4792
  },
@@ -5851,15 +5926,17 @@ sub ProcessExif($$$)
5851
5926
  my $base = $$dirInfo{Base} || 0;
5852
5927
  my $firstBase = $base;
5853
5928
  my $raf = $$dirInfo{RAF};
5854
- my $verbose = $et->Options('Verbose');
5855
- my $validate = $et->Options('Validate');
5856
- my $saveFormat = $et->Options('SaveFormat');
5929
+ my ($verbose,$validate,$saveFormat) = @{$$et{OPTIONS}}{qw(Verbose Validate SaveFormat)};
5857
5930
  my $htmlDump = $$et{HTML_DUMP};
5858
5931
  my $success = 1;
5859
- my ($tagKey, $dirSize, $makerAddr, $strEnc, %offsetInfo, $offName, $nextOffName);
5932
+ my ($tagKey, $dirSize, $makerAddr, $strEnc, %offsetInfo, $offName, $nextOffName, $doMD5);
5860
5933
  my $inMakerNotes = $$tagTablePtr{GROUPS}{0} eq 'MakerNotes';
5861
5934
  my $isExif = ($tagTablePtr eq \%Image::ExifTool::Exif::Main);
5862
5935
 
5936
+ # set flag to calculate image data MD5 if requested
5937
+ $doMD5 = 1 if $$et{ImageDataMD5} and (($$et{FILE_TYPE} eq 'TIFF' and not $base and not $inMakerNotes) or
5938
+ ($$et{FILE_TYPE} eq 'RAF' and $dirName eq 'FujiIFD'));
5939
+
5863
5940
  # set encoding to assume for strings
5864
5941
  $strEnc = $et->Options('CharsetEXIF') if $$tagTablePtr{GROUPS}{0} eq 'EXIF';
5865
5942
 
@@ -5868,7 +5945,12 @@ sub ProcessExif($$$)
5868
5945
  $isExif and $$et{FILE_TYPE} =~ /^(JPEG|TIFF|PSD)$/)
5869
5946
  {
5870
5947
  my $path = $et->MetadataPath();
5871
- unless ($path =~ /^(JPEG-APP1-IFD0|TIFF-IFD0|PSD-EXIFInfo-IFD0)$/) {
5948
+ if ($path =~ /^(JPEG-APP1-IFD0|TIFF-IFD0|PSD-EXIFInfo-IFD0)$/) {
5949
+ unless ($$et{DOC_NUM}) {
5950
+ $et->Warn("Duplicate EXIF at $path") if $$et{HasExif};
5951
+ $$et{HasExif} = 1;
5952
+ }
5953
+ } else {
5872
5954
  if ($Image::ExifTool::MWG::strict) {
5873
5955
  $et->Warn("Ignored non-standard EXIF at $path");
5874
5956
  return 0;
@@ -6332,10 +6414,10 @@ sub ProcessExif($$$)
6332
6414
  $tval .= " ($rational)" if defined $rational;
6333
6415
  if ($htmlDump) {
6334
6416
  my ($tagName, $colName);
6335
- if ($tagID == 0x927c and $dirName eq 'ExifIFD') {
6336
- $tagName = 'MakerNotes';
6337
- } elsif ($tagInfo) {
6417
+ if ($tagInfo) {
6338
6418
  $tagName = $$tagInfo{Name};
6419
+ } elsif ($tagID == 0x927c and $dirName eq 'ExifIFD') {
6420
+ $tagName = 'MakerNotes';
6339
6421
  } else {
6340
6422
  $tagName = sprintf("Tag 0x%.4x",$tagID);
6341
6423
  }
@@ -6410,6 +6492,9 @@ sub ProcessExif($$$)
6410
6492
  }
6411
6493
  # add value data block (underlining maker notes data)
6412
6494
  $et->HDump($exifDumpPos,$size,"$tagName value",'SAME', $flag, $sid);
6495
+ if ($subdir and $$tagInfo{MakerNotes} and $$tagInfo{NotIFD}) {
6496
+ $et->HDump($exifDumpPos,$size,"$tagName value",undef,undef,$$dirInfo{OffsetName});
6497
+ }
6413
6498
  }
6414
6499
  } else {
6415
6500
  if ($tagID <= $lastID and not $inMakerNotes) {
@@ -6696,7 +6781,7 @@ sub ProcessExif($$$)
6696
6781
  }
6697
6782
  $val = join(' ', @vals);
6698
6783
  }
6699
- if ($validate) {
6784
+ if ($validate or $doMD5) {
6700
6785
  if ($$tagInfo{OffsetPair}) {
6701
6786
  $offsetInfo{$tagID} = [ $tagInfo, $val ];
6702
6787
  } elsif ($saveForValidate{$tagID} and $isExif) {
@@ -6714,9 +6799,11 @@ sub ProcessExif($$$)
6714
6799
  }
6715
6800
  }
6716
6801
 
6717
- # validate image data offsets for this IFD
6718
- if ($validate and %offsetInfo) {
6719
- Image::ExifTool::Validate::ValidateOffsetInfo($et, \%offsetInfo, $$dirInfo{DirName}, $inMakerNotes)
6802
+ if (%offsetInfo) {
6803
+ # calculate image data MD5 if requested
6804
+ AddImageDataMD5($et, $dirInfo, \%offsetInfo) if $doMD5;
6805
+ # validate image data offsets for this IFD (note: modifies %offsetInfo)
6806
+ Image::ExifTool::Validate::ValidateOffsetInfo($et, \%offsetInfo, $dirName, $inMakerNotes) if $validate;
6720
6807
  }
6721
6808
 
6722
6809
  # scan for subsequent IFD's if specified
@@ -21,7 +21,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
21
21
  use Image::ExifTool::Exif;
22
22
  use Image::ExifTool::ASF; # for GetGUID()
23
23
 
24
- $VERSION = '1.41';
24
+ $VERSION = '1.44';
25
25
 
26
26
  sub ProcessFPX($$);
27
27
  sub ProcessFPXR($$$);
@@ -318,6 +318,10 @@ my %fpxFileType = (
318
318
  unrecognized Windows Compound Binary file as a FlashPix (FPX) file. See
319
319
  L<http://graphcomp.com/info/specs/livepicture/fpx.pdf> for the FlashPix
320
320
  specification.
321
+
322
+ Note that Microsoft is not consistent with the time zone used for some
323
+ date/time tags, and it may be either UTC or local time depending on the
324
+ software used to create the file.
321
325
  },
322
326
  "\x05SummaryInformation" => {
323
327
  Name => 'SummaryInfo',
@@ -483,10 +487,29 @@ my %fpxFileType = (
483
487
  },
484
488
  IeImg => {
485
489
  Name => 'EmbeddedImage',
486
- Notes => 'embedded images in Scene7 vignette VNT files',
490
+ Notes => q{
491
+ embedded images in Scene7 vignette VNT files. The EmbeddedImage Class and
492
+ Rectangle are also extracted for applicable images, and may be associated
493
+ with the corresponding EmbeddedImage via the family 3 group name
494
+ },
487
495
  Groups => { 2 => 'Preview' },
488
496
  Binary => 1,
489
497
  },
498
+ IeImg_class => {
499
+ Name => 'EmbeddedImageClass',
500
+ Notes => q{
501
+ not a real tag. This information is extracted if available for the
502
+ corresponding EmbeddedImage from the Contents of a VNT file
503
+ },
504
+ # eg. "Cache", "Mask"
505
+ },
506
+ IeImg_rect => { #
507
+ Name => 'EmbeddedImageRectangle',
508
+ Notes => q{
509
+ not a real tag. This information is extracted if available for the
510
+ corresponding EmbeddedImage from the Contents of a VNT file
511
+ },
512
+ },
490
513
  );
491
514
 
492
515
  # Summary Information properties
@@ -1059,6 +1082,7 @@ my %fpxFileType = (
1059
1082
  %Image::ExifTool::FlashPix::Contents = (
1060
1083
  PROCESS_PROC => \&ProcessProperties,
1061
1084
  GROUPS => { 2 => 'Image' },
1085
+ OriginalFileName => { Name => 'OriginalFileName', Hidden => 1 }, # (not a real tag -- extracted from Contents of VNT file)
1062
1086
  );
1063
1087
 
1064
1088
  # CompObj tags
@@ -1537,11 +1561,46 @@ sub ProcessContents($$$)
1537
1561
  my $isFLA;
1538
1562
 
1539
1563
  # all of my FLA samples contain "Contents" data, and no other FPX-like samples have
1540
- # this, but check the data for a familiar pattern to be sure this is FLA: the
1541
- # Contents of all of my FLA samples start with two bytes (0x29,0x38,0x3f,0x43 or 0x47,
1542
- # then 0x01) followed by a number of zero bytes (from 0x18 to 0x26 of them, related
1543
- # somehow to the value of the first byte), followed by the string "DocumentPage"
1544
- $isFLA = 1 if $$dataPt =~ /^..\0+\xff\xff\x01\0\x0d\0CDocumentPage/s;
1564
+ # this (except Scene7 VNT viles), but check the data for a familiar pattern to be
1565
+ # sure this is FLA: the Contents of all of my FLA samples start with two bytes
1566
+ # (0x29,0x38,0x3f,0x43 or 0x47, then 0x01) followed by a number of zero bytes
1567
+ # (from 0x18 to 0x26 of them, related somehow to the value of the first byte),
1568
+ # followed by the string "DocumentPage"
1569
+ if ($$dataPt =~ /^..\0+\xff\xff\x01\0\x0d\0CDocumentPage/s) {
1570
+ $isFLA = 1;
1571
+ } elsif ($$dataPt =~ /^\0{4}.(.{1,255})\x60\xa1\x3f\x22\0{5}(.{8})/sg) {
1572
+ # this looks like a VNT file
1573
+ $et->OverrideFileType('VNT', 'image/x-vignette');
1574
+ # hack to set proper file description (extension is the same for V-Note files)
1575
+ $Image::ExifTool::static_vars{OverrideFileDescription}{VNT} = 'Scene7 Vignette',
1576
+ my $name = $1;
1577
+ my ($w, $h) = unpack('V2',$2);
1578
+ $et->FoundTag(ImageWidth => $w);
1579
+ $et->FoundTag(ImageHeight => $h);
1580
+ $et->HandleTag($tagTablePtr, OriginalFileName => $name);
1581
+ if ($$dataPt =~ /\G\x01\0{4}(.{12})/sg) {
1582
+ # (first 4 bytes seem to be number of objects, next 4 bytes are zero, then ICC size)
1583
+ my $size = unpack('x8V', $1);
1584
+ # (not useful?) $et->FoundTag(NumObjects => $num);
1585
+ if ($size and pos($$dataPt) + $size < length($$dataPt)) {
1586
+ my $dat = substr($$dataPt, pos($$dataPt), $size);
1587
+ $et->FoundTag(ICC_Profile => $dat);
1588
+ pos($$dataPt) += $size;
1589
+ }
1590
+ $$et{IeImg_lkup} = { };
1591
+ $$et{IeImg_class} = { };
1592
+ # - the byte before \x80 is 0x0d, 0x11 or 0x1f for separate images in my samples,
1593
+ # and 0x1c or 0x23 for inline masks
1594
+ # - the byte after \xff\xff is 0x3b in my samples for $1 containing 'VnMask' or 'VnCache'
1595
+ while ($$dataPt =~ /\x0bTargetRole1(?:.\x80|\xff\xff.\0.\0Vn(\w+))\0\0\x01.{4}(.{24})/sg) {
1596
+ my ($index, @coords) = unpack('Vx4V4', $2);
1597
+ next if $index == 0xffffffff;
1598
+ $$et{IeImg_lkup}{$index} and $et->WarnOnce('Duplicate image index');
1599
+ $$et{IeImg_lkup}{$index} = "@coords";
1600
+ $$et{IeImg_class}{$index} = $1 if $1;
1601
+ }
1602
+ }
1603
+ }
1545
1604
 
1546
1605
  # do a brute-force scan of the "Contents" for UTF-16 XMP
1547
1606
  # (this may always be little-endian, but allow for either endianness)
@@ -2337,8 +2396,28 @@ sub ProcessFPX($$)
2337
2396
  );
2338
2397
  my $subTablePtr = GetTagTable($$subdir{TagTable});
2339
2398
  $et->ProcessDirectory(\%dirInfo, $subTablePtr, $$subdir{ProcessProc});
2399
+ } elsif (defined $size and $size > length($buff)) {
2400
+ $et->WarnOnce('Truncated object');
2340
2401
  } else {
2341
- $et->FoundTag($tagInfo, $buff);
2402
+ $buff = substr($buff, 0, $size) if defined $size and $size < length($buff);
2403
+ if ($tag =~ /^IeImg_0*(\d+)$/) {
2404
+ # set document number for embedded images and their positions (if available, VNT files)
2405
+ my $num = $1;
2406
+ $$et{DOC_NUM} = ++$$et{DOC_COUNT};
2407
+ $et->FoundTag($tagInfo, $buff);
2408
+ if ($$et{IeImg_lkup} and $$et{IeImg_lkup}{$num}) {
2409
+ # save position of this image
2410
+ $et->HandleTag($tagTablePtr, IeImg_rect => $$et{IeImg_lkup}{$num});
2411
+ delete $$et{IeImg_lkup}{$num};
2412
+ if ($$et{IeImg_class} and $$et{IeImg_class}{$num}) {
2413
+ $et->HandleTag($tagTablePtr, IeImg_class => $$et{IeImg_class}{$num});
2414
+ delete $$et{IeImg_class}{$num};
2415
+ }
2416
+ }
2417
+ delete $$et{DOC_NUM};
2418
+ } else {
2419
+ $et->FoundTag($tagInfo, $buff);
2420
+ }
2342
2421
  }
2343
2422
  # save object index number for all found tags
2344
2423
  my $num2 = $$et{NUM_FOUND};
@@ -2380,7 +2459,7 @@ sub ProcessFPX($$)
2380
2459
  }
2381
2460
  $$et{INDENT} = $oldIndent if $verbose;
2382
2461
  # try to better identify the file type
2383
- if ($$et{VALUE}{FileType} eq 'FPX') {
2462
+ if ($$et{FileType} eq 'FPX') {
2384
2463
  my $val = $$et{CompObjUserType} || $$et{Software};
2385
2464
  if ($val) {
2386
2465
  my %type = ( '^3ds Max' => 'MAX', Word => 'DOC', PowerPoint => 'PPT', Excel => 'XLS' );
@@ -2395,6 +2474,10 @@ sub ProcessFPX($$)
2395
2474
  # process Word document table
2396
2475
  ProcessDocumentTable($et);
2397
2476
 
2477
+ if ($$et{IeImg_lkup} and %{$$et{IeImg_lkup}}) {
2478
+ $et->Warn('Image positions exist without corresponding images');
2479
+ }
2480
+
2398
2481
  return 1;
2399
2482
  }
2400
2483
 
@@ -31,7 +31,7 @@ use vars qw($VERSION);
31
31
  use Image::ExifTool qw(:DataAccess :Utils);
32
32
  use Image::ExifTool::Exif;
33
33
 
34
- $VERSION = '1.86';
34
+ $VERSION = '1.87';
35
35
 
36
36
  sub ProcessFujiDir($$$);
37
37
  sub ProcessFaceRec($$$);
@@ -808,6 +808,7 @@ my %faceCategories = (
808
808
  0x00 => 'Normal',
809
809
  0x10 => 'F-log',
810
810
  0x20 => 'HLG',
811
+ 0x30 => 'F-log2', #forum14384
811
812
  },
812
813
  },
813
814
  0x3804 => { #forum10037
@@ -1371,6 +1372,7 @@ my %faceCategories = (
1371
1372
  0xf007 => {
1372
1373
  Name => 'StripOffsets',
1373
1374
  IsOffset => 1,
1375
+ IsImageData => 1,
1374
1376
  OffsetPair => 0xf008, # point to associated byte counts
1375
1377
  },
1376
1378
  0xf008 => {
@@ -1669,11 +1671,11 @@ sub ProcessRAF($$)
1669
1671
  my ($rafNum, $ifdNum) = ('','');
1670
1672
  foreach $offset (0x5c, 0x64, 0x78, 0x80) {
1671
1673
  last if $offset >= $jpos;
1672
- unless ($raf->Seek($offset, 0) and $raf->Read($buff, 4)) {
1674
+ unless ($raf->Seek($offset, 0) and $raf->Read($buff, 8)) {
1673
1675
  $warn = 1;
1674
1676
  last;
1675
1677
  }
1676
- my $start = unpack('N',$buff);
1678
+ my ($start, $len) = unpack('N2',$buff);
1677
1679
  next unless $start;
1678
1680
  if ($offset == 0x64 or $offset == 0x80) {
1679
1681
  # parse FujiIFD directory
@@ -1684,7 +1686,10 @@ sub ProcessRAF($$)
1684
1686
  $$et{SET_GROUP1} = "FujiIFD$ifdNum";
1685
1687
  my $tagTablePtr = GetTagTable('Image::ExifTool::FujiFilm::IFD');
1686
1688
  # this is TIFF-format data only for some models, so no warning if it fails
1687
- $et->ProcessTIFF(\%dirInfo, $tagTablePtr, \&Image::ExifTool::ProcessTIFF);
1689
+ unless ($et->ProcessTIFF(\%dirInfo, $tagTablePtr, \&Image::ExifTool::ProcessTIFF)) {
1690
+ # do MD5 of image data if necessary
1691
+ $et->ImageDataMD5($raf, $len, 'raw') if $$et{ImageDataMD5} and $raf->Seek($start,0);
1692
+ }
1688
1693
  delete $$et{SET_GROUP1};
1689
1694
  $ifdNum = ($ifdNum || 1) + 1;
1690
1695
  } else {
@@ -482,13 +482,13 @@ sub PrintTimeStamp($)
482
482
  #------------------------------------------------------------------------------
483
483
  # Convert degrees to DMS, or whatever the current settings are
484
484
  # Inputs: 0) ExifTool reference, 1) Value in degrees,
485
- # 2) format code (0=no format, 1=CoordFormat, 2=XMP format)
485
+ # 2) format code (0=no format, 1=CoordFormat, 2=XMP format, 3=signed unformatted)
486
486
  # 3) 'N' or 'E' if sign is significant and N/S/E/W should be added
487
487
  # Returns: DMS string
488
488
  sub ToDMS($$;$$)
489
489
  {
490
490
  my ($et, $val, $doPrintConv, $ref) = @_;
491
- my ($fmt, @fmt, $num, $sign, $rtnVal);
491
+ my ($fmt, @fmt, $num, $sign, $rtnVal, $neg);
492
492
 
493
493
  unless (length $val) {
494
494
  # don't convert an empty value
@@ -505,6 +505,10 @@ sub ToDMS($$;$$)
505
505
  }
506
506
  $ref = " $ref" unless $doPrintConv and $doPrintConv eq '2';
507
507
  } else {
508
+ if ($doPrintConv and $doPrintConv eq '3') {
509
+ $neg = 1 if $val < 0;
510
+ $doPrintConv = 0;
511
+ }
508
512
  $val = abs($val);
509
513
  $ref = '';
510
514
  }
@@ -554,6 +558,7 @@ sub ToDMS($$;$$)
554
558
  # trim trailing zeros in XMP
555
559
  $rtnVal =~ s/(\d)0+$ref$/$1$ref/ if $doPrintConv eq '2';
556
560
  } else {
561
+ $neg and map { $_ *= -1 } @c;
557
562
  $rtnVal = "@c$ref";
558
563
  }
559
564
  return $rtnVal;