exiftool-vendored.pl 13.17.0 → 13.25.1

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 (50) hide show
  1. package/bin/Changes +102 -7
  2. package/bin/MANIFEST +14 -0
  3. package/bin/META.json +1 -1
  4. package/bin/META.yml +1 -1
  5. package/bin/README +46 -46
  6. package/bin/config_files/example.config +1 -1
  7. package/bin/exiftool +211 -121
  8. package/bin/lib/Image/ExifTool/Apple.pm +12 -2
  9. package/bin/lib/Image/ExifTool/BuildTagLookup.pm +2 -2
  10. package/bin/lib/Image/ExifTool/CanonRaw.pm +1 -1
  11. package/bin/lib/Image/ExifTool/DJI.pm +190 -29
  12. package/bin/lib/Image/ExifTool/DarwinCore.pm +22 -11
  13. package/bin/lib/Image/ExifTool/EXE.pm +2 -9
  14. package/bin/lib/Image/ExifTool/GM.pm +1 -1
  15. package/bin/lib/Image/ExifTool/GPS.pm +3 -3
  16. package/bin/lib/Image/ExifTool/Geolocation.dat +0 -0
  17. package/bin/lib/Image/ExifTool/GoPro.pm +86 -48
  18. package/bin/lib/Image/ExifTool/ICO.pm +2 -2
  19. package/bin/lib/Image/ExifTool/JPEG.pm +5 -1
  20. package/bin/lib/Image/ExifTool/JSON.pm +5 -1
  21. package/bin/lib/Image/ExifTool/Kodak.pm +3 -2
  22. package/bin/lib/Image/ExifTool/Nikon.pm +943 -1237
  23. package/bin/lib/Image/ExifTool/Olympus.pm +2 -1
  24. package/bin/lib/Image/ExifTool/PCAP.pm +462 -0
  25. package/bin/lib/Image/ExifTool/PDF.pm +10 -1
  26. package/bin/lib/Image/ExifTool/PLIST.pm +92 -29
  27. package/bin/lib/Image/ExifTool/PNG.pm +7 -1
  28. package/bin/lib/Image/ExifTool/Photoshop.pm +2 -2
  29. package/bin/lib/Image/ExifTool/Plot.pm +713 -0
  30. package/bin/lib/Image/ExifTool/Protobuf.pm +24 -11
  31. package/bin/lib/Image/ExifTool/Qualcomm.pm +78 -1
  32. package/bin/lib/Image/ExifTool/QuickTime.pm +347 -318
  33. package/bin/lib/Image/ExifTool/QuickTimeStream.pl +75 -27
  34. package/bin/lib/Image/ExifTool/Sony.pm +33 -14
  35. package/bin/lib/Image/ExifTool/TagLookup.pm +5056 -4967
  36. package/bin/lib/Image/ExifTool/TagNames.pod +443 -334
  37. package/bin/lib/Image/ExifTool/Trailer.pm +3 -3
  38. package/bin/lib/Image/ExifTool/Validate.pm +4 -4
  39. package/bin/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
  40. package/bin/lib/Image/ExifTool/WriteExif.pl +9 -4
  41. package/bin/lib/Image/ExifTool/WritePDF.pl +1 -1
  42. package/bin/lib/Image/ExifTool/WriteQuickTime.pl +58 -5
  43. package/bin/lib/Image/ExifTool/Writer.pl +14 -13
  44. package/bin/lib/Image/ExifTool/XMP.pm +34 -6
  45. package/bin/lib/Image/ExifTool/XMP2.pl +2 -0
  46. package/bin/lib/Image/ExifTool.pm +63 -29
  47. package/bin/lib/Image/ExifTool.pod +83 -86
  48. package/bin/perl-Image-ExifTool.spec +45 -45
  49. package/bin/windows_exiftool.txt +95 -71
  50. package/package.json +6 -3
package/bin/exiftool CHANGED
@@ -11,7 +11,9 @@ use strict;
11
11
  use warnings;
12
12
  require 5.004;
13
13
 
14
- my $version = '13.17';
14
+ my $version = '13.25';
15
+
16
+ $^W = 1; # enable global warnings
15
17
 
16
18
  # add our 'lib' directory to the include list BEFORE 'use Image::ExifTool'
17
19
  my $exePath;
@@ -52,7 +54,7 @@ sub EncodeXML($);
52
54
  sub FormatXML($$$);
53
55
  sub EscapeJSON($;$);
54
56
  sub FormatJSON($$$;$);
55
- sub PrintCSV();
57
+ sub PrintCSV(;$);
56
58
  sub AddGroups($$$$);
57
59
  sub ConvertBinary($);
58
60
  sub IsEqual($$);
@@ -189,6 +191,7 @@ my $outFormat; # -1=Canon format, 0=same-line, 1=tag names, 2=values only
189
191
  my $outOpt; # output file or directory name
190
192
  my $overwriteOrig; # flag to overwrite original file (1=overwrite, 2=in place)
191
193
  my $pause; # pause before returning
194
+ my $plot; # flag for plot output format
192
195
  my $preserveTime; # flag to preserve times of updated files (2=preserve FileCreateDate only)
193
196
  my $progress; # flag to calculate total files to process (0=calculate but don't display)
194
197
  my $progressCount; # count of files processed
@@ -216,6 +219,7 @@ my $structOpt; # output structured XMP information (JSON and XML output onl
216
219
  my $tabFormat; # non-zero for tab output format
217
220
  my $tagOut; # flag for separate text output file for each tag
218
221
  my $textOut; # extension for text output file (or undef for no output)
222
+ my $textOut2; # complete file name for single text output file
219
223
  my $textOverwrite; # flag to overwrite existing text output file (2=append, 3=over+append)
220
224
  my $tmpFile; # temporary file to delete on exit
221
225
  my $tmpText; # temporary text file
@@ -459,8 +463,8 @@ undef %filterExt;
459
463
  undef %ignore;
460
464
  undef %outComma;
461
465
  undef %outTrailer;
462
- undef %printFmt;
463
466
  undef %preserveTime;
467
+ undef %printFmt;
464
468
  undef %seqFileDir;
465
469
  undef %setTags;
466
470
  undef %setTagsList;
@@ -1176,6 +1180,7 @@ for (;;) {
1176
1180
  }
1177
1181
  /^overwrite_original$/i and $overwriteOrig = 1, next;
1178
1182
  /^overwrite_original_in_place$/i and $overwriteOrig = 2, next;
1183
+ /^plot$/i and require Image::ExifTool::Plot and $plot = Image::ExifTool::Plot->new, next;
1179
1184
  if (/^p(-?)$/ or /^printformat(-?)$/i) {
1180
1185
  my $fmt = shift;
1181
1186
  if ($pass) {
@@ -1391,7 +1396,8 @@ for (;;) {
1391
1396
  # add geotag/geosync/geolocate commands first
1392
1397
  unshift @newValues, pop @newValues;
1393
1398
  if (lc $2 eq 'geotag' and (not defined $addGeotime or $addGeotime) and length $val) {
1394
- $addGeotime = ($1 || '') . 'Geotime<DateTimeOriginal#';
1399
+ $addGeotime = [ ($1 || '') . 'Geotime<DateTimeOriginal#',
1400
+ ($1 || '') . 'Geotime<SubSecDateTimeOriginal#' ];
1395
1401
  }
1396
1402
  }
1397
1403
  }
@@ -1465,15 +1471,10 @@ if (not @files and not $outOpt and not @newValues) {
1465
1471
  # print help
1466
1472
  unless ((@tags and not $outOpt) or @files or @newValues or $geoOnly) {
1467
1473
  if ($doGlob and $doGlob == 2) {
1468
- Warn "No matching files\n";
1469
- $rtnVal = 1;
1470
- next;
1471
- }
1472
- if ($outOpt) {
1473
- Warn "Nothing to write\n";
1474
- $rtnVal = 1;
1474
+ Error "No matching files\n";
1475
1475
  next;
1476
1476
  }
1477
+ $outOpt and Error("Nothing to write\n"), next;
1477
1478
  unless ($helped) {
1478
1479
  # catch warnings if we have problems running perldoc
1479
1480
  local $SIG{'__WARN__'} = sub { $evalWarning = $_[0] };
@@ -1498,38 +1499,34 @@ unless ((@tags and not $outOpt) or @files or @newValues or $geoOnly) {
1498
1499
  if (defined $deleteOrig and (@newValues or @tags)) {
1499
1500
  if (not @newValues) {
1500
1501
  my $verb = $deleteOrig ? 'deleting' : 'restoring from';
1501
- Warn "Can't specify tags when $verb originals\n";
1502
+ Error "Can't specify tags when $verb originals\n";
1502
1503
  } elsif ($deleteOrig) {
1503
- Warn "Can't use -delete_original when writing.\n";
1504
- Warn "Maybe you meant -overwrite_original ?\n";
1504
+ Error "Can't use -delete_original when writing.\n";
1505
+ Error "Maybe you meant -overwrite_original ?\n";
1505
1506
  } else {
1506
- Warn "It makes no sense to use -restore_original when writing\n";
1507
+ Error "It makes no sense to use -restore_original when writing\n";
1507
1508
  }
1508
- $rtnVal = 1;
1509
1509
  next;
1510
1510
  }
1511
1511
 
1512
1512
  if ($overwriteOrig > 1 and $outOpt) {
1513
- Warn "Can't overwrite in place when -o option is used\n";
1514
- $rtnVal = 1;
1513
+ Error "Can't overwrite in place when -o option is used\n";
1515
1514
  next;
1516
1515
  }
1517
1516
 
1518
- if (($tagOut or defined $diff) and ($csv or $json or %printFmt or $tabFormat or $xml or
1517
+ if (($tagOut or defined $diff) and ($csv or $json or %printFmt or $tabFormat or $xml or $plot or
1519
1518
  ($verbose and $html)))
1520
1519
  {
1521
1520
  my $opt = $tagOut ? '-W' : '-diff';
1522
- Warn "Sorry, $opt may not be combined with -csv, -htmlDump, -j, -p, -t or -X\n";
1523
- $rtnVal = 1;
1521
+ Error "Sorry, $opt may not be combined with -csv, -htmlDump, -j, -p, -t or -X\n";
1524
1522
  next;
1525
1523
  }
1526
1524
 
1527
1525
  if ($csv and $csv eq 'CSV' and not $isWriting) {
1528
1526
  $json = 0; # (not compatible)
1529
1527
  if ($textOut) {
1530
- Warn "Sorry, -w may not be combined with -csv\n";
1531
- $rtnVal = 1;
1532
- next;
1528
+ $textOut2 = $textOut;
1529
+ undef $textOut;
1533
1530
  }
1534
1531
  if ($binaryOutput) {
1535
1532
  $binaryOutput = 0;
@@ -1541,6 +1538,32 @@ if ($csv and $csv eq 'CSV' and not $isWriting) {
1541
1538
  }
1542
1539
  require Image::ExifTool::XMP if $setCharset;
1543
1540
  }
1541
+ if ($plot and $textOut) {
1542
+ $textOut2 = $textOut;
1543
+ undef $textOut;
1544
+ }
1545
+ if ($textOut2) {
1546
+ if ($textOverwrite > 1) {
1547
+ Error "Can not append to multi-file output format\n";
1548
+ undef $textOut2;
1549
+ next;
1550
+ }
1551
+ if (not $textOverwrite and $mt->Exists($textOut2, 1)) {
1552
+ Error "Output file $textOut2 already exists\n";
1553
+ undef $textOut2;
1554
+ next;
1555
+ }
1556
+ # make sure we can write the output text file before processing all input files
1557
+ CreateDirectory($textOut2); # create directory if necessary
1558
+ if ($mt->Open(\*OUTFILE, $textOut2, '>')) {
1559
+ close(\*OUTFILE);
1560
+ unlink($textOut2); # (this was just a test)
1561
+ } else {
1562
+ Error("Error creating $textOut2\n");
1563
+ undef $textOut2;
1564
+ next;
1565
+ }
1566
+ }
1544
1567
 
1545
1568
  if ($escapeHTML or $json) {
1546
1569
  # must be UTF8 for HTML conversion and JSON output
@@ -1554,7 +1577,7 @@ if ($escapeHTML or $json) {
1554
1577
  # set sort option
1555
1578
  if ($sortOpt) {
1556
1579
  # (note that -csv sorts alphabetically by default anyway if more than 1 file)
1557
- my $sort = ($outFormat > 0 or $xml or $json or $csv) ? 'Tag' : 'Descr';
1580
+ my $sort = ($outFormat > 0 or $xml or $json or $csv or $plot) ? 'Tag' : 'Descr';
1558
1581
  $mt->Options(Sort => $sort, Sort2 => $sort);
1559
1582
  }
1560
1583
 
@@ -1565,7 +1588,11 @@ if ($mt->Options('Struct') and not $structOpt) {
1565
1588
  }
1566
1589
 
1567
1590
  # set up for RDF/XML, JSON and PHP output formats
1568
- if ($xml) {
1591
+ if ($plot) {
1592
+ undef $joinLists;
1593
+ $mt->Options(List => 1);
1594
+ $plot->Settings($mt->Options('Plot'));
1595
+ } elsif ($xml) {
1569
1596
  require Image::ExifTool::XMP; # for EscapeXML()
1570
1597
  my $charset = $mt->Options('Charset');
1571
1598
  # standard XML encoding names for supported Charset settings
@@ -1637,11 +1664,10 @@ if (Image::ExifTool::IsPC()) {
1637
1664
  unless (@files) {
1638
1665
  unless ($outOpt) {
1639
1666
  if ($doGlob and $doGlob == 2) {
1640
- Warn "No matching files\n";
1667
+ Error "No matching files\n";
1641
1668
  } else {
1642
- Warn "No file specified\n";
1669
+ Error "No file specified\n";
1643
1670
  }
1644
- $rtnVal = 1;
1645
1671
  next;
1646
1672
  }
1647
1673
  push @files, ''; # create file from nothing
@@ -1670,8 +1696,9 @@ if (@newValues) {
1670
1696
  # assume -geotime value if -geotag specified without -geotime
1671
1697
  if ($addGeotime) {
1672
1698
  AddSetTagsFile($setTagsFile = '@') unless $setTagsFile and $setTagsFile eq '@';
1673
- push @{$setTags{$setTagsFile}}, $addGeotime;
1674
- $verbose and print $vout qq{Argument "-$addGeotime" is assumed\n};
1699
+ push @{$setTags{$setTagsFile}}, @$addGeotime;
1700
+ my @a = map qq("-$_"), @$addGeotime;
1701
+ $verbose and print $vout 'Arguments ',join(' and ', @a)," are assumed\n";
1675
1702
  }
1676
1703
  my %setTagsIndex;
1677
1704
  # add/delete option lookup
@@ -1703,8 +1730,7 @@ if (@newValues) {
1703
1730
  next; # set tags from dynamic file later
1704
1731
  }
1705
1732
  unless ($mt->Exists($newVal) or $newVal eq '-') {
1706
- Warn "File '${newVal}' does not exist for -tagsFromFile option\n";
1707
- $rtnVal = 1;
1733
+ Error "File '${newVal}' does not exist for -tagsFromFile option\n";
1708
1734
  next Command;
1709
1735
  }
1710
1736
  my $setTags = $setTags{$newVal};
@@ -1768,19 +1794,20 @@ if (@newValues) {
1768
1794
  }
1769
1795
  }
1770
1796
  unless ($isWriting or $outOpt or @tags) {
1771
- Warn "Nothing to do.\n";
1772
- $rtnVal = 1;
1797
+ Error "Nothing to do.\n";
1773
1798
  next;
1774
1799
  }
1775
1800
  } elsif (grep /^(\*:)?\*$/, @exclude) {
1776
- Warn "All tags excluded -- nothing to do.\n";
1777
- $rtnVal = 1;
1801
+ Error "All tags excluded -- nothing to do.\n";
1778
1802
  next;
1779
1803
  }
1780
1804
  if ($isWriting) {
1781
1805
  if (defined $diff) {
1782
1806
  Error "Can't use -diff option when writing tags\n";
1783
1807
  next;
1808
+ } elsif ($plot) {
1809
+ Error "Can't use -plot option when writing tags\n";
1810
+ next;
1784
1811
  } elsif (@tags and not $outOpt and not $csv) {
1785
1812
  my ($tg, $s) = @tags > 1 ? ("$tags[0] ...", 's') : ($tags[0], '');
1786
1813
  Warn "Ignored superfluous tag name$s or invalid option$s: -$tg\n";
@@ -1929,9 +1956,6 @@ ProcessFiles($mt);
1929
1956
 
1930
1957
  Error "No file with specified extension\n" if $filtered and not $validFile;
1931
1958
 
1932
- # print CSV information if necessary
1933
- PrintCSV() if $csv and not $isWriting;
1934
-
1935
1959
  # print folder/file trailer if necessary
1936
1960
  if ($textOut) {
1937
1961
  foreach (keys %outTrailer) {
@@ -1947,6 +1971,37 @@ if ($textOut) {
1947
1971
  } else {
1948
1972
  print $sectTrailer if $sectTrailer;
1949
1973
  print $fileTrailer if $fileTrailer and not $fileHeader;
1974
+ # print CSV or SVG output file if necessary
1975
+ my ($fp, $err);
1976
+ if ($textOut2) {
1977
+ if ($mt->Open(\*OUTFILE, $textOut2, '>')) {
1978
+ $fp = \*OUTFILE;
1979
+ } else {
1980
+ Error("Error creating $textOut2\n");
1981
+ $err = 1;
1982
+ }
1983
+ }
1984
+ unless ($err) {
1985
+ PrintCSV($fp) if $csv and not $isWriting;
1986
+ # print SVG plot
1987
+ if ($plot) {
1988
+ $plot->Draw($fp || \*STDOUT);
1989
+ if ($$plot{Error}) {
1990
+ Error("Error: $$plot{Error}\n");
1991
+ $err = 1;
1992
+ } elsif ($$plot{Warn}) {
1993
+ Warn("Warning: $$plot{Warn}\n");
1994
+ }
1995
+ }
1996
+ }
1997
+ if ($fp) {
1998
+ close($fp) or $err = 1;
1999
+ if ($err) {
2000
+ $mt->Unlink($textOut2);
2001
+ } else {
2002
+ $created{$textOut2} = 1;
2003
+ }
2004
+ }
1950
2005
  }
1951
2006
 
1952
2007
  my $totWr = $countGoodWr + $countBadWr + $countSameWr + $countCopyWr +
@@ -1991,7 +2046,7 @@ if (defined $deleteOrig) {
1991
2046
  # print summary
1992
2047
  my $tot = $count + $countBad;
1993
2048
  if ($countDir or $totWr or $countFailed or $tot > 1 or $textOut or %countLink) {
1994
- my $o = (($html or $json or $xml or %printFmt or $csv) and not $textOut) ? \*STDERR : $vout;
2049
+ my $o = (($html or $json or $xml or %printFmt or $csv or $plot) and not $textOut) ? \*STDERR : $vout;
1995
2050
  printf($o "%5d directories scanned\n", $countDir) if $countDir;
1996
2051
  printf($o "%5d directories created\n", $countNewDir) if $countNewDir;
1997
2052
  printf($o "%5d files failed condition\n", $countFailed) if $countFailed;
@@ -2003,7 +2058,7 @@ if (defined $deleteOrig) {
2003
2058
  printf($o "%5d files weren't created due to errors\n", $countBadCr) if $countBadCr;
2004
2059
  printf($o "%5d image files read\n", $count) if ($tot+$countFailed)>1 or ($countDir and not $totWr);
2005
2060
  printf($o "%5d files could not be read\n", $countBad) if $countBad;
2006
- printf($o "%5d output files created\n", scalar(keys %created)) if $textOut;
2061
+ printf($o "%5d output files created\n", scalar(keys %created)) if $textOut or $textOut2;
2007
2062
  printf($o "%5d output files appended\n", scalar(keys %appended)) if %appended;
2008
2063
  printf($o "%5d hard links created\n", $countLink{Hard} || 0) if $countLink{Hard} or $countLink{BadHard};
2009
2064
  printf($o "%5d hard links could not be created\n", $countLink{BadHard}) if $countLink{BadHard};
@@ -2208,7 +2263,7 @@ sub GetImageInfo($$)
2208
2263
 
2209
2264
  my $lineCount = 0;
2210
2265
  my ($fp, $outfile, $append);
2211
- if ($textOut and ($verbose or $et->Options('PrintCSV')) and not ($tagOut or defined $diff)) {
2266
+ if ($textOut and ($verbose or $et->Options('PrintCSV')) and not ($tagOut or defined $diff or $plot)) {
2212
2267
  ($fp, $outfile, $append) = OpenOutputFile($orig);
2213
2268
  $fp or EFile($file), ++$countBad, return;
2214
2269
  # delete file if we exit prematurely (unless appending)
@@ -2248,7 +2303,7 @@ sub GetImageInfo($$)
2248
2303
  }
2249
2304
  # print file/progress message
2250
2305
  my $o;
2251
- unless ($binaryOutput or $textOut or %printFmt or $html > 1 or $csv) {
2306
+ unless ($binaryOutput or $textOut or %printFmt or $html > 1 or $csv or $plot) {
2252
2307
  if ($html) {
2253
2308
  require Image::ExifTool::HTML;
2254
2309
  my $f = Image::ExifTool::HTML::EscapeHTML($file);
@@ -2351,7 +2406,7 @@ sub GetImageInfo($$)
2351
2406
  unless (defined $outfile or $tagOut) {
2352
2407
  ($fp, $outfile, $append) = OpenOutputFile($orig);
2353
2408
  $fp or EFile($file), ++$countBad, return;
2354
- $tmpText = $outfile unless $append;
2409
+ $tmpText = $outfile if defined $outfile and not $append;
2355
2410
  }
2356
2411
 
2357
2412
  # print differences if requested
@@ -2462,9 +2517,8 @@ T2: foreach $t2 (@tags2) {
2462
2517
  $done2{$tag2} = 1 if defined $tag2;
2463
2518
  }
2464
2519
  print $fp "(no metadata differences)\n" unless $wasDiff;
2465
- undef $tmpText;
2466
2520
  if (defined $outfile) {
2467
- ++$created{$outfile};
2521
+ $created{$outfile} = 1;
2468
2522
  close($fp);
2469
2523
  undef $tmpText;
2470
2524
  }
@@ -2539,6 +2593,17 @@ T2: foreach $t2 (@tags2) {
2539
2593
  delete $printFmt{HEAD} unless defined $outfile; # print header only once per output file
2540
2594
  my $errs = $et->GetInfo('Warning', 'Error');
2541
2595
  PrintErrors($et, $errs, $file) and EFile($file);
2596
+ } elsif ($plot) {
2597
+ # add points from this file to the plot
2598
+ my $tagExtra = $$et{TAG_EXTRA};
2599
+ my ($tag, %docNum);
2600
+ foreach $tag (keys %$info) {
2601
+ next unless $$tagExtra{$tag} and $$tagExtra{$tag}{G3};
2602
+ $docNum{$tag} = $1 if $$tagExtra{$tag}{G3} =~ /(\d+)/;
2603
+ }
2604
+ $$plot{DocNum} = \%docNum;
2605
+ $$plot{EE} = 1 if $et->Options('ExtractEmbedded');
2606
+ $plot->AddPoints($info, \@foundTags);
2542
2607
  } elsif (not $disableOutput) {
2543
2608
  my ($tag, $line, %noDups, %csvInfo, $bra, $ket, $sep, $quote);
2544
2609
  if ($fp) {
@@ -3771,8 +3836,10 @@ sub FormatCSV($)
3771
3836
 
3772
3837
  #------------------------------------------------------------------------------
3773
3838
  # Print accumulated CSV information
3774
- sub PrintCSV()
3839
+ # Inputs: 0) file ref
3840
+ sub PrintCSV(;$)
3775
3841
  {
3842
+ my $fp = shift || \*STDOUT;
3776
3843
  my ($file, $lcTag, @tags);
3777
3844
 
3778
3845
  @csvTags or @csvTags = sort keys %csvTags;
@@ -3780,7 +3847,7 @@ sub PrintCSV()
3780
3847
  foreach $lcTag (@csvTags) {
3781
3848
  push @tags, FormatCSV($csvTags{$lcTag}) if $csvTags{$lcTag};
3782
3849
  }
3783
- print join($csvDelim, 'SourceFile', @tags), "\n";
3850
+ print $fp join($csvDelim, 'SourceFile', @tags), "\n";
3784
3851
  my $empty = defined($forcePrint) ? $forcePrint : '';
3785
3852
  foreach $file (@csvFiles) {
3786
3853
  my @vals = (FormatCSV($file)); # start with full file name
@@ -3791,7 +3858,7 @@ sub PrintCSV()
3791
3858
  defined $val or push(@vals,$empty), next;
3792
3859
  push @vals, FormatCSV($val);
3793
3860
  }
3794
- print join($csvDelim, @vals), "\n";
3861
+ print $fp join($csvDelim, @vals), "\n";
3795
3862
  }
3796
3863
  }
3797
3864
 
@@ -4125,9 +4192,8 @@ sub ProcessFiles($;$)
4125
4192
  $filtered = 1;
4126
4193
  Progress($vout, "-------- $file (wrong extension)") if $verbose;
4127
4194
  } else {
4128
- Warn "Error: File not found - $file\n";
4195
+ Error "Error: File not found - $file\n";
4129
4196
  FileNotFound($file);
4130
- $rtnVal = 1;
4131
4197
  }
4132
4198
  } else {
4133
4199
  $validFile = 1;
@@ -4886,7 +4952,7 @@ sub PrintTagList($@)
4886
4952
  my $msg = shift;
4887
4953
  print $msg, ":\n" unless $quiet;
4888
4954
  my $tag;
4889
- if ($outFormat < 0 and $msg =~ /file extensions$/ and @_) {
4955
+ if (($outFormat < 0 or $verbose) and $msg =~ /file extensions$/ and @_) {
4890
4956
  foreach $tag (@_) {
4891
4957
  printf(" %-11s %s\n", $tag, GetFileType($tag, 1));
4892
4958
  }
@@ -4989,50 +5055,50 @@ supported by ExifTool (r = read, w = write, c = create):
4989
5055
 
4990
5056
  File Types
4991
5057
  ------------+-------------+-------------+-------------+------------
4992
- 360 r/w | DOCX r | ITC r | NUMBERS r | RAW r/w
4993
- 3FR r | DPX r | J2C r | NXD r | RIFF r
4994
- 3G2 r/w | DR4 r/w/c | JNG r/w | O r | RSRC r
4995
- 3GP r/w | DSS r | JP2 r/w | ODP r | RTF r
4996
- 7Z r | DV r | JPEG r/w | ODS r | RW2 r/w
4997
- A r | DVB r/w | JSON r | ODT r | RWL r/w
4998
- AA r | DVR-MS r | JXL r/w | OFR r | RWZ r
4999
- AAC r | DYLIB r | K25 r | OGG r | RM r
5000
- AAE r | EIP r | KDC r | OGV r | SEQ r
5001
- AAX r/w | EPS r/w | KEY r | ONP r | SKETCH r
5002
- ACR r | EPUB r | LA r | OPUS r | SO r
5003
- AFM r | ERF r/w | LFP r | ORF r/w | SR2 r/w
5004
- AI r/w | EXE r | LIF r | ORI r/w | SRF r
5005
- AIFF r | EXIF r/w/c | LNK r | OTF r | SRW r/w
5006
- APE r | EXR r | LRV r/w | PAC r | SVG r
5007
- ARQ r/w | EXV r/w/c | M2TS r | PAGES r | SWF r
5008
- ARW r/w | F4A/V r/w | M4A/V r/w | PBM r/w | THM r/w
5009
- ASF r | FFF r/w | MACOS r | PCD r | TIFF r/w
5010
- AVI r | FITS r | MAX r | PCX r | TORRENT r
5011
- AVIF r/w | FLA r | MEF r/w | PDB r | TTC r
5012
- AZW r | FLAC r | MIE r/w/c | PDF r/w | TTF r
5013
- BMP r | FLIF r/w | MIFF r | PEF r/w | TXT r
5014
- BPG r | FLV r | MKA r | PFA r | VCF r
5015
- BTF r | FPF r | MKS r | PFB r | VNT r
5016
- C2PA r | FPX r | MKV r | PFM r | VRD r/w/c
5017
- CHM r | GIF r/w | MNG r/w | PGF r | VSD r
5018
- COS r | GLV r/w | MOBI r | PGM r/w | WAV r
5019
- CR2 r/w | GPR r/w | MODD r | PLIST r | WDP r/w
5020
- CR3 r/w | GZ r | MOI r | PICT r | WEBP r/w
5021
- CRM r/w | HDP r/w | MOS r/w | PMP r | WEBM r
5022
- CRW r/w | HDR r | MOV r/w | PNG r/w | WMA r
5023
- CS1 r/w | HEIC r/w | MP3 r | PPM r/w | WMV r
5024
- CSV r | HEIF r/w | MP4 r/w | PPT r | WPG r
5025
- CUR r | HTML r | MPC r | PPTX r | WTV r
5026
- CZI r | ICC r/w/c | MPG r | PS r/w | WV r
5027
- DCM r | ICO r | MPO r/w | PSB r/w | X3F r/w
5028
- DCP r/w | ICS r | MQV r/w | PSD r/w | XCF r
5029
- DCR r | IDML r | MRC r | PSP r | XISF r
5030
- DFONT r | IIQ r/w | MRW r/w | QTIF r/w | XLS r
5031
- DIVX r | IND r/w | MXF r | R3D r | XLSX r
5032
- DJVU r | INSP r/w | NEF r/w | RA r | XMP r/w/c
5033
- DLL r | INSV r | NKA r | RAF r/w | ZIP r
5034
- DNG r/w | INX r | NKSC r/w | RAM r |
5035
- DOC r | ISO r | NRW r/w | RAR r |
5058
+ 360 r/w | DOCX r | ITC r | NUMBERS r | RAM r
5059
+ 3FR r | DPX r | J2C r | NXD r | RAR r
5060
+ 3G2 r/w | DR4 r/w/c | JNG r/w | O r | RAW r/w
5061
+ 3GP r/w | DSS r | JP2 r/w | ODP r | RIFF r
5062
+ 7Z r | DV r | JPEG r/w | ODS r | RSRC r
5063
+ A r | DVB r/w | JSON r | ODT r | RTF r
5064
+ AA r | DVR-MS r | JXL r/w | OFR r | RW2 r/w
5065
+ AAC r | DYLIB r | K25 r | OGG r | RWL r/w
5066
+ AAE r | EIP r | KDC r | OGV r | RWZ r
5067
+ AAX r/w | EPS r/w | KEY r | ONP r | RM r
5068
+ ACR r | EPUB r | LA r | OPUS r | SEQ r
5069
+ AFM r | ERF r/w | LFP r | ORF r/w | SKETCH r
5070
+ AI r/w | EXE r | LIF r | ORI r/w | SO r
5071
+ AIFF r | EXIF r/w/c | LNK r | OTF r | SR2 r/w
5072
+ APE r | EXR r | LRV r/w | PAC r | SRF r
5073
+ ARQ r/w | EXV r/w/c | M2TS r | PAGES r | SRW r/w
5074
+ ARW r/w | F4A/V r/w | M4A/V r/w | PBM r/w | SVG r
5075
+ ASF r | FFF r/w | MACOS r | PCAP r | SWF r
5076
+ AVI r | FITS r | MAX r | PCAPNG r | THM r/w
5077
+ AVIF r/w | FLA r | MEF r/w | PCD r | TIFF r/w
5078
+ AZW r | FLAC r | MIE r/w/c | PCX r | TORRENT r
5079
+ BMP r | FLIF r/w | MIFF r | PDB r | TTC r
5080
+ BPG r | FLV r | MKA r | PDF r/w | TTF r
5081
+ BTF r | FPF r | MKS r | PEF r/w | TXT r
5082
+ C2PA r | FPX r | MKV r | PFA r | VCF r
5083
+ CHM r | GIF r/w | MNG r/w | PFB r | VNT r
5084
+ COS r | GLV r/w | MOBI r | PFM r | VRD r/w/c
5085
+ CR2 r/w | GPR r/w | MODD r | PGF r | VSD r
5086
+ CR3 r/w | GZ r | MOI r | PGM r/w | WAV r
5087
+ CRM r/w | HDP r/w | MOS r/w | PLIST r | WDP r/w
5088
+ CRW r/w | HDR r | MOV r/w | PICT r | WEBP r/w
5089
+ CS1 r/w | HEIC r/w | MP3 r | PMP r | WEBM r
5090
+ CSV r | HEIF r/w | MP4 r/w | PNG r/w | WMA r
5091
+ CUR r | HTML r | MPC r | PPM r/w | WMV r
5092
+ CZI r | ICC r/w/c | MPG r | PPT r | WPG r
5093
+ DCM r | ICO r | MPO r/w | PPTX r | WTV r
5094
+ DCP r/w | ICS r | MQV r/w | PS r/w | WV r
5095
+ DCR r | IDML r | MRC r | PSB r/w | X3F r/w
5096
+ DFONT r | IIQ r/w | MRW r/w | PSD r/w | XCF r
5097
+ DIVX r | IND r/w | MXF r | PSP r | XISF r
5098
+ DJVU r | INSP r/w | NEF r/w | QTIF r/w | XLS r
5099
+ DLL r | INSV r | NKA r | R3D r | XLSX r
5100
+ DNG r/w | INX r | NKSC r/w | RA r | XMP r/w/c
5101
+ DOC r | ISO r | NRW r/w | RAF r/w | ZIP r
5036
5102
 
5037
5103
  Meta Information
5038
5104
  ----------------------+----------------------+---------------------
@@ -5100,6 +5166,7 @@ L<Input-output text formatting|/Input-output text formatting>
5100
5166
  -n (--printConv) No print conversion
5101
5167
  -p[-] STR (-printFormat) Print output in specified format
5102
5168
  -php Export tags as a PHP Array
5169
+ -plot Output tags as SVG plot file
5103
5170
  -s[NUM] (-short) Short output format (-s for tag names)
5104
5171
  -S (-veryShort) Very short output format
5105
5172
  -sep STR (-separator) Set separator string for list items
@@ -5678,14 +5745,16 @@ option may be used to split them back into separate items when importing.
5678
5745
  Special feature: B<-csv>+=I<CSVFILE> may be used to add items to existing
5679
5746
  lists. This affects only list-type tags. Also applies to the B<-j> option.
5680
5747
 
5681
- Note that this option is fundamentally different than all other output
5682
- format options because it requires information from all input files to be
5683
- buffered in memory before the output is written. This may result in
5684
- excessive memory usage when processing a very large number of files with a
5685
- single command. Also, it makes this option incompatible with the B<-w> and
5686
- B<-W> options. When processing a large number of files, it is recommended
5687
- to either use the JSON (B<-j>) or XML (B<-X>) output format, or use B<-p> to
5688
- generate a fixed-column CSV file instead of using the B<-csv> option.
5748
+ Note that this and the B<-plot> options are fundamentally different than all
5749
+ other output format options because they require information from all input
5750
+ files to be buffered in memory before the output is written. This may
5751
+ result in excessive memory usage when processing a very large number of
5752
+ files with a single command. Also, when used with B<-csv>, the B<-w> option
5753
+ changes to specify a complete file name with no filename formatting codes or
5754
+ append mode allowed, and B<-W> may not be used. When processing a large
5755
+ number of files, it is recommended to either use the JSON (B<-j>) or XML
5756
+ (B<-X>) output format, or use B<-p> to generate a fixed-column CSV file
5757
+ instead of using the B<-csv> option.
5689
5758
 
5690
5759
  =item B<-csvDelim> I<STR>
5691
5760
 
@@ -5984,7 +6053,7 @@ with this command:
5984
6053
 
5985
6054
  produces output like this:
5986
6055
 
5987
- -- Generated by ExifTool 13.17 --
6056
+ -- Generated by ExifTool 13.25 --
5988
6057
  File: a.jpg - 2003:10:31 15:44:19
5989
6058
  (f/5.6, 1/60s, ISO 100)
5990
6059
  File: b.jpg - 2006:05:23 11:57:38
@@ -6033,6 +6102,21 @@ showing how this could be used in a PHP script:
6033
6102
  print_r($array);
6034
6103
  ?>
6035
6104
 
6105
+ =item B<-plot>
6106
+
6107
+ Write output for all specified tags and all input files as a single
6108
+ SVG-formatted plot. When combined with this feature, the B<-w> option
6109
+ argument is a complete file name with no format codes and the append feature
6110
+ may not be used. Each tag specified on the command line represents a
6111
+ dataset in the plot (or more for array values or if the Split plot setting
6112
+ is used). Non-numerical values are ignored. Each input file may contribute
6113
+ multiple points to a dataset if it contains sub-documents and the B<-ee>
6114
+ option is used, or if the tag value is a delimited string of numbers (valid
6115
+ delimiters are: space, comma, semicolon, tab and newline). Line, Scatter
6116
+ and Histogram plot types are available. See the API Plot Option and
6117
+ L<https://exiftool.org/plot.html> for more details and information about the
6118
+ plot settings.
6119
+
6036
6120
  =item B<-s>[I<NUM>] (B<-short>)
6037
6121
 
6038
6122
  Short output format. Prints tag names instead of descriptions. Add I<NUM>
@@ -6170,6 +6254,10 @@ ways to create a single output file from multiple source files:
6170
6254
  # 3. With the -W option (see the -W option below)
6171
6255
  exiftool -W+! out.txt FILE1 FILE2 ...
6172
6256
 
6257
+ 3) The B<-w> option changes when used with a multi-file output format
6258
+ (B<-csv> or B<-plot>). With these, the argument of B<-w> is a complete file
6259
+ name with no formatting codes, and the append feature may not be used.
6260
+
6173
6261
  Advanced features:
6174
6262
 
6175
6263
  A substring of the original file name, directory or extension may be taken
@@ -6458,13 +6546,13 @@ across directory boundaries if multiple input directories are specified.
6458
6546
  =item B<-i> I<DIR> (B<-ignore>)
6459
6547
 
6460
6548
  Ignore specified directory name. I<DIR> may be either an individual folder
6461
- name, or a full path. If a full path is specified, it must match the
6462
- Directory tag exactly to be ignored. Use multiple B<-i> options to ignore
6463
- more than one directory name. A special I<DIR> value of C<SYMLINKS> (case
6464
- sensitive) may be specified to avoid recursing into directories which are
6549
+ name, or a full path, and is case sensitive. If a full path is specified,
6550
+ it must match the Directory tag exactly to be ignored. Use multiple B<-i>
6551
+ options to ignore more than one directory name. A special I<DIR> value of
6552
+ C<SYMLINKS> may be specified to avoid recursing into directories which are
6465
6553
  symbolic links when the B<-r> option is used. As well, a value of C<HIDDEN>
6466
- (case sensitive) may be used to ignore files with names that start with a
6467
- "." (ie. hidden files on Unix systems) when scanning a directory.
6554
+ may be used to ignore files with names that start with a "." (ie. hidden
6555
+ files on Unix systems) when scanning a directory.
6468
6556
 
6469
6557
  =item B<-if>[I<NUM>] I<EXPR>
6470
6558
 
@@ -6771,12 +6859,12 @@ B<-listw> and B<-listx> options may be followed by an additional argument of
6771
6859
  the form C<-GROUP:All> to list only tags in a specific group, where C<GROUP>
6772
6860
  is one or more family 0-2 group names (excepting EXIF IFD groups) separated
6773
6861
  by colons. With B<-listg>, I<NUM> may be given to specify the group family,
6774
- otherwise family 0 is assumed. The B<-l> option may be combined with
6775
- B<-listf>, B<-listr> or B<-listwf> to add file descriptions to the list.
6776
- The B<-lang> option may be combined with B<-listx> to output descriptions in
6777
- a single language, and the B<-sort> and/or B<-lang> options may be combined
6778
- with B<-listgeo>. Also, the API GeolocMinPop, GeolocFeature and
6779
- GeolocAltNames options apply to the B<-listgeo> output. Here are some
6862
+ otherwise family 0 is assumed. The B<-l> or B<-v> option may be combined
6863
+ with B<-listf>, B<-listr> or B<-listwf> to add file descriptions to the
6864
+ list. The B<-lang> option may be combined with B<-listx> to output
6865
+ descriptions in a single language, and the B<-sort> and/or B<-lang> options
6866
+ may be combined with B<-listgeo>. Also, the API GeolocMinPop, GeolocFeature
6867
+ and GeolocAltNames options apply to the B<-listgeo> output. Here are some
6780
6868
  examples:
6781
6869
 
6782
6870
  -list # list all tag names
@@ -7808,8 +7896,9 @@ the B<-geotag> option.)
7808
7896
 
7809
7897
  Geotag an image (C<a.jpg>) from position information in a GPS track log
7810
7898
  (C<track.log>). Since the C<Geotime> tag is not specified, the value of
7811
- DateTimeOriginal is used for geotagging. Local system time is assumed
7812
- unless DateTimeOriginal contains a timezone.
7899
+ SubSecDateTimeOriginal (preferentially) or DateTimeOriginal is used for
7900
+ geotagging. Local system time is assumed unless the time contains a
7901
+ timezone.
7813
7902
 
7814
7903
  =item C<exiftool -geotag track.log -geolocate=geotag a.jpg>
7815
7904
 
@@ -7854,7 +7943,8 @@ Delete XMP GPS tags which were added by the geotag feature.
7854
7943
 
7855
7944
  =item C<exiftool -xmp:geotag=track.log a.jpg>
7856
7945
 
7857
- Geotag an image with XMP tags, using the time from DateTimeOriginal.
7946
+ Geotag an image with XMP tags, using the time from SubSecDateTimeOriginal or
7947
+ DateTimeOriginal.
7858
7948
 
7859
7949
  =item C<exiftool -geotag a.log -geotag b.log -r dir>
7860
7950
 
@@ -16,7 +16,7 @@ use vars qw($VERSION);
16
16
  use Image::ExifTool::Exif;
17
17
  use Image::ExifTool::PLIST;
18
18
 
19
- $VERSION = '1.14';
19
+ $VERSION = '1.15';
20
20
 
21
21
  sub ConvertPLIST($$);
22
22
 
@@ -307,7 +307,17 @@ sub ConvertPLIST($$);
307
307
  Name => 'Apple_0x004f',
308
308
  Unknown => 1,
309
309
  ValueConv => \&ConvertPLIST,
310
- }
310
+ },
311
+ 0x0054 => {
312
+ Name => 'Apple_0x0054',
313
+ Unknown => 1,
314
+ ValueConv => \&ConvertPLIST,
315
+ },
316
+ 0x005a => {
317
+ Name => 'Apple_0x005a',
318
+ Unknown => 1,
319
+ ValueConv => \&ConvertPLIST,
320
+ },
311
321
  );
312
322
 
313
323
  # PLIST-format CMTime structure (ref PH)